Swift Markdown Kit · DOCS
单文档渲染
单文档渲染
适用于「一篇内容」而不是「一段会话」的场景:文章、更新日志、帮助页、单条模型 回答。
SwiftUI
import SwiftUI
import SwiftMarkdownKit
struct ArticleView: View {
let article: String
var body: some View {
MarkdownRenderView(markdown: article)
}
}
绑定一个不断变长的字符串就能实现流式:新值是旧值的前缀扩展时,视图只追加增量; 其他情况才整体重渲染。
想观察渲染器的状态,传一个回调:
MarkdownRenderView(markdown: article) { event in
switch event {
case .ready:
break
case .rendered(let height), .heightChanged(let height):
print("height", height)
case .action(let action):
print("action", action)
case .error(let error):
print(error.code, error.message)
@unknown default:
break
}
}
UIKit
import UIKit
import SwiftMarkdownKit
final class ArticleViewController: UIViewController {
private let renderer = MarkdownRenderViewController()
override func viewDidLoad() {
super.viewDidLoad()
addChild(renderer)
renderer.view.frame = view.bounds
renderer.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(renderer.view)
renderer.didMove(toParent: self)
renderer.render("# Hello\n\n它 **能用**。")
}
}
render(_:) 替换内容,clear() 清空,reload() 从头重建渲染器 —— 最后一个
通常用不到:WebKit 在内存压力下回收内容进程时,SDK 会自动重新加载并回放内容。
单文档的流式
renderer.startStreaming()
renderer.appendChunk("流式 **Markdown")
renderer.appendChunk("**,带公式 $x^2$", isFinal: true)
或者每次把累计的全文交给它,由它算增量:
renderer.renderStream(everythingSoFar)
两条路径都走增量渲染:已完成块边界之前的 HTML 会被缓存,只有不稳定的尾部重新 渲染,所以整条流的总成本随最终长度线性增长,而不是平方增长。
布局
渲染器默认自己滚动。嵌进你自己的 ScrollView 时,关掉它并改用高度回调:
struct EmbeddedArticle: View {
let markdown: String
@State private var height: CGFloat = 0
var body: some View {
ScrollView {
VStack {
Text("上面的任意内容")
MarkdownRenderView(
markdown: markdown,
options: MarkdownRenderOptions(isScrollEnabled: false)
) { event in
if case .rendered(let measured) = event { height = measured }
if case .heightChanged(let measured) = event { height = measured }
}
.frame(height: height)
}
}
}
}
流式过程中 heightChanged 会防抖,避免每帧触发一次布局;间隔由
heightChangeDebounceInterval 控制。
解析器的容错
模型输出不是教科书式的 Markdown,解析器就是为此设计的。价格旁边的 $、方括号
引用、右花括号还没流完的公式,都不会变红。KaTeX 解析不了的内容会退回模型实际
写下的字符,颜色与正文一致。
var options = MarkdownRenderOptions()
options.markdown.math = true // KaTeX,行内与块级
options.markdown.taskLists = true // - [x] / - [ ]
options.markdown.emoji = true // :smile:
options.markdown.linkify = true // 裸 URL 自动成为链接
options.markdown.typographer = true // 智能引号、破折号、省略号
options.markdown.breaks = false // 单个换行转成 <br>
options.markdown.allowRawHTML = false // 模型输出请保持关闭
allowRawHTML 默认关闭,对模型写的内容应当一直保持关闭。推理折叠不需要它 ——
<think> 的识别不依赖开放原始 HTML。
var options = MarkdownRenderOptions()
options.markdown.reasoning.completedLabel = "已深度思考"
这里配置的是单文档里的折叠。会话请改用
MarkdownChatRenderOptions.reasoning,它同时还驱动模型思考过程中的实时折叠。