Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to show HTML or Markdown in a SwiftUI Text?

Tags:

How can I set a SwiftUI Text to display rendered HTML or Markdown?

Something like this:

Text(HtmlRenderedString(fromString: "<b>Hi!</b>"))

or for MD:

Text(MarkdownRenderedString(fromString: "**Bold**"))

Perhaps I need a different View?

like image 391
Div Avatar asked Jul 04 '19 18:07

Div


People also ask

How do I show HTML in Swiftui?

struct htmlAttributedLabel: UIViewRepresentable { @Binding var htmlText: String var width: CGFloat @Binding var size:CGSize var lineLimit = 0 //var textColor = Color(. label) func makeUIView(context: Context) -> UILabel { let label = UILabel() label. lineBreakMode = . byWordWrapping label.

How do I convert HTML to text in Swiftui?

You can convert HTML entities to their equivalent using an extension like this: import UIKit extension String { var decoded: String { let attr = try? NSAttributedString(data: Data(utf8), options: [ . documentType: NSAttributedString.


2 Answers

If you don't need to specifically use a Text view. You can create a UIViewRepresentable that shows a WKWebView and simple call loadHTMLString().

import WebKit
import SwiftUI

struct HTMLStringView: UIViewRepresentable {
    let htmlContent: String

    func makeUIView(context: Context) -> WKWebView {
        return WKWebView()
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {
        uiView.loadHTMLString(htmlContent, baseURL: nil)
    }
}

In your body simple call this object like this:

import SwiftUI

struct Test: View {
    var body: some View {
        VStack {
            Text("Testing HTML Content")
            Spacer()
            HTMLStringView(htmlContent: "<h1>This is HTML String</h1>")
            Spacer()
        }
    }
}

struct Test_Previews: PreviewProvider {
    static var previews: some View {
        Test()
    }
}
like image 91
Tomas Avatar answered Sep 23 '22 05:09

Tomas


iOS 15 (beta)

Text now supports basic Markdown!

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Regular")
            Text("*Italics*")
            Text("**Bold**")
            Text("~Strikethrough~")
            Text("`Code`")
            Text("[Link](https://apple.com)")
            Text("***[They](https://apple.com) ~are~ `combinable`***")
        }
    }
}

Result:

Markdown result


However, if you store a String that contains Markdown in a property, it doesn't render. I'm pretty sure this is a bug.

struct ContentView: View {
    @State var textWithMarkdown = "***[They](https://apple.com) ~are~ `combinable`***"
    var body: some View {
        Text(textWithMarkdown)
    }
}

Result:

Text does not render Markdown and renders the raw String instead

You can work around this by converting textWithMarkdown to an AttributedString, using init(markdown:options:baseURL:).

struct ContentView: View {
    @State var textWithMarkdown = "***[They](https://apple.com) ~are~ `combinable`***"
    var body: some View {
        Text(textWithMarkdown.markdownToAttributed()) /// pass in AttributedString to Text
    }
}

extension String {
    func markdownToAttributed() -> AttributedString {
        do {
            return try AttributedString(markdown: self) /// convert to AttributedString
        } catch {
            return AttributedString("Error parsing markdown: \(error)")
        }
    }
}

Result:

Markdown rendered

like image 28
aheze Avatar answered Sep 23 '22 05:09

aheze