A zero-dependency SwiftUI markdown renderer for iOS 18, macOS 15, and beyond. Built on Foundation's AttributedString with PresentationIntent run-walking — no third-party parsers, no heavyweight abstractions.
- Full block-level rendering — headings H1–H6, paragraphs, ordered and unordered lists, code blocks, block quotes, tables, thematic breaks
- Inline formatting — bold, italic, strikethrough, inline code, links
- Zero dependencies — built entirely on Foundation and SwiftUI
- Simple theming — one
MarkdownThemestruct, no protocol hierarchies - Swift 6 strict concurrency — fully
Sendable, safe across actors - Interactive playground — live editor + theme comparison built in
Add the package to your Package.swift:
dependencies: [
.package(url: "https://github.com/onmyway133/swiftui-markdown", from: "1.0.0"),
],Render markdown:
import SwiftUIMarkdown
struct ContentView: View {
var body: some View {
ScrollView {
MarkdownView("""
# Hello from SwiftUIMarkdown
Render **bold**, *italic*, `code`, and [links](https://github.com/onmyway133).
> Simple. Zero dependencies. Swift 6.
""")
.padding()
}
}
}Inline-only text:
MarkdownLabel("Download the **latest** version [here](https://example.com).")| Block | Syntax | Notes |
|---|---|---|
| Heading | # H1 … ###### H6 |
Levels 1–6 |
| Paragraph | Plain text | Inline formatting supported |
| Unordered list | - item |
Nested via indentation |
| Ordered list | 1. item |
Ordinal labels |
| Code block | ```lang |
Optional language caption |
| Block quote | > text |
Left bar accent |
| Table | GFM pipe syntax | Header row bolded |
| Thematic break | --- |
Standard divider |
| Inline bold | **text** |
|
| Inline italic | *text* |
|
| Inline code | `code` |
Themed color |
| Inline link | [text](url) |
Accent color |
| Strikethrough | ~~text~~ |
Apply a built-in preset:
MarkdownView(markdown)
.markdownTheme(.github)Customize by copy-and-modifying a preset:
var theme = MarkdownTheme.default
theme.headingColor = .purple
theme.quoteBarColor = .purple
theme.linkColor = .orange
theme.blockSpacing = 16
MarkdownView(markdown)
.markdownTheme(theme)MarkdownTheme properties:
| Property | Type | Description |
|---|---|---|
headingFont |
(Int) -> Font |
Font for heading levels 1–6 |
headingColor |
Color |
Heading text color |
bodyFont |
Font |
Paragraph font |
bodyColor |
Color |
Paragraph text color |
codeFont |
Font |
Monospaced font for code |
codeBackground |
Color |
Code block background fill |
codeForeground |
Color |
Code text and inline code color |
quoteBarColor |
Color |
Left bar color for block quotes |
quoteTextColor |
Color |
Block quote text color |
linkColor |
Color |
Hyperlink color |
blockSpacing |
CGFloat |
Vertical gap between blocks |
An Xcode project is included in Examples/MarkdownPreview/. It contains a three-tab iOS app:
- Blocks — all supported block types rendered with the default theme
- Themes — side-by-side comparison of
.defaultand.github - Editor — live markdown editor with real-time preview
Open it directly:
open Examples/MarkdownPreview/MarkdownPreview.xcodeprojThe project references SwiftUIMarkdown as a local package (no network required). Each view in ContentView.swift also has #Preview macros for instant canvas rendering.
MarkdownView(markdown)
│
▼ AttributedString(markdown:, options: .full)
│
▼ attrStr.blockGroups() ← walks runs, groups by PresentationIntent identity
│
▼ BlockRenderer ← VStack dispatching on BlockGroup.Kind
│
├─ HeadingBlockView ← InlineRenderer.text() + themed font
├─ ParagraphBlockView ← InlineRenderer.text() + body style
├─ ListBlockView ← HStack(bullet, text) + depth indent
├─ CodeBlockView ← ScrollView + monospaced + language caption
├─ QuoteBlockView ← HStack(bar, text)
├─ TableBlockView ← Grid + GridRow per row
└─ DividerBlockView ← Divider()
Inline formatting (bold, italic, code, link) is handled inside InlineRenderer, which iterates AttributedString.runs and applies theme overrides on top of what Text(AttributedString) already renders natively.
- Swift 6.0+
- iOS 18+ / macOS 15+ / tvOS 18+ / watchOS 11+ / visionOS 2+
MIT © onmyway133


