Advertisement
ronerez

Untitled

Apr 25th, 2025
27
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 5.39 KB | Source Code | 0 0
  1. import SwiftUI
  2. import WebKit
  3.  
  4. // MARK: - Simple WKWebView Wrapper
  5. struct WebView: UIViewRepresentable {
  6.     let html: String
  7.     let onContentSizeChange: (CGSize) -> Void
  8.    
  9.     func makeUIView(context: Context) -> WKWebView {
  10.         let webView = WKWebView()
  11.         webView.scrollView.isScrollEnabled = false
  12.         webView.isOpaque = false
  13.         webView.backgroundColor = .clear
  14.         webView.navigationDelegate = context.coordinator
  15.         return webView
  16.     }
  17.    
  18.     func updateUIView(_ uiView: WKWebView, context: Context) {
  19.         uiView.loadHTMLString(html, baseURL: nil)
  20.     }
  21.    
  22.     // Create a Coordinator to handle content size changes
  23.     func makeCoordinator() -> Coordinator {
  24.         return Coordinator(onContentSizeChange: onContentSizeChange)
  25.     }
  26.    
  27.     class Coordinator: NSObject, WKNavigationDelegate {
  28.         let onContentSizeChange: (CGSize) -> Void
  29.        
  30.         init(onContentSizeChange: @escaping (CGSize) -> Void) {
  31.             self.onContentSizeChange = onContentSizeChange
  32.         }
  33.        
  34.         func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
  35.             // Get the content size after the page has loaded
  36.             let contentSize = webView.scrollView.contentSize
  37.             onContentSizeChange(contentSize)
  38.         }
  39.     }
  40. }
  41.  
  42. // MARK: - HTMLWebView with KaTeX Support
  43. struct HTMLWebView: View {
  44.     let text: String
  45.     let fontSize: Int
  46.     let borderColor: Color
  47.     let borderWidth: CGFloat
  48.     let cornerRadius: CGFloat
  49.     @State private var contentHeight: CGFloat = 0 // Default height is 0 initially
  50.     @State private var isContentRendered: Bool = false // Track if content is rendered
  51.    
  52.     // Custom Initializer with Default Parameters
  53.     init(
  54.         text: String,
  55.         fontSize: Int = 16,
  56.         borderColor: Color = .blue,
  57.         borderWidth: CGFloat = 2,
  58.         cornerRadius: CGFloat = 10
  59.     ) {
  60.         self.text = text
  61.         self.fontSize = fontSize
  62.         self.borderColor = borderColor
  63.         self.borderWidth = borderWidth
  64.         self.cornerRadius = cornerRadius
  65.     }
  66.    
  67.     var body: some View {
  68.         let htmlContent = composeHTML(text: text)
  69.        
  70.         return VStack {
  71.             WebView(html: htmlContent, onContentSizeChange: { size in
  72.                 // Update the height of the content
  73.                 if size.height > 0 {
  74.                     self.contentHeight = size.height
  75.                     self.isContentRendered = true // Set the flag to true when content is rendered
  76.                 }
  77.             })
  78.             .frame(height: contentHeight)
  79.             .padding()
  80.             .overlay(
  81.                 // Only display the border once the content is rendered
  82.                 isContentRendered ? RoundedRectangle(cornerRadius: cornerRadius)
  83.                     .stroke(borderColor, lineWidth: borderWidth) : nil
  84.             )
  85.         }
  86.         .padding(0) // Remove padding to make sure the content fits precisely
  87.     }
  88.    
  89.     private func composeHTML(text: String) -> String {
  90.         """
  91.        <!DOCTYPE html>
  92.        <html>
  93.        <head>
  94.            <meta name="viewport" content="width=device-width, initial-scale=1.0">
  95.            <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css">
  96.             <script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.js"></script>
  97.             <script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/contrib/auto-render.min.js"
  98.                 onload="renderMathInElement(document.body, {
  99.                    delimiters: [
  100.                        {left: '\\\\(', right: '\\\\)', display: false},
  101.                        {left: '\\\\[', right: '\\\\]', display: true}
  102.                    ]
  103.                });">
  104.             </script>
  105.             <style>
  106.                 body {
  107.                     font-family: -apple-system, sans-serif;
  108.                     font-size: \(fontSize)px;
  109.                     margin: 0; /* Remove margins to prevent extra space */
  110.                     color: #000;
  111.                     background-color: transparent;
  112.                 }
  113.                 p {
  114.                     text-align: left;
  115.                 }
  116.                 .katex {
  117.                     font-size: \(fontSize)px;
  118.                 }
  119.             </style>
  120.         </head>
  121.         <body>
  122.             \(text)
  123.         </body>
  124.         </html>
  125.         """
  126.    }
  127. }
  128.  
  129. #Preview {
  130.    HTMLWebView(text: #"""
  131.         Here are some famous formulas:
  132.         <br>
  133.         1. <strong>Quadratic Formula</strong>: \[
  134.         x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
  135.         \]
  136.  
  137.         2. <strong>Newton's Second Law</strong>: \[
  138.         F = ma
  139.         \]
  140.  
  141.         3. <strong>Pythagorean Theorem</strong>: \[
  142.         a^2 + b^2 = c^2
  143.         \]
  144.  
  145.         4. <strong>Matrix Example</strong>: \[
  146.         \begin{pmatrix}
  147.         1 & 2 \\
  148.         3 & 4
  149.         \end{pmatrix}
  150.         \]
  151.    
  152.         5. <strong>Binet's formula</strong>: \[
  153.         F(n) = \frac{1}{\sqrt{5}} \left( \left( \frac{1 + \sqrt{5}}{2} \right)^n - \left( \frac{1 - \sqrt{5}}{2} \right)^n \right)
  154.         \]
  155.         is the closed form for the Fibonacci sequence \[
  156.         \begin{cases}
  157.         a_0 = 0 \\
  158.         a_1 = 1 \\
  159.         a_n = a_{n-1} + a_{n-2} \quad \text{for} \quad n > 1
  160.         \end{cases}
  161.         \]
  162.         <br>
  163.     """#)
  164.    .padding()
  165. }
  166.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement