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?
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.
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.
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()
}
}
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:
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:
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With