什麼是 GFM?它如何成為業界標準
- GFM 是 GitHub 的 Markdown 方言,2017 年正式發佈,定義為 CommonMark 的嚴格超集合。
- 規格本身只多五樣東西:表格、待辦清單、刪除線、裸網址自動連結,以及原始 HTML 過濾。
- 警示框、@提及、表情符號代碼、註腳與 Mermaid 來自 GitHub 的渲染器,不在規格之內。
- 預設就寫 GFM。在不支援的地方它會退回純文字,不會把整頁弄壞。
GitHub 風格 Markdown(GitHub Flavored Markdown,簡稱 GFM)是 GitHub 平台全面採用的 Markdown 方言。README、Issue、Pull Request、留言、Wiki、Gist 全都靠它運作。GFM 保留原始 Markdown 語法,再補上技術寫作者長年期盼的功能:表格、待辦清單、刪除線,以及網址自動連結。
GFM 如何變成預設選擇
它的歷史正好解釋了它的影響力。GitHub 於 2008 年上線、2009 年採用 Markdown,當時 2004 年的語法說明相當鬆散,同一份文件在兩套解析器下可能長得不一樣。GitHub 就在上面疊加自家擴充功能。每天有數百萬名開發者在 GitHub 上寫 README,GitHub 的版本於是悄悄變成大家實際學會的版本。
2017 年,GitHub 把一切釘死,正式發佈 GFM 規格書。那是一份嚴謹、經過完整測試的文件,定義為 CommonMark 的嚴格超集合。任何合法的 CommonMark 文件在 GFM 下的渲染結果完全相同,GFM 只是額外定義了一組固定而明確的擴充功能。
除了 GitHub,哪裡也吃 GFM
精確的規格書,加上全球最大的程式碼託管平台,這個組合很難被超越。核心擴充功能現在幾乎到處都能用:
- 程式碼託管:GitHub、GitLab、Bitbucket。
- 編輯器與筆記:Obsidian、Typora、VS Code 的預覽功能。
- 聊天與知識庫:Discord、Notion。
- 發佈工具:Hugo 以及多數現代靜態網站產生器。
所以當有人說「用 Markdown 寫就好」,他指的幾乎一定是 GFM。如果你對 Markdown 本身還不熟,建議先讀我們的 Markdown 完整教學再回來。如果你還在猶豫該用哪一層來寫,Markdown 與 HTML 的比較會把這個問題講清楚。
表格:用純文字呈現結構化資料
表格是原始 Markdown 最令人想念的功能。直線符號(|)分隔欄位,一列由連字號組成的分隔線區分表頭與內容,分隔線裡的冒號則決定對齊方式。
| 功能 | 原始 Markdown | GFM |
|:---------|:------------:|----:|
| 表格 | 無 | 有 |
| 待辦清單 | 無 | 有 |
| 刪除線 | 無 | 有 |
分隔線如何決定對齊
對齊全靠那一列。把冒號想成磁鐵,文字會被吸過去:
:---或單純的---是靠左對齊,也是預設值。:---:置中,適合「有/無」這類短短的狀態字。---:靠右,數字與金額用這個最好讀。
直線符號在原始碼裡不必對得整整齊齊,解析器只在乎符號有沒有出現。但排列整齊還是值得多按幾下空白鍵,因為下一個編輯這份檔案的人,看到的是純文字。
GFM 表格的極限在哪裡
這套語法刻意做得很小。不能合併儲存格、不能巢狀表格,儲存格裡也放不了真正的換行。要顯示直線符號本身,得寫成 \|,否則會被當成欄位邊界;要在儲存格內換行,就得改用 <br> 標籤。
表格也是實務上最常出包的結構。跳脫規則、產生器,以及什麼時候該乾脆改用 HTML 表格,Markdown 表格指南都有完整說明。
待辦清單:在文件裡放核取方塊
待辦清單就是一般的項目清單,只是每一項以 [ ](未完成)或 [x](已完成)開頭。成敗取決於兩個空格:空方括號裡面要有一個,右方括號後面也要有一個。
## 發佈檢查清單
- [x] 更新變更記錄
- [x] 調升版本號
- [ ] 建立版本標籤
- [ ] 發佈版本說明
- [ ] 巢狀子任務也支援
在 GitHub 上可以直接點選
待辦清單最強的地方,是它可以是互動的。在 Issue、Pull Request 描述與留言中,渲染出來的核取方塊可以直接點。你打勾的同時,GitHub 會替你改掉底層的 Markdown 原始碼。它還會顯示進度,例如 Issue 列表和引用該 PR 的地方都會出現「3 of 5 tasks」。Notion、Obsidian 和許多待辦事項應用程式,也把相同語法當成可點選的核取方塊。
其他地方是唯讀的方塊
在靜態輸出裡,方塊照樣會渲染出來,只是不能點。README、部落格文章、匯出的 HTML 檔都屬於這一類。發佈一份檢查清單仍然是對讀者最清楚的做法,因為他們可以直接複製原始碼再利用。
子任務走的是一般清單的縮排規則,所以一般清單的陷阱也照樣成立:子項目要縮排到父項目的文字下方,而且千萬不要把 Tab 和空格混著用。各家渲染器到底期待幾個空格,Markdown 清單語法寫得很清楚。
刪除線、自動連結與 HTML 過濾
還有三個比較小的擴充功能收尾。其中兩個是加語法,第三個則是刻意做減法。
刪除線:兩個波浪號
刪除線用兩個波浪號包住文字,~~像這樣~~ 就會渲染成劃掉的文字。它最適合誠實地呈現修正,例如 ~~$99~~ $79 讓舊價格仍然看得見。也可以用來標記某一行已經完成,而不必真的把內容刪掉。
自動連結:裸網址與電子郵件
自動連結省去了括號的麻煩。在原始 Markdown 中,直接貼上的網址如 https://mdeditor.tw 只是一段死文字,除非你用角括號或完整連結語法包起來。GFM 會自己認出裸網址與電子郵件地址,直接轉成可點擊的連結。
這在 Issue 留言裡是恩賜,在正式文件裡則是小陷阱。一串裸網址不會告訴讀者它通往哪裡,所以帶描述文字的寫法 [MD Editor](https://mdeditor.tw) 讀起來還是比較好。
禁用原始 HTML 標籤
原始 HTML 過濾是唯一做減法的擴充。Markdown 向來允許直接把 HTML 寫進文件,這正是 Markdown 與 HTML 比較那一頁的主題之一。但在一個有數百萬陌生人留言的平台上,這份自由就是安全漏洞。
因此 GFM 規格會過濾一份固定的危險標籤清單:<script>、<title>、<textarea>、<style>、<iframe>、<xmp>、<noembed>、<noframes>、<plaintext>。它會把開頭的角括號跳脫掉,讓標籤以文字形式出現而不會執行。一般排版用的 HTML,像 <br>、<sub>、<details>,仍然完全可用。
注意:這個過濾機制,就是你在自家部落格能用的影片嵌入碼,貼進 GitHub README 卻不見蹤影的原因。過程中不會有任何警告,那個 <iframe> 在渲染結果裡就是消失了。
GitHub 平台專屬功能:警示框、提及、註腳、Mermaid
在正式的 GFM 規格之外,GitHub 自家的渲染器還加了一層平台功能。有些只在 GitHub 上有效;有些,例如註腳與 Mermaid,如今在別處也走得相當順。
警示框:五種彩色提示方塊
警示框是用引用區塊語法做出來的提示方塊。引用的第一行寫上類型,GitHub 就會給它專屬的顏色與圖示:
> [!WARNING]
> 此操作將永久刪除你的資料。
[!NOTE]- 讀者略讀時也不該跳過的資訊。[!TIP]- 可有可無、但能讓事情更順的小撇步。[!IMPORTANT]- 沒看到就做不成功的關鍵資訊。[!WARNING]- 需要立刻注意的風險。[!CAUTION]- 某個動作可能造成的不良後果。
警示框是疊在規格之上的功能,不在規格裡面。在其他工具中它會退回成普通的引用區塊,一樣讀得懂。它借用的語法,包括巢狀與空行規則,都收在引用區塊語法那一頁。
@提及、Issue 與 commit 參照
輸入 @使用者名稱 會連到該使用者的個人頁面並發出通知。輸入 #123 會連到同一個儲存庫的第 123 號 Issue 或 Pull Request,直接貼上 commit 的 SHA 值也會連到那次提交。這些功能讓 GitHub 上的討論緊密串連,同時也是本頁最帶不走的一組語法:在其他渲染器裡,它們只是普通文字。
表情符號代碼
在冒號之間打上名稱,GitHub 就會換成圖案。:tada: 變成 🎉、:rocket: 變成 🚀、:bug: 變成 🐛。GitHub 支援數百個這類代碼,Discord 與 Slack 也採用相同慣例,習慣可以直接沿用。
註腳
註腳分成兩部分:句子裡的參照標記,以及可以放在檔案任何位置的定義。正文寫 某個論點。[^1],另外再加一行 [^1]: 資料來源。GitHub 會把所有定義集中到頁面底部,並自動補上返回連結。標籤可以用文字而不用數字,註腳語法指南非常推薦這個習慣。
Mermaid 與語法上色的程式碼區塊
在開頭圍欄後加上語言名稱 - ```python、```js、```bash - 整個區塊就會依該語言上色。把圍欄標成 mermaid,GitHub 還會更進一步:把內容渲染成即時圖表,而且像其他文字一樣受版本控制。下一節會完整說明這兩件事。
程式碼區塊的語法上色
圍欄式程式碼區塊就是三個反引號、你的程式碼,再三個反引號,中間的內容會原封不動保留。真正讓那個灰色方塊變成彩色程式碼的,是語言代碼:緊接在開頭圍欄之後、中間不留空格的一個短字。
```python
def greet(name):
print(f"Hello, {name}")
```
```js
const greet = (name) => console.log(`Hello, ${name}`);
```
GitHub 靠開源的語言辨識函式庫 Linguist 決定怎麼上色,也就是替每個儲存庫畫出語言比例條的那個元件。Linguist 認得數百種語言以及它們常見的別名,所以 py 和 python 會導向同一組上色規則。
萬一你寫了它不認得的代碼,不會壞掉,也不會跳出錯誤。那個區塊只會降級成普通的等寬程式碼區塊,就像你根本沒寫語言代碼一樣。圍欄還有幾條值得知道的規則,都整理在程式碼區塊語法那一頁。
你真正會用到的語言代碼
| 語言代碼 | 別名 | 適用場合 |
|---|---|---|
python | py | Python 腳本與程式片段 |
javascript | js | 瀏覽器與 Node.js 程式碼 |
typescript | ts | 帶型別的 JavaScript、型別定義檔 |
bash | sh、shell | 終端機指令與安裝步驟 |
json | 無 | API 回應、設定檔、套件清單 |
yaml | yml | CI 流程、Docker Compose、front matter |
html | 無 | 標記範例與樣板 |
css | 無 | 樣式表與選擇器範例 |
sql | 無 | 查詢語法、資料表結構、遷移腳本 |
diff | patch | 呈現前後差異、程式碼審查建議 |
plaintext | text、txt | 輸出、log,以及任何不想上色的內容 |
diff 區塊比文字描述更清楚
diff 值得單獨學起來。行首加 + 代表新增、加 - 代表刪除,GitHub 會把它們分別染成綠色與紅色:
```diff
- const port = 3000;
+ const port = process.env.PORT || 3000;
```
刻意關掉上色
另一個極端是 text,也可以寫成 plaintext。它的任務就是把上色關掉。終端機輸出、log 片段、目錄樹、ASCII 圖,都該用它。把上色器放進這些內容裡,它只會硬套上根本不存在的語法。
上色是渲染器的功能,不是 Markdown 的功能
這一點比表格裡任何一個代碼都重要。CommonMark 與 GFM 規格都沒有規定圍欄一定要上色。規格只說圍欄後面那串文字是「資訊字串(info string)」,渲染器可以自行運用。
實務上,那串文字會變成 <code> 元素上的 class="language-python",接著由樣式表或上色函式庫接手。所以結果會因工具而異:
- GitHub 與 GitLab 會直接替你上色。
- 純 CommonMark 解析器不會,它本來也沒答應過要上色。
- 靜態網站產生器要先接上 Prism、highlight.js 或 Chroma 才會上色。
我們自己的線上編輯器也會上色,用的是 highlight.js,而且只在文件真的含有程式碼時才載入。有標語言代碼的圍欄會上色;沒標的則刻意維持素色,因為猜錯語言只會把程式碼染成錯的顏色。
小提醒:每個圍欄都標上語言代碼,連放終端機輸出的也一樣。寫 text 等於告訴下一個讀者「這塊本來就不該上色」,也避免日後某個工具猜錯。
用一般圍欄畫出 Mermaid 圖表
Mermaid 是 GitHub 對資訊字串最搶眼的運用。把圍欄標成 mermaid,GitHub 完全不會上色,而是把內容渲染成一張真正的圖:
```mermaid
graph TD;
A[撰寫 Markdown] --> B[提交];
B --> C[GitHub 渲染成圖表];
```
流程圖、時序圖、類別圖、狀態圖、甘特圖都能這樣寫。每一張都以純文字存在儲存庫裡,也像其他檔案一樣可以做版本比對。GitLab、Notion、Obsidian 同樣支援 Mermaid;不支援的渲染器則單純顯示成一般程式碼區塊。
上面那段不用離開本站就能試。把它貼進線上編輯器,預覽窗格就會把圖畫出來。萬一 Mermaid 語法打錯,那個圍欄會維持成程式碼區塊,不會跳錯誤訊息,所以寫到一半的圖不會拖垮整個預覽。
數學公式:$ 與 $$
GitHub 同樣支援 LaTeX 風格的數學式。行內公式放在單個錢字號之間,例如 $E = mc^2$;獨立展示的公式則放在各自成行的兩個錢字號之間:
$$
\frac{1}{n}\sum_{i=1}^{n} x_i
$$
GitHub 會在 README、Issue、留言與 Wiki 中用 MathJax 渲染這些公式。一般文句裡的錢字號可能被誤判成公式起點,所以要顯示錢字號本身時請寫成 \$。數學公式和語法上色一樣依賴渲染器:GitHub、Obsidian、Typora 與 Pandoc 都支援,純 CommonMark 解析器則會把錢字號原樣印出來。
本站的線上編輯器也會渲染數學公式,用的是 KaTeX。它接受 $行內$ 與 $$展示$$,也接受 LaTeX 使用者習慣打的 \(...\) 與 \[...\]。所以你可以先在這裡確認公式排出來對不對,再貼進 README。
GFM、CommonMark 與原始 Markdown 的差異
這三個名字經常被搞混,先把族譜理清楚:
- 原始 Markdown(2004)是 John Gruber 寫的 Perl 腳本,加上一份非正式的語法說明。開創性十足,但模糊到讓各家解析器為了邊界情況爭論了十年。
- CommonMark(2014)是嚴謹的標準化計畫。它用正式規格與數百個測試案例把每一處歧義釘死,而且刻意不新增任何功能。
- GFM(2017 年定稿)是 CommonMark 加上 GitHub 的擴充功能。這也是為什麼能解析 GFM 的工具,一定也能完美解析 CommonMark。
逐項比較
| 功能 | 原始版(2004) | CommonMark | GFM |
|---|---|---|---|
| 標題、清單、連結、強調 | 有 | 有 | 有 |
| 正式規格+測試套件 | 無 | 有 | 有 |
| 表格 | 無 | 無 | 有 |
| 待辦清單 | 無 | 無 | 有 |
| 刪除線 | 無 | 無 | 有 |
| 裸網址自動連結 | 無 | 無 | 有 |
| 原始 HTML 標籤過濾 | 無 | 無 | 有 |
那到底該寫哪一種?
直接寫 GFM。它的降級表現很優雅:表格在只支援 CommonMark 的渲染器裡,頂多顯示成幾條直線符號,而不是壞掉的頁面。而且 GFM 正是你的同事、你的工具,還有未來的你最可能預期的方言。
例外情況是你無法掌控、也無法測試的目的地。不確定對方支援到哪裡時,就守住標題、清單、連結與強調這四樣,每種方言的處理方式都一致。我們的線上編輯器提供完整的 GFM 即時預覽,README、Issue 留言或 Wiki 頁面都能在發佈前先看清楚。
相容性資料驗證日期
常見問題
GFM 與一般 Markdown 相容嗎?
相容。GFM 被定義為 CommonMark 的嚴格超集合,而 CommonMark 又涵蓋原始 Markdown 的全部核心語法。任何標準 Markdown 文件在 GFM 下都能正確渲染;反過來就不一定了,因為表格、待辦清單等 GFM 專屬功能需要支援 GFM 的渲染器。
GFM 的表格和待辦清單在 GitHub 以外的地方能用嗎?
大多可以。GitLab、Bitbucket、Obsidian、Typora、VS Code 預覽、Hugo 以及多數現代渲染器都支援 GFM 的核心擴充功能。通常「帶不走」的是:@提及、#123 Issue 參照,以及可點選(互動式)的核取方塊 - 這些依賴 GitHub 平台本身。
如何在 GFM 中加入提示框或警告框?
使用警示框語法:在引用區塊的第一行寫 [!NOTE]、[!TIP]、[!IMPORTANT]、[!WARNING] 或 [!CAUTION],GitHub 會渲染成帶顏色與圖示的提示框。注意警示框是 GitHub 疊加在 GFM 規格之上的平台功能,部分其他渲染器只會顯示成普通的引用區塊。
為什麼我的 HTML 在 GitHub README 裡失效?
基於安全考量,GFM 會過濾特定的危險標籤 - <script>、<style>、<iframe>、<textarea> 等。無害的標籤如 <details>、<sub>、<br> 仍然有效。如果排版用的 HTML 看起來被忽略,也請確認它沒有被包在程式碼區塊裡。
發佈前可以在哪裡測試 GFM 語法?
我們的免費線上 Markdown 編輯器會即時渲染 GFM - 表格、待辦清單、刪除線、程式碼區塊等 - 讓你在貼進 GitHub 之前就確認 README 或 Issue 留言的效果。你輸入的內容完全不會離開瀏覽器。
CommonMark 是什麼?
CommonMark 是一份正式規格,總算把「Markdown 到底代表什麼意思」定義清楚。Gruber 在 2004 年寫的語法說明是散文形式,同一份檔案在兩套解析器下可能出現兩種結果;2014 年的規格用精確的規則加上數百個測試案例取代它,而且刻意不新增任何功能。GFM 被定義為它的嚴格超集合,所以任何合法的 CommonMark 檔案在 GitHub 上的渲染結果完全一致。這段故事的其餘部分都寫在什麼是 Markdown。
Markdown 可以打表情符號嗎?
可以。直接把 Unicode 表情符號貼進檔案就行,到哪裡都顯示得出來,因為對 Markdown 來說它就跟其他文字沒兩樣。至於 :tada: 這種冒號代碼寫法就是另一回事了:那是平台功能,不是 Markdown 語法。GitHub、GitLab、Discord 和 Slack 會自動換成圖案,純 CommonMark 則會把冒號原樣留在畫面上。
Markdown 的 Mermaid 是什麼?
Mermaid 讓你在標成 mermaid 的圍欄區塊裡,用純文字描述一張圖,再由渲染器把圖畫出來。GitHub 和 GitLab 會直接渲染成流程圖、時序圖或甘特圖,所以圖表能以文字形式存在儲存庫裡,跟其他檔案一樣做版本比對。其他多數渲染器只會顯示原始的 Mermaid 程式碼,因為這是渲染器的功能,不是 Markdown 語法,圍欄本身就只是一個貼了標籤的普通程式碼區塊。
延伸閱讀
立即使用編輯器
立即使用編輯器