在 Swift 中为 iOS 和 macOS 处理 Markdown:从解析到渲染
Markdown 是最流行的文本格式化标记语言之一。在 Swift (iOS/macOS) 生态系统中,有几个强大的库可以解析、转换和显示 Markdown。在本文中,我们将介绍两个主要库:Down(快速且灵活)和 SwiftMarkdown(Apple 官方库)。您将了解如何将它们集成到您的项目中,将 Markdown 转换为 NSAttributedString、HTML,并在 SwiftUI 中显示。
1. Down 库(基于 cmark)
Down 是用 Swift 编写的流行 C 解析器 cmark 的封装。它提供高性能,并支持所有主要的 Markdown 元素(标题、列表、代码、链接、图片、表格等)。
安装
通过 Swift Package Manager 添加包:
// Package.swiftdependencies: [ .package(url: "https://github.com/johnxnguyen/Down.git", from: "0.11.0")]示例:将 Markdown 转换为 HTML
import Down
let markdownString = "# 你好,世界!
这是**粗体文本**和*斜体*。"let down = Down(markdownString: markdownString)let html = try? down.toHTML()print(html ?? "")// 输出:<h1>你好,世界!</h1><p>这是 <strong>粗体文本</strong> 和 <em>斜体</em>。</p>渲染为 NSAttributedString
Down 可以直接创建 NSAttributedString,用于在 UILabel、UITextView 或 NSTextView 中显示:
let attributedString = try? down.toAttributedString()// 在 UITextView 中使用:textView.attributedText = attributedStringSwiftUI 支持
对于 SwiftUI,可以创建一个显示 AttributedString(iOS 15+)的封装:
struct MarkdownView: View { let markdown: String
var body: some View { if let nsAttr = try? Down(markdownString: markdown).toAttributedString() { Text(AttributedString(nsAttr)) } else { Text(markdown) } }}2. SwiftMarkdown(来自 Apple)
SwiftMarkdown 是 Apple 的官方库,属于 swift-markdown。它提供了一个完整的 Markdown 解析器,支持自定义和生成各种格式(HTML、CommonMark、AST)。
安装
// Package.swiftdependencies: [ .package(url: "https://github.com/apple/swift-markdown.git", branch: "main")]解析和处理 AST
该库构建了一个抽象语法树(AST),可以进行分析和修改:
import Markdown
let source = """# 文档
功能列表:- `foo()` — 第一个函数- `bar()` — 第二个函数"""
let document = Document(parsing: source)let heading = document.child(at: 0) as? Headingprint(heading?.plainText ?? "") // "文档"
// 遍历所有元素for child in document.children { if let list = child as? UnorderedList { for item in list.children { print((item as? ListItem)?.plainText ?? "") } }}生成 HTML
let html = document.format(options: [.unsafeTags])print(html)// 输出:<h1>文档</h1>...<ul><li><code>foo()</code> — 第一个函数</li>...通过 AttributedString 渲染(iOS 15+)
SwiftMarkdown 支持直接转换为 AttributedString,并使用样式:
import Markdownimport SwiftUI
struct ContentView: View { let markdown = "**重要**:请点击*这里*。"
var body: some