註腳是延伸語法,不是標準 Markdown

重點摘要
  • 註腳屬於延伸語法,原始 Markdown 與 CommonMark 規格裡都沒有它。
  • 參考標記(例如 [^1])寫在正文,對應的定義放在檔案任何位置都可以。
  • 標籤用單字比用數字好,因為讀者看到的編號一律由渲染器重新指派。
  • 註腳裡的第二段必須縮排四個空格,否則它會脫離註腳掉進正文。

先講實話。註腳不存在於 John Gruber 2004 年的原始 Markdown,也不存在於 CommonMark 規格。所有實作都來自延伸語法:PHP Markdown Extra 在 2005 年定義了這套寫法,MultiMarkdown 與 Pandoc 跟進採用,GitHub 則遲至 2021 年才支援。

支援度很廣,但不是全面

GitHub、GitLab、Obsidian、Pandoc、MultiMarkdown 以及幾乎所有靜態網站產生器都支援註腳;RedditDiscord、Notion 與任何純 CommonMark 解析器則不支援。不支援的渲染器沒有降級方案可用,只能把方括號原樣印出來。

這不代表註腳是壞主意,只代表它是看場合的功能,性質跟 GitHub 風格 Markdown 裡的表格與待辦清單同一類。核心為什麼設計得這麼精簡,Markdown 是什麼有說明。

插圖:段落中的小型上標編號,以一條弧線連向頁面底部的附註

參考標記與定義

註腳分成兩半:參考標記寫在正文,定義放註腳內容:

這個解析器在 2019 年整個重寫過。[^1]

[^1]: 這次重寫把正規表達式引擎換成了真正的詞法分析器。

參考標記是方括號裡放一個插入符號;定義則是同一組標籤、冒號、空格,然後接註腳內容。整套語法就這樣。

定義該放哪裡

文件裡任何地方都可以:引用它的段落正下方、該章節結尾,或全部堆在檔案最底部。渲染結果完全相同,因為渲染器會蒐集所有定義,統一印在頁面最下方。

兩種慣例都很好用:草稿階段把定義放在參考標記旁邊,發佈前再統一搬到底部;或者從一開始就全部放底部,當成參考書目維護。真正不該做的是隨手亂放 - 渲染頁面不在乎,但下一個編輯檔案的人會很在乎。

渲染器會自動幫你做的三件事

以下三件事你完全不用自己寫:

  • 在頁面底部畫一條分隔線,並列出所有註腳。
  • 正文第一次出現的順序指派編號,跟標籤內容無關。
  • 在每則註腳結尾加上返回箭頭,連回正文中的確切位置。

讀者真正有感的是最後那一項,因為它讓人跳下去看完再跳回來,不會弄丟閱讀位置。同一則註腳被引用兩次,GitHub 會產生兩個返回連結。

具名標籤比數字好用

標籤不一定要是數字,任何不含空格的字串都可以:

我們的定價在三月做了調整。[^pricing-2024]
資料遷移還在進行中。[^migration-status]

[^pricing-2024]: 量價級距從三階改成五階。
[^migration-status]: 約 60% 的資料列已完成回填。

這是整頁最值得養成的習慣。用數字當標籤會遇到跟手動編號清單一樣的問題:在長文件中間插入一則註腳,你不是得把後面全部重編,就是得忍受 [^1][^2][^7][^3] 這種順序。具名標籤不必重編、搬動段落也不會壞,光看標籤就知道內容。

兩種寫法對讀者毫無差別。不管標籤是數字還是單字,讀者看到的都是依正文順序排列的 1、2、3,因為顯示編號由渲染器指派。標籤純粹是寫給你自己看的。

標籤的規則

  • 只用英數字與連字號。空格會讓多數解析器對不上,所以 [^pricing note] 失敗、[^pricing-note] 成功。
  • 比對幾乎都不分大小寫[^Note][^note] 會被當成同一則註腳。
  • 註腳標籤與連結參考位於不同命名空間[^spec] 不會和名為 [spec] 的參考式連結衝突。

小提醒:標籤請照「它支撐哪一句話」命名,不要照來源命名。[^churn-figure] 半年後還看得懂,[^smith2023] 則得先想起 Smith 是誰。參考式連結適用完全相同的習慣。

多段落註腳與四格縮排

註腳可以寫成好幾個段落,也可以放清單或程式碼區塊。後續內容必須縮排四個空格,解析器才知道它屬於這則註腳:

