Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import SwiftUI
- import WebKit
- // MARK: - Simple WKWebView Wrapper
- struct WebView: UIViewRepresentable {
- let html: String
- let onContentSizeChange: (CGSize) -> Void
- func makeUIView(context: Context) -> WKWebView {
- let webView = WKWebView()
- webView.scrollView.isScrollEnabled = false
- webView.isOpaque = false
- webView.backgroundColor = .clear
- webView.navigationDelegate = context.coordinator
- return webView
- }
- func updateUIView(_ uiView: WKWebView, context: Context) {
- uiView.loadHTMLString(html, baseURL: nil)
- }
- // Create a Coordinator to handle content size changes
- func makeCoordinator() -> Coordinator {
- return Coordinator(onContentSizeChange: onContentSizeChange)
- }
- class Coordinator: NSObject, WKNavigationDelegate {
- let onContentSizeChange: (CGSize) -> Void
- init(onContentSizeChange: @escaping (CGSize) -> Void) {
- self.onContentSizeChange = onContentSizeChange
- }
- func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
- // Get the content size after the page has loaded
- let contentSize = webView.scrollView.contentSize
- onContentSizeChange(contentSize)
- }
- }
- }
- // MARK: - HTMLWebView with KaTeX Support
- struct HTMLWebView: View {
- let text: String
- let fontSize: Int
- let borderColor: Color
- let borderWidth: CGFloat
- let cornerRadius: CGFloat
- @State private var contentHeight: CGFloat = 0 // Default height is 0 initially
- @State private var isContentRendered: Bool = false // Track if content is rendered
- // Custom Initializer with Default Parameters
- init(
- text: String,
- fontSize: Int = 16,
- borderColor: Color = .blue,
- borderWidth: CGFloat = 2,
- cornerRadius: CGFloat = 10
- ) {
- self.text = text
- self.fontSize = fontSize
- self.borderColor = borderColor
- self.borderWidth = borderWidth
- self.cornerRadius = cornerRadius
- }
- var body: some View {
- let htmlContent = composeHTML(text: text)
- return VStack {
- WebView(html: htmlContent, onContentSizeChange: { size in
- // Update the height of the content
- if size.height > 0 {
- self.contentHeight = size.height
- self.isContentRendered = true // Set the flag to true when content is rendered
- }
- })
- .frame(height: contentHeight)
- .padding()
- .overlay(
- // Only display the border once the content is rendered
- isContentRendered ? RoundedRectangle(cornerRadius: cornerRadius)
- .stroke(borderColor, lineWidth: borderWidth) : nil
- )
- }
- .padding(0) // Remove padding to make sure the content fits precisely
- }
- private func composeHTML(text: String) -> String {
- """
- <!DOCTYPE html>
- <html>
- <head>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/contrib/auto-render.min.js"
- onload="renderMathInElement(document.body, {
- delimiters: [
- {left: '\\\\(', right: '\\\\)', display: false},
- {left: '\\\\[', right: '\\\\]', display: true}
- ]
- });">
- </script>
- <style>
- body {
- font-family: -apple-system, sans-serif;
- font-size: \(fontSize)px;
- margin: 0; /* Remove margins to prevent extra space */
- color: #000;
- background-color: transparent;
- }
- p {
- text-align: left;
- }
- .katex {
- font-size: \(fontSize)px;
- }
- </style>
- </head>
- <body>
- \(text)
- </body>
- </html>
- """
- }
- }
- #Preview {
- HTMLWebView(text: #"""
- Here are some famous formulas:
- <br>
- 1. <strong>Quadratic Formula</strong>: \[
- x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
- \]
- 2. <strong>Newton's Second Law</strong>: \[
- F = ma
- \]
- 3. <strong>Pythagorean Theorem</strong>: \[
- a^2 + b^2 = c^2
- \]
- 4. <strong>Matrix Example</strong>: \[
- \begin{pmatrix}
- 1 & 2 \\
- 3 & 4
- \end{pmatrix}
- \]
- 5. <strong>Binet's formula</strong>: \[
- F(n) = \frac{1}{\sqrt{5}} \left( \left( \frac{1 + \sqrt{5}}{2} \right)^n - \left( \frac{1 - \sqrt{5}}{2} \right)^n \right)
- \]
- is the closed form for the Fibonacci sequence \[
- \begin{cases}
- a_0 = 0 \\
- a_1 = 1 \\
- a_n = a_{n-1} + a_{n-2} \quad \text{for} \quad n > 1
- \end{cases}
- \]
- <br>
- """#)
- .padding()
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement