Working with Markdown in Swift (iOS/macOS): Libraries and Practical Examples
Markdown is a lightweight markup language widely used for text formatting in documentation, chats, and educational applications. In the Swift ecosystem (iOS/macOS), there are several mature libraries that allow parsing, rendering, and converting Markdown into native views. In this article, we will look at the main tools: Down, Ink, and SwiftMarkdown, and show examples of integration into SwiftUI and UIKit.
1. Down Library (cmark-based)
Down is the most popular library for working with Markdown in Swift. It is based on the high-performance C parser cmark and supports the CommonMark standard. Down allows you to convert Markdown to HTML, NSAttributedString, PDF, and even AST (Abstract Syntax Tree).
Installation
Add to Package.swift:
dependencies: [ .package(url: "https://github.com/johnxnguyen/Down.git", from: "0.9.4")]Example: Rendering Markdown to NSAttributedString
import Down
let markdownString = "# Heading
This is **bold** text and *italic*."let down = Down(markdownString: markdownString)
do { let attributedString = try down.toAttributedString() // Use in UITextView or UILabel textView.attributedText = attributedString} catch { print("Parsing error: \\(error)")}Down also supports custom styles via DownStyler:
let styler = DownStyler(configuration: DownStylerConfiguration( fonts: FontCollection( heading1: .boldSystemFont(ofSize: 24), body: .systemFont(ofSize: 16) ), colors: ColorCollection( heading1: .systemBlue, body: .label )))let attributedString = try down.toAttributedString(styler: styler)2. Ink Library (John Sundell)
Ink is a lightweight Markdown parser by John Sundell. It requires no external dependencies (pure Swift) and is ideal for simple tasks: extracting headings, lists, links. Ink returns a tree of block-level elements that can be customized.
Installation via Swift Package Manager
dependencies: [ .package(url: "https://github.com/JohnSundell/Ink.git", from: "0.6.0")]Example: Parsing and Extracting Headings
import Ink
let markdown = """# Main Heading## SubheadingRegular text with **bold** emphasis."""
let parser = MarkdownParser()let result = parser.parse(markdown)
for heading in result.headings { print("Level \\(heading.level): \\(heading.text)")}// Output:// Level 1: Main Heading// Level 2: SubheadingInk also supports custom modifiers for extending syntax:
let modifier = Modifier(target: .inlineCode) { html, markdown in return "<span style=\\"color: red;\\">\\(html)</span>"}let parser = MarkdownParser(modifiers: [modifier])3. SwiftMarkdown (from Apple)
SwiftMarkdown is an official library from Apple, introduced at WWDC 2022. It is deeply integrated with the SwiftUI ecosystem and supports all Markdown extensions, including tables, code blocks with syntax highlighting, and nested lists. SwiftMarkdown uses AttributedString from Foundation, simplifying localization and dynamic fonts.
Installation
Add to your project via Xcode: File → Add Packages → apple/swift-markdown.
Example: Displaying Markdown in SwiftUI
import MarkdownUIimport SwiftUI
struct ContentView: View { let markdown = """ # Welcome This is an **example** used