A Markdown parsing and rendering library for iOS, built on TextKit 2 with full GFM support, Mermaid diagram rendering, and LaTeX math display.
- Standard Markdown — headings, paragraphs, bold, italic, strikethrough, links, images, code
- GFM Extensions — tables, task lists, autolinks, strikethrough, footnotes
- Mermaid Diagrams — code blocks with
mermaidlanguage render as Flowcharts, Sequence Diagrams, Class Diagrams, ER Diagrams - LaTeX Math — inline (
$...$) and block ($$...$$) math rendered via iosMath - Syntax Highlighting — code blocks with language-aware highlighting (Swift + generic)
- Footnotes — GFM-style footnote references and definitions with backlink navigation
- Nested Blockquotes — with customizable bar colors and backgrounds
- Fully Customizable — fonts, colors, spacing for every element via
MMarkStyleConfiguration - TextKit 2 — modern layout engine, designed for iOS 15+
- Dark Mode — Mermaid diagrams auto-adapt when system appearance changes
- iOS 15.0+
- Swift 5.7+
- Xcode 15.0+
pod 'MMarkParser', :git => 'https://github.com/6d616c66/MMarkParser.git', :tag => '1.0.0'MMarkParser depends on:
- md4c — Markdown parsing engine (SAX/callback model)
- iosMath — LaTeX math rendering
- Kingfisher — remote image loading (for
images) - BeautifulMermaidSwift — Mermaid diagram rendering (bundled)
- ElkSwift — Elk layout engine for Mermaid (bundled)
- Splash — Swift syntax highlighting (bundled)
import MMarkParser
// Parse markdown to NSAttributedString
let markdown = "# Hello\n\nThis is **Markdown** with $E=mc^2$"
let attributedString = MMarkParser.parse(markdown: markdown)
// Or use the String extension
let attributedString = markdown.parseMarkdown()
// Display in MMarkTextView (handles link taps, blockquote bars, etc.)
let textView = MMarkTextView()
textView.setMarkdown(markdown)
view.addSubview(textView)var config = MMarkStyleConfiguration.defaultStyle
// Customize heading fonts
config.headingStyles[1] = .init(
font: UIFont.systemFont(ofSize: 32, weight: .bold),
textColor: .label
)
// Customize code blocks
config.codeBlockStyle = .init(
font: UIFont.monospacedSystemFont(ofSize: 14, weight: .regular),
textColor: .white,
backgroundColor: .darkGray
)
// Customize blockquote appearance
config.blockquoteBorderColor = .systemBlue
config.blockquoteBorderWidth = 4
config.blockquoteBackgroundColor = UIColor.systemBlue.withAlphaComponent(0.05)
// Customize Mermaid theme
config.mermaidStyle.theme = .zincLight
config.mermaidStyle.autoDarkMode = true // auto-switch to dark theme
config.mermaidStyle.cornerRadius = 12
let result = MMarkParser.parse(markdown: markdown, configuration: config)See MMarkStyleConfiguration.swift for all available options.
| Element | Support |
|---|---|
| Headings (H1-H6) | Full |
| Bold, Italic | Full |
| Strikethrough | GFM |
| Inline Code | Full |
| Code Blocks (fenced) | Full + syntax highlighting |
| Links | Full + delegate |
| Images | Full (remote via Kingfisher) |
| Blockquotes | Full + nesting |
| Ordered Lists | Full |
| Unordered Lists | Full |
| Task Lists | GFM |
| Tables | GFM |
| Horizontal Rules | Full |
| LaTeX Math | $...$ inline, $$...$$ block |
| Mermaid Diagrams | ```mermaid code blocks |
| Footnotes | GFM |
| Autolinks | URL, email, www |
Render diagrams directly in Markdown using ```mermaid fenced code blocks:
```mermaid
graph TD
A[Start] --> B{Choice}
B -->|Yes| C[Option 1]
B -->|No| D[Option 2]
```- Flowchart (
graph TD,graph LR, etc.) - Sequence Diagram (
sequenceDiagram) - Class Diagram (
classDiagram) - ER Diagram (
erDiagram) - State Diagram (
stateDiagram) - XY Chart (
xychart)
| Property | Type | Default | Description |
|---|---|---|---|
mermaidStyle.theme |
DiagramTheme |
.default |
Base rendering theme |
mermaidStyle.autoDarkMode |
Bool |
true |
Auto-switch theme on appearance change |
mermaidStyle.backgroundColor |
UIColor |
systemGray alpha 0.1 | Body background |
mermaidStyle.headerBackgroundColor |
UIColor |
systemGray alpha 0.3 | Header background |
mermaidStyle.cornerRadius |
CGFloat |
12 | Rounded corners |
mermaidStyle.padding |
CGFloat |
12 | Content padding |
mermaidStyle.headerHeight |
CGFloat |
32 | Header bar height |
┌─────────────────────────────────────────────────────────────┐
│ Public API │
│ MMarkParser.swift │
│ parse(markdown:configuration:) │
│ String.parseMarkdown() │
└────────────┬──────────────────────────────────┬─────────────┘
│ │
▼ ▼
┌────────────────────────┐ ┌──────────────────────────────┐
│ Parser │ │ Renderer │
├────────────────────────┤ ├──────────────────────────────┤
│ CMarkParser.swift │ │ MMarkTextView.swift │
│ Parse options & flags│ │ TextKit 2 display view │
│ md4c initialization │ │ Blockquote bar drawing │
│ │ │ Link tap handling │
│ MMarkParserWrapper.swift │ │
│ md4c SAX callbacks │ │ MMarkStreamTextView.swift │
│ enter_block/leave_ │ │ Streaming text support │
│ block/enter_span/ │ │ │
│ leave_span/text │ │ MMarkStyleConfiguration.swift│
│ Attribute stacking │ │ Full style definitions │
│ Table accumulation │ │ │
│ Mermaid detection │ │ MMarkFontLoader.swift │
│ Footnote processing │ │ KaTeX font registration │
│ │ │ │
│ │ │ MMarkTextCommon.swift │
│ │ │ Shared types & helpers │
└────────────┬───────────┘ └──────────────┬───────────────┘
│ │
│ NSAttributedString │
│ with custom attributes │
│ & NSTextAttachments │
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ Attachments │
├─────────────────────────────────────────────────────────────┤
│ MMarkBaseAttachment/Model Base classes for all views │
│ MMarkCodeBlockAttachment Syntax-highlighted code │
│ MMarkImageAttachment Remote images (Kingfisher) │
│ MMarkTableAttachment GFM table rendering │
│ MMarkMathBlockAttachment LaTeX math (iosMath) │
│ MMarkMermaidAttachment Mermaid diagram rendering │
│ MMarkHorizontalRuleAttachment Horizontal rule separator │
│ MMarkListMarkerAttachment List bullet/number markers │
└─────────────────────────────────────────────────────────────┘
graph TD
A[Markdown String] --> B[MMarkParser.parse]
B --> C[CMarkParser: configure md4c flags & options]
C --> D[md4c SAX Parser]
D --> E{Callbacks}
E -->|enter_block| F[_MD4CHandler]
E -->|leave_block| F
E -->|enter_span| F
E -->|leave_span| F
E -->|text| F
F -->|pushAttrs/popAttrs| G[Attribute Stack]
F -->|accumulate| H[Table/Code Buffer]
F --> G
F --> H
G --> I[NSAttributedString]
H --> I
I --> J[MMarkTextView]
J --> K[TextKit 2 Layout]
K --> L[Screen]
flowchart LR
A[```mermaid code block] --> B{Language = mermaid?}
B -->|Yes| C[MMarkMermaidModel.create]
B -->|No| D[MMarkCodeBlock: syntax highlight]
C --> E[MermaidRenderer.renderImage]
E --> F[MMarkMermaidAttachment]
F --> G[MMarkMermaidViewProvider]
G --> H[MMarkMermaidView]
H --> I[Scrollable Image with Header]
MMarkParser/
├── MMarkParser.swift # Public API entry point
├── Parser/
│ ├── CMarkParser.swift # Parser configuration & md4c options
│ └── MMarkParserWrapper.swift # md4c SAX callback handler (~1450 lines)
├── Renderer/
│ ├── MMarkTextView.swift # TextKit 2 text view with blockquote bars
│ ├── MMarkStreamTextView.swift # Streaming markdown text view
│ ├── MMarkStyleConfiguration.swift # Style definitions for all elements
│ ├── MMarkFontLoader.swift # KaTeX font registration
│ ├── MMarkTextCommon.swift # Shared types, constants, helpers
│ └── Attachments/
│ ├── MMarkBaseAttachment/ # Base attachment & model classes
│ ├── MMarkCodeBlockAttachment/ # Code block (model + view + provider)
│ ├── MMarkImageAttachment/ # Remote image (Kingfisher integration)
│ ├── MMarkTableAttachment/ # GFM table (model + view + provider)
│ ├── MMarkMathBlockAttachment/ # LaTeX math block (iosMath integration)
│ ├── MMarkMermaidAttachment/ # Mermaid diagram (BeautifulMermaidSwift)
│ ├── MMarkHorizontalRuleAttachment/ # Horizontal rule separator
│ └── MMarkListMarkerAttachment/ # List bullet/number rendering
├── Resources/ # KaTeX font files (.ttf)
│ └── MMarkParser.bundle/
│ └── KaTeXFonts/
Local Pods:
├── Splash/ # Syntax highlighting (extracted pod)
├── BeautifulMermaidSwift/ # Mermaid diagram rendering engine
└── ElkSwift/ # Elk layout engine bridge
- md4c SAX model: Uses callback-driven parsing (
enter_block/leave_block/enter_span/leave_span/text) instead of AST tree traversal. Incrementally buildsNSAttributedStringduring the parse walk. - Attribute stacking: An attribute stack (
pushAttrs/popAttrs) tracks style context through nested block/inline structures, ensuring correct attribute propagation (e.g., blockquote attributes carry into bold/italic/link children). - TextKit 2 attachments: Complex elements (code blocks, tables, math, images, Mermaid, horizontal rules, list markers) are rendered as
NSTextAttachmentsubclasses with correspondingNSTextAttachmentViewProviderclasses for lazy view creation. - Blockquote bars: Drawn via Core Graphics
draw(_:)override inMMarkTextView, usingenumerateTextLayoutFragments(TextKit 2 API) to determine fragment positions — avoids subview management issues. - Mermaid detection: Code blocks with language
mermaidare intercepted inleaveBlock— the content is rendered to aUIImageviaBeautifulMermaidSwift, then presented as a scrollable attachment view with a header bar showing the diagram type.
MMarkParser referenced the implementations of the following two libraries:
MMarkParser is available under the MIT license. See the LICENSE file for more info.
- md4c — C Markdown parser
- iosMath — LaTeX math rendering
- Kingfisher — Image downloading
- Splash — Swift syntax highlighting
- BeautifulMermaidSwift — Mermaid diagram rendering
- ElkSwift — Elk layout engine

