Markdown 为什么简单又复杂:语法、扩展与安全的权衡

原标题Markdown’s Simplicity and Complexity: Syntax, Extensions and Security

Theo Browne 读一篇 Markdown 批评文章,讨论等效语法、内联 HTML 和文档处理系统的复杂度。

TBTheo Browne讲者 · T3
频道
Theo - t3․gg
发布
2026年4月27日
视频
22:06
阅读
7 分钟
幻灯片
4
原文
英语
在 YouTube 打开
往下滚动阅读时,视频会缩到右下角继续播放。字幕跟随阅读语言。
阅读语言共 2 种语言可读
由 AI 从英语原文翻译。打开“对照原文”可以逐段核对。
摘要

30 秒看懂

Theo Browne 回顾自己对 Markdown 的喜爱,并解读 Brock 对其语法和扩展机制的批评。他讨论解析器漏洞、内联 HTML、引用解析和替代方案,强调格式的便利与完整处理流程的复杂度之间存在权衡。

  1. 1易读的源文件Markdown 让简单文档容易以文本形式编写和分享。
  2. 2多种等效形式不同标题和强调写法增加了实现需要处理的情况。
  3. 3解析器安全markdown-it 漏洞公告涉及特定受影响版本,而非所有 Markdown 解析器。
  4. 4文档级引用后面的定义可以决定前面的文本是否成为引用式链接。
  5. 5提出的替代方向作者提出使用明确规范的标记格式、显式扩展和构建系统。

要点建议

  1. Markdown 适合简单文本,但等效写法和扩展会使渲染复杂化。
  2. 内联 HTML 和可执行扩展需要明确的信任与安全决策。
  3. CommonMark 引用式链接可以依赖其他位置的定义;脚注则是扩展。
  4. 不能把特定解析器版本的漏洞推广到所有实现。
  5. 应根据所需功能、处理方式和安全边界选择文档工具。
全文

按章节阅读整理后的全文

只看原始文稿
01

为什么重新审视 Markdown?

Theo 解释自己为何采用 Markdown,以及用途扩张为何引出新问题。

我推崇 Markdown 已经很多年。过去我把简历以 Markdown 放在 GitHub 上,甚至放弃过一些不接受这种格式的申请。它的吸引力在于:源文件简单易读,不需要复杂工具就能生成排版漂亮的文档。

我感谢 John Gruber 和 Aaron Swartz 创造了 Markdown。大学时尝试 LaTeX 遇到不少困难,后来 Markdown 对我来说一下子变得顺手,也成为我写作的默认格式。正因如此,一篇追问我们为什么还在使用 Markdown 的文章吸引了我。

Markdown 的用途已经超出简单文档。我们嵌入其他格式、添加扩展,也越来越多地用它与语言模型和代理交流。我想问的是:原本的格式在哪些地方很好用,而新的需求又在哪里带来了摩擦?

02

写起来简单,解析起来复杂

文章对比易上手的语法、多种等效写法和解析器边缘情况。

我读的是 Brock 的文章《Why the heck are we still using Markdown?》:https://bgslabs.org/blog/why-are-we-using-markdown/。作者主要讨论 CommonMark,认为一种原本追求简单的格式积累了复杂语法和过多期待。我认同其中很多不满,尽管自己每天仍在使用它。

Markdown 的优点是真实存在的:基础写法容易上手,纯文本也能读懂,标题、强调和链接都很方便。CommonMark 为实现提供了一份详细的共同规范。普通作者无需学完整套解析规则,也能很快得到有用的输出。

不同语法,相似输出
幻灯片 1 / 4不同语法,相似输出文章示例中,两种 Markdown 写法产生相同的显示结构。

问题从多种写法产生相同结果时开始。文章展示了一个用井号写的标题和另一个用下划线形式写的标题;强调文本也可以在星号和下划线之间切换。这些选择方便了作者,却给工具带来了更多需要处理的情况。