[^benchmark]: 所有計時都在 2023 年的 M2 Pro 上單次執行取得。

    僅計入熱快取。冷啟動大約慢 40%,因為每次落差太大而未列入。

    ```bash
    hyperfine --warmup 3 './parse corpus.md'
    ```

四個空格是唯一要背的數字。少了它,那段文字就會脫離註腳,掉進正文裡定義所在的位置,通常就是檔案最底部。Tab 在某些解析器有效、某些無效,請一律用空格,理由跟清單參考一樣。

註腳內部可以有空行,只要後續每一行都維持縮排。單行註腳不需要縮排,所以這條規則總是等到註腳長成第二段時才咬人。

註腳裡放不了的東西

在 GitHub 上,定義不能寫在表格儲存格裡;註腳裡再包一層註腳也沒有平台可靠支援。標題寫在註腳裡雖然渲染得出來卻很怪,因為註腳本身已是清單項目。簡短文字、一個連結、一小段程式碼,才是最適合的內容。

注意:註腳裡的圍欄式程式碼區塊,縮排要連圍欄本身一起算,不是只縮排程式碼。只縮排其中一邊,區塊就會裂開,把後面的註腳內容一起拖出去。

插圖:一則註腳區塊,第二個段落被一段標示為四格的縮排往右推開

行內註腳

Pandoc 與 Obsidian 支援一種簡寫,直接把註腳內容寫在句子裡,不必另外寫定義,也不必想標籤:

這個建置流程可完整重現。^[前提是 lockfile 與工具鏈版本相同。]

一個插入符號,接著用方括號包住註腳內容。渲染器一樣會編號、搬到頁面底部並加上返回連結。要寫一句簡短補充,這是 Markdown 裡最快的方法。

兩個必須知道的限制

  • GitHub 不支援行內註腳。GitLab 不支援,MkDocs 使用的 Python-Markdown 也不支援。上面那一行會原樣印出插入符號加方括號文字,看起來像打錯字。
  • 行內註腳裡不能有空行,所以它裝不下第二個段落。補充說明一旦寫長,就改成具名註腳。

檔案只要有可能進到程式碼儲存庫,就請用兩段式的 [^標籤] 寫法,行內註腳留給 Obsidian 與 Pandoc。它其他的自家擴充與同樣的可攜性問題,Obsidian 指南裡有整理。

各平台支援對照表

最該看的是最後一欄,因為註腳失效時不會安靜地失效:

平台[^1] 參考式語法行內 ^[文字]不支援時的實際結果
GitHub支援,2021 年起不支援行內寫法原樣印出
GitLab支援不支援行內寫法原樣印出
Obsidian支援支援不適用
Pandoc支援支援不適用
MkDocs(Python-Markdown)需啟用 footnotes 擴充不支援未啟用擴充時方括號原樣印出
Docusaurus(MDX + remark-gfm)支援不支援行內寫法原樣印出
Hugo(Goldmark)支援,預設開啟不支援行內寫法原樣印出
Jekyll(kramdown)支援不支援行內寫法原樣印出
Reddit不支援不支援^ 是上標語法,會變成方括號包住的上標數字
Discord不支援不支援每個字元都照你打的樣子顯示
Notion不支援不支援貼上後只會變成純文字
純 CommonMark不支援不支援參考標記原樣保留,定義那一行變成普通段落

Reddit 那一列最陰險

因為 Reddit 用 ^ 表示上標。你寫下的 [^1] 會變成被方括號包住的上標數字,看起來幾乎正確卻連不到任何地方,定義那一行則變成一段莫名其妙的文字。過程中不會有任何錯誤提示,貼文就這樣壞著上線了。

小提醒:要把檔案交給不熟悉的平台之前,先發一則測試用的註腳,然後看頁面最底部。花三十秒確認,勝過事後回頭重寫四十個參考標記;哪些平台值得優先測,語法速查表裡看得出來。

什麼時候不該用註腳

註腳是用來放「讀者跳過也沒關係」的內容。以下三種情況換別的寫法更好:

改用括號補充

如果補充說明只有十來個字,寫在句子裡的括號幾乎不花讀者成本。註腳卻要他們跳到頁面底部再跳回來,在手機上干擾相當明顯。

改用一般連結

