返回博客
Reference 2026-04-26

Markdown风味比较: CommonMark, GFM, MDX

为文档、博客或内容管理选择正确的Markdown风味。

Markdown不是一种语言,而是一个恰好同姓的方言家族。John Gruber在2004年发布的原版是一个Perl脚本加一份非正式说明,留下了许多核心问题没有回答:强调标记如何嵌套?多少缩进才算延续列表项?嵌套块之前是否需要空行?每个实现都给出了不同答案,这就是同一份文档在三个平台上能渲染出三种样子的原因。理解主要的风味——以及你的工具链实际说的是哪一种——能消除一整类格式化意外。

CommonMark: 正式的基线

CommonMark(2014年,由以Pandoc闻名的John MacFarlane主导)把那份非正式说明变成了严谨的规范,包含六百多个一致性示例和两个参考实现:C语言的cmark和commonmark.js。它精确固定了过去各解析器互不相同的歧义点:

  • 精确的强调规则:分隔符是开启还是关闭强调,由左右侧翼分隔符序列决定——这就是词内星号对会变斜体、而被空格包围的星号保持原样的原因
  • 列表延续:内容缩进到列表项的内容列即属于该项,而不是神奇的四个空格
  • 七种不同类型的HTML块,各有自己的开始和结束条件
  • 优先级:链接语法胜过强调,代码片段胜过一切内联元素

如果你的内容必须在多种工具间渲染一致,就按CommonMark来写,并避开它未定义的一切。

一级标题

========

__粗体__ 和 _斜体_ 和 代码

[链接](https://example.com)

1. 有序列表项

缩进到内容列的延续段落

GFM: CommonMark加上开发者真正需要的东西

GitHub Flavored Markdown在形式上是严格超集——GitHub把它作为规范发布,在CommonMark之上恰好扩展了五项:表格、任务列表项、删除线、自动链接,以及剥除危险原始HTML标签的tagfilter。脚注、emoji短代码和提及是叠加在上面的GitHub平台功能,不属于GFM规范——当另一个「GFM兼容」渲染器拒绝你的脚注时,这一点就很重要了。

|列  |类型|

|----|----|

|id |int |

* [x] 已发布

* [ ] 待处理

~~已废弃~~ 和 https://autolinked.example.com

一个微妙的分歧:在 .md 文件中GitHub遵循规范——单个换行是软换行——但在issue和评论中单个换行会变成硬换行。在两种上下文之间复制文本会改变其渲染结果。

MDX: 会编译的Markdown

MDX与其说是标记方言,不如说是编译目标:每个文件都会成为一个ES模块。你可以导入组件、导出值、嵌入JSX、内联求值表达式:

import { Chart } from '../components/Chart';

export const data = [4, 8, 15, 16];

总计为 {data.reduce((a, b) => a + b, 0)}。

<Chart values={data} />

这种能力伴随着真实的代价。原始HTML不再直接通过——尖括号内容会被解析为JSX,所以 class 必须写成 className,像 <br> 这样未闭合的标签是语法错误,一个游离的 { 就会开启表达式。一份文档的构建错误可能弄垮整个站点的构建,非开发者贡献者也失去了让Markdown有吸引力的「它只是文本」的保证。当文档真正需要活组件时(交互式文档、设计系统)选MDX;当所有人都要参与撰写和评审时选GFM。

更广的家族

  • Pandoc Markdown — 学术界的重器:引用、数学公式、定义列表、属性块,以及向LaTeX、DOCX等格式的转换。
  • Djot — MacFarlane在CommonMark之后的实验,移除了Markdown的解析疣点(没有惰性延续,没有缩进歧义);值得关注,尚未主流。
  • markdown-it, remark, goldmark, comrak — 解析器层。remark把文档暴露为带插件流水线的AST(MDX和大多数React文档框架的基础);goldmark驱动Hugo;comrak是Rust的GFM实现。

安全提示

Markdown的原始HTML直通意味着用户提交的Markdown默认就是XSS向量。处理不可信输入的渲染流水线需要在渲染之后做净化——对HTML输出使用rehype-sanitize或DOMPurify——而不是对Markdown源码做正则过滤,后者可以被稳定地绕过。

如何选择

  • README、Wiki、团队文档: GFM
  • 交互式文档站点: MDX (Docusaurus、Astro、Next.js)
  • 跨渲染器最大可移植性: 严格CommonMark
  • 学术或面向印刷的写作: Pandoc

Front Matter与数学公式

有两个扩展常见到让人以为是Markdown核心,实际却不属于任何规范。YAML front matter——文件顶部 --- 围栏之间的元数据——是Jekyll推广的静态站点约定;除非有插件剥离它,CommonMark解析器会把它当作主题分隔线加后续正文。数学公式类似:$x^2$ 行内式和 $$...$$ 块由remark-math、markdown-it-texmath或平台侧的KaTeX/MathJax渲染处理,各家的定界符在空格与转义规则上略有差异。这两个特性在没有对应插件的渲染器上都会静默退化成可见的乱码,所以请把流水线启用了哪些扩展写进文档——仓库README里的一行说明能避免大多数「为什么我的元数据直接显示出来了」的bug报告。

用 sdk.is/markdown-editor 的Markdown编辑器边写边预览你的文档渲染效果。