chrisgve/markdownextendedview
A native SwiftUI Markdown renderer with LaTeX equation support.
Features
- GitHub Flavored Markdown parsing via Apple's swift-markdown
- LaTeX equations rendered natively via ExtendedSwiftMath
- Inline math: $...$ - Display math: $$...$$
- Task lists with checkbox rendering (
- [ ]and- [x]) - Clickable links with in-app browser (iOS) or system browser (macOS)
- Remote image loading using AsyncImage
- Syntax highlighting for 13+ languages
- Mermaid diagrams via embedded WKWebView
- Theming system with built-in themes (default, gitHub, compact)
- Privacy-first - network features disabled by default
- Cross-platform support for iOS 16+ and macOS 13+
- Pure SwiftUI - minimal WebView usage (only for Mermaid)
Supported Markdown Elements
| Element | Syntax | Status | |---------|--------|--------| | Headings | # H1 through ###### H6 | Supported | | Bold | text or text | Supported | | Italic | text or text | Supported | | Strikethrough | ~~text~~ | Supported | | Inline code | ` code | Supported | | Code blocks | `` fenced blocks | Supported (with syntax highlighting) | | Block quotes | > quote | Supported | | Ordered lists | 1. item | Supported (with nesting) | | Unordered lists | - item or item | Supported (with nesting) | | Task lists | - [ ] and - [x] | Supported | | Tables | GFM pipe tables | Supported | | Links | text | Opt-in (.links feature) | | Images | [alt] | Opt-in (.images feature) | | Mermaid diagrams | `mermaid | Opt-in (.mermaid feature) | | Footnotes | [^1] and [^1]: text | Opt-in (.footnotes feature) | | Thematic breaks | --- or ** | Supported | | Inline LaTeX | $E=mc^2$ | Supported | | Display LaTeX | $$...$$ | Supported |
Installation
Add to your Package.swift:
dependencies: [
.package(url: "https://github.com/ChrisGVE/MarkdownExtendedView.git", from: "1.0.0")
]Then add the dependency to your target:
.target(
name: "YourApp",
dependencies: ["MarkdownExtendedView"]
)Or in Xcode: File > Add Package Dependencies and enter the repository URL.
Usage
import SwiftUI
import MarkdownExtendedView
struct ContentView: View {
var body: some View {
ScrollView {
MarkdownView("""
# Hello World
This is **bold** and this is *italic*.
Inline equation: $E = mc^2$
Display equation:
$$\\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}$$
""")
.padding()
}
}
}Theming
MarkdownView(content)
.markdownTheme(.gitHub)Available themes:
.default- Clean, readable defaults that adapt to system appearance.gitHub- GitHub-style rendering with specific font sizes.compact- Reduced spacing for dense content
Custom Theme
Create a custom theme by modifying any of the available properties:
var customTheme = MarkdownTheme.default
// Typography
customTheme.bodyFont = .system(size: 15)
customTheme.heading1Font = .system(size: 28, weight: .bold)
customTheme.codeFont = .system(.body, design: .monospaced)
customTheme.codeBlockFont = .system(.callout, design: .monospaced)
// Colors
customTheme.textColor = .primary
customTheme.secondaryTextColor = .secondary
customTheme.linkColor = .blue
customTheme.codeBackgroundColor = Color(white: 0.95)
customTheme.blockQuoteBorderColor = Color(white: 0.75)
customTheme.tableBorderColor = Color(white: 0.80)
customTheme.tableHeaderBackgroundColor = Color(white: 0.90)
// Spacing
customTheme.paragraphSpacing = 12
customTheme.listItemSpacing = 4
customTheme.indentation = 20
customTheme.codeBlockPadding = 12
MarkdownView(content)
.markdownTheme(customTheme)Feature Flags
For privacy, network-dependent features are disabled by default. Enable them using the .markdownFeatures() modifier:
// Enable clickable links
MarkdownView(content)
.markdownFeatures(.links)
// Enable multiple features
MarkdownView(content)
.markdownFeatures([.links, .images, .syntaxHighlighting])
// Enable all features
MarkdownView(content)
.markdownFeatures(.all)Available Features
| Feature | Description | Network Required | |---------|-------------|------------------| | .links | Makes links tappable. iOS opens in SFSafariViewController, macOS opens in default browser | Optional | | .images | Loads and displays remote images using AsyncImage | Yes | | .syntaxHighlighting | Colorizes code blocks based on language | No | | .mermaid | Renders Mermaid diagrams using WKWebView | Yes (CDN) | | .footnotes | Processes footnote syntax ([^1]) and renders as superscripts | No |
Custom Link Handler
Override the default link behavior:
MarkdownView(content)
.markdownFeatures(.links)
.onLinkTap { url in
// Custom handling
print("Tapped: \(url)")
}Syntax Highlighting
When .syntaxHighlighting is enabled, code blocks with language specifiers are colorized:
MarkdownView("""
```swift
let greeting = "Hello, World!"
print(greeting)
```
""")
.markdownFeatures(.syntaxHighlighting)Supported languages: Swift, Python, JavaScript, TypeScript, Java, C, C++, Go, Rust, Ruby, Kotlin, PHP, C#.
Customize syntax colors via the theme:
var theme = MarkdownTheme.default
theme.syntaxColors.keyword = .purple
theme.syntaxColors.string = .red
theme.syntaxColors.comment = .grayMermaid Diagrams
When .mermaid is enabled, Mermaid code blocks are rendered as diagrams:
MarkdownView("""
```mermaid
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[OK]
B -->|No| D[Cancel]
```
""")
.markdownFeatures(.mermaid)Supports all Mermaid diagram types: flowcharts, sequence diagrams, class diagrams, state diagrams, Gantt charts, pie charts, and more.
Footnotes
When .footnotes is enabled, footnote syntax is processed and rendered:
MarkdownView("""
This statement needs a citation[^1].
Another point with a named reference[^note].
[^1]: Source: Academic Paper, 2024.
[^note]: See the documentation for details.
""")
.markdownFeatures(.footnotes)Footnotes are:
- Rendered as superscript numbers (¹, ², ³...)
- Collected and displayed in a footnotes section at the end
- Numbered in order of first appearance in the text
LaTeX Support
The math rendering is powered by ExtendedSwiftMath, our companion library for native LaTeX rendering with extended symbol coverage.
Inline Math
Use single dollar signs for inline equations that flow with text:
The famous equation $E = mc^2$ changed physics.Display Math
Use double dollar signs for centered, block-level equations:
The quadratic formula:
$$x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}$$Supported LaTeX Commands
ExtendedSwiftMath supports a wide range of LaTeX math commands including:
- Greek letters:
\alpha,\beta,\gamma,\pi,\theta, etc. - Operators:
\sum,\prod,\int,\lim,\log,\sin,\cos, etc. - Fractions:
\frac{a}{b} - Roots:
\sqrt{x},\sqrt[n]{x} - Superscripts/subscripts:
x^2,x_i,x_i^2 - Brackets:
\left(,\right),\{,\},\langle,\rangle - Matrices:
\begin{matrix}...\end{matrix},\begin{pmatrix}...\end{pmatrix} - Accents:
\hat{x},\bar{x},\vec{x},\dot{x} - Symbols:
\infty,\partial,\nabla,\forall,\exists
For a complete reference, see the ExtendedSwiftMath documentation.
Known Limitations
Current limitations that may be addressed in future versions:
| Feature | Status | Notes | |---------|--------|-------| | Reference-style links | Not verified | [text][ref] syntax may not work | | HTML blocks | Partial | Raw HTML is not rendered | | Definition lists | Not supported | Not part of GFM |
Requirements
- iOS 16.0+ / macOS 13.0+
- Swift 5.9+
- Xcode 15.0+
Dependencies
- swift-markdown - Apple's Markdown parser (CommonMark + GFM)
- ExtendedSwiftMath - Our companion library for native LaTeX rendering
Contributing
Contributions are welcome! Please feel free to submit issues and pull requests.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
Apache License 2.0 - Copyright 2025 Christian C. Berclaz. See LICENSE and NOTICE for details.
Package Metadata
Repository: chrisgve/markdownextendedview
Default branch: main
README: README.md