使用 Bun 原生解析 Markdown
如果你曾经为了将 Markdown 字符串转换为 HTML 而组合过 unified、remark-parse、remark-rehype 和 rehype-stringify,你一定了解其中的开销。Bun 1.3.8(2026 年 1 月发布)内置了一个 Markdown 解析器,可以用一个 API 调用替代整个处理链——无需安装、无需导入、无需配置插件。
本文将介绍新的 Bun.markdown API 的功能、工作原理,以及它在你的工作流程中的应用场景。
核心要点
Bun.markdown是内置于 Bun 运行时的原生 Markdown 解析器,由 md4c C 库的 Zig 移植版本驱动。html()方法可以在一次调用中将 Markdown 转换为 HTML,无需外部库。render()通过为每种元素类型提供 JavaScript 回调函数,支持自定义输出格式(样式化 HTML、ANSI、纯文本)。react()直接返回 React 元素,允许将 Markdown 内容作为组件树的一部分进行渲染。- 该 API 目前仍标记为不稳定状态,因此请锁定你的 Bun 版本,并在部署到生产环境之前验证输出结果。
什么是 Bun Markdown 解析器?
Bun.markdown 是直接内置于 Bun 运行时的原生 Markdown 解析器。它遵循 CommonMark 规范,并实现为 md4c C 库的 Zig 移植版本——md4c 是一个在性能敏感环境(如 Qt)中使用的解析器。
由于它以编译的 Zig 代码而非 JavaScript 运行,因此避免了基于 JavaScript 的解析管道(如 unified 和 remark)的开销。Bun 不需要将多个包链接在一起,而是提供了一个用于 Markdown 处理的单一运行时 API。
注意:
Bun.markdownAPI 目前在官方 Bun 文档中标记为不稳定状态。该接口目前可以正常工作,但特定选项和方法签名可能在未来的 Bun 版本中发生变化。在生产环境升级之前,请查看 Bun 发布说明。
Bun Markdown 转 HTML:html() 方法
最简单的用例——将 Markdown 转换为 HTML 字符串——无需任何设置:
const html = Bun.markdown.html("# Hello **world**")
// "<h1>Hello <strong>world</strong></h1>\n"
将选项作为第二个参数传递。headings 选项对于文档站点和目录生成很有用:
const html = Bun.markdown.html("## Getting Started", {
headings: { ids: true }
})
// '<h2 id="getting-started">Getting Started</h2>\n'
GitHub 风格 Markdown (GFM) 扩展默认启用,包括表格、删除线(~~text~~)、任务列表(- [x] done)和宽松的自动链接。还支持 wikiLinks、latexMath 和标题自动链接等其他选项。
使用 Bun.markdown.render() 自定义渲染
当你需要的输出不是标准 HTML——样式化标记、ANSI 终端输出或纯文本——时,render() 接受每种元素类型的 JavaScript 回调函数:
// 为元素添加 CSS 类
const html = Bun.markdown.render("# Title\n\nHello **world**", {
heading: (children, { level }) => `<h${level} class="title">${children}</h${level}>`,
paragraph: (children) => `<p class="body">${children}</p>`,
strong: (children) => `<b>${children}</b>`,
})
// 去除所有格式,转换为纯文本
const plain = Bun.markdown.render("# Title\n\n**bold** text", {
heading: (children) => children + "\n",
strong: (children) => children,
paragraph: (children) => children + "\n",
})
// 返回 null 以完全省略特定元素
const noImages = Bun.markdown.render("# Title\n\n", {
image: () => null,
heading: (children) => `<h1>${children}</h1>`,
})
这使得 render() 对于 CLI 工具、邮件生成或任何 HTML 不是目标格式的处理管道都很有用。
Discover how at OpenReplay.com.
使用 react() 进行 Bun Markdown React 渲染
Bun.markdown.react() 返回可直接在组件树中使用的 React 元素:
function Markdown({ text }: { text: string }) {
return Bun.markdown.react(text)
}
// 将 Markdown 元素映射到自定义组件
const element = Bun.markdown.react("# Hello", {
h1: ({ children }) => <h1 className="page-title">{children}</h1>,
})
// 支持服务端渲染
import { renderToString } from "react-dom/server"
const html = renderToString(Bun.markdown.react("# Hello **world**"))
如果你使用的是 React 18 或更早版本,可以传递兼容性选项:
Bun.markdown.react(markdownText, undefined, { reactVersion: 18 })
何时使用 Bun.markdown 与 Remark
| 场景 | 推荐方案 |
|---|---|
| 基本的 Markdown 转 HTML 转换 | Bun.markdown.html() |
| 自定义输出(ANSI、样式化 HTML) | Bun.markdown.render() |
| React 组件树 | Bun.markdown.react() |
| 语法高亮、脚注、复杂插件 | 继续使用 unified/remark |
总结
如果你已经在运行 Bun 1.3.8 或更高版本,Bun.markdown 是全局可用的——无需安装。对于简单的内容处理管道,从 Bun.markdown.html() 开始;当你需要对输出有更多控制时,可以使用 render() 或 react()。
鉴于该 API 仍标记为不稳定状态,请锁定你的 Bun 版本,并在部署到生产环境之前针对预期的 HTML 测试渲染输出。
常见问题
不支持。Bun.markdown 处理标准的 Markdown 到 HTML 转换,但不包含内置的语法高亮功能。对于代码高亮,你需要使用 Shiki 或 Prism 等库对 HTML 输出进行后处理,或者使用带有专用高亮插件的 unified/remark 管道。
不可以。Bun.markdown 是内置于 Bun 运行时的原生 API,在 Node.js 中不可用。如果你的项目运行在 Node 上,你需要继续使用 unified、remark 或 markdown-it 等库进行 Markdown 解析。
Bun.markdown 不包含内置的 HTML 清理功能。如果你要处理用户提交的 Markdown,在浏览器中渲染之前,请将生成的 HTML 通过 DOMPurify 或 sanitize-html 等清理库进行处理,以防止跨站脚本攻击问题。
不支持。Bun.markdown 实现了 CommonMark 和 GitHub 风格 Markdown 扩展。它不支持 MDX、自定义指令或通过 unified 和 remark 提供的插件生态系统。对于这些用例,基于 remark 的管道仍然是更好的选择。
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.