Markdown 定义列表

在写技术文档或者整理术语表的时候,经常需要列出"术语 — 解释"这样的成对信息。HTML 里有专门的 <dl><dt><dd> 标签干这件事,但在 Markdown 里,定义列表(Definition List)属于扩展语法——也就是说,不是所有平台都支持。今天就来把这个语法的写法、兼容性和替代方案一次讲清楚。

什么是定义列表

定义列表就是一组"术语 + 解释"的结构,比如:

Markdown
  一种轻量级标记语言,用纯文本格式编写文档

HTML
  超文本标记语言,网页的标准语言

在 HTML 里,这对应 <dl>(definition list)、<dt>(definition term)、<dd>(definition description)三个标签。Markdown 的定义列表语法本质上是这三个标签的快捷写法 。

定义列表的语法写法

冒号语法(最常用)

绝大多数支持定义列表的 Markdown 解析器用的是冒号语法,写法很简单——术语单独一行,下一行以冒号加空格开头写定义:

Markdown
: 一种轻量级标记语言,用纯文本格式编写文档

HTML
: 超文本标记语言,网页的标准语言

渲染后,"Markdown"和"HTML"会显示为术语(<dt>),对应的解释会缩进显示为定义(<dd>) 。

一个术语多个定义

一个术语下面可以跟多个定义,每行一个冒号:

API
: Application Programming Interface,应用程序编程接口
: 也常泛指某个服务对外暴露的调用方式

这在写技术文档时很常用——有些术语确实需要从不同角度解释 。

多行定义

如果一条定义比较长,需要分成多行来写,续行要缩进(一般是 2 到 4 个空格):

Python
: 一种解释型的高级编程语言
  由 Guido van Rossum 于 1991 年发布
  以代码简洁可读著称

第二行和第三行缩进了 2 个空格,它们会被合并到同一个 <dd> 标签里,作为同一段内容渲染 。

定义中包含格式

定义的内容里可以正常使用其他 Markdown 语法,比如 Markdown 加粗、链接、行内代码等:

变量
: 程序中用于**存储数据**的命名容器,比如 `user_name = "Alice"`

JSON
: JavaScript Object Notation,一种轻量级的[数据交换格式](https://www.json.org/)

这大大增强了定义列表的表达能力,不是只能写纯文本 。

HTML 替代方案:所有平台通用

说实话,定义列表最大的坑不是语法本身,而是很多平台根本不支持这个语法。遇到这种情况,直接写 HTML 的 <dl><dt><dd> 是最靠谱的替代方案:

<dl>
  <dt>Markdown</dt>
  <dd>一种轻量级标记语言,用纯文本格式编写文档</dd>
  <dt>HTML</dt>
  <dd>超文本标记语言,网页的标准语言</dd>
</dl>

这个写法的好处是几乎所有的 Markdown 渲染器都会原样保留 HTML 标签。虽然写起来啰嗦一些,但至少保证内容能正确渲染 。

我之前有一次在 GitHub 的 README 里用了冒号语法的定义列表来写 API 参数说明,结果推上去一看全是乱码——冒号开头的行被当成了普通文本。后来才知道 GitHub 的 Markdown 渲染器根本不支持这个扩展语法,只好老老实实换成 HTML 标签。所以如果不确定目标平台是否支持,直接用 HTML 写是最安全的。

各平台兼容性对比

这是大家最关心的部分。我整理了主流平台对定义列表的支持情况:

平台冒号语法 :HTML <dl>备注
Python-Markdown需启用 def_list 扩展
PHP Markdown Extra最早支持定义列表的解析器之一
MultiMarkdown冒号语法 + 波浪线语法
GitLabGLFM 原生支持
Obsidian不支持冒号语法,需用 HTML
GitHub不支持冒号语法,需用 HTML
Typora不支持冒号语法,需用 HTML
VS Code 预览不支持冒号语法
CommonMark标准规范不包含此语法

几个要点:

  • GitHub 和 Obsidian 是最常见的"不支持"平台,在这两个平台上只能用 HTML 标签
  • GitLab 是少有的原生支持冒号语法的大平台,在 GitLab 上写文档可以直接用
  • Python-Markdown 需要手动启用扩展,默认不打开。配置方式是在初始化时加上 md = markdown.Markdown(extensions=['def_list'])

我在用 Python-Markdown 做静态网站生成的时候,花了好一会儿才搞明白为什么定义列表不渲染——原来是忘了在扩展列表里加 def_list。这个坑挺隐蔽的,因为 Python-Markdown 默认不会报错,只是把冒号开头的行当成了普通文本。

实际使用场景

定义列表在以下场景特别好使:

术语表 / 词汇表 — 这是定义列表最经典的用途。写技术文档的时候,在开头列一个术语表,读者一眼就能看明白文章里提到的专业词汇:

术语表
: API:应用程序编程接口
: SDK:软件开发工具包
: IDE:集成开发环境

API 参数说明 — 后端接口文档里经常用定义列表来列参数:

username
: 用户名,长度 3-20 个字符,只允许字母和数字

password
: 密码,长度 8-32 个字符,需包含大小写字母和数字

配置选项说明 — 项目配置文件的可选项解释:

port
: 服务监听端口,默认值为 `8080`

debug
: 是否开启调试模式,可选值为 `true` 或 `false`

如果不需要"术语 — 解释"这种成对结构,只是普通的信息罗列,用 Markdown 列表 就够了,不必硬套定义列表的格式。

常见问题

GitHub 上怎么写定义列表?

GitHub 不支持冒号语法。替代方案有两种:

一是直接用 HTML 标签:

<dl>
  <dt>术语</dt>
  <dd>解释</dd>
</dl>

二是用表格来模拟,虽然没有语义上的 <dl> 结构,但视觉上也能达到"术语 — 解释"的效果:

| 术语 | 解释 |
|------|------|
| API  | 应用程序编程接口 |

定义列表是 Markdown 标准的一部分吗?

不是。定义列表属于扩展语法,不在 CommonMark 规范中,也不在原始的 Markdown 语法说明里 。它是 PHP Markdown Extra 最早引入的,后来被 MultiMarkdown、Python-Markdown 等解析器以扩展的方式支持。

Obsidian 里能用定义列表吗?

Obsidian 目前不支持冒号语法的定义列表。但你可以在 Obsidian 里直接写 HTML 的 <dl> 标签,渲染和导出都没有问题。

定义列表能嵌套吗?

理论上可以。在某些支持定义列表的解析器中,你可以在 <dd> 里面继续嵌套列表或代码块。但不同解析器对嵌套的处理方式有差异,建议实际测试一下目标平台的效果。如果不放心,保持扁平结构是最稳妥的。


参考来源

: Markdown Guide — Extended Syntax: Definition Lists,Markdown 社区权威参考 : Python-Markdown 官方文档 — Definition Lists Extension: Fuchsia 项目文档 — Markdown Reference Guide,Google 官方文档规范 : MarkdownLang — Definition Lists: GitLab Docs — GitLab Flavored Markdown (GLFM)