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: Python-Markdown 官方文件 — Definition Lists Extension: Fuchsia 專案文件 — Markdown Reference Guide: MarkdownLang — Definition Lists: GitLab Docs — GitLab Flavored Markdown (GLFM)