嵌套的强调语法甚至在实现解析器之前就可能变得难以阅读。我们在 T3 Chat 遇到过许多奇怪的渲染情况,尤其是处理生成内容时。因此,看似简单的格式,可能给必须接受所有有效写法的软件带来相当大的复杂度。

文章提到了 markdown-it 的一个正则表达式拒绝服务漏洞。这是特定受影响版本和代码路径中的缺陷,并不证明每个 Markdown 解析器都有漏洞。公告列出的受影响范围是 13.0.0 起至 14.1.1 之前,14.1.1 包含修复:https://github.com/advisories/GHSA-38c4-r59v-3vqw。

03

内联 HTML 与扩展

混合格式增加能力,也增加复杂度;安全取决于具体实现和信任边界。

作者把 Markdown 中的内联 HTML 比作加入一个强大的逃生口。它让作者使用基础语法无法表达的元素和属性,但渲染流程也因此需要决定如何处理两种语法及其相互作用。灵活性是有代价的。

内联 HTML 示例
幻灯片 2 / 4内联 HTML 示例示例把 Markdown 文本与 HTML 元素和属性混在一起。

我自己也感受过这个问题。一位朋友曾试图让同一份字节既作为 GitHub 个人主页的 Markdown 文件,又作为 HTML 首页;让两个渲染环境结果一致非常费劲。Markdown 能包含部分 HTML,并不意味着所有渲染器都会以相同方式处理混合文档。

作者常常需要的不止是标题和段落:还有嵌入媒体、图表、数学公式、脚注、引用、样式或交互组件。每增加一种能力,就要对语法、依赖和信任边界作选择。一种原本轻量的文本格式逐渐变得像文档处理系统。

我查看了自己的博客,很快就发现了 iframe,以及放在 Markdown 链接里的 HTML 图片。重点不是这些具体片段天然不安全,而是实际发布需求会把我们推离最简单的 Markdown 示例,进入混合格式工作流。

博客文章中的 HTML
幻灯片 3 / 4博客文章中的 HTMLTheo 展示自己博客源码中放在 Markdown 链接里的图片元素。

允许原始 HTML、插件或可执行扩展会改变安全模型。内容不可信时,应用需要适当的清理和安全边界;解析器本身不能替代完整的安全策略。不同实现和配置所承担的风险也不同。

04

历史语法与引用

Theo 讨论多种语法形式和文档级引用解析。脚注是 CommonMark 扩展,而非核心语法。

Markdown 借鉴了纯文本邮件和网络讨论中的习惯。这段历史留下了多种表达类似结构的方式:标题样式、列表标记、分隔线和强调定界符。熟悉的写法便于使用,但重叠和变化也让边缘情况更难推理。

有序列表也是一个例子:作者可以重复使用数字标记,让渲染器生成显示出来的顺序。调整条目时这很方便,但文件中的文字与最终输出并不总是一一对应。

文章展示了一个引用:它如何被解释取决于文档其他地方是否有对应定义。CommonMark 支持引用式链接;脚注属于扩展,而不是 CommonMark 核心功能。渲染器可能需要文档级引用表或多次处理才能解析这些链接。

引用定义示例
幻灯片 4 / 4引用定义示例文档其他位置的定义改变了引用的渲染方式。

作者用形式语言术语描述这种依赖,认为 Markdown 比简单的局部替换复杂。实际现象很明确:后面的定义可以影响前面的引用。至于形式分类,那是作者的论证,不能仅凭展示的例子就视为已证明。

05

替代方案与权衡

提出的构建系统与受控扩展可以使格式用途更清晰,但每种选择仍有复杂度和安全决策。

如果再添加脚注、自定义提示块、数学公式和样式,处理流程会进一步增长。知识管理系统可能需要插件、排版库以及样式隔离方式。选择格式时要考虑整个处理链,而不只是作者输入的字符。

