行內程式碼:一對反引號

重點摘要
  • 一對反引號包住句子裡的一個詞組;三個反引號各自獨立成行則包住一整段程式碼。
  • 圍欄之間的內容原封不動保留,縮排與所有原本會被解讀成語法的字元都算在內。
  • 開頭圍欄後面接語言名稱就會啟動語法標示,寫錯也只是沒有顏色,不會出錯。
  • 開了圍欄卻忘了收尾,會把後面整份文件吃掉 - 這是 Markdown 裡破壞力最強的錯誤。

用一對反引號把內容包起來,它就會以等寬字體顯示,而且裡面所有 Markdown 語法一律失效:

請先執行 `npm install`,再編輯 `config/*.json`。
在這裡面寫 `**粗體**` 會原封不動顯示出來。

第二行就是重點所在。在反引號裡面,**粗體** 會顯示成四個星號而不會變粗;my_var_name 中間的底線不會把字變斜體;<div> 會以文字形式顯示,不會被當成 HTML。行內程式碼就是所有語法字元的逃生門

內容本身含有反引號怎麼辦

外層的反引號比內層多就好,兩個、三個,需要幾個就用幾個:

``用 ` 這個字元可以開始一段行內程式碼``

``` 內容含有 ``兩個`` 的情況就需要三個 ```

如果內容的開頭或結尾就是反引號,請在分隔符內側各補一個空格。渲染器只會剝掉一個開頭與一個結尾空格,所以 `` ` `` 得到的就是一個孤零零的反引號。第一次看到確實會覺得荒謬,但所有 Markdown 教學都是這樣寫的。

行內程式碼不該拿來做什麼

它不是螢光筆。拿反引號來讓產品名稱「看起來醒目」,會給螢幕閱讀器錯誤的訊號,也會讓文章看起來像一份設定檔。請保留給讀者真的可能照打或複製的東西:指令、檔名、函式名、鍵、HTML 標籤。想強調語氣請改用粗體或斜體,想指向文件請用正規的連結

插圖:一句話裡的某個詞被封進一顆等寬字體的保護膠囊中

圍欄式程式碼區塊

只要內容超過一個詞組,就用三個反引號各自獨立成行,把程式碼包在中間:

```
def greet(name):
    return f"Hello, {name}"
```

圍欄之間的一切都會被完整保留:縮排、空行、標點,以及所有原本會被當成 Markdown 語法的字元。圍欄式寫法源自 GitHub 風格 Markdown,現在幾乎所有值得一用的渲染器都支援。

波浪號圍欄

三個波浪號的效果一模一樣:

~~~
console.log("結果相同");
~~~

波浪號只在一種情況下真正有用:當你要展示的內容本身含有反引號圍欄。用 ~~~ 包住一段內含 ``` 的 Markdown,兩者就不會打架。除此之外反引號才是慣例。兩種符號不能混用,用反引號開頭就必須用反引號收尾。

圍欄長度與空行

區塊能不能乾淨收尾,由兩條規則決定:

  • 結尾圍欄的長度不能短於開頭圍欄,用四個反引號開的區塊要用四個以上收尾。
  • 開頭圍欄之前、結尾圍欄之後都要留一行空行

少了那一行空行,有些解析器會把整個區塊黏進上下段落。這是五秒鐘就能修好、卻讓人卡二十分鐘的問題。

四個空格的縮排寫法,以及圍欄為何勝出

2004 年的原始 Markdown 沒有圍欄。只要連續幾行縮排四個空格(或一個 Tab),那就是程式碼區塊:

範例如下:

    $ git status
    On branch main

回到一般段落。

這種寫法至今在所有渲染器裡仍然有效,老舊的 README 或十年前的 Stack Overflow 答案裡都會遇到。但還是請一律改用圍欄,理由有四個:

  • 沒地方寫語言。縮排區塊無法做語法標示,因為根本沒有位置可以宣告語言。
  • 縮排本身就是資料。Python、YAML、Makefile 都在意行首空白。每行多加四個空格、閱讀時再心算扣掉,是自找麻煩。
  • 複製貼上就毀了。貼進來的程式碼沒有縮排,每次修改都得手動一行一行補。
  • 會和清單打架。在清單項目裡,四個空格本來就代表「這一項的延續內容」,兩套規則直接衝突。

請把四個空格的寫法當成「要看得懂」的語法,而不是「要拿來寫」的語法。

小提醒:轉換舊檔案其實是純機械工作。選取整塊、每行去掉四個空格、包上圍欄,再補一個語言名稱即可。多數編輯器按一次 Shift+Tab 就能完成去縮排。

語言識別字與語法標示

把語言名稱緊接在開頭圍欄後面,中間不要空格:

```python
def greet(name):
    return f"Hello, {name}"
