語(yǔ)法詳解:純文本寫作的核心技巧與避坑指南)
寫技術(shù)文檔這幾年我?guī)缀趺刻於荚诟?Markdown 打交道。無(wú)論是寫項(xiàng)目說(shuō)明、整理筆記、發(fā)博客還是給團(tuán)隊(duì)寫內(nèi)部協(xié)作文檔Markdown 都是我首選的寫作格式。它看似簡(jiǎn)單——幾個(gè)符號(hào)、幾行標(biāo)記卻能解決內(nèi)容排版里最煩人的那批問(wèn)題字號(hào)不統(tǒng)一、樣式復(fù)制失敗、換個(gè)平臺(tái)格式就亂。我見過(guò)不少剛接觸的人的第一反應(yīng)是這玩意兒不就是幾個(gè) # 和 * 嗎有什么好學(xué)的。但實(shí)際用上一段時(shí)間就會(huì)發(fā)現(xiàn)越基礎(chǔ)的東西越值得把細(xì)節(jié)摳清楚。這一篇我不打算寫教科書式的條目匯編而是以一個(gè)日常使用者的角度把 Markdown 基礎(chǔ)語(yǔ)法里最常用的那部分講透順便聊聊哪些地方容易踩坑、為什么這么寫、以及怎么根據(jù)自己的習(xí)慣搭一套順手的寫作流程。如果你正在學(xué) Markdown或者已經(jīng)用了一段時(shí)間但總感覺有些地方不順手這篇文章會(huì)很適合你。內(nèi)容會(huì)覆蓋設(shè)計(jì)思路、核心語(yǔ)法、實(shí)操中的各種細(xì)節(jié)、常見問(wèn)題排查、還有不同平臺(tái)的兼容性差異。我不保證講完全部冷門用法但我可以保證讀完你會(huì)對(duì)標(biāo)注、嵌套、表格、代碼塊這些常用操作心里有底寫起來(lái)不再猶豫。1. 從設(shè)計(jì)思路說(shuō)起Markdown 為什么是純文本聊語(yǔ)法之前我想先說(shuō)說(shuō) Markdown 的底層邏輯。很多人直接上手學(xué)符號(hào)學(xué)會(huì)了卻總在奇怪的地方卡殼本質(zhì)上就是沒搞懂它為什么要做成現(xiàn)在這個(gè)樣子。1.1 極簡(jiǎn)標(biāo)記專注內(nèi)容本身Markdown 的核心思想其實(shí)特別樸素我寫的是一份帶標(biāo)記的純文本文件而不是一份“排版好的文檔”。傳統(tǒng)編輯器的做法是你一邊輸入內(nèi)容一邊定義它的格式——選中文字、點(diǎn)按鈕、調(diào)字體、改顏色。聽起來(lái)很直觀但實(shí)際帶來(lái)的問(wèn)題是你的注意力一直被格式牽引真正的內(nèi)容反而不那么連貫了。Markdown 反過(guò)來(lái)它把排版需要的信息用幾個(gè)字符直接寫進(jìn)文本里。想寫個(gè)大標(biāo)題就在行首放一個(gè)#想讓某個(gè)詞加粗就用兩個(gè)星號(hào)把它包起來(lái)。這樣做的第一個(gè)好處是寫作的時(shí)候手不需要離開鍵盤不需要去點(diǎn)任何菜單思路不會(huì)被打斷。第二個(gè)好處更加實(shí)際因?yàn)樗羌兾谋灸愀静挥脫?dān)心格式會(huì)丟。不管把這個(gè)文件拿到什么編輯器、什么系統(tǒng)、什么設(shè)備上打開內(nèi)容本身永遠(yuǎn)都是完整的。1.2 一次編寫處處轉(zhuǎn)換我記得最早接觸 Markdown 的時(shí)候有個(gè)疑問(wèn)光寫純文本怎么轉(zhuǎn)成那種排版精美的頁(yè)面后來(lái)才明白Markdown 的渲染思路其實(shí)是“中間層”。你寫的是帶標(biāo)記的源文件外面套一層轉(zhuǎn)換引擎就能把它變成 HTML、PDF、Word、微信公眾號(hào)格式等各種各樣的輸出。這種思路很像寫代碼的人常說(shuō)的一句話數(shù)據(jù)與展示分離。你用統(tǒng)一的標(biāo)記語(yǔ)言寫好數(shù)據(jù)展示層可以隨時(shí)換皮膚。同一個(gè) Markdown 文件放在代碼托管平臺(tái)上是帶高亮的源碼風(fēng)格放在筆記軟件里是清爽干凈的閱讀風(fēng)格放到博客系統(tǒng)里又是完全不一樣的主題樣式。如果換作傳統(tǒng)編輯器輸出的文檔你得為每個(gè)平臺(tái)重新排版一遍操心字體大小、圖片位置、行間距這些工作本身和內(nèi)容創(chuàng)作毫無(wú)關(guān)系純粹是消耗精力。1.3 通用性帶來(lái)長(zhǎng)期價(jià)值讓我真正堅(jiān)定用 Markdown 的是它的通用性。我這些年積攢下來(lái)的筆記和文檔有幾百篇中間換過(guò)好幾款筆記軟件、博客平臺(tái)、協(xié)作工具但從來(lái)沒有遇到過(guò)內(nèi)容遷移的問(wèn)題。原因很簡(jiǎn)單Markdown 是純文本只要有文本編輯器就能打開它有統(tǒng)一的基本約定幾乎所有平臺(tái)都支持解析。而這些約定簡(jiǎn)單到不可能徹底失效。這其實(shí)也解釋了為什么很多簡(jiǎn)歷、開源項(xiàng)目說(shuō)明、技術(shù)博客、甚至?xí)某醺宥荚谟?Markdown。它不是某個(gè)獨(dú)立軟件創(chuàng)造出來(lái)的私有格式而是一種事實(shí)標(biāo)準(zhǔn)用戶的選擇成本很低轉(zhuǎn)移的代價(jià)也極低。所以我建議每個(gè)剛開始寫作的人不管寫的是技術(shù)文章還是日常生活記錄都可以從 Markdown 入手。它給你的不是一套排版方案而是一種穩(wěn)定、可靠、能長(zhǎng)期跟著你走的寫作方式。2. 基礎(chǔ)語(yǔ)法拆解每個(gè)標(biāo)記都學(xué)明白這一節(jié)會(huì)進(jìn)入實(shí)用層面。我不打算把語(yǔ)法一條條列完就收工那樣的話網(wǎng)上隨便找張速查表就夠用了。我想在講每個(gè)標(biāo)記的同時(shí)把背后容易忽略的細(xì)節(jié)、常見誤區(qū)一并說(shuō)出來(lái)這樣你學(xué)習(xí)的時(shí)候能少走一些彎路。2.1 標(biāo)題注意空格別吞字標(biāo)題是最高頻的語(yǔ)法之一寫法是行首加#從一級(jí)到六級(jí)依次對(duì)應(yīng) 1 到 6 個(gè)井號(hào)。但這里有個(gè)很多人一開始就忽略的點(diǎn)#和標(biāo)題文字之間要加一個(gè)空格。比如# 一級(jí)標(biāo)題 ## 二級(jí)標(biāo)題 ### 三級(jí)標(biāo)題加了空格之后渲染器才明確知道井號(hào)是標(biāo)記符號(hào)而不是標(biāo)題內(nèi)容的一部分。如果你寫#核心功能在部分平臺(tái)里它可能被識(shí)別成標(biāo)題也可能把#直接當(dāng)成文字輸出表現(xiàn)不一致。這種不一致一旦出現(xiàn)在你交付的文檔里結(jié)果很難看。標(biāo)題的層級(jí)邏輯也需要提前想清楚。一級(jí)標(biāo)題在一個(gè)頁(yè)面里最好只有一個(gè)類似文章總題二級(jí)標(biāo)題是章節(jié)三級(jí)、四級(jí)往下依次細(xì)分。不要跳過(guò)層級(jí)比如從二級(jí)直接跳到四級(jí)渲染效果雖然不會(huì)報(bào)錯(cuò)但閱讀結(jié)構(gòu)會(huì)很亂尤其在生成目錄時(shí)跳級(jí)會(huì)導(dǎo)致目錄結(jié)構(gòu)斷裂。實(shí)操里我的習(xí)慣是正文常駐二級(jí)標(biāo)題章節(jié)內(nèi)部用三級(jí)遇到特殊情況才用四級(jí)。這個(gè)習(xí)慣能保證整篇文檔的結(jié)構(gòu)清楚、不過(guò)度嵌套。另外標(biāo)題下面建議空一行再接正文即使不空也能渲染但空一行對(duì) Markdown 源碼的可讀性非常有幫助尤其是別人拿到你的源文件時(shí)一眼能分清結(jié)構(gòu)。2.2 強(qiáng)調(diào)語(yǔ)法星號(hào)與下劃線的差別強(qiáng)調(diào)包括加粗、斜體和刪除線它們是行內(nèi)文字排版最常見的需求。加粗是一對(duì)雙星號(hào)或雙下劃線**加粗文字** __也可以加粗__斜體是單星號(hào)或單下劃線*斜體文字* _也可以斜體_刪除線是用兩個(gè)波浪號(hào)包起來(lái)~~刪除內(nèi)容~~這里有一個(gè)非常值得說(shuō)的細(xì)節(jié)同一種效果星號(hào)和下劃線幾乎是等效的但我的實(shí)際推薦是盡量統(tǒng)一使用星號(hào)。原因是下劃線在英文里有時(shí)會(huì)和單詞本身混淆比如_hello_world_這種形式有些渲染器會(huì)把它理解成斜體標(biāo)記而更多情況下閱讀源碼時(shí)會(huì)覺得奇怪。星號(hào)沒有這種困擾。強(qiáng)調(diào)符號(hào)里還有一個(gè)常見誤區(qū)符號(hào)和文字之間不能有空格。比如** 加粗 **在不少平臺(tái)上渲染不出來(lái)因?yàn)榍昂蠖嗔丝崭窠馕銎鲿?huì)按字面空格看待。正確寫法是符號(hào)與文字緊貼不加空格。另外嵌套強(qiáng)調(diào)時(shí)要注意配對(duì)順序比如加粗里面嵌斜體可以寫**這是加粗里的 *斜體* 文字**星號(hào)的配對(duì)是逐層的寫反了會(huì)漏掉一部分效果。2.3 列表有序和無(wú)序的差異與嵌套列表是整理信息的利器分無(wú)序列表和有序列表兩種。無(wú)序列表只要在行首加-、*或后面跟一個(gè)空格再接內(nèi)容例如- 第一項(xiàng) - 第二項(xiàng) - 第三項(xiàng)有序列表是數(shù)字加英文句點(diǎn)加空格1. 第一步 2. 第二步 3. 第三步這里容易出問(wèn)題的是兩個(gè)地方。第一有序列表的數(shù)字不需要連續(xù)正確。你可以全部寫1.渲染時(shí)它會(huì)自動(dòng)按順序遞增。這其實(shí)是個(gè)很實(shí)用的技巧因?yàn)槟阍谡{(diào)整條目順序時(shí)不需要手動(dòng)改序號(hào)只要保證條目順序?qū)托袖秩境鰜?lái)始終是 1、2、3、4。第二列表嵌套需要縮進(jìn)。子列表要在父列表項(xiàng)下面另起一行并且縮進(jìn)兩個(gè)或四個(gè)空格具體看平臺(tái)。嵌套例子- 分類一 - 子項(xiàng) A - 子項(xiàng) B - 分類二如果縮進(jìn)不對(duì)子列表會(huì)被拍平變成平級(jí)條目整個(gè)結(jié)構(gòu)的層級(jí)感就沒了。我踩過(guò)不少次這個(gè)坑后來(lái)養(yǎng)成了一個(gè)習(xí)慣凡寫嵌套列表都會(huì)在源碼里刻意檢查縮進(jìn)是否整齊。你可能會(huì)問(wèn)為什么非要在源碼層面較真因?yàn)?Markdown 源碼的整潔度決定了后期維護(hù)的難度現(xiàn)在嫌檢查麻煩以后改結(jié)構(gòu)時(shí)更麻煩。2.4 引用多層次嵌套與實(shí)用場(chǎng)景引用在 Markdown 里用右尖括號(hào)表示通常用于轉(zhuǎn)述他人觀點(diǎn)、引用文獻(xiàn)片段、或者突出強(qiáng)調(diào)某段重要說(shuō)明?;緦懛?這是一個(gè)引用塊引用塊可以嵌套引用塊內(nèi)部再寫一個(gè)就能嵌套二級(jí)引用這在逐層追溯信息來(lái)源時(shí)非常好用 外層引用 內(nèi)層引用引用塊還可以包含其他元素比如標(biāo)題、列表、代碼塊。它們只需要在引用內(nèi)部按普通 Markdown 語(yǔ)法編寫即可。比如 ## 引用內(nèi)的標(biāo)題 - 列表?xiàng)l目一 - 列表?xiàng)l目二 這是正文。寫引用時(shí)要注意每個(gè)引用行最好都以開頭哪怕中間有空行也要寫成空行的形式。有些平臺(tái)允許“懶寫法”即只要段落第一行有后續(xù)幾行不寫也算引用內(nèi)但換來(lái)?yè)Q去容易出錯(cuò)。我個(gè)人的習(xí)慣是每行都帶一勞永逸。引用還有一個(gè)思路上的應(yīng)用很多人會(huì)忽略寫教程或提示信息時(shí)拿引用塊裝“注意事項(xiàng)”比用普通段落醒目得多。尤其在一個(gè)較長(zhǎng)文檔里讀者快速掃視時(shí)眼睛會(huì)優(yōu)先注意到引用塊的顏色變化這其實(shí)是閱讀體驗(yàn)上的一種引導(dǎo)技巧。2.5 鏈接與圖片路徑和尺寸都要上心鏈接的基本語(yǔ)法是[顯示文字](目標(biāo)地址)例如[我的博客](https://example.com)鏈接可以分為外部鏈接和相對(duì)鏈接。外部鏈接指向完整的網(wǎng)址相對(duì)鏈接指向本地文件在寫項(xiàng)目說(shuō)明時(shí)非常常用。比如你在文檔里引用同目錄下的另一份文檔可以寫[開發(fā)指南](docs/guide.md)這樣點(diǎn)擊時(shí)可以直接跳轉(zhuǎn)到該文件。圖片語(yǔ)法只比鏈接多一個(gè)感嘆號(hào)這里我特別想提醒三件事第一替代文字不是隨便寫的。它用于圖片加載失敗時(shí)顯示的文字也是無(wú)障礙閱讀和搜索引擎識(shí)別圖片內(nèi)容的依據(jù)。認(rèn)真的文檔里替代文字應(yīng)當(dāng)簡(jiǎn)明描述圖片內(nèi)容像“登錄頁(yè)面截圖”“架構(gòu)圖”這樣而不是空著或?qū)懸淮畞y碼。第二相對(duì)路徑的寫法要非常小心。如果你用 Markdown 寫項(xiàng)目文檔并存放圖片推薦在項(xiàng)目里建一個(gè)assets或images文件夾文中引用時(shí)使用相對(duì)路徑比如。如果直接用絕對(duì)路徑文檔從一臺(tái)電腦拷到另一臺(tái)電腦時(shí)圖片就全部失效。你也不能依賴網(wǎng)絡(luò)圖床鏈接外部鏈接一旦失效文檔里就是一堆碎圖。第三Markdown 原生的圖片語(yǔ)法不支持設(shè)置寬度、高度、居中。想調(diào)圖片尺寸常用的方案是直接使用 HTML 的img標(biāo)簽像這樣img srcassets/screenshot.png width60% /幾乎所有的 Markdown 渲染器都允許混入 HTML。這個(gè)特性在普通文本里用得少但在寫正式文檔時(shí)用處不小我們后面還會(huì)專門聊。2.6 表格注意管道符與對(duì)齊表格是 Markdown 基礎(chǔ)語(yǔ)法里最“有脾氣”的一部分。它用管道符|分隔列用一行短橫線作為表頭與內(nèi)容的分隔行?;A(chǔ)寫法| 功能 | 快捷鍵 | 適用場(chǎng)景 | | ---- | :---: | -------: | | 加粗 | CtrlB | 強(qiáng)調(diào)重點(diǎn) | | 斜體 | CtrlI | 引入名詞 | | 刪除線 | ~~ | 標(biāo)記廢棄 |第二行| ---- |是分隔行它還承擔(dān)著對(duì)齊方式的任務(wù)。冒號(hào)在左邊表示左對(duì)齊兩邊都有冒號(hào)表示居中冒號(hào)在右邊表示右對(duì)齊。上面的示例里“功能”沒有冒號(hào)即默認(rèn)左對(duì)齊“快捷鍵”是居中“適用場(chǎng)景”是右對(duì)齊。表格最容易踩的坑是管道符周圍的空格。Markdown 解析表格時(shí)依賴管道符來(lái)區(qū)分列所以每一行管道符數(shù)量必須相同。如果你某一行少了一個(gè)管道符整個(gè)表格就會(huì)渲染異常有時(shí)甚至?xí)?dǎo)致后續(xù)內(nèi)容全部變成表格的一部分亂成一團(tuán)。我見過(guò)不少人為了美觀把表格里的內(nèi)容用大量空格對(duì)齊。這種美化其實(shí)完全沒有必要因?yàn)殇秩境鰜?lái)看的是最終表格源碼里的空格只是輔助解析的渲染器會(huì)自動(dòng)忽略多余的空白。與其花時(shí)間對(duì)齊源碼不如保證每一行管道符數(shù)量一致內(nèi)容緊貼管道符即可。2.7 分割線三個(gè)符號(hào)的安全寫法分割線用三個(gè)或以上的-、*、_獨(dú)行書寫即可--- *** ___這里有一個(gè)老手才知道的坑---不光是分割線它還有可能是二級(jí)標(biāo)題的另一種寫法。在 Markdown 里任何一段文字下面緊跟一行---都會(huì)被解析成二級(jí)標(biāo)題。比如我的標(biāo)題 ---這樣寫的后果是“我的標(biāo)題”會(huì)被渲染成二級(jí)標(biāo)題而不是正文上方的分割線。想避免這種歧義可以在分割線上下都保留空行并且盡量讓分割線前后不要緊貼著正文段落。最穩(wěn)妥的做法是分割線單獨(dú)成段和上下文都隔一個(gè)空行。很多編輯器在你寫---后會(huì)自動(dòng)補(bǔ)出空行就是在規(guī)避這個(gè)問(wèn)題。3. 代碼與代碼塊寫技術(shù)內(nèi)容的必備姿勢(shì)如果一定要我選出 Markdown 語(yǔ)法里最值錢的一部分我可能會(huì)把票投給代碼相關(guān)的語(yǔ)法。它讓 Markdown 成了寫技術(shù)文檔的標(biāo)準(zhǔn)語(yǔ)言。3.1 行內(nèi)代碼反引號(hào)的配對(duì)魔法行內(nèi)代碼用于在普通句子中提到變量名、函數(shù)名、命令等。用單個(gè)反引號(hào)包住內(nèi)容即可這里需要執(zhí)行 git commit 命令。行內(nèi)代碼的樣式通常是等寬字體加底色和正文有明顯區(qū)分。它和普通文字最大的區(qū)別是內(nèi)部的符號(hào)不會(huì)被當(dāng)作 Markdown 語(yǔ)法解析。比如你想在文章里寫*不重要*如果直接放在正文里會(huì)把文字變成斜體如果放在反引號(hào)里就能原樣輸出星號(hào)和文字。但反引號(hào)本身也有一個(gè)坑如果內(nèi)容里恰好需要用到反引號(hào)怎么辦比如你想在文章里寫“使用 符號(hào)表示行內(nèi)代碼”這時(shí)候外層包裹的反引號(hào)會(huì)和內(nèi)層反引號(hào)沖突。解決辦法是加長(zhǎng)邊界反引號(hào)用兩個(gè)反引號(hào)包裹一個(gè)反引號(hào)例如 這個(gè)是反引號(hào)同理內(nèi)容里如果有兩個(gè)連續(xù)反引號(hào)外層就可以用三個(gè)。理解了邊界加長(zhǎng)的思路這部分就不難了。3.2 圍欄代碼塊別忘記標(biāo)注語(yǔ)言多行代碼塊使用三個(gè)反引號(hào)包裹也可以使用三個(gè)波浪號(hào)。前一種寫法更常見也是我的首選。圍欄代碼塊最大的優(yōu)勢(shì)是可以指定編程語(yǔ)言讓渲染器做語(yǔ)法高亮function hello() { console.log(Hello, Markdown!); }圍欄代碼塊是一把雙刃劍高度靈活但也容易出錯(cuò)。最常見的錯(cuò)誤是忘記關(guān)閉三個(gè)反引號(hào)結(jié)果后面的所有內(nèi)容全部被當(dāng)成了代碼直到下一個(gè)三個(gè)反引號(hào)出現(xiàn)代碼塊才結(jié)束。這種錯(cuò)誤的特征是排版突然變成等寬字體、所有 Markdown 標(biāo)記全部失效。排查時(shí)只要上下找找漏掉的那行圍欄就行。另一個(gè)常見問(wèn)題是語(yǔ)言標(biāo)注寫錯(cuò)。不寫語(yǔ)言標(biāo)注并不影響渲染但會(huì)失去高亮閱讀體驗(yàn)差一截。標(biāo)注語(yǔ)言時(shí)用規(guī)范的小寫名稱比如javascript、python、bash、json不同平臺(tái)支持的語(yǔ)法高亮器略有差異但通用名基本都能識(shí)別。3.3 縮進(jìn)代碼塊老式寫法的優(yōu)缺點(diǎn)除了圍欄代碼塊還有一種更原始的方式每行前縮進(jìn)四個(gè)空格或一個(gè)制表符。這是一個(gè)縮進(jìn)代碼塊 內(nèi)容放在四個(gè)空格之后 第二行也在縮進(jìn)里這種寫法的優(yōu)點(diǎn)是簡(jiǎn)潔缺點(diǎn)也很明顯無(wú)法指定語(yǔ)言高亮在列表里很難控制縮進(jìn)層級(jí)。如果你在列表項(xiàng)里需要再放代碼塊縮進(jìn)會(huì)變得層層疊疊極易出錯(cuò)。所以現(xiàn)在的主流平臺(tái)幾乎都不再推薦這種寫法了但你在閱讀老文檔時(shí)還是可能會(huì)遇到需要知道它是什么。我的原則很簡(jiǎn)單能用圍欄代碼塊就不用縮進(jìn)代碼塊尤其是寫正式文檔時(shí)可讀性和高亮效果都明顯更好。4. 搭建日常寫作流程編輯、渲染與管理學(xué)會(huì)了標(biāo)記語(yǔ)法之后真正決定效率的是工作流。不會(huì)用工具語(yǔ)法學(xué)得再熟也白搭。這一節(jié)我會(huì)講講怎么圍繞 Markdown 搭建一套順手的工作流包括編輯器選擇、圖片管理、目錄生成和版本沉淀。4.1 編輯器選擇思路市面上的 Markdown 編輯器很多各有偏向但選擇時(shí)主要看三條編輯體驗(yàn)、渲染預(yù)覽、擴(kuò)展能力。如果你追求所見即所得可以選那些“實(shí)時(shí)渲染”型的編輯器左側(cè)是源碼右側(cè)是渲染預(yù)覽也有的編輯器直接輸入即渲染光標(biāo)所在行顯示源碼其他行顯示效果。這類編輯器對(duì)新手很友好犯錯(cuò)時(shí)會(huì)立刻看到異常效果調(diào)試起來(lái)快。如果你更喜歡代碼風(fēng)格可以考慮用代碼編輯器加 Markdown 插件的方式。這樣做的優(yōu)勢(shì)是你只需要熟悉一個(gè)編輯器就夠不用在多個(gè)工具之間切來(lái)切去而且代碼編輯器里的 Git 集成、文件樹、全局搜索等能力都很成熟對(duì)管理一大套文檔非常順手。如果你是重度筆記用戶那就直接選一款筆記軟件。它們通常自帶云同步、全文檢索、標(biāo)簽體系這些功能對(duì)寫零散知識(shí)記錄很有幫助。不管選哪類我都建議你一定試一下它的導(dǎo)出能力有的工具導(dǎo)出 PDF 時(shí)樣式混亂有的導(dǎo)出圖片會(huì)丟相對(duì)路徑這些問(wèn)題在選定工作流之前發(fā)現(xiàn)比等到交付文檔時(shí)才措手不及要好得多。4.2 圖片文件管理方案圖片是文檔里最容易出問(wèn)題的一環(huán)。我早期寫文檔時(shí)喜歡直接把圖片拖進(jìn)編輯器編輯器會(huì)自動(dòng)生成一份本地文件但目錄結(jié)構(gòu)一團(tuán)糟圖片名字也是隨機(jī)生成的根本看不出哪張圖對(duì)應(yīng)哪段內(nèi)容。后來(lái)我固定了一套方案每個(gè)項(xiàng)目建立獨(dú)立的目錄如assets/圖片命名要有語(yǔ)義比如login-dialog-error.png文中引用一律使用相對(duì)路徑如同一項(xiàng)目?jī)?nèi)所有相對(duì)路徑以項(xiàng)目根目錄為基準(zhǔn)文件夾移動(dòng)時(shí)同步調(diào)整這套辦法看起來(lái)很簡(jiǎn)單但它解決了一個(gè)真實(shí)痛點(diǎn)項(xiàng)目變多以后你不需要打開圖片看內(nèi)容光看文件名和引用位置就能知道文檔在說(shuō)什么。對(duì)協(xié)同伙伴來(lái)講也友好他們拿到整個(gè)項(xiàng)目文件夾打開文檔時(shí)所有圖片都能正常顯示不需要額外問(wèn)路徑。4.3 生成目錄和錨點(diǎn)跳轉(zhuǎn)有些寫作場(chǎng)景要求開頭有個(gè)目錄結(jié)構(gòu)尤其是長(zhǎng)文檔。Markdown 生成目錄有兩種方式自動(dòng)和手動(dòng)。自動(dòng)目錄由渲染器提供一般在文檔中插入一個(gè)占位標(biāo)記渲染時(shí)自動(dòng)掃描所有標(biāo)題生成目錄。這種方式適合平臺(tái)和工具支持能力強(qiáng)的場(chǎng)景改標(biāo)題后目錄會(huì)跟著更新幾乎不用維護(hù)。手動(dòng)目錄是手寫的鏈接列表指向各標(biāo)題的錨點(diǎn)。Markdown 渲染 HTML 時(shí)標(biāo)題會(huì)自帶錨點(diǎn)鏈接到錨點(diǎn)的方法在 2.5 節(jié)提過(guò)[文字](#鏈接目標(biāo))。不過(guò)不同平臺(tái)對(duì)中文錨點(diǎn)的處理策略不同有的自動(dòng)轉(zhuǎn)拼音有的保留中文有的忽略大小寫和空格。手寫錨點(diǎn)時(shí)最穩(wěn)的做法是先去預(yù)覽頁(yè)面里復(fù)制實(shí)際生成的錨點(diǎn)地址拿來(lái)直接用不要憑想象寫。我個(gè)人更傾向于自動(dòng)生成目錄。原因很直白文檔經(jīng)常要改標(biāo)題手寫目錄表同步更新很容易遺漏而自動(dòng)目錄不會(huì)出這種問(wèn)題。維護(hù)成本低出錯(cuò)率低長(zhǎng)期看一定更劃算。4.4 配合版本管理沉淀資產(chǎn)最后想提一下版本管理。如果你寫的是項(xiàng)目文檔強(qiáng)烈建議把 Markdown 文檔目錄一起納入版本管理。這樣每次改動(dòng)都有記錄時(shí)間久了可以回溯也可以對(duì)比不同版本之間內(nèi)容的變化。Markdown 是純文本差異對(duì)比非常清晰哪個(gè)詞被改了、哪一段被刪了都?xì)v歷在目。這個(gè)習(xí)慣在合作場(chǎng)景下價(jià)值更大。幾個(gè)人同時(shí)維護(hù)一份文檔版本合并的沖突提示非常直觀Markdown 不像二進(jìn)制文件那樣需要專業(yè)工具才能解析直接用文本對(duì)比工具就能解決大部分沖突。我講一個(gè)真實(shí)的體會(huì)曾經(jīng)有一次合作者改完文檔后不小心刪掉了一整節(jié)內(nèi)容但因?yàn)槲臋n在版本管理里幾分鐘就找回了舊版本避免了返工。5. 常見問(wèn)題與排查技巧實(shí)錄很多人學(xué)完語(yǔ)法就開始寫但寫著寫著會(huì)遇到各種奇怪的現(xiàn)象感覺好像哪兒都不對(duì)。這一節(jié)我把實(shí)際使用里最常遇到的問(wèn)題和排查思路整理成速查式的列表你遇到類似情況時(shí)可以直接對(duì)照。5.1 換行不生效這是被問(wèn)得最多的問(wèn)題。很多新手在 Markdown 里寫完一段后直接按一次回車渲染出來(lái)發(fā)現(xiàn)和上一段擠在一起。原因在于Markdown 中單個(gè)換行符在大多數(shù)平臺(tái)上會(huì)被當(dāng)作普通空格處理只有空一行才能表示段落換行。這是一個(gè)歷史遺留約定但今天幾乎所有主流渲染器都會(huì)這樣處理。解決辦法有三個(gè)段落之間空一行在行尾加兩個(gè)空格再換行或者直接使用 HTML 的br標(biāo)簽。我最推薦的是空一行它語(yǔ)義最清晰源碼也更整潔。行尾加空格是個(gè)隱藏技巧肉眼幾乎看不出來(lái)在編輯文檔時(shí)容易造成誤解。br適合不想分段、只想強(qiáng)制斷行的情況但盡量少用因?yàn)樗鼤?huì)破壞純文本的可讀性。5.2 表格錯(cuò)亂表格渲染異常十有八九是管道符數(shù)量不統(tǒng)一。當(dāng)你看到表格幾行單元格錯(cuò)位、多出一列或者直接漏掉內(nèi)容時(shí)先逐行數(shù)管道符。管道符數(shù)量一致是對(duì)齊的底線。另一個(gè)坑是表頭分隔行缺失。沒有第二行| --- |渲染器就不會(huì)把后續(xù)內(nèi)容當(dāng)表格而是當(dāng)普通段落文字處理。有些新手以為只要用管道符分隔了內(nèi)容就能自動(dòng)生成表格其實(shí)不對(duì)表頭分隔行才是觸發(fā)表格渲染的開關(guān)。5.3 列表里嵌代碼塊失效在列表項(xiàng)里放代碼塊縮進(jìn)層級(jí)是一個(gè)大坑。列表項(xiàng)后面的內(nèi)容要縮進(jìn)到和列表內(nèi)容相同的層級(jí)否則會(huì)被拍平成列表外的內(nèi)容。最典型的場(chǎng)景- 第一項(xiàng) python print(hello)這里的代碼塊前面直接縮進(jìn)兩個(gè)空格是配合列表項(xiàng)內(nèi)容對(duì)齊的。如果你把代碼塊頂格寫渲染時(shí)代碼塊會(huì)直接跳出列表位置錯(cuò)亂。我的建議是遇到復(fù)雜列表內(nèi)嵌代碼的情況優(yōu)先考慮把代碼塊和列表拆開各自獨(dú)立成塊。形式上的嵌套好看但維護(hù)起來(lái)很容易出問(wèn)題。文檔的第一要?jiǎng)?wù)是內(nèi)容清晰而不是源碼精美。 ### 5.4 圖片要么不變大要么不居中 圖片占不滿寬度、沒法居中是另一個(gè)高頻問(wèn)題。原生 Markdown 圖片語(yǔ)法不提供尺寸和位置控制這在寫正式文檔時(shí)尤為頭疼。多數(shù)平臺(tái)的渲染器會(huì)保留圖片原始尺寸除非你在圖片地址后跟了尺寸設(shè)置但不同平臺(tái)的擴(kuò)展語(yǔ)法格式不一通用性很差。 我的做法是直接用 HTML 的 img 標(biāo)簽代替。雖然它帶一點(diǎn)樣式味道但幾乎所有接近完整的渲染引擎都支持。寫正式文檔時(shí)圖片寬度設(shè)置為 100% 是相當(dāng)常見的處理方式它能保證圖片在不同屏幕寬度下自適應(yīng)不會(huì)被原始分辨率限制。 另外要注意HTML 標(biāo)簽在 Markdown 里只寫一行前后不要有多余空行否則某些嚴(yán)格模式下的渲染器會(huì)把 HTML 標(biāo)簽單獨(dú)識(shí)別為段落塊導(dǎo)致布局出現(xiàn)意外空白。 ### 5.5 不同平臺(tái)顯示效果不一樣 同一個(gè) Markdown 文件在編輯器和博客平臺(tái)上的渲染效果可能天差地別。原因在于并不存在一個(gè)官方權(quán)威的 Markdown 規(guī)范各家實(shí)現(xiàn)都是在一個(gè)共同子集上做擴(kuò)展。兼容性問(wèn)題的根源在這里。 我的經(jīng)驗(yàn)是優(yōu)先寫“通用子集”語(yǔ)法也就是絕大多數(shù)渲染器都能正確解析的那部分。遇到漂亮的擴(kuò)展語(yǔ)法時(shí)先想清楚這份文檔只在當(dāng)前平臺(tái)看還是以后可能遷移如果要遷移擴(kuò)展語(yǔ)法能不用就不用。進(jìn)階用法在交付外部文檔時(shí)尤其要克制。 還有一個(gè)很實(shí)用的小技巧發(fā)布前在至少兩款不同的渲染器里預(yù)覽一遍。如果兩款都能正常渲染基本就不會(huì)出大問(wèn)題。如果只有一款正常趕緊找出問(wèn)題源頭的語(yǔ)法不要等到讀者反饋才發(fā)現(xiàn)。 ## 6. 用 Markdown 寫作的長(zhǎng)期習(xí)慣 寫了這么久我對(duì) Markdown 最深的體會(huì)是它沒有綁定任何一家公司的生態(tài)也沒有特定的軟件限制。它的形態(tài)極其簡(jiǎn)單以至于幾乎不可能被淘汰。我剛接觸時(shí)覺得這不過(guò)是給技術(shù)人員準(zhǔn)備的排版工具后來(lái)慢慢發(fā)現(xiàn)它其實(shí)在改變寫作習(xí)慣本身——你開始把注意力放在結(jié)構(gòu)和內(nèi)容上而不是讓格式牽著鼻子走。 如果現(xiàn)在讓我給剛開始用 Markdown 的人提一個(gè)建議我不會(huì)推薦某款編輯器也不會(huì)上來(lái)就布置一堆高級(jí)語(yǔ)法任務(wù)而是建議從今天開始找一篇你最近要寫的文檔強(qiáng)迫自己用 Markdown 寫完整。第一次肯定會(huì)不習(xí)慣會(huì)頻繁查看語(yǔ)法會(huì)忘記空行會(huì)把表格寫散架。這些都是正常的寫兩三篇之后就會(huì)順暢起來(lái)。到那時(shí)候你再回頭看傳統(tǒng)排版工具會(huì)很自然地明白為什么這么多人離不開它。 至于進(jìn)階方向等你基礎(chǔ)牢固了可以試試模板化寫作、主題樣式定制、甚至自己寫一個(gè)小腳本批量轉(zhuǎn)換文檔。但這些都是后話。先把 # 和 * 這些最基礎(chǔ)的符號(hào)用順比什么技巧都重要。