Skip to content

Instantly share code, notes, and snippets.

@Mcrich23
Created January 1, 2026 08:42
Show Gist options
  • Select an option

  • Save Mcrich23/5cab89f874c2d0ee96eade93aece3a1e to your computer and use it in GitHub Desktop.

Select an option

Save Mcrich23/5cab89f874c2d0ee96eade93aece3a1e to your computer and use it in GitHub Desktop.
A styled markdown initializer for AttributedString
extension AttributedString {
init(styledMarkdown markdownString: String) throws {
let newLine = AttributedString("\n")
let markdownString = markdownString
.replacingOccurrences(of: "\n\n", with: "\u{2029}\u{2029}\n\n")
var output = try AttributedString(
markdown: markdownString,
options: .init(
allowsExtendedAttributes: true,
interpretedSyntax: .full,
failurePolicy: .returnPartiallyParsedIfPossible
),
baseURL: nil
)
while let range = output.range(of: "\u{2029}\u{2029}") {
output[range] = newLine[newLine.startIndex..<newLine.endIndex]
}
for (intentBlock, intentRange) in output.runs[AttributeScopes.FoundationAttributes.PresentationIntentAttribute.self].reversed() {
guard let intentBlock = intentBlock else { continue }
for intent in intentBlock.components {
switch intent.kind {
case .header(level: let level):
switch level {
case 1:
output[intentRange].font = .system(.title).bold()
case 2:
output[intentRange].font = .system(.title2).bold()
case 3:
output[intentRange].font = .system(.title3).bold()
default:
break
}
default:
break
}
}
if intentRange.lowerBound != output.startIndex {
output.characters.insert(contentsOf: "\n", at: intentRange.lowerBound)
}
}
self = output
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment