Skip to content

Instantly share code, notes, and snippets.

@MANTENN
Created June 18, 2025 01:42
Show Gist options
  • Save MANTENN/31b5f22861b45c32de302b9c0e7dcb04 to your computer and use it in GitHub Desktop.
Save MANTENN/31b5f22861b45c32de302b9c0e7dcb04 to your computer and use it in GitHub Desktop.
RichText preview in swift UI
import SwiftUI
import PlaygroundSupport
struct AttributeSet: Equatable {
let isBold: Bool
let isItalic: Bool
let link: URL?
}
struct RichTextNode: Identifiable {
let id = UUID()
let text: String
let attributes: AttributeSet
}
func parseAttributedString(_ attrString: AttributedString) -> [RichTextNode] {
var result: [RichTextNode] = []
for run in attrString.runs {
let substring = String(attrString[run.range].characters)
let presentation = run.inlinePresentationIntent
let isBold = presentation == .stronglyEmphasized || presentation == [.stronglyEmphasized]
let isItalic = presentation == .emphasized || presentation == [.emphasized]
let link = run.link
let attrs = AttributeSet(isBold: isBold, isItalic: isItalic, link: link)
result.append(RichTextNode(text: substring, attributes: attrs))
}
return result
}
struct RichTextView: View {
let nodes: [RichTextNode]
var body: some View {
HStack(spacing: 0) {
ForEach(nodes) { node in
Text(node.text)
.bold(node.attributes.isBold)
.italic(node.attributes.isItalic)
.foregroundColor(node.attributes.link != nil ? .blue : .primary)
.underline(node.attributes.link != nil)
}
}
}
}
struct ContentView: View {
@State private var attrString: AttributedString = {
var str = AttributedString("Visit Apple and make text bold or italic.")
if let range = str.range(of: "Visit Apple") {
str[range].link = URL(string: "https://apple.com")
}
if let range = str.range(of: "make text") {
str[range].inlinePresentationIntent = .stronglyEmphasized
}
if let range = str.range(of: "italic") {
str[range].inlinePresentationIntent = .emphasized
}
return str
}()
var body: some View {
VStack(alignment: .leading, spacing: 16) {
Text("Raw Text:")
Text(attrString)
Text("Parsed View:")
RichTextView(nodes: parseAttributedString(attrString))
}
.padding()
}
}
PlaygroundPage.current.setLiveView(ContentView().frame(width: 400, height: 800))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment