add html email rendering with wkwebview, script/tracker blocking

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 21:23:15 +01:00
parent e3159d61e8
commit 74179cb534

View File

@@ -0,0 +1,64 @@
import SwiftUI
import WebKit
#if os(macOS)
struct MessageWebView: NSViewRepresentable {
let html: String
func makeNSView(context: Context) -> WKWebView {
let config = WKWebViewConfiguration()
config.preferences.isElementFullscreenEnabled = false
let prefs = WKWebpagePreferences()
prefs.allowsContentJavaScript = false
config.defaultWebpagePreferences = prefs
let webView = WKWebView(frame: .zero, configuration: config)
return webView
}
func updateNSView(_ webView: WKWebView, context: Context) {
let sanitized = sanitizeHTML(html)
webView.loadHTMLString(sanitized, baseURL: nil)
}
}
#else
struct MessageWebView: UIViewRepresentable {
let html: String
func makeUIView(context: Context) -> WKWebView {
let config = WKWebViewConfiguration()
let prefs = WKWebpagePreferences()
prefs.allowsContentJavaScript = false
config.defaultWebpagePreferences = prefs
let webView = WKWebView(frame: .zero, configuration: config)
webView.scrollView.isScrollEnabled = false
return webView
}
func updateUIView(_ webView: WKWebView, context: Context) {
let sanitized = sanitizeHTML(html)
webView.loadHTMLString(sanitized, baseURL: nil)
}
}
#endif
private func sanitizeHTML(_ html: String) -> String {
var result = html
let scriptPattern = "<script[^>]*>[\\s\\S]*?</script>"
result = result.replacingOccurrences(of: scriptPattern, with: "", options: .regularExpression)
let eventPattern = "\\s+on\\w+\\s*=\\s*\"[^\"]*\""
result = result.replacingOccurrences(of: eventPattern, with: "", options: .regularExpression)
let imgPattern = "(<img[^>]*?)\\ssrc\\s*=\\s*\"(https?://[^\"]*)\""
result = result.replacingOccurrences(of: imgPattern, with: "$1 data-blocked-src=\"$2\"", options: .regularExpression)
return """
<!DOCTYPE html>
<html><head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body { font-family: -apple-system, system-ui; font-size: 14px; padding: 8px; }
img[data-blocked-src] { display: none; }
</style>
</head><body>
\(result)
</body></html>
"""
}