
選Markdown在線編輯器這件事看著是選工具其實是在選一條渲染鏈路。我過去一年里在各種編輯器之間來回搬文檔光Markdown文件就存了好幾百份最后真正讓我頭疼的不是打字手感而是同一個文件在A站點渲染正常、到B站點樣式全丟、導出PDF又跑版。這篇文章我把選型思路、渲染管線里最容易踩的3個坑以及Markdown轉PDF時那些“看著小事、改起來要命”的排版問題一次性拆開講清楚。想省時間的可以直接跳到第4章的速查表想搞明白背后原理的建議從頭看。1. 在線Markdown編輯器怎么選先想清楚這三件事1.1 第一件事編輯內核決定輸入體驗但渲染端才決定輸出結果很多人在選編輯器時只看界面好不好看、支不支持實時預覽其實這里有個經常被忽略的分工編輯區(qū)和渲染區(qū)是兩套完全獨立的東西。編輯區(qū)負責的是“寫”常見的內核有CodeMirror、Monaco Editor這類它們負責光標、縮進、代碼高亮、自動補全。寫Markdown的人對這塊感知最強的就是表格對齊、代碼塊縮進、列表自動續(xù)行是否順手。以我的實際體驗來說Monaco在代碼塊編輯上更接近VSCode的手感CodeMirror則更輕更流暢但這兩者差異并不會影響最終產物。渲染區(qū)負責的是“讀”也就是把你寫的那串帶井號、星號、橫線的純文本變成帶標題層級、加粗斜體、代碼高亮的頁面。不同編輯器在這一步的差距非常大而這一步恰恰決定了你“看到的樣子”是不是文檔的真正樣子。選型時先問自己一個問題我主要在哪里看渲染效果如果寫技術文檔渲染區(qū)和線上文檔站點的效果是否一致如果用在線編輯器寫完后要復制到公眾號、知乎、語雀那渲染結果會不會被平臺再處理一遍很多人踩坑都是因為忽略了這個問題把在線編輯器當成“所見即所得”工具最后發(fā)現它的渲染結果根本不能代表最終效果。1.2 第二件事渲染規(guī)范是“共同語言”不認GFM的編輯器會坑哭你Markdown看似簡單實際上存在多套規(guī)范版本。最原始的CommonMark是基礎版但很多常用語法它并不支持比如表格、刪除線、任務列表、自動鏈接。而現在大家在日常寫作中最常用的其實是GitHub Flavored Markdown也就是GFM。GFM是在CommonMark基礎上擴展出來的方言它加入了表格、任務列表、刪除線、錨點跳轉等實用功能。絕大多數主流編輯器比如Typora、語雀、Notion、Obsidian、StackEdit都是按GFM或者GFM超集來渲染的。但問題來了不同編輯器對GFM的支持程度并不一致。有的編輯器不認GFM只支持CommonMark那么你辛辛苦苦寫的表格在編輯器里不會渲染成表格而會變成一堆管道符和短橫線有的編輯器干脆把表格當作HTML解析遇到特殊符號就斷行。我自己就遇到過寫任務列表- [ ] 待辦在A工具里顯示成復選框粘貼到B工具里直接變成三個字符[ ]跑在正文里的情況非常離譜。所以選型時要確認清楚編輯器支持哪套規(guī)范最好直接拿一段包含表格、刪除線、任務列表、多級列表、嵌套代碼塊的測試文檔同時丟進去比一比渲染結果這比看宣傳頁上的“支持GFM”五個字靠譜得多。1.3 第三件事導出能力不是附加項是選型的硬指標Markdown文件本身是純文本這意味著它天然適合跨平臺傳播版本管理也方便。但問題是不是所有人都愿意或者能夠直接閱讀Markdown源碼絕大多數場景下你得把Markdown轉成PDF、Word或者HTML交給別人。這就涉及導出能力。不同在線編輯器的導出能力差距極大有的只能導出HTML導出的PDF要自己用瀏覽器打印有的PDF導出實際上是“打印網頁”支持程度取決于瀏覽器有的走Pandoc后端導出理論上支持任意格式但實際效果和主題模板強相關有的干脆不支持導出只能在網頁里看。我建議選型時把導出能力放在和編輯體驗同等重要的位置上來考慮。你可以問自己幾個問題導出PDF時能不能自定義頁邊距中文字體是否正常代碼塊會不會被截斷表格會不會超出頁面范圍這些在后面的章節(jié)里會詳細展開。我給一個非常樸素的選型建議如果你的主力需求是本地寫作、偶爾導出Typora仍然是最順手的工具之一如果是在線協(xié)作、實時共享Notion、語雀這類偏產品的編輯器更好用如果是寫技術文檔且要進代碼倉庫那VSCode加Markdown Preview Enhanced插件才是真正的歸宿因為它把渲染和導出都交給了同一個后端減少了很多不必要的轉換損耗。2. 渲染管線的3個坑同一個md為什么到哪都不一樣2.1 渲染管線到底是什么markdown到頁面要經過幾個環(huán)節(jié)很多人把Markdown到頁面看成一步到位實際上它是一條完整的管線Markdown源碼先被解析成AST也就是抽象語法樹然后由HTML渲染器生成HTML字符串接著由瀏覽器或Electron容器把HTML解析成DOM再套用CSS樣式完成最終頁面渲染。這條鏈路里的每一個環(huán)節(jié)都可能改變最終結果。AST階段決定“哪些語法被識別”HTML渲染器決定“識別之后生成什么結構”瀏覽器決定“結構和樣式怎么結合”。三個環(huán)節(jié)里任何一個出現差異你看到的頁面就會不一樣。這也是為什么同一個Markdown文件在Typora里面渲染是一個樣子在語雀里面又是一個樣子到了瀏覽器Markdown預覽插件里又變成第三個樣子。不是誰做錯了而是它們各自渲染管線的參數和過濾規(guī)則不一樣。我這樣類比Markdown源碼是一份菜譜AST解析相當于翻譯成廚師能看懂的操作步驟HTML渲染器相當于按步驟把菜做出來CSS樣式則是擺盤。步驟翻譯不同、做菜火候不同、擺盤風格不同最后端上桌的菜自然不一樣。2.2 坑一規(guī)格混戰(zhàn)GFM和CommonMark之間差了一個表格這是最常見也最隱蔽的坑。很多在線編輯器會標榜自己支持GFM但細看它的渲染結果其實只支持CommonMark加表格其他擴展語法一個也沒跟上。我實際踩過的一個例子是用某在線編輯器寫包含多行表格的Markdown文檔表格里有|符號和反斜杠轉義在源碼里看完全正常預覽時表格卻直接裂開——有的行識別成了普通段落有的行錯位。查了半天發(fā)現那個編輯器用的解析器是marked的舊版本舊版的表格解析對反斜杠轉義支持不友好遇到特殊字符就原樣輸出。還有一個更隱蔽的問題是任務列表。GFM規(guī)范里任務列表是把[ ]和[x]放在列表項的開頭但某些編輯器只識別小寫x不識別大寫X甚至只識別[ ]和[x]無法識別[X]。如果你用大寫X標記已完成渲染出來仍然是未勾選狀態(tài)。我的建議是平時寫文檔盡量用GFM規(guī)范但別把某個編輯器對GFM的“宣傳支持”當成“完整支持”。最穩(wěn)妥的辦法是準備一份語法自檢測試平時寫長文檔時每隔幾段就切到源碼模式看一眼。不要只在預覽模式里寫那會讓你以為一切正常實際上渲染結果很可能是錯誤的。2.3 坑二過濾規(guī)則不同HTML和樣式被靜默吞掉Markdown允許內嵌HTML這是它的一個重要特性但也帶來一個問題在網頁環(huán)境里瀏覽器出于安全考慮會對HTML進行過濾尤其是script標簽、事件屬性和危險的CSS表達式。這種過濾機制每個團隊實現得不一樣有的過濾程度很嚴格有的則相對寬松。我在使用在線編輯器時就遇到過這種情況為了給某段文字加個自定義樣式在Markdown里寫了一段span stylecolor:red警示/span結果預覽時樣式直接消失了既不報錯也不提示就像那段HTML被靜默吞掉了一樣。后來才發(fā)現那個編輯器為了防XSS對所有內聯樣式做了白名單過濾color屬性不在白名單里整個span標簽被剝成了純文本。這種靜默失敗是非??尤说?。因為從源碼看一切正常從預覽看好像也沒太大異常但你期望的紅色文字就是不會出現。更麻煩的是如果你把這段Markdown復制到另一個編輯器里過濾規(guī)則不一樣這段HTML可能又被原樣渲染出來了。所以在不同編輯器之間遷移文檔時帶有自定義HTML的段落一定要重點檢查。要想避開這個坑分兩步第一步寫作時盡量避免依賴內嵌HTML和自定義樣式Markdown本身提供的語法足夠覆蓋99%的排版需求第二步如果確需自定義樣式可以先把內容在本地編輯器里確認渲染效果再往在線編輯器里粘粘完后切到預覽模式和源碼模式對比看別嫌麻煩。2.4 坑三容器樣式繼承換個主題就變“另一篇文檔”這個問題很多人沒意識到但它的殺傷力比前兩個都大。每個編輯器都有自己的預設CSS包括默認字體、標題大小、行高、代碼塊背景色、引用塊的左邊框顏色、表格的邊框樣式。這些樣式通常隱藏在主題里你寫文檔時看到的排版效果其實是“你的內容這個主題的CSS”共同作用的結果。一旦換主題或者把內容粘貼到另一個渲染環(huán)境里你的文檔看起來就會完全不一樣。我舉個具體例子在A工具里三級標題顯示為18像素、加粗、帶下劃線粘貼到B工具里三級標題變成22像素、加粗、但顏色變成了主題藍。你原來的“第三層標題”在視覺上可能變得比第二層還大整個層級感就亂了。更隱蔽的是代碼塊。每個編輯器對代碼塊的默認字體、背景色、行號顯示、滾動條樣式都不同代碼塊里的中文換行行為也不一樣。我在某個在線編輯器里寫的代碼塊粘貼到另一個工具后長行直接被折行顯示完全不能看。查了半天才發(fā)現是代碼塊容器的white-space屬性不同導致的。要解決這個問題最好的辦法是不要依賴編輯器的主題樣式來傳達文檔結構。也就是說標題層級的意義應該由Markdown語法本身來保證而不是由某個主題下的視覺效果來保證。在選編輯器時盡量選擇主題之間差異較小的或者選能導出為標準CSS的工具這樣至少在不同環(huán)境之間遷移時樣式損失會更小。3. md轉PDF跑版記錄那些年我們追過的頁邊距3.1 一次真實的跑版事故表格飛出頁面代碼塊被攔腰截斷先說一個我最近遇到的真實案例。有一個技術文檔項目里面用Markdown寫了一份三十多頁的接口說明內容包括大量代碼塊、接口表格和流程圖。項目經理要求輸出一份PDF版本放在歸檔系統(tǒng)里。我用在線編輯器直接導出PDF第一次跑版就來了一張六列接口參數表直接超出頁面邊界最右邊的兩列內容被硬生生裁掉連滾動條都沒有因為PDF是靜態(tài)頁面。更麻煩的是表格中間一行恰好跨到了下一頁表頭沒有重復那一行數據被切成兩半看著就像文檔印錯了。代碼塊的問題更突出。一段很長的JSON配置樣例在頁面上顯示得好好的導出PDF后代碼塊每行都在中間位置斷開換行縮進完全錯亂有的行末尾還被截斷。我用瀏覽器打印功能重新導了一次雖然代碼塊不斷行了但代碼塊和正文之間的分頁又不對了——有的代碼塊直接從頁面底部被切掉半截可讀性非常差。這就是典型的PDF跑版問題。它不是某一個編輯器的問題而是Markdown到PDF轉換過程中三個環(huán)節(jié)的銜接出了問題解析階段沒處理好Markdown結構樣式階段沒適配打印頁面排版階段沒有考慮分頁細節(jié)。3.2 排查路徑先區(qū)分機器問題、解析問題還是布局問題遇到PDF跑版時不要急著換工具先按這個思路排查先確認是不是解析問題再確認是樣式問題最后才是布局問題。第一步先在編輯器里確認Markdown源碼是否能正確渲染成HTML。如果連預覽都跑版那就是解析階段的問題換導出工具也沒用得改源碼或者換編輯器。第二步如果預覽正常導出PDF跑版就要看導出工具是怎么工作的。有的工具是直接對預覽頁面執(zhí)行打印有的是先轉HTML再轉PDF還有的是走Pandoc轉LaTeX再生成PDF。這三種路線的渲染邏輯完全不同跑版原因也各不相同。比如我遇到的那個表格超出頁面邊界的問題就是典型的布局問題——HTML表格默認不會自動縮放列寬來適應頁面寬度如果列太多就會溢出頁邊距。這跟瀏覽器打印時沒有對表格應用合適的CSS樣式有很大關系。第三步確認跑版是全局性的還是局部性的。全局性的比如所有中文都亂碼、所有頁邊距都異常通常是主題或者渲染工具配置的問題局部性的比如某個表格跑版、某段代碼被截斷通常是內容本身和布局規(guī)則沖突。按這個思路排查能省下大量瞎試的時間。推薦一個很實用的工具組合先用VSCode的Markdown Preview Enhanced插件把Markdown導出為HTML再用瀏覽器打印成PDF。這樣至少能分辨出問題到底是出在Markdown解析階段還是PDF布局階段。3.3 三條主流導出路徑的實測心得目前Markdown轉PDF的主流路徑有三條我分別說下實測心得。第一條是“在線編輯器自帶導出”。這類導出大多是網頁打印優(yōu)點是方便缺點也很明顯——頁邊距、紙張大小、打印縮放全都由編輯器預設了用戶可控參數非常少。適合快速出小文檔不適合正式交付。我一般只在文件三頁以內、格式要求不高時用。第二條是“VSCode插件導出”。網上很多教程會提到VSCode里要把Markdown導出為PDF需要下載安裝PrinceXML然后通過Markdown Preview Enhanced插件調用PrinceXML來生成PDF。這個說法是對的但容易讓人誤會以為不裝PrinceXML就不能導出。實際上Markdown Preview Enhanced有多種導出方式可以直接用Chrome打印也可以借助Pandoc轉成PDFPrinceXML只是其中一種可選路徑。PrinceXML的特點是排版引擎非常成熟生成的PDF質量很高對CSS的支持遠比瀏覽器打印好表格分頁、頁邊距控制、頁眉頁腳這些細節(jié)都支持得很好。但是它是商業(yè)軟件非商業(yè)用途免費商用需要購買授權。如果你在VSCode里導出PDF時遇到了“ requires princexml ”之類的提示并且需要商用建議直接用Chrome打印替代效果也不會差太多。第三條是“本地裝Pandoc加LaTeX引擎”。這是最強大但門檻也最高的一條路。Pandoc能把Markdown轉成PDF中間默認走LaTeX引擎。LaTeX能處理幾乎所有排版細節(jié)包括中文排版、頁邊距、表格分頁、代碼塊跨頁但你需要安裝對應字體和宏包第一次配置往往要折騰幾個小時。我個人的建議是如果你需要頻繁生成正式PDF文檔這個方案值得認真配一次如果只是偶爾導出用Chrome打印就足夠了。3.4 中文排版專項字體、換行和“孤兒標點”很多人以為Markdown轉PDF跑版是解析問題結果折騰半天發(fā)現是中文排版根本沒被處理。中文排版的坑和英文完全不一樣我單獨拎出來說。第一個坑是字體缺失。很多導出工具默認字體是英文的遇到中文就會回退到系統(tǒng)默認字體效果千奇百怪。有的環(huán)境回退到宋體但字重不對有的回退到黑體但字間距過大最離譜的是有些環(huán)境直接當成亂碼處理。所以在導出PDF之前一定要在導出設置里檢查中文字體配置確保指定了系統(tǒng)中存在的中文字體比如Microsoft YaHei、PingFang SC、Noto Sans CJK SC。第二個坑是換行規(guī)則。中文默認是無空格書寫每行文字之間沒有天然斷點。PDF布局引擎在排版時會對中文按字符寬度折行但如果在長英文單詞或者URL附近折行位置就會變得非常難看。更麻煩的是引用塊或者列表項里換行后的縮進對不齊。第三個坑是“孤兒標點”就是行首出現逗號、句號、引號、括號這類標點。中文排版規(guī)范要求行首不能出現這些標點但很多PDF生成引擎不會自動處理。要解決這個問題最簡單的方法是選對引擎——Pandoc加XeLaTeX引擎默認處理得比較好PrinceXML對中文標點壓縮也處理得相當不錯。瀏覽器打印在這方面表現不一如果遇到行首標點問題可以試試調整頁面縮放比例或者換一個打印引擎。4. 常見問題速查表與我的避坑清單4.1 高頻問題速查表我把自己在Markdown編輯和轉PDF時踩過的高頻問題整理成了一個速查表方便你直接對照排查現象大概率原因解決思路表格超出頁面邊界HTML表格默認不自動收縮列寬打印時沒有額外的表格CSS導PDF前先導出HTML在HTML里加table { width: 100%; table-layout: fixed; }表格跨頁后表頭不重復打印樣式沒有設置thead重復展示在打印CSS里設置表格頭部行屬性若用Pandoc導出則檢查LaTeX模板代碼塊被攔腰截斷分頁時沒有對pre、code設置分頁避讓規(guī)則打印CSS加pre { page-break-inside: avoid; }或使用支持該規(guī)則的導出引擎代碼塊長行折行white-space屬性被設置為normal或pre-wrap檢查打印CSS將code的white-space設為pre并開啟橫向滾動或橫向分頁中文變成亂碼或字體失真導出環(huán)境缺少中文字體或指定的字體名不存在在導出工具里顯式指定系統(tǒng)中存在的中文字體必要時安裝Noto Sans CJK SC行首出現逗號句號PDF排版引擎不支持中文標點擠壓規(guī)則換用XeLaTeX引擎或PrinceXML導出瀏覽器打印則嘗試調高打印縮放相同文檔在不同工具渲染結果不同各工具對應的Markdown解析器版本和擴展語法支持不同遷移文檔時重點檢查表格、任務列表、刪除線、內嵌HTML這四類語法編輯器預覽和導出PDF效果不一致預覽頁面應用的是屏幕樣式PDF應用的是打印樣式在CSS里單獨為media print優(yōu)化排版規(guī)則這里尤其要提醒一下表格寬度問題這是跑版重災區(qū)。如果你經常用Markdown寫表格建議養(yǎng)成一個習慣表格列數不超過四列列內容盡量簡短。如果確實需要寬表格優(yōu)先考慮拆表或者改成列表形式而不是硬塞進PDF。4.2 選型與遷移前的檢查清單在把大量文檔寫進某個編輯器之前先把這套檢查清單過一遍能省下后續(xù)很多遷庫的麻煩第一檢查語法兼容性。拿一段包含標題、列表、表格、代碼塊、引用、刪除線、任務列表、腳注的測試文檔在候選編輯器里逐個渲染截圖對比。這個過程半小時就夠但能幫你篩掉一半不靠譜的工具。第二檢查導入導出閉環(huán)。相當于要確認兩個方向一是把這個編輯器導出的HTML或PDF重新粘貼到其他平臺格式是否保持二是把其他平臺復制的富文本粘貼到編輯器是否能自動轉成Markdown。很多編輯器只做了導出或只做了導入閉環(huán)能力弱長期使用會很難受。第三檢查存儲格式。在線編輯器的數據是存在云端數據庫里的還是能導出標準的.md文件這個直接關系到你的數據自由。建議選擇能導出標準Markdown文件的編輯器并且養(yǎng)成定期導出備份的習慣。第四檢查渲染延遲和性能。文檔超過幾千行時拖動滾動條是否卡頓長表格能否流暢滾動代碼高亮是否正常有些編輯器在短文檔時表現良好長文檔一寫就卡這是內核層面的問題靠設置解決不了。遷移老文檔時我建議分三批遷移先遷一批格式最簡單的確認基本流程沒問題再遷一批帶表格和代碼塊的排查擴展語法兼容性最后遷一批含圖片和特殊符號的確認資源引用路徑是否有效。4.3 我的幾條私藏經驗最后分享幾條我在實際操作中積累的經驗這些不會寫在官方文檔里但真的很實用。第一長文檔轉PDF前一定先導出一份HTML做“中間檢查”。Markdown到PDF是兩步轉換插一層HTML能讓你輕松分辨跑版到底發(fā)生在哪一步。導出HTML后用瀏覽器打開看一眼目錄結構對不對、表格寬度是否正常再決定要不要繼續(xù)轉PDF。這一步能幫你節(jié)省大量試錯時間。第二PDF導出前清空不必要的自定義HTML。我在第2章提過不同編輯器的HTML過濾規(guī)則不一樣。導PDF時如果你在Markdown里嵌入了大量自定義HTML和行內樣式很容易在轉換過程中出現意外。不是不能用而是要在導出前檢查一遍發(fā)現問題逐一排查不要在轉換工具上反復調參。第三頁邊距是MD轉PDF最重要的參數。很多跑版根本不是渲染問題而是頁邊距太小。我用Pandoc導出時默認頁邊距是2.5厘米左右夠用但用瀏覽器打印時默認頁邊距可能只有1厘米甚至0.5厘米表格稍微寬一點就會貼著頁邊。建議統(tǒng)一設置成上下2.5厘米、左右2厘米適配大多數場景。第四寫文檔時就要想著“將來要導出PDF”。這是最根本的一條經驗。Markdown寫作時盡量用規(guī)范語法少依賴某個編輯器的私有擴展代碼塊里不要寫超長的單行文本表格不要塞太多列圖片設置好相對路徑和高度。這樣不管以后換什么工具都不會太痛苦。我在實際使用中的體會是沒有完美的Markdown編輯器只有適合自己工作流的編輯器。你把大量內容寫進一個封閉編輯器之前先花半小時測清楚它的渲染規(guī)范和導出能力遠比你寫了幾百個文件之后再來遷移劃算得多。如果你現在正在選型不妨就拿這篇里面的測試清單去試一圈相信你很快就能判斷哪個工具和你合拍。