三個步驟把 HTML 轉成 Markdown
- 文字、標題、清單、連結、圖片與引用,都會完整活著出來。
- class、行內樣式、id、表單與 iframe 不會,因為 Markdown 沒有這些詞彙。
- 巢狀或合併儲存格的表格會保留成原始 HTML,這才是正確結果。
- turndown.js 在你的分頁裡執行,標記不會離開你的電腦。
輸出框裡已經是你的 Markdown 了。接下來要做的是檢查有什麼沒跟上,因為這個方向一定會掉東西。這一頁就是告訴你會掉哪些。
回到純文字的三個步驟
- 把 HTML 貼進輸入框。來源可以是瀏覽器另存的網頁、從 CMS 編輯器複製的片段、匯出的客服文章、電子報範本,或只是一個你想改成管線語法的
<table>。從線上頁面抓的話,只複製你要的那個元素,不要連整頁框架一起帶進來。 - 在輸出框讀 Markdown。標題縮成
#、粗體變成**、連結變成[文字](網址),外層的 div 直接消失。花幾秒掃過一次,這正是你發現什麼被壓平的時刻。 - 複製或下載結果。「複製」把 Markdown 放進剪貼簿,可以用在 README、wiki、靜態網站文章或 Obsidian 筆記;「下載」則存成
.md檔,可以直接 commit 進版本庫。
turndown.js 在做什麼
引擎是 turndown.js,許多編輯器裡「貼上為 Markdown」功能背後就是它。瀏覽器會先把你貼進來的標記建成 DOM,turndown 再走過這棵樹,把每個節點改寫成對應的 Markdown。
整個過程沒有任何東西送到伺服器。輸出沒問題之後,首頁的免費 Markdown 編輯器是很自然的下一站,可以邊看即時預覽邊整理內容。
實例:HTML 進去,Markdown 出來
下面是一段很寫實的片段,連真實 CMS 會塞給你的外層 div 和行內樣式都一併保留:
<div class="post">
<h2>Release Notes</h2>
<p>We shipped <strong>dark mode</strong> and fixed the <em>export</em> bug.</p>
<ul>
<li>Faster preview</li>
<li>Smaller <code>bundle.js</code></li>
</ul>
<p style="color:#888">See the <a href="https://example.com/changelog">changelog</a>.</p>
</div>
轉出來的 Markdown
十一行標記變成六行文字,而且不必開瀏覽器就讀得懂:
## Release Notes
We shipped **dark mode** and fixed the *export* bug.
- Faster preview
- Smaller `bundle.js`
See the [changelog](https://example.com/changelog).
悄悄不見的東西
內容完整保留,但有兩樣東西不見了,找找看:
<div class="post">消失了。turndown 會把容器拆開,只留下裡面的文字。style="color:#888"消失了。Markdown 沒有描述顏色的詞彙,那段灰字現在就是普通文字。
這不是錯誤,而是你降到較簡單格式時必須接受的交易。輸出全程依照 GitHub 風格 Markdown 的慣例:標題用 # 的 ATX 寫法、項目符號用 -、程式碼用圍籬區塊而不是四個空白縮排。
這些預設值讓結果貼進 README、GitLab wiki 或任何靜態網站產生器都不會出問題。對兩種格式的差異還不熟的話,Markdown 與 HTML 比較說明兩者各自的用途,什麼是 Markdown 則從頭介紹這個格式。
常見 HTML 標籤與對應的 Markdown 寫法
這是轉換器套用的對照規則。真正有價值的資訊在「說明」那一欄,因為它告訴你途中悄悄改變了什麼:
| HTML 標籤 | Markdown 對應寫法 | 說明 |
|---|---|---|
<h1> 到 <h6> | # 到 ###### | 標題層級完整保留 |
<p> | 後面接一個空行的文字 | class 與 style 一律丟棄 |
<strong>、<b> | **文字** | 兩個標籤合併成同一種語法 |
<em>、<i> | *文字* | 兩者之間的語意差別會消失 |
<a href> | [文字](網址) | title 保得住,target 和 rel 保不住 |
<img> |  | width、height、loading 都會被丟掉 |
<ul> 與 <li> | - 項目 | 巢狀層級靠縮排保留 |
<ol> 與 <li> | 1. 項目 | start 屬性會遺失,編號從 1 重新開始 |
<code> | 用反引號包住的文字 | 內含反引號時會自動加長圍籬 |
<pre><code class="language-js"> | 標註 js 的圍籬區塊 | 只有語言寫在可辨識的 class 裡才抓得到 |
<blockquote> | > 文字 | 巢狀引用會變成 >> |
<hr> | --- | 單純對應,不會損失任何資訊 |
<br> | 行尾兩個空白再換行 | 在原始碼裡看不見,很容易被誤刪 |
<del>、<s> | ~~文字~~ | 僅限 GFM,原始 Markdown 沒有刪除線 |
<table> | 管線符號表格 | 只支援單純的格狀資料,第一列會變成表頭 |
<div>、<span>、<section> | 不留痕跡,只保留內容 | 容器被拆開,屬性一併消失 |
<script>、<style>、<noscript> | 整段移除 | 標籤與內容都不會留下 |
<iframe>、<form>、<input>、<video> | 保留成原始 HTML 或直接丟棄 | Markdown 根本沒有對應語法 |
有兩列值得看兩次
<br>那一列。硬換行會變成行尾空白,而多數編輯器存檔時會自動清掉行尾空白,所以它是轉換後最脆弱的東西。- 容器那一列。它解釋了幾乎所有「我的版面跑去哪了」的疑問:版面靠容器和 class 撐起來,Markdown 兩樣都沒有。
語法速查表讓你一眼看完目標語法,完整 Markdown 指南則把每個元素講清楚。要轉的東西是格狀資料嗎?先讀表格指南,管線語法比看起來嚴格。
哪些東西轉不乾淨,以及為什麼
HTML 是比 Markdown 大得多的語言,所以這個方向本質上就會失真。清楚知道損失發生在哪裡,就能事先安排對策。
Markdown 沒有詞彙可用的東西
- 巢狀與合併儲存格的表格。用了
colspan、rowspan,或儲存格內含巢狀清單,管線語法完全無法表達。turndown 會把它壓成歪掉的格子,或乾脆把<table>原樣留成 HTML。 - 行內樣式、class 與 id。
style="color:red"、class="callout"、id="section-3"全都會消失,因為 Markdown 表達的是結構而不是外觀。 - 表單、iframe 與多媒體嵌入。
<form>、<input>、<iframe>、<video>、<audio>完全沒有對應語法,只能保留成原始 HTML 或直接丟棄。
複雜表格留成 HTML 是解法,不是失敗:Markdown 渲染器會把區塊層級的 HTML 原樣輸出,表格照樣正常顯示。如果 id="section-3" 這種錨點很重要,就在 Markdown 裡手動補一小段 <span id="section-3"></span>。另外,GitHub 渲染 README 時本來就會濾掉 <iframe>,所以影片嵌入即使轉換時活下來,發佈時還是可能消失。
會悄悄改變的東西
- 依賴定位的版面。多欄格線、浮動元素、絕對定位的區塊,都會依原始碼順序壓成一條線性文字流,而原始碼順序常常不等於閱讀順序。
- 看不見的字元。不斷行空白與零寬字元會安靜地留在檔案裡,幾週後製造莫名其妙的 diff。
- 實體與跳脫。
會被解碼成真正的字元,而文字中原有的*、_、#會被加上反斜線,以免變成格式符號。
注意:版面型頁面轉換後,一定要從頭到尾讀過一次再發佈。在 Markdown 裡,原始碼順序就等於閱讀順序,而多欄版面正是兩者分道揚鑣的地方。
幫你省麻煩的習慣
轉換完之後,先在預覽裡完整讀過一遍再送出。把輸出貼進編輯器,和原始頁面對照,修掉那幾處跑掉的地方就好。
回頭路是 Markdown 轉 HTML 轉換器,而那個方向不會有任何損失。常見問題裡的如何把 Markdown 轉成 HTML 說明了為什麼兩個方向並不對稱。
這個工具、Pandoc,還是在 Node 跑 turndown?
能做這件事的工具有三種,適用情境其實差很多。選錯就是白白浪費一個下午。
這個頁面:一次一份文件
零安裝、立即出結果,在什麼都不准裝的公司筆電上也能用,標記從頭到尾不離開你的電腦。多數真實任務都屬於這一類:把文章從 CMS 裡救出來、把複製來的表格改成管線語法、把一封信整理成 wiki 頁面。
Pandoc:大批舊檔案與特殊格式
Pandoc 是命令列文件轉換器,支援的格式數量無人能及。一行指令就能完成:
pandoc -f html -t gfm page.html -o page.md
它處理定義清單、註腳和複雜表格比瀏覽器函式庫優雅,也讀得懂 DOCX、LaTeX、EPUB,所以當輸入根本不是 HTML 時,它才是正解。代價是要在本機安裝,而且正規化很有主見,可能把輸出重排成你不想要的樣子。搭配一行 shell 迴圈掃過資料夾,它就變成批次工具。
在 Node 跑 turndown:可重複的大規模搬遷
從舊 CMS 搬出幾百頁,或每次改版都要重新匯出的文件網站,答案就是它:
npm install turndown turndown-plugin-gfm
因為引擎和這個頁面完全相同,輸出會跟你在這裡預覽到的一致。走 Node 路線的真正理由是自訂規則:把每個 <div class="callout"> 轉成引用區塊,或清掉所有連結的追蹤參數。放進 CI 執行,一千頁每次都轉出一模一樣的結果。
小提醒:兩種併用最省力。先在這裡拿三份代表性頁面驗證效果,再把摸索出來的規則寫成 Node 腳本,套用到剩下的九百九十七頁。本來就只需要轉一頁的話,做完第一步就收工。
這一頁沒講到的問題,常見問題大多有答案;想確認轉好的檔案渲染是否符合預期,用 Markdown 檢視器打開最快。
相容性資料驗證日期
常見問題
HTML 轉 Markdown 會失真嗎?
會,而且無法避免。Markdown 沒有 class、行內樣式、id、表單、iframe 或合併儲存格的語法,這些只能被丟棄或保留成原始 HTML。文字、標題、清單、連結、圖片、引用和單純的表格則會完整保留。
我的 HTML 會離開瀏覽器嗎?
不會。turndown.js 以一般 JavaScript 在你的分頁內執行,轉換全在本機完成。不上傳、不記錄,所以內部頁面和客戶專案都可以放心使用,頁面載入後即使離線也照常運作。
為什麼我的表格轉出來還是原始 HTML?
因為它用了管線表格表達不出來的東西,通常是 colspan、rowspan,或儲存格裡塞了巢狀清單。保留成 HTML 才是正確結果:Markdown 渲染器會把區塊 HTML 原樣輸出,表格照常顯示。管線語法的極限請見表格指南。
可以一次轉換整個網站或很多檔案嗎?
這個瀏覽器工具不行,它一次處理一份文件。要批次處理,請用 Node 腳本跑 turndown,或用命令列的 Pandoc - 上面的比較段落有完整說明。
怎麼把 Markdown 再轉回 HTML?
用另一個工具 Markdown 轉 HTML 轉換器,或直接用編輯器的「複製 HTML」與 .html 按鈕。那個方向不會失真,因為 Markdown 本來就是 HTML 表達能力的子集。
延伸閱讀
立即使用編輯器
開啟編輯器