```

那個字叫做 info string。渲染器會把它交給 Prism、highlight.js 或 Chroma 之類的標示器,替關鍵字、字串和註解上色。識別字不分大小寫,寫錯也不會出事,只會得到沒有顏色的區塊。既然猜錯零成本,就每個區塊都標上語言。

值得記住的識別字

識別字常見別名典型用途
javascriptjsnode瀏覽器與 Node.js 程式碼
typescripttstsx有型別的 JavaScript、React 元件
pythonpypython3腳本、資料處理、教學範例
bashshshellzshShell 指令與腳本
consoleshell-session含提示符號與輸出的終端機畫面
jsonjsonc設定檔、API 回應
yamlymlCI 流程、Kubernetes、front matter
htmlxmlsvg標記語言與模板
cssscssless樣式表
sqlpostgresqlmysql查詢語句與資料表結構
gogolangGo 原始碼
rustrsRust 原始碼
java-Java 原始碼
c / cppc++cchC 與 C++ 原始碼及標頭檔
php-PHP 原始碼與模板
markdownmd當作範例展示的 Markdown 原始碼
diffpatch變更內容,加減號會分別上色
textplaintexttxtnone刻意關閉語法標示

diff 區塊

diff 這個識別字會依每行的第一個字元上色:+ 是綠色,- 是紅色。不需要任何額外工具,就能把程式碼區塊變成前後對照:

```diff
 function total(items) {
-  return items.length
+  return items.reduce((sum, i) => sum + i.price, 0)
 }
```

注意未變更的行前面有一個空格,正是它告訴標示器這行維持原色;忘了加就會出現半邊上色的怪 diff。

刻意關閉語法標示

當顏色會誤導讀者時,就把區塊標成 text:日誌輸出、ASCII 示意圖、目錄樹、錯誤訊息都屬於這類。把堆疊追蹤丟給標示器,它會把一堆隨機單字當成關鍵字上色,結果反而更難讀。選 text 是真正的決定,不是退而求其次。

插圖:一段灰色的程式碼被貼上語言標籤後整段染上顏色

清單裡的程式碼區塊,以及圍欄裡的圍欄

放進清單項目裡

清單裡的圍欄必須縮排到和該項目的文字對齊,否則清單會被它從中間切成兩段。無序清單通常是兩到三個空格,有序清單則是三到四個:

1. 安裝相依套件:

   ```bash
   npm install
   ```

2. 啟動開發伺服器:

   ```bash
   npm run dev
   ```

規則和 Markdown 清單裡所有延續內容相同,三點就講完了:

  • 縮排要對齊項目文字的第一個字,不是對齊項目符號。
  • 開頭與結尾圍欄的縮排必須一致。
  • 圍欄前留一行空行,嚴格的解析器才不會抱怨。

注意:縮排寫錯的典型症狀是:區塊後面的編號會重新從 1 開始。看到重新編號,就代表清單在圍欄那裡結束了,而不是延續下去。

在圍欄裡展示圍欄

想展示一段本身含有程式碼區塊的 Markdown,就讓外層圍欄比內層更長。外面四個反引號,裡面三個:

````markdown
程式碼區塊的寫法如下:

```js
alert("hi");
```
````

所有教 Markdown 的教學都靠這個機制運作,包括這一頁。內層若已用四個反引號,外層就用五個;另一個選擇是外層改用 ~~~,它和反引號永遠不會撞在一起。

語法標示到底在哪裡才會生效

圍欄本身幾乎到處都支援,但顏色不是,因為語法標示是另一套獨立的函式庫,平台有沒有內建全看它自己。

平台圍欄式區塊語法標示
本站的線上編輯器支援支援,只要圍欄有標語言代碼
GitHub、GitLab支援支援,數百種語言,在伺服器端處理
VS Code 預覽支援支援,直接沿用編輯器本身的語法定義
Hugo、Jekyll、Astro、Docusaurus支援支援,但要在設定檔裡啟用標示器
Obsidian、Notion支援支援,並提供語言選單
Discord、Slack支援Discord 有,Slack 沒有
markedmarkdown-it 輸出支援不支援,除非自己接上 Prism 或 highlight.js
電子郵件、多數 CMS 留言框不一定不支援

本站的預覽也照這張表的規則走:有標語言代碼的圍欄會交給 highlight.js 上色,沒標的則維持素色,不去猜語言。

實務上的結論:不要讓顏色承載意義。讀者非注意某一行不可時,就在區塊上方的文字裡講明,或在程式碼裡用註解標出來。一個在別處會變成灰色的高亮關鍵字,等於什麼都沒說。各家聊天與筆記軟體怎麼處理圍欄,Discord 指南Notion 指南有實測。

行長與水平捲動

多數渲染器不會替程式碼區塊自動換行。一行 200 個字元就會生出水平捲軸,手機讀者只看得到前三分之一。範例每一行請盡量壓在 80 個字元以內,四個習慣就夠了:

  • 長的 shell 指令用行尾反斜線斷行。
  • 長的函式呼叫拆成多行
  • 把佔位用的變數名稱改短、改直白。
  • 範例網址只留有意義的那一段。

真的無法縮短時,就在文字裡把重點講完,讓沒人需要靠捲動才能理解。這裡也是很多人會想改用原生 HTML 寫個會換行的 <pre> 的地方;改貼截圖更糟,因為程式碼的圖片不能複製、不能搜尋,也無法被唸出來。

常見錯誤與修法

沒有收尾的圍欄

這是頭號災難,而且發作起來非常壯觀:

錯誤:
```js
const a = 1;

