A streaming Markdown generator for Swift, following CommonMark 0.31.2 and GitHub Flavored Markdown (GFM) specifications.
- Streaming Architecture: No intermediate AST, direct output for memory efficiency
- High Conformance: 92% CommonMark Block, 91% CommonMark Inline, 80% GFM Extensions
- Type-Safe API: Swift-native API with proper escaping
- Zero Dependencies: Pure Swift implementation
Add to your Package.swift:
dependencies: [
.package(url: "https://github.com/PsychQuant/markdown-swift.git", from: "0.1.0")
]import MarkdownSwift
// Create output and writer
var output = StringOutput()
var writer = MarkdownWriter(output: output)
// Write content
try writer.heading("Hello, Markdown!", level: 1)
try writer.paragraph("This is a streaming Markdown generator.")
try writer.bulletItem("Fast")
try writer.bulletItem("Memory efficient")
try writer.bulletItem("Spec compliant")
try writer.endList()
try writer.codeBlock("let x = 1", language: "swift")
print(writer.getOutput().content)Output:
# Hello, Markdown!
This is a streaming Markdown generator.
- Fast
- Memory efficient
- Spec compliant
```swift
let x = 1
## API Overview
### Block Elements (MarkdownWriter)
```swift
// Headings
writer.heading("Title", level: 1) // # Title
writer.setextHeading("Title", level: 1) // Title\n=====
// Paragraphs
writer.paragraph("Text")
// Lists
writer.bulletItem("Item") // - Item
writer.bulletItem("Nested", level: 1) // - Nested
writer.numberedItem("First") // 1. First
writer.taskItem("Todo", checked: false) // - [ ] Todo
writer.taskItem("Done", checked: true) // - [x] Done
writer.endList()
// Code
writer.codeBlock("code", language: "swift") // ```swift
writer.indentedCodeBlock("code") // code
// Other blocks
writer.blockquote("Quote") // > Quote
writer.horizontalRule() // ---
writer.table(headers: ["A"], rows: [["1"]]) // | A |\n|---|\n| 1 |
// References
writer.linkReference(id: "ref", url: "https://example.com")
writer.footnote(id: "1", text: "Note")
MarkdownInline.bold("text") // **text**
MarkdownInline.italic("text") // _text_
MarkdownInline.boldItalic("text") // ***text***
MarkdownInline.strikethrough("text") // ~~text~~
MarkdownInline.code("code") // `code`
MarkdownInline.link("text", url: "url") // [text](url)
MarkdownInline.image("alt", url: "url") // 
MarkdownInline.autolink("https://example.com") // <https://example.com>
MarkdownInline.hardBreak() // " \n"
MarkdownInline.htmlEntity("amp") // &
MarkdownInline.footnoteRef("1") // [^1]MarkdownEscaping.escape("*text*", context: .paragraph) // \*text\*
MarkdownEscaping.escape("a|b", context: .tableCell) // a\|b
MarkdownEscaping.escape("url with space", context: .url) // url%20with%20space| Specification | Coverage |
|---|---|
| CommonMark Block Elements | 92% (11/12) |
| CommonMark Inline Elements | 91% (10/11) |
| GFM Extensions | 80% (4/5) |
See docs/conformance.md for detailed coverage.
This library follows the streaming architecture principle:
convert(doc) = for e in extract(doc): emit(f(e))
- f is a pure mapping function:
Element -> String - emit outputs directly, no intermediate AST
- Memory usage remains constant regardless of document size
- macOS 13.0+
- Swift 5.9+
MIT License
- macdoc - Word to Markdown converter using this library
- ooxml-swift - OOXML parser for Swift