教學 · HTML → Markdown
HTML 轉 Markdown
HTML 能表達的東西比 Markdown 多得多。所以這次轉換主要在處理一個問題:那些沒有對應寫法的東西怎麼辦。
三種答案,看標籤是哪個:對應過去、去掉標籤留下文字、兩樣都去掉。哪種答案由一張白名單決定,值得知道上面有什麼。
白名單,不是黑名單
只有在 Markdown 裡有意義的標籤能過第一道:標題、段落、清單、連結、圖片、強調、引言、程式碼、表格,以及圍著它們的那幾個行內標籤。別的都刪掉,文字留下。
用白名單的理由是:黑名單要預判所有危險標籤,而 HTML 還在不斷加新的。漏一個就是一個洞。這樣一來,對任何不認識的東西預設答案是「不」。
指令碼、事件屬性、javascript: 連結都會沒;script、style、iframe、object、embed 這幾個連內容一起刪 —— 不只是標籤。留下 <script> 裡的文字,等於把它的程式碼當成內文貼進你的文件。
屬性同樣是白名單:只有 href、src、alt、title、colspan、rowspan、start。所以 class、id、style 永遠到不了輸出。這不只是安全 —— Markdown 也沒地方放它們。
什麼都不算繪,為什麼還要淨化
這一頁從來不算繪你的 HTML,所以這裡沒有什麼能執行。淨化器存在的理由是它之後會發生什麼。
一個寫成 [click me](javascript:alert(1)) 的連結,會被 Markdown 轉換器原樣忠實地帶過去,等到有人把這份 Markdown 發到一個會算繪它的站上,它就是一個能用的攻擊。風險不落在我們身上,是被交給了用這份輸出的人。
所以網址會按協定白名單查一遍 —— http、https、mailto、ftp,還有相對路徑 —— 別的一律丟掉。有東西被刪掉時輸出會說刪了什麼,而不是背著你悄悄把你的輸入收拾乾淨。
表格:留著,還是壓平
預設表格變成 Markdown 的直線表格。格子裡的直線轉義掉,格子內的空白塌成單個空格,短列補齊到最寬那列的寬度,表格保持是個矩形。
壓平是另一個選項,它是為那些本來就不是表格的表格準備的。用表格做定位排版的頁面轉出來是一張全是空格子的直線表格;壓平之後每列變成一行文字,格子之間用一個間隔點連起來,讀著好得多。
兩樣東西怎麼都留不下。<caption> 會被丟掉,因為直線表格沒地方放它 —— 需要的話自己把它抄成表格上方的一行。還有格子裡的區塊級內容會塌掉:一格裡的清單出來是幾項連在一起,因為直線表格的一列必須是一行。
<table><tr><th>Part</th><th>Qty</th></tr>
<tr><td>Bolt | M6</td><td>12</td></tr></table>| Part | Qty |
| --- | --- |
| Bolt \| M6 | 12 |保留成 HTML 的那幾個標籤
上標和下標保留成 <sup> 和 <sub>。Markdown 沒有這兩種語法,而把 x² 寫成 x2 會改變一個公式的意思 —— 裸 HTML 在 Markdown 裡是合法的,這兩個標籤每個算繪器都認。
底線沒有這個待遇。它沒有需要保留的意義:在網頁上底線就是連結,留著它是在誤導人。帶底線的文字出來是純文字。
刪除線轉成 ~~,這是 GitHub 風格的 Markdown 而不是原始規範,但現在通用到丟掉它才是更奇怪的選擇。
清單、程式碼區塊,和那幾個開關
清單項寫成「- item」,一個空格。大多數 Markdown 工具鏈都這麼寫,而另一種常見寫法 —— 標記後面三個空格 —— 在一個檔案被兩邊輪流編輯時會讓 diff 很吵。
嵌套清單按標記的寬度縮排;清單項裡接著寫的段落縮排到跟上面文字對齊,而不是跳出清單。<ol> 上的 start 屬性會保留編號。
項目符號字元可以是 -、* 或 +,程式碼圍籬可以是 ``` 或 ~~~。按這份檔案要進的地方挑,功能上沒有區別。標題也可以換成底線式的,不過只有前兩級有這種寫法 —— 第三級往下不管怎麼選都還是 # 號,選之前值得知道這件事。
<ol><li><p>First para</p>
<p>Still item one</p></li></ol>1. First para
Still item one兩種輸入,一條路
你可以把 HTML 原始碼貼進框裡,也可以拖一個 .html 檔案進來。兩者處理方式完全一樣,因為在程式碼看來它們是同一個東西:一段不可信的 HTML 字串。
25 MB 的上限是按單次輸入算的,比任何頁面的原始碼都大得多。什麼都不上傳 —— 解析、淨化、轉換全在這個分頁裡。
結果回來是空的,輸出會說明。通常是輸入裡全是標記沒有文字:一個頁面的 <head>,或者一段只有樣式的片段。
貼原始碼或者拖檔案,決定表格是不是還當表格,然後把 Markdown 拷走。全程在你的瀏覽器裡跑。
HTML → MD