整則內容只有一個網址的註腳,其實就是穿上戲服的連結。直接寫 [2023 年報告](https://example.com/report) 讓讀者點就好。註腳請留給需要脈絡的來源:頁碼、但書、數據擷取日期。

改用手工的「附註」章節

目標渲染器不支援註腳時,就用錨點自己做出同樣效果。工序比較多,但在任何地方都能降級成可讀的文字:

第三季營收翻倍。<sup id="ref-1">[1](#note-1)</sup>

## 附註

<a id="note-1"></a>
1. 內部帳務數據,未經查核。[回到正文](#ref-1)

這些標籤需要渲染器允許行內 HTML,聊天軟體以外大多允許。若標籤被過濾掉,就改成連到 #notes 標題錨點;那些錨點怎麼產生,標題參考有說明。聊天室裡誠實的答案是:把附註放進下一則訊息或一段引言區塊,別再假裝那是註腳。

常見錯誤與修正寫法

1. 定義漏了冒號。少了冒號,那一行只是普通段落,參考標記無處可綁。錯誤寫法:

[^1] 這次重寫換掉了正規表達式引擎。

正確寫法:

[^1]: 這次重寫換掉了正規表達式引擎。

2. 後續段落沒有縮排。第二段會脫離註腳,跑到正文裡。錯誤寫法:

[^benchmark]: 計時取自 2023 年的 M2 Pro。

僅計入熱快取,冷啟動未列入。

縮排四個空格就正確了:

[^benchmark]: 計時取自 2023 年的 M2 Pro。

    僅計入熱快取,冷啟動未列入。

3. 標籤裡有空格。參考標記與定義對不上,兩者都會原樣印出。錯誤寫法:

定價調整了。[^pricing note]

[^pricing note]: 級距從三階改成五階。

改用連字號就正確了:

定價調整了。[^pricing-note]

[^pricing-note]: 級距從三階改成五階。

另外三種沒有範例可看的錯誤

  • 有參考標記卻沒有定義。找不到對應定義的 [^3] 會在句子中間原樣印出。發佈前請把每個標籤都搜尋一遍。
  • 有定義卻沒人引用。反過來的情況更安靜:沒被引用的定義在 GitHub 上根本不會渲染,於是你以為加好的附註從未出現。通常是編輯過程中參考標記被刪掉,定義卻留在原地。
  • 兩個定義用了同一個標籤。各家解析器行為不一致:有的取第一個、有的取最後一個、有的兩個都印。不要依賴這種行為,把其中一個改名就好。

最可靠的檢查是發佈前先渲染一次:把檔案貼進編輯器,看頁面底部。每一則註腳都該在那裡,依正文提及的順序編號,返回連結也都能點。完整指南把註腳放回整體脈絡;接下來會冒出來的問題,常見問題大多答得到。

相容性資料驗證日期

常見問題

Markdown 註腳算是標準語法嗎?

不算。原始 Markdown 與 CommonMark 都沒有註腳,它源自 PHP Markdown Extra,後來被 Pandoc、MultiMarkdown、GitHub、GitLab、Obsidian 與多數靜態網站產生器採用。Reddit、Discord、Notion 與純 CommonMark 解析器則會把方括號當成普通文字。

註腳的定義要放在文件的哪個位置?

放哪裡都可以。渲染器會蒐集所有定義並統一印在頁面底部,原始檔裡的位置不影響輸出。實務上草稿時放在參考標記附近、發佈前再搬到結尾,是很好用的做法。

註腳標籤可以用英文單字取代數字嗎?

可以,而且建議這樣做。[^pricing-2024][^7] 好維護太多,因為插入新註腳不必重新編號。讀者看到的仍是依正文順序排列的 1、2、3,因為顯示編號由渲染器指派。標籤裡請避免空格。

為什麼註腳的第二段跑到正文裡去了?

因為後續段落沒有縮排。註腳中第一段之後的每一段都要縮排四個空格才能留在註腳裡。少了縮排,那段文字就會脫離註腳,出現在定義所在的位置,通常是檔案最底部。

行內註腳在 GitHub 上能用嗎?

不能。^[註腳內容] 只有 Obsidian 與 Pandoc 支援,GitHub、GitLab 與 MkDocs 都會原樣印出插入符號與方括號文字。可能進到程式碼儲存庫的檔案,請一律用兩段式的 [^標籤] 寫法。

延伸閱讀

立即使用編輯器

立即使用編輯器