從這裡開始的所有內容都變成程式碼了。
標題、清單、連結,全部被吞掉。

開了圍欄卻沒有收尾,它會把文件剩下的全部吃光。症狀非常好認:從某個位置開始,整頁變成一大塊等寬字體。往上捲到排版死掉的那一點,補上漏掉的 ``` 即可。收尾圍欄必須自己獨佔一行,寫成 const a = 1;``` 不算。

小提醒:有即時預覽的話,圍欄一少收尾就會當場現形。這也是「先在編輯器裡打草稿,再貼進 pull request 說明欄」最實際的理由。

被換成彎引號

錯誤: const greeting = “hello”;
修正: const greeting = "hello";

彎引號和直引號是不同的字元,沒有編譯器吃得下。程式碼區塊裡 Markdown 渲染器不會替你轉換,但文字很可能在送進來之前就被轉過了:文書軟體、通訊軟體、CMS 編輯器,或 macOS 的系統層級自動替換。-- 被換成長橫線也是同一類問題。貼進來的程式碼若爆出莫名其妙的語法錯誤,先看引號。

從文書軟體貼過來

從 Word、Google 文件或電子郵件裡複製程式碼,會一併帶進幾種看不見的東西:

  • 和一般空格長得一模一樣的不斷行空格
  • 被轉成不定寬縮排的 Tab
  • 完全沒有外觀的零寬字元
  • 上面提過的彎引號與長橫線

結果就是看起來完全正確,就是跑不動。請先經過一道純文字關卡再貼:文字編輯器、終端機,或本站編輯器的左側面板,在送出之前先看清楚原始字元。

圍欄縮排太多

錯誤:
    ```js
    const a = 1;
    ```

行首縮排四個空格本來就代表縮排式程式碼區塊,於是圍欄符號被當成純文字顯示出來。除非區塊放在清單項目裡,否則圍欄請貼齊左邊界。

語言名稱拼錯

寫成 ```JavaScipt 的代價只是沒有顏色,不會有錯誤訊息,所以表面上一切正常。該上色的區塊沒上色時,先對照上表檢查 info string 的拼字,再去怪平台。其餘部分請見完整 Markdown 指南快速參考表常見問題

相容性資料驗證日期

常見問題

Markdown 的程式碼區塊怎麼寫?

先單獨一行打三個反引號,下面接程式碼,最後再單獨一行打三個反引號。想要語法標示,就在開頭圍欄後面緊接語言名稱,例如 ```python。如果只是句子中間的一個詞或一行指令,改用一對反引號即可。

為什麼我文件後面全部變成程式碼了?

上面某處有一個開了卻沒收尾的圍欄,把後面的內容全部吞掉了。往上捲到排版開始失效的位置,補上單獨一行的 ``` 就好。有即時預覽的話,這種錯誤打字當下就會被抓到。

有哪些語言識別字可以用?

取決於渲染器用的標示器認得哪些,GitHub 支援的是數百個名稱再加上別名。日常會用到的大致是 jstspythonbashjsonyamlhtmlcsssqldiff。不認得的識別字只會變成沒有顏色的區塊,所以猜錯不會有代價。

行內程式碼裡面要顯示反引號怎麼辦?

外層的反引號比內層多就行,如果內容的開頭或結尾就是反引號,再各補一個空格。兩個外層反引號可以包住含有一個反引號的內容,三個可以包住含有兩個的,以此類推。

表格裡可以放程式碼區塊嗎?

只有行內程式碼可以。圍欄式區塊屬於區塊級元素,無法放進表格儲存格,因為換行就代表這一列結束了。儲存格裡放一對反引號的行內程式碼,多行的範例則移到表格下方用圍欄式區塊呈現。

.markdown 檔要用什麼開啟?

任何文字編輯器都行。.markdown 檔和 .md 檔是同一種東西,只是副檔名用了比較長的寫法,底層都是純文字。記事本、TextEdit、VS Code、Obsidian、手機的備忘錄全都打得開,不用轉檔也不用安裝任何東西。想看排版後的樣子而不是原始碼,可以丟進我們的 Markdown 檢視器,或把副檔名改成 .md,讓更多軟體一眼認出它。

延伸閱讀

立即使用編輯器

立即使用編輯器