import SwiftUI import WebKit import AppKit struct MarkdownRenderer: NSViewRepresentable { let content: String func makeNSView(context: Context) -> WKWebView { print("MarkdownRenderer makeNSView called") let webView = WKWebView() webView.navigationDelegate = context.coordinator // Set a background color to see if the view is created webView.wantsLayer = true webView.layer?.backgroundColor = NSColor.systemYellow.cgColor return webView } func updateNSView(_ webView: WKWebView, context: Context) { print("MarkdownRenderer updateNSView called with content length: \(content.count)") let htmlContent = convertMarkdownToHTML(content) print("Generated HTML length: \(htmlContent.count)") webView.loadHTMLString(htmlContent, baseURL: nil) } func makeCoordinator() -> Coordinator { Coordinator() } class Coordinator: NSObject, WKNavigationDelegate { func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { print("WebView finished loading") } func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { print("WebView navigation failed: \(error)") } func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { print("WebView provisional navigation failed: \(error)") } } private func convertMarkdownToHTML(_ markdown: String) -> String { guard !markdown.isEmpty else { return "

No content to display

" } var html = markdown // Handle headers (more robust approach) let headerRegex1 = try! NSRegularExpression(pattern: "^# (.+)$", options: [.anchorsMatchLines]) let headerRegex2 = try! NSRegularExpression(pattern: "^## (.+)$", options: [.anchorsMatchLines]) let headerRegex3 = try! NSRegularExpression(pattern: "^### (.+)$", options: [.anchorsMatchLines]) let headerRegex4 = try! NSRegularExpression(pattern: "^#### (.+)$", options: [.anchorsMatchLines]) let headerRegex5 = try! NSRegularExpression(pattern: "^##### (.+)$", options: [.anchorsMatchLines]) let headerRegex6 = try! NSRegularExpression(pattern: "^###### (.+)$", options: [.anchorsMatchLines]) let range = NSRange(location: 0, length: html.count) html = headerRegex6.stringByReplacingMatches(in: html, options: [], range: range, withTemplate: "
$1
") html = headerRegex5.stringByReplacingMatches(in: html, options: [], range: NSRange(location: 0, length: html.count), withTemplate: "
$1
") html = headerRegex4.stringByReplacingMatches(in: html, options: [], range: NSRange(location: 0, length: html.count), withTemplate: "

$1

") html = headerRegex3.stringByReplacingMatches(in: html, options: [], range: NSRange(location: 0, length: html.count), withTemplate: "

$1

") html = headerRegex2.stringByReplacingMatches(in: html, options: [], range: NSRange(location: 0, length: html.count), withTemplate: "

$1

") html = headerRegex1.stringByReplacingMatches(in: html, options: [], range: NSRange(location: 0, length: html.count), withTemplate: "

$1

") // Handle bold (before italic to avoid conflicts) let boldRegex = try! NSRegularExpression(pattern: "\\*\\*(.*?)\\*\\*", options: []) html = boldRegex.stringByReplacingMatches(in: html, options: [], range: NSRange(location: 0, length: html.count), withTemplate: "$1") // Handle italic let italicRegex = try! NSRegularExpression(pattern: "\\*(.*?)\\*", options: []) html = italicRegex.stringByReplacingMatches(in: html, options: [], range: NSRange(location: 0, length: html.count), withTemplate: "$1") // Handle inline code let codeRegex = try! NSRegularExpression(pattern: "`([^`]+)`", options: []) html = codeRegex.stringByReplacingMatches(in: html, options: [], range: NSRange(location: 0, length: html.count), withTemplate: "$1") // Handle horizontal rules (-- on its own line) let hrRegex = try! NSRegularExpression(pattern: "^--$", options: [.anchorsMatchLines]) html = hrRegex.stringByReplacingMatches(in: html, options: [], range: NSRange(location: 0, length: html.count), withTemplate: "
") // Handle links let linkRegex = try! NSRegularExpression(pattern: "\\[([^\\]]+)\\]\\(([^\\)]+)\\)", options: []) html = linkRegex.stringByReplacingMatches(in: html, options: [], range: NSRange(location: 0, length: html.count), withTemplate: "$1") // Convert line breaks to paragraphs let paragraphs = html.components(separatedBy: "\n\n") html = paragraphs.map { paragraph in let trimmed = paragraph.trimmingCharacters(in: .whitespacesAndNewlines) if trimmed.isEmpty { return "" } // Don't wrap headers or horizontal rules in paragraphs if trimmed.hasPrefix("" { return trimmed.replacingOccurrences(of: "\n", with: "
") } return "

" + trimmed.replacingOccurrences(of: "\n", with: "
") + "

" }.filter { !$0.isEmpty }.joined(separator: "\n") let fullHTML = """ \(html) """ return fullHTML } }