TL;DR — CommonMark 与 GFM 的区别
- GitHub 上常见的"GitHub Markdown 语法"中,表格、删除线、任务列表、URL 自动链接实际上不是标准语法,而是扩展功能。CommonMark 是 Markdown 的"标准规范",只严格定义标题、列表、强调、链接、图片、代码、引用等基础语法。
- GFM(GitHub Flavored Markdown)是 GFM 规范自称"CommonMark 严格超集"的方言。它在 CommonMark 基础上添加了表格、删除线、任务列表、扩展自动链接、禁用原始 HTML 这 5 种扩展。
- GitHub.com 上可用的
[!NOTE]等提示块(callout)、表情快捷代码、@mention、Issue 引用、Mermaid 图表、数学公式、脚注,这些都不是 GFM 规范的内容,而是 GitHub.com 独有的功能层。在 GitHub 之外基本不可用。 - 段落内单次换行(软换行)是否变成
<br>,在 CommonMark 和 GFM 规范中行为一致(不会变成<br>)。只有 GitHub.com 的 Issue/PR 评论区是例外,.md文件的行为与之一不同。 - 如果不确定该用哪种方言来写,纯 CommonMark 范围内兼容性最高;如果以 GitHub 为中心,可以使用到 GFM 扩展为止。
- FormatArc 的 Markdown to HTML 转换器支持 GFM 扩展(表格、删除线、任务列表、自动链接)。你也可以用它来检查自己的 Markdown 是否依赖了 GFM 扩展。
要点:表格不属于 CommonMark 核心规范。它在 GFM 规范中作为扩展功能定义,与删除线、任务列表、扩展自动链接、禁用原始 HTML 并列。
CommonMark 与 GFM 的关系 — GFM 是在 CommonMark 基础上的扩展规范
CommonMark在新标签页中打开 是一个将原本含糊的 Markdown 语法用测试套件严格重新定义的项目。它的目标是消除实现差异,让任何解析器处理都得到相同的结果。作为规范,它有意不纳入扩展,只规定标题、段落、列表、链接、图片、强调、代码、引用等核心语法。
GFM(GitHub Flavored Markdown)在新标签页中打开 是 GitHub 使用的 Markdown 方言,GFM 规范自身将其描述为"CommonMark 的严格超集"。从语法关系上来说:
- 合法的 CommonMark 文档在 GFM 解析器中会完全一致地渲染
- GFM 只是在 CommonMark 基础上"添加"了几种扩展,并没有改变核心语法
但"超集"这个说法只在 GFM 规范描述范围内成立。如果考虑 GitHub.com 的实际渲染、各库的实现、CommonMark 最新版本的细节差异,也存在例外。本文区分"GFM 规范定义的扩展"和"GitHub.com 自行添加的功能"。
对照表 — CommonMark 与 GFM 的功能对比
| 功能 | CommonMark | GFM 规范 | GitHub.com 额外支持 |
|---|---|---|---|
标题(#) | ✓ | ✓ | — |
| 段落、列表、引用 | ✓ | ✓ | — |
强调(**加粗** / _斜体_) | ✓ | ✓ | — |
| 链接、图片 | ✓ | ✓ | — |
| 行内代码、围栏代码块 | ✓ | ✓ | — |
| 原始 HTML 嵌入 | ✓ | ✓(部分标签禁用) | 额外净化 |
表格(| col |) | ✗ | ✓ | ✓ |
删除线(~~text~~) | ✗ | ✓ | ✓ |
任务列表(- [ ] / - [x]) | ✗ | ✓ | ✓ |
| 扩展自动链接(URL 自动链接化) | ✗ | ✓ | ✓ |
提示块(> [!NOTE] 等) | ✗ | ✗ | ✓ |
表情快捷代码(:smile:) | ✗ | ✗ | ✓ |
@mention / Issue、PR 引用 / commit SHA | ✗ | ✗ | ✓ |
| Mermaid 图表 / 数学公式(KaTeX) | ✗ | ✗ | ✓ |
脚注([^1]) | ✗ | ✗ | ✓ |
关键在于三列的划分。表格、删除线等是 GFM 规范的扩展,所以任何支持 GFM 的解析器在 GitHub 之外也能正常工作。而提示块、表情、脚注不在 GFM 规范中,只有 GitHub.com(或模仿它的平台)才保证支持。
哪些 GFM 扩展默认开启 — 6 种渲染器实测
上面的对照表告诉你"每个规范定义了什么",但你手头的解析器在默认配置下实际表现如何,它不会告诉你。所以我们做了实测。将相同的 Markdown 片段(管道表格、~~x~~、~x~、- [ ] todo、裸 URL、脚注 [^1])分别通过 5 种 JavaScript 解析器和 GitHub 官方 Markdown API,结果如下(2026-07-31 实测。复现脚本和结果已提交到仓库的 scripts/benchmarks/commonmark-vs-gfm/):
| 渲染器(版本) | 表格 | ~~x~~ | ~x~ 单波浪号 | 任务列表 - [ ] | 裸 URL | 脚注 [^1] |
|---|---|---|---|---|---|---|
| commonmark.js 0.31.2(参考实现) | 管道保持原样 | 保持原样 | 保持原样 | [ ] 保持原样 | 保持原样 | 变成链接 |
| marked 18.0.5(默认配置) | <table> | <del> | <del> | 复选框 | 自动链接 | 变成链接 |
| markdown-it 14.2.0(默认预设) | <table> | <s> | 保持原样 | [ ] 保持原样 | 保持原样 | 变成链接 |
| remark 15.0.1(无插件) | 管道保持原样 | 保持原样 | 保持原样 | [ ] 保持原样 | 保持原样 | 变成链接 |
| remark 15.0.1 + remark-gfm 4.0.1 | <table> | <del> | <del> | 复选框 | 自动链接 | 正常渲染脚注 |
GitHub Markdown API(markdown 模式) | <table> | <del> | <del> | [ ] 保持原样 | 自动链接 | 正常渲染脚注 |
实测揭示的要点:
- 同样的
~~x~~,marked / remark-gfm / GitHub 输出<del>,而 markdown-it 输出<s>。即使是"支持 GFM"的解析器之间,元素名称本身就不同 - GFM 规范的删除线规则允许 1 个或 2 个波浪号。marked / remark-gfm / GitHub 都能将
~x~渲染为删除线,但 markdown-it 要求必须 2 个波浪号,~x~会被保留为原文 - GitHub 官方 Markdown API 在默认
markdown模式下将- [ ]保留为方括号文本。只有用于评论上下文的gfm模式才会输出<input type="checkbox">。README 里看到的任务列表复选框并不是所有 GitHub 端点都有的 - markdown-it 的默认预设开启了表格和删除线,但裸 URL 自动链接(
linkify)是关闭的。所谓"默认支持 GFM"只是部分正确 - 不支持脚注的解析器不会忽略
[^1]: note,而是将其解析为链接引用定义。结果text[^1]会静默变成<a href="note">^1</a>。反过来,remark-gfm 和 GitHub 虽然脚注不在 GFM 规范中,但仍会将其渲染为脚注
想知道自己的 Markdown 在支持 GFM 的解析器中会怎样转换,可以粘贴到 Markdown to HTML 转换器 中查看。它使用 marked(gfm: true),完全在浏览器内运行。
CommonMark 为什么没有表格 — 核心规范有意排除
CommonMark 规范有意将表格排除在核心语法之外。由管道符和连字符组成的表格(| col | col |)是在 GFM 规范中定义的,其章节标题本身就是"Tables (extension)在新标签页中打开"——GFM 自己就把表格标记为扩展功能。同样的"(extension)"标记也出现在删除线、任务列表、扩展自动链接、禁用原始 HTML 的章节上,说明它们都是扩展而非核心语法。
也就是说,未启用扩展的纯 CommonMark 渲染器会把 | col | 当作带管道符的段落,而支持 GFM 的渲染器才会将其解析为 <table>。这一背景在 CommonMark 论坛的讨论帖在新标签页中打开和 commonmark-spec#393在新标签页中打开 中反复被讨论,表格不在核心规范范围内这一点可以从原始规范中确认。
如果想确认某个特定渲染器是否将表格作为 GFM 扩展处理,可以把一个两行的表格粘贴到 Markdown to HTML 转换器 中,看输出中是否出现 <table>。
纯文本是否是合法的 CommonMark 文档
用程序校验 Markdown 时经常遇到的疑问是:"纯文本段落算不算合法的 Markdown?"CommonMark 规范在 2.1 节"Characters and lines"中直接回答了这个问题。
Any sequence of characters is a valid CommonMark document.
也就是说,不存在"非法的 CommonMark 文档"。解析不会失败,它只是判断文本包含哪些语法元素。普通行序列由 4.8 节"Paragraphs"处理。
A sequence of non-blank lines that cannot be interpreted as other kinds of blocks forms a paragraph.
因此,只包含普通句子的文件作为"段落集合"是一个合法的 CommonMark 文档(0.31.2 规范的 2.1 节在新标签页中打开和 4.8 节在新标签页中打开)。而且由于 GFM 规范是 CommonMark 的严格超集,同样的文本也是合法的 GFM 文档。扩展只是添加语法,不会使现有文本变得非法。市面上那些"Markdown 校验器"检查的是风格约定或渲染预期而非语法错误,原因就是规范层面不存在 Markdown 语法错误。
纯文本不再被当作段落的边界只有一个,同样由 4.8 节定义:
However, the first line may be preceded by up to three spaces of indentation. Four spaces of indentation is too many:
行首缩进 3 个半角空格以内仍然是段落。4 个则变成 4.4 节在新标签页中打开 定义的缩进代码块。同一节还规定 "An indented code block cannot interrupt a paragraph, so there must be a blank line between a paragraph and a following indented code block.",即段落后面直接跟 4 空格缩进(无空行)不会变成代码块。
3 个空格缩进。
到这里还是一个段落。
空行后 4 个空格缩进。
这是代码块。
规则就这些。在空行后使用 4 空格缩进之前,普通文字就是普通文字。
实际转换为 HTML 时有什么不同
只处理 CommonMark 的解析器和支持 GFM 的解析器,对相同的 Markdown 会输出不同的 HTML。用以下输入对比:
| 商品 | 库存 |
| --- | --- |
| 苹果 | 3 |
~~售罄~~ 有库存
- [x] 确认到货
- [ ] 更换价签
纯 CommonMark 解析器中,| 商品 | 库存 | 行不会变成表格,而是带管道符的段落;~~售罄~~ 也不会变成删除线,波浪号原样保留;- [x] 只是普通列表项。支持 GFM 的解析器则会输出包含 <table>、<del>、<input type="checkbox"> 的 HTML。
所以当你觉得"Markdown 显示乱了"时,原因往往是平台之间的方言差异。想确认自己的 Markdown 是否依赖 GFM 扩展,最快的方法就是粘贴到 Markdown to HTML 转换器 中查看输出 HTML。
GFM 为 CommonMark 添加的 5 种扩展
表格
由管道符 | 和连字符 - 组成的表格。CommonMark 没有表格定义,因此表格是 GFM 扩展功能,在 GFM 规范的 Tables (extension)在新标签页中打开 章节(GFM 规范第 4.10 节)中定义。纯 CommonMark 渲染器不会将其渲染为表格,管道符文本原样保留。对齐标记(:--- / :---: / ---:)或单元格内管道符转义等细节规则,请参考上面的对照表和实测表。完整写法见 Markdown 表格语法。
删除线
~~想要删除的文字~~ 会变成 <del> 元素。用两个波浪号包裹的写法是 GFM 扩展,不属于 CommonMark。参见 GFM 规范的 Strikethrough (extension)在新标签页中打开 章节(GFM 规范第 6.5 节)。是否允许单个波浪号(~x~)因解析器而异,上面的实测中只有 markdown-it 要求必须 2 个。
任务列表
在列表项前写 - [ ](未完成)或 - [x](已完成)即可渲染为复选框。这个语法在 GFM 规范的 Task list items (extension)在新标签页中打开 章节(GFM 规范第 5.3 节)中定义。在 GitHub 上可以点击 Issue 或 PR 正文中的复选框来切换状态,但那个"点击切换"的行为是 GitHub.com 的功能,普通 HTML 渲染器只会输出静态复选框。
扩展自动链接
直接写 https://example.com 就会自动变成链接。在 CommonMark 中要将 URL 变成链接需要用尖括号包裹(<https://example.com>),而 GFM 能检测无括号的裸 URL 并自动链接化。这个裸 URL 行为在 GFM 规范的 Autolinks (extension)在新标签页中打开 章节(GFM 规范第 6.9 节)中规定,与 CommonMark 自身的尖括号自动链接是不同的机制。
禁用原始 HTML
CommonMark 和 GFM 都允许在 Markdown 中嵌入原始 HTML。区别在于 GFM 将 <script> / <iframe> / <style> 等极少数标签作为"禁用的原始 HTML"进行无效化。此外,GitHub.com 在另一个层级施加了更严格的 HTML 净化(如移除属性等)。FormatArc 的 Markdown to HTML 转换器 只做语法转换,如果你转换了不可信的输入,请单独对输出 HTML 做净化处理。
每条规则在哪里定义 — 直接查阅规范原文
如果想确认上述内容的原始出处,请直接查阅规范本身而非第三方总结。
- 核心语法由 CommonMark 规范在新标签页中打开(John MacFarlane 著)定义。涵盖标题、段落、列表、链接、图片、强调、代码、引用,但未明确定义表格、删除线、任务列表、裸 URL 自动链接。
- 本文涉及的 4 种 GFM 扩展分别在 GitHub Flavored Markdown 规范在新标签页中打开 中有独立章节,且所有章节标题都带有"(extension)"标记:
- Tables (extension)在新标签页中打开 — GFM 规范第 4.10 节
- Task list items (extension)在新标签页中打开 — GFM 规范第 5.3 节
- Strikethrough (extension)在新标签页中打开 — GFM 规范第 6.5 节
- Autolinks (extension)在新标签页中打开 — GFM 规范第 6.9 节
每个 GFM 章节标题中的"(extension)"标记就是规范自身表明这些是 CommonMark 的附加内容而非核心语法的标识。禁用原始 HTML 的规则同样在 GFM 规范的 Disallowed Raw HTML (extension)在新标签页中打开 章节中定义。
GFM 规范中没有的 GitHub.com 独有功能
以下功能经常被当作"GitHub Markdown"来介绍,但 GFM 规范中并没有它们。可以认为它们只在 GitHub.com(以及少数模仿它的服务)上可用。
- 提示块(callout)—
> [!NOTE]/> [!TIP]/> [!IMPORTANT]/> [!WARNING]/> [!CAUTION]共 5 种。渲染为带颜色的提示块。 - 表情快捷代码 —
:smile:这类:name:写法。标准 Markdown 没有表情的概念。 @mention/ Issue、PR 引用 / commit SHA —@username、#123、commit 哈希会自动变成链接。没有仓库上下文就没有意义的功能。- Mermaid 图表 / 数学公式 —
```mermaid代码块和$...$数学公式。这也是 GitHub.com 渲染管线的附加功能。 - 脚注 —
[^1]形式。GitHub.com 支持,但不在 GFM 规范的差异范围内。remark-gfm或 Hugo 的 Goldmark 等工具可能会将脚注与 GFM 扩展一起启用,但那是各实现的选择。
使用这些功能的 Markdown 如果拿到 GitHub 之外(如把 README 原样粘贴到博客、文档工具等),大多会以纯文本形式显示。建议将其视为 GitHub.com 专用语法。
段落内换行(hard line break)的处理差异
这里是容易误解的地方。无论在 CommonMark 还是 GFM 规范中,段落内单次换行(软换行)都不会变成 <br>,前后行会合并为一个段落。要让换行变成 <br>,需要在行尾放 2 个半角空格、行尾放反斜杠 \、或直接写 <br> 标签。这在 CommonMark 和 GFM 中行为一致。另外,反斜杠除了换行外还可以作为转义字符,防止符号被解释为格式标记。完整列表见 Markdown 转义字符一览。
行尾 2 个空格有一条限制,同样由 4.8 节规定:"Final spaces or tabs are stripped before inline parsing, so a paragraph that ends with two or more spaces will not end with a hard line break:"。行尾空格生效的位置是段落内部连接行的位置,在段落末尾则无效。
例外是 GitHub.com 的 Issue / PR / Discussion 评论区,这里配置为"单次换行直接变成 <br>"。而同样在 GitHub 上,.md 文件(README 或文档)遵循 CommonMark / GFM 标准行为,仍然需要 2 个空格或 \。"GitHub 评论区能换行但 README 里不行"的原因就是这个。
各平台/工具使用哪种方言
更准确地说,是"纯 CommonMark""CommonMark + GFM 扩展""自有方言"中哪种更接近。整理一些代表性的:
| 平台 / 工具 | 采用的 Markdown |
|---|---|
| GitHub.com | GFM + GitHub.com 独有功能(提示块、表情、mention、Mermaid、脚注等) |
| GitLab | GLFM(GitLab Flavored Markdown)。CommonMark + GFM 兼容 + GitLab 自有扩展 |
| 飞书 / 语雀 | 自有方言(基于 CommonMark,表格和删除线可用,部分 GFM 功能未实现) |
| Typora | 基于 markdown-it(CommonMark + GFM 表格、删除线等扩展) |
| Obsidian | CommonMark + 自有扩展([[wikilink]]、提示块、标签等)。也支持 GFM 表格和任务列表 |
| Notion | 自有方言。导出的 Markdown 偏 GFM,但编辑器内的写法是 Notion 特有的 |
| VS Code 预览 | 基于 markdown-it(CommonMark + GFM 表格、删除线等扩展) |
| Hugo | Goldmark(CommonMark 合规 + GFM 兼容扩展,通过配置启用) |
| Jekyll | kramdown(自有方言,有 GFM 兼容处理模式) |
| Astro / Docusaurus | 基于 remark,通常用 remark-gfm 启用 GFM 扩展 |
| MkDocs | Python-Markdown(自有方言,通过扩展插件添加功能) |
标有"GFM 支持"的不一定意味着也支持 GitHub.com 的提示块或表情。反过来,"纯 CommonMark"的工具加上插件后通常也能使用 GFM 扩展。最终还是要看你使用的库或服务的文档中"哪些扩展已启用"。
如何确认你的环境支持 GFM
不需要复杂的调查,按以下步骤大致可以判断:
- 分别写一个表格(
| col |)、删除线(~~text~~)、任务列表(- [ ]),看是否都能渲染。如果可以,说明支持 GFM 扩展 - 如果使用库,查看配置。
marked需要gfm: true,remark 需要remark-gfm插件,markdown-it 默认开启 GFM 表格和删除线(但裸 URL 自动链接默认关闭,除非开启linkify,见上方实测矩阵) - 如果使用静态站点生成器,检查配置文件。Hugo 看
markup.goldmark.extensions,Astro 看markdown.remarkPlugins中是否有remark-gfm等
如果只是想确认某个 Markdown 文件是否依赖 GFM 扩展,粘贴到 Markdown to HTML 转换器 中,看表格和删除线是否变成了 HTML 即可一目了然。
应该用哪种方言来写 Markdown
- 兼容性最高的是限制在纯 CommonMark 范围内。在几乎所有渲染器中都能按预期显示
- 如果目标平台是 GitHub 或类似平台(GitLab、飞书、语雀、大多数文档工具),使用 GFM 扩展(表格、删除线、任务列表、自动链接)没有问题。实际工作中这个范围是标准配置
- 提示块(
[!NOTE]等)、表情快捷代码、@mention、Mermaid、脚注,请基于"在 GitHub.com 之外会失效"的前提来使用。在 README 中很方便,但复制到博客里就变成了纯文本 - 如果考虑分发或移植,尽量不混入原始 HTML。无论是 CommonMark 还是 GFM,包含原始 HTML 的文档行为会受净化处理和渲染器实现的影响
FormatArc 的 Markdown 转换工具用哪种方言
FormatArc 的 Markdown to HTML 转换器 内部使用 marked 以 gfm: true 运行。因此:
- GFM 规范的扩展(表格、删除线、任务列表、扩展自动链接)会直接转换为 HTML
- 段落内换行(软换行)遵循
breaks: false行为,不会变成<br>。与 CommonMark / GFM 规范一致,与 GitHub.com 评论区的换行行为不同 - GitHub.com 独有的提示块(
[!NOTE]等)、表情快捷代码、@mention、Mermaid、脚注不支持。因为这些不是 GFM 规范的功能
反向的 HTML to Markdown 转换器 输出的 Markdown 也是包含表格和删除线的 GFM 风格格式。两者都在浏览器内完成处理,无需注册也无需上传。即使粘贴公司内部未公开文档,也不会发送到外部。详细步骤见 Markdown 转 HTML 指南 和 HTML 转 Markdown 指南。
常见问题
CommonMark 和 GFM 应该选哪个来写 Markdown?
兼容性最高的是纯 CommonMark 范围。如果目标平台是 GitHub 或类似平台,使用 GFM 扩展(表格、删除线、任务列表、自动链接)没有问题。[!NOTE] 等 GitHub.com 独有功能请基于"在 GitHub 之外会失效"的前提来使用。
CommonMark 没有表格语法吗?
没有。表格是 GFM 扩展功能,不包含在 CommonMark 规范中。纯 CommonMark 渲染器会将 | col | 原样显示为带管道符的文本。如果表格没有渲染出来,先检查表头行和分隔行的列数是否一致。
GitHub 的 [!NOTE] 提示块能在其他工具中使用吗?
基本上只能在 GitHub.com(以及少数模仿它的服务)中使用。GFM 规范没有提示块定义,所以其他 Markdown 渲染器会将 > [!NOTE] 原样显示为引用块内的文本。
Obsidian 和 Notion 支持 GFM 吗?
不完全支持。Obsidian 基于 CommonMark,支持 GFM 表格和任务列表,同时有 [[wikilink]] 等自有写法。Notion 也是自有方言,导出的 Markdown 偏 GFM,但编辑器内的写法是 Notion 特有的。使用前请查阅各工具的文档确认支持的语法。
FormatArc 用哪种方言进行转换?
偏向 GFM。Markdown to HTML 转换器 使用 marked 以 gfm: true 运行,因此支持表格、删除线、任务列表、自动链接。段落内换行不会变成 <br>(与 CommonMark / GFM 规范一致)。GitHub.com 独有的提示块、表情、mention、Mermaid、脚注不支持。
总结
CommonMark 是 Markdown 的标准规范,GFM 是在其基础上添加了 5 种扩展(表格、删除线、任务列表、扩展自动链接、禁用原始 HTML)的方言。在 GitHub.com 上看到的提示块和表情、@mention、Mermaid、脚注是再上面一层的 GitHub.com 独有功能层,在 GitHub 之外基本不可用。
如果不确定该用哪种方言来写:兼容性优先就选 CommonMark,以 GitHub 为中心就用到 GFM 扩展,GitHub.com 独有功能则基于"会失效"的前提。想确认自己的 Markdown 是否依赖 GFM 扩展,或者想将 Markdown 转换为 HTML 时,使用 Markdown to HTML 转换器。完全在浏览器中完成,无需注册也无需上传。

