多年來,我每個工作日都會編寫 Markdown - 外掛程式自述文件、變更日誌、文件 工具。dev,發布 WP Adminify 的註釋,我一半的提交訊息。在那段時間的大部分時間裡,我把渲染步驟視為魔法。你寫星號,GitHub 顯示粗體。美好的。繼續前進。
然後我建立了一個文檔部分,將 Markdown 從資料庫中刪除並將其渲染到 Next。js 頁面中,魔力變成了我必須做出的非常具體的決定的清單。一條換行符會變成a嗎 <br>? (GitHub 評論說是。Markdown 規範說不是。)確實如此 <div> 在來源渲染中作為 div 或文字? (取決於誰在問,以及您是否信任作者。)什麼類別會出現在圍欄程式碼區塊上,以便螢光筆拾取它?為什麼一個解析器會轉動 **bold**text 變成粗體而另一個則不管它?
這些都不是異國情調。這只是沒人告訴你的事情,因為 Markdown 看起來很簡單,人們會認為它下面什麼都沒有。它下面有很多。這 標記到 HTML toolz。dev 上的轉換器將這些決策公開為開關而不是隱藏它們,這是我在調試為什麼我的換行符不斷消失時想要的該工具的版本。
TL;DR: Markdown 是一種書寫格式; HTML 是顯示格式。必須將一個編譯成另一個。使人們陷入困境的規則:連續行加入一個段落,除非您用兩個空格結束一行(或打開 "breaks"選項),原始 HTML 要么通過,要么轉義,具體取決於解析器'信任設置,以及 GitHub's 方言 (GFM) 在上面新增表格、任務清單、刪除線和裸 URL 自動連結 通用標記 基線。圍欄代碼編譯為
<pre><code class="language-js">,這是鉤子棱鏡,突出顯示。js 和 Shiki 尋找。這 標記為 HTML 轉換器 在瀏覽器中執行所有這些操作,並公開每個開關。
什麼是 Markdown?為什麼它需要轉換?
Markdown 是 John Gruber 於 2004 年發布的一種純文字語法,有一個明確的設計目標:Markdown 文件應該可以按原樣發布,可以作為純文字閱讀,而不看起來已經標記了標籤。這就是為什麼語法借鑒了人們在電子郵件中已經使用的約定--強調單字周圍的星號,標題下的一行破折號,a > 報價。
結果是 Markdown 不是渲染格式。沒有任何內容顯示 Markdown。瀏覽器顯示 HTML 以及您曾經擁有過的每個位置 看見了 渲染的 Markdown - GitHub、靜態網站、文件入口網站、聊天應用程式 - 首先運行解析器並將 HTML 放在螢幕上。
所以轉換必須發生在某個地方。你的選擇大致是:
- 在建造時間,在靜態網站產生器或捆綁器中。當內容駐留在您的回購中時,效果很好。
- 在要求的時間,在伺服器上。當內容來自資料庫時是必要的,如果您在不快取的情況下對每個請求執行此操作,則成本高昂。
- 在瀏覽器中,此時此刻你需要它。這就是你想要的答案"我只需要 HTML 即可完成這一件事"是複製貼上,而不是建置管道。
第三種情況比聽起來更常見。將發行說明貼上到僅包含 HTML 的 CMS 欄位中。將自述文件放入電子郵件範本中。在提交文件之前檢查文件的外觀。將用黑曜石編寫的草稿轉換為您可以交給設計者的東西。這些都不能證明將解析器連接到專案是合理的。
CommonMark 和 CommonMark 有什麼不同 Github 口味降價?
格魯伯'最初的規格是一頁散文和一個 Perl 腳本,它留下了足夠的模糊性,以至於每個實現都在邊緣情況下存在分歧。 通用標記 答案是:一個嚴格的、可測試的規範,具有數百個範例的一致性套件,以便兩個一致的解析器為相同的輸入產生相同的輸出。它定義了基線 - 標題、段落、重點、連結、圖像、列表、區塊引用、程式碼區塊、主題中斷、反斜線轉義、HTML 區塊。
GitHub 風味降價 (GFM) 是 CommonMark 的正式超集,由 GitHub 指定,它添加了人們不斷要求的東西:
| 特色 | 通用標記 | GFM | 語法 |
|---|---|---|---|
| 表格 | 不 | 是的 | | a | b | 與a | --- | --- | 分隔行 |
| 任務列表 | 不 | 是的 | - [x] done / - [ ] todo |
| 擊穿 | 不 | 是的 | ~~gone~~ |
| 自動連結的裸 URL | 不 | 是的 | https://toolz.dev 沒有括號 |
| 註腳 | 不 | 是的(GitHub 擴充) | [^1] |
| 標題、清單、代碼、重點 | 是的 | 是的 | 相同的 |
如果您的 Markdown 來自 GitHub README、GitLab wiki、Notion 匯出或大多數現代編輯器,則它是 GFM。在轉換器中開啟 GFM,否則您的表格將呈現為文字管道,這是第一個"轉換器損壞"任何運送這些工具的人都會收到支援問題。
為什麼我的斷線消失了?
因為 Markdown 遵循純文字電子郵件的慣例,將連續的非空白行視為一個段落。這:
Line one
Line two
產生 <p>Line one\nLine two</p>- 一個段落,當瀏覽器渲染它時,換行符會折疊到一個空格。這不是錯誤;它是規範,它的存在是為了讓您可以將散文硬包裝在文字編輯器中的 80 列,而不會導致包裝洩漏到輸出中。
獲得實際休息的方法有三種:
- 一條空白線 開始一個新段落。這就是你大部分時間想要的。
- 兩個尾隨空間 在一行的末尾產生一個硬中斷 -
<br />. 這是標準的技巧,在你的編輯器中是看不見的,這就是為什麼人們覺得它令人發瘋。 - 反斜線 在 CommonMark 中,行尾也做了同樣的事情,並且至少是可見的。
然後是第四條路,這是混亂的根源: 許多平台打開 "breaks"模式 其中每一條換行符都變成a <br />。 GitHub 評論和問題就是這樣做的。大多數聊天應用程式都會這樣做。 GitHub 自述文件 不要. 因此,同一文本在 GitHub 問題和同一儲存庫的自述文件中的呈現方式有所不同,這確實是一個糟糕的設計,我們現在都陷入了困境。
轉換器將其公開為開關。如果您的來源是為聊天式渲染器編寫的,請打開換行符。如果是文檔,請將其關閉並按照規範使用空白行。
原始 HTML 如何處理?
Markdown 允許內聯 HTML - 原始規範明確表明您編寫的任何 HTML 都會直接傳遞。這是當您是作者時的一個功能(您需要您的) <details> 塊,你的 <img> 具有寬度屬性,您的錨點具有 rel),當你不這樣做時,這是一種責任。
因為如果您啟用了 HTML 傳遞來呈現不受信任的 Markdown,則存在 XSS 漏洞。 <script>alert(document.cookie)</script> 是有效的降價。也是如此 <img src=x onerror="...">. 一個也是如此 <a href="javascript:...">. 評論框、使用者個人資料簡介、公共維基(任何陌生人寫Markdown 供其他人閱讀的地方)必須要么逃避HTML,要么用真正的消毒劑消毒輸出(DOMPurify 是通常的答案,而它正是真正的消毒劑,因為正規表示式不足以用於敵對輸入)。
此轉換器預設為 逃跑 原始 HTML: <div> 在您的來源中顯示為文字 <div> 在輸出中,就像您寫的一樣 <div>. 當來源是您的時,您可以開啟傳遞。無論該設定如何,即時預覽條都會顯示 <script>, <style>, 內聯 on* 事件處理程序和 javascript: 渲染之前的 URL - 深度防禦措施,因此貼上其他人'將自述文件放入預覽窗格中無法執行其程式碼。這是預覽安全措施,而不是通用消毒劑:如果您正在建立渲染使用者 Markdown 的產品,請使用專用的消毒劑伺服器端並且不信任正規表示式,包括我的。
如果你需要逃避一個角色 從 標記,因此它按字面意思呈現 - 一個應該保留星號的星號,檔案名稱中的下劃線 - 反斜線可以做到這一點: \*not emphasis\*. 如果你正在向另一個方向爭論實體,那麼 HTML 實體編碼器/解碼器 是該工作的工具。
一個好的轉換器實際上應該發出什麼 HTML?
語意、無聊、無類別的 HTML - 但有一個例外。
- 標題變成了
<h1>相對<h6>。 啟用標題 ID 後,每個標題 ID 也會變為 slugifiedid,當兩個標題共用一個標題時,重複刪除 (#setup,#setup-1).這就是製作#anchor深層連結可以工作,這就是目錄產生器所懸掛的東西。 - 帶有資訊字串的圍欄塊 -
```js- 成為<pre><code class="language-js">. *這是例外。** `language-` class is the convention Prism, highlight.js and Shiki all look for, and it is why the converter emits a class at all。轉換器不會為您的程式碼著色;頁面上的螢光筆可以,並且需要那個掛鉤。 - 列表成為
<ul>/<ol>,這是一個值得了解的微妙之處: 緊 清單(項目之間沒有空白行)將文字直接放入其中<li>,雖然a 鬆動 清單(項目之間的空白行)包裝每個項目'的內容<p>. 這是 CommonMark 的行為,而不是怪癖,這就是為什麼當您在兩個項目符號之間添加一條空白行時,您的清單會突然增加垂直間距。 CSS 未損壞; HTML 確實改變了。 - 表格變得真實
<table>/<thead>/<tbody>標記,與style="text-align:center"當分隔符號行使用時在儲存格上:---:. - 任務列表成為
<input type="checkbox" disabled>內<li>,這正是 GitHub 發出的。
內容優先,沒有包裝器部門,沒有實用程式類別。你從外面設計它,用一個 .prose 類別或您自己的規則,並且標記保持可移植性。
如何使用轉換器?
第 1 步:貼上降價
放入自述文件、變更日誌、發布說明、草稿。鍵入時輸出更新 - 沒有轉換按鈕,也沒有上傳任何內容。
第 2 步:設定開關
GitHub 風味 來源是否有表格、任務清單或刪除線(可能確實如此)。 標題 ID 如果你想要錨的話。 換線 僅當來源是為聊天風格渲染器編寫的。 允許原始 HTML 僅當來源是您的時才開啟。 完整文件 如果您想要一個完整的 HTML5 頁面,其中包含 doctype、字元集、視窗和一個 <title> 取自你的第一個 <h1>- 當您想要直接在瀏覽器中開啟結果或將其放在靜態主機上時非常有用。
第三步:檢查預覽
切換到預覽選項卡並確認結構。統計行告訴您單字、標題、連結、圖像、程式碼區塊和閱讀時間 - 檢查貼文時方便的是您發布貼文之前認為的長度。為了更徹底的計數, 字計數器 同一文本的可讀性和關鍵字密度。
第四步:取得輸出
複製 HTML,下載為 .html 文件,或複製產生的目錄 - 連結到每個標題錨點的 Markdown 嵌套列表,準備貼回文件頂部。
如果您將結果貼上到位元組重要的頁面中,請將其運行到 HTML 縮小器 之後。轉換器's 輸出是縮排的,以提高可讀性,而不是電線。
常見用例
將自述文件發佈到網站上
外掛程式和套件作者寫了一個好的自述文件,然後需要在登陸頁面上提供相同的內容。自述文件是帶有表格和徽章的 GFM;登陸頁面需要 HTML。使用現有的 CSS 轉換、貼上、樣式。標題 ID 免費為您提供側邊欄 TOC。
發佈到僅接受 HTML 的 CMS
許多 CMS 欄位、電子郵件平台和舊版管理面板都採用 HTML,僅此而已。如果您在 Markdown 中起草 - 大多數定期寫作的人都會這樣做 - 這就是橋樑。與轉換 完整文件 關閉,這樣您就可以獲得片段而不是整頁,並將其貼到欄位中。
為文檔頁面製作原型
在將內容提交到文檔網站之前,在本地轉換它會向您顯示實際的標題層次結構以及您的程式碼圍欄是否帶有正確的語言。一個 h3 那應該是 h2 在 TOC 中很明顯,在來源中不可見。
審核別人寫的內容
貼上貢獻者'向下標記,查看發出的 HTML,您可以立即看到他們是否使用真實標題或加粗一行來偽造標題 - 這種習慣會破壞文件結構和可訪問性。螢幕閱讀器按標題導航; **Big Text** 不是標題,而是粗體段落,轉換器會向您顯示在一行輸出中。
提取目錄
長文檔需要一個,手工維護可以保證它過時。從標題生成它,粘貼它,每當標題發生變化時重新生成。
高級:此解析器做什麼和不做什麼
它是一個手寫解析器,大約 400 行,沒有依賴關係 - 這是故意的,因為將 200KB 依賴關係拉入整個點都很快的頁面的 Markdown 解析器是一個糟糕的交易。
涵蓋: ATX 標題 (# x)和 setext 標題(下劃線為 === / ---)、段落、強調和強(()*, _, **, __)、帶有反向勾選運行匹配的內聯代碼、帶有信息字串的圍欄代碼、縮進代碼塊、帶有惰性延續的區塊報價、嵌套列表(有序和無序、緊密和鬆散)、主題中斷、帶有標題的連結和圖像、角度括號自動連結、電子郵件自動連結、反斜線轉義和 GFM 集:帶有對齊的表格、任務列表、刪除線、裸 URL 自動連結。
不涵蓋: 參考樣式連結 ([text][ref] 與a [ref]: url 其他地方的定義)、腳註、定義列表以及一些真正晦澀難懂的 CommonMark 角落案例圍繞著 HTML 區塊中斷段落。如果您針對它運行 CommonMark 一致性套件,它不會獲得 100% 的分數。如果您正在轉換自述文件、變更日誌或部落格文章,您不會注意到。
這是一筆誠實的交易,這也是轉換器立即加載並關閉網路的原因。對於需要精確的 CommonMark 一致性的內容管道,請使用 markdown-it, remark 或者 cmark 在你的建造中;這就是他們的目的。
問號
如何將降價轉換為 HTML?
將 Markdown 貼到編輯器中,HTML 會立即出現 - 沒有轉換按鈕,也沒有檔案可供上傳。如果您的來源使用表格或任務列表,請開啟 GitHub 風格的 Markdown,然後複製 HTML 或將其作為。html 檔案下載。所有內容都在您的瀏覽器中運行,因此未發布的草稿和內部文件永遠不會離開您的裝置。
什麼是 GitHub 口味的降價?
GitHub Flavored Markdown (GFM) 是 CommonMark 的正式指定超集,它添加了表格、任務列表複選框、雙波形符刪除線以及裸 URL 的自動連結。這是 GitHub 用於渲染自述文件和問題的方言,也是當今大多數 Markdown 編輯器發出的。預設情況下,它在此轉換器中啟用。
為什麼我的單線中斷消失了?
標準 Markdown 將連續行加入單一段落;只有當您以兩個空格結束該行、使用尾隨反斜線或留下一行空白行時,換行符才會保留。如果您希望每條換行符都變成 a <br />啟用換行選項 - 這就是 GitHub 評論和大多數聊天應用程式使用的行為,但這不是 README 檔案所做的。
轉換器會突出顯示我的程式碼嗎?
它會發出螢光筆所需的標記,但不會為程式碼本身著色。標有該語言的圍欄代碼塊 js 成為 <pre><code class="language-js">,這是類別約定 Prism,highlight。js 和 Shiki 都在尋找。將這些庫之一新增到貼上輸出的頁面,並且突出顯示會自動出現。
我的 Markdown 中的原始 HTML 是否保存下來?
預設情況下它是轉義的,所以 <div> 顯示為文字而不是標籤。開啟 allow-raw-HTML 選項可直接傳遞標籤,這就是當 Markdown 故意混合在 HTML 中時您想要的 - a <details> 區塊,或具有屬性的圖像。僅將其啟用為您信任的來源,因為來自不受信任作者的原始 HTML 是 XSS 向量。
貼上我沒有寫的降價是否安全?
是的。預設情況下,HTML 會轉義,即時預覽還會在渲染之前剝離腳本和樣式標籤、內聯事件處理器和 javascript: URL。您貼上的任何內容都不會傳輸到任何地方。如果您正在建立從陌生人那裡渲染 Markdown 的產品,請仍然使用專用的消毒劑,例如 DOMPurify 伺服器端 - 預覽過濾器不能取代它。
我可以從標題產生目錄嗎?
是的。啟用標題 ID 後,每個標題都會有一個經過條碼處理、去重複的錨點,並且該工具會建立一個連結到每個標題的 Markdown 目錄。將其複製回文件的頂部,連結將根據生成的 ID 進行解析。每當標題發生變化時,就會重新生成它,而不是手動維護它。
此轉換器是否完全實作 CommonMark?
它實現了人們實際編寫的構造 - ATX 和 setext 標題、段落、重點、連結、圖像、自動連結、區塊引用、嵌套和鬆散列表、圍欄和縮排程式碼、主題中斷、反斜線轉義 - 以及 GFM 擴充。不涵蓋參考式連結、腳註和一些罕見的 CommonMark HTML 區塊邊緣情況。為了在建置管道中實現位元精確一致性,請使用 markdown-it、備註或 cmark。
相關工具: 標記到 HTML · HTML 實體 · HTML 縮小器 · 字計數器 · 蛞蝓發電機
相關閱讀: Web 開發人員's 工具包 · 文字工具指南