我喜欢 Notion 对 Markdown 语法的另一种用法:输入井号和空格可以把块变成标题。在这里,熟悉的语法更像编辑器快捷操作。这与把整篇文档存储并渲染为 Markdown 是不同用途,导出也可能有自己的局限。

作者考虑了纯文本、reStructuredText 和 MDX,但认为每种方案都有权衡。他提出的替代方向是:采用规范清楚的标记格式、构建系统、明确的短代码和受控钩子,取代不受限制的内联 HTML。这是一项设计提议,并非已被证明适用于所有场景的现成替代品。

构建系统和钩子可以让扩展点更明确,但它们也会引入自己的复杂度和安全决策。关键问题是文档实际需要哪些功能,以及处理过程中哪些代码可以被信任执行。更简洁的语法本身不能保证任意扩展安全。

文章还涉及形式语言理论和编程语言的定义。这些区分取决于讨论的具体语言和计算模型;一段有趣的 Markdown 论辩,不应被当作 Markdown 本身具有图灵完备性的证明。

人们对 Markdown 歧义和实现错误的抱怨已有很长历史,也曾呼吁制定更清楚的标准。CommonMark 是对这段历史的一种回应。标准化行为可以提高一致性,但仍不能自动回答:这些行为对某个应用是否好用、是否合适。

这篇文章让我意识到,自己每天使用的一种格式包含了多少习以为常的复杂度。我不是建议大家立刻重写所有文档。我希望我们认识到其中的权衡:Markdown 适合简单文本,但扩展、混合 HTML 和渲染需求可能让周边系统难得多。

我也有冲动发明一种新的标记语言,但冲动本身并不是解决方案。首先要确定需要表达什么、文档如何处理,以及哪些安全边界重要;然后再根据这些需求选择或设计工具。

同频道的其他文章

5 张幻灯片38:47EN → 简体中文
Theo - t3․gg· 2026年10月28日Theo 的长时间 Agent 实验:验证、算力与成本Theo Browne · Ping Labs滑板游戏和两个编译器项目展示了反复检查与弹性算力如何支撑 agent 工作,也揭示了循环可能带来的高昂成本。编程智能体智能体工程AI cost & performance+2
5 张幻灯片36:07EN → 简体中文
Theo - t3․gg· 2026年10月27日Theo 谈 Token 成本、编程智能体与 AI 能力的价格Theo Browne · Ping Labs一则关于 Lauren 的 AI 支出估算广泛传播,引出了对缓存计价、基准测试和编程智能体工作方式的讨论。AI cost & performance编程智能体Inference+1
5 张幻灯片30:37EN → 简体中文
Theo - t3․gg· 2026年10月26日Theo 的三个技能:用编程智能体审查和交付代码Theo Browne · Ping Labssol-loop、full-send 和 full-stop 如何定义审查、验证以及不同程度的合并权限。Agent skills编程智能体Code review & verification+2
2 张幻灯片0:43EN → 简体中文
Theo - t3․gg· 2026年10月23日Theo 区分安全漏洞与实际攻击Theo Browne · Ping Labs一段简短讲解:软件漏洞披露和攻击事件为何属于不同类型的安全新闻。CybersecuritySoftware engineering
6 张幻灯片29:22EN → 简体中文
Theo - t3․gg· 2026年10月22日Theo 谈安全漏洞、被盗 API 密钥与 AITheo Browne · Ping Labs从漏洞披露到补丁部署之间的风险窗口,以及被盗推理密钥为何可能有价值的推测。CybersecurityAI securitySoftware engineering+1
4 张幻灯片31:13EN → 简体中文
Theo - t3․gg· 2026年10月20日Theo:更聪明的模型为何能帮助更多人Theo Browne · Ping Labs从游戏修改到编译器实验,Theo 重新思考谁能从更强大的 AI 中受益。编程智能体Developer productivityHuman-AI Collaboration+1