HTML Cleaner 透過瀏覽器內建的 DOMParser(以 text/html 模式)處理輸入,將解析後文件的 body 內部 innerHTML 序列化至唯讀文字框中,唯一可選的刪除動作是 HTML 註解節點,藉此標準化 HTML 片段。這個單一定義即說明整個工具的全部功能:貼上標記、可選擇啟用註解移除,再讀回規範化的 body 文字,且不預覽也不執行結果。解析發生在與主文件分離的 DOMParser 文件內,因此嵌入的腳本在整個清理過程中始終處於非啟用狀態。超過 500,000 UTF-16 程式碼單位的輸入會在解析前遭到拒絕,而規範化後的 body 若超過 1,000,000 程式碼單位則會以明確的錯誤訊息失敗,因此不會發生靜默截斷。當你需要查看真實瀏覽器會如何修復片段、去除僅供開發使用的註解,或在手動編輯、貼到其他環境之前產生穩定的 body 標記時,請使用此工作流程。

瀏覽器中的「清理」HTML 究竟代表什麼
「清理 HTML 文字」一詞涵蓋幾種不同的任務,而你要選擇的工具取決於你實際面對的是哪一項。同樣搜尋這個關鍵字的兩位讀者,可能想要截然不同的東西:一位想修復從 Word 文件複製貼上的標記,另一位想在匯出片段前移除 <!-- TODO --> 之類的註解,還有第三位則試圖讓貼上的電子郵件 HTML 對 CMS 來說是安全的。以瀏覽器為基礎的標準化工具可以乾淨地處理前兩項,但明確無法處理第三項。在開啟工具之前,值得先誠實面對你究竟需要哪一類清理。
兩個值得區分清楚的意思:
- 標準化:將標記送入解析器,並套用每個瀏覽器都會套用的相同樹狀建構規則。元素名稱會轉為小寫、屬性會加上引號、缺失的結尾標籤會被補上,而隱含元素(例如 tbody)會被插入。輸出會是規範化的瀏覽器序列化結果。
- 淨化:移除或重寫危險結構,例如 script、事件處理屬性、javascript: URL 與 iframe。這是一項安全任務,威脅模型不同,需要一個針對目標環境設定、具備白名單功能的程式庫。
HTML Cleaner 是一個標準化工具,僅有一條可選的刪除規則。產品說明將其描述為「瀏覽器標準化與格式化輔助工具,而非安全淨化器」。這個區別是你在使用此工具時,最值得牢記在心的單一事實。
HTML Cleaner 在標準化工作流程中的定位
當你想要以瀏覽器相同的視角檢視片段時,請選擇 HTML Cleaner。以下幾個具體情境符合本工具的適用範圍:
- 從 CMS 匯出檔、電子郵件模板或第三方 API 取得的片段,想在動手修改前先查看瀏覽器的樹狀結構。
- 需要穩定的規範化序列化結果作為比對基準的測試素材,避免直接比對對空白敏感、原始未處理的來源。
- 充滿除錯與 TODO 註解的片段,需要一份乾淨的、僅含 body 的副本,用於說明文件或靜態網站產生器。
- HTML 解析器錯誤的除錯過程,想取得真實瀏覽器所產生的復原樹,而非原始來源。
以上正是本工具設計要處理的案例。產品說明明確列出:「當你想查看瀏覽器如何標準化片段、從其他未變動的解析結構中移除註解,或準備供手動檢視的 body 標記時,請使用本工具。」超出這個範圍的工作,包括淨化、整份文件的保留、驗證與美化,皆不適合使用本工具。
清理 HTML 片段
- 開啟工具。頁面左側呈現輸入區,右側為唯讀輸出區,並提供單一切換鈕控制註解移除。
- 將片段貼入輸入區。可接受完整 HTML 文件(含 <!DOCTYPE html>、<html>、<head> 與 <body>),但輸出僅會顯示解析後 body 的子節點。最多接受 500,000 UTF-16 程式碼單位,超過的輸入會在解析前以明確訊息拒絕。
- 決定是否移除註解節點。這個切換鈕控制流程中唯一可選的刪除動作。啟用時,工具會走訪解析後的 body 及任何嵌套的 template DocumentFragment,並於序列化前移除所有 Comment 節點。關閉時,註解會依照瀏覽器解析後的形式保留在輸出中。
- 觸發標準化流程。工具以 DOMParser(text/html 模式)解析輸入、確認 body 存在、執行可選的註解走訪,再將 body.innerHTML 序列化至唯讀輸出區。不提供即時 HTML 預覽,也不執行腳本。
- 檢視僅含 body 的輸出與註解移除數量。將結果視為非啟用的文字讀取。若發生解析器 API 例外、缺少 body,或結果超出 1,000,000 程式碼單位的限制,工具會回報具體錯誤,而非切片或部分序列化。
- 僅在決定目的地是否仍需要真正的 HTML 淨化器後,再複製完整結果。將標準化後的 body 貼入 innerHTML、CMS 欄位、電子郵件模板或任何執行環境,可能會重新啟動腳本、事件處理器、javascript: URL 與嵌入的 iframe。
瀏覽器解析器會靜默修復的內容
HTML text/html 解析器本質上是寬容的。在嚴格的 XML 解析器會拒絕輸入之處,WHATWG 解析器遵循樹狀建構規則並產生一個復原樹。當你想查看真實瀏覽器會建構出什麼時,這很有幫助;同時這也是格式錯誤的 HTML 會產生輸出而非錯誤的原因。
你應該預期會發生的具體修復:
- 元素名稱會轉為小寫。<DIV>、<Span> 與 <P> 在輸出中會變成 <div>、<span> 與 <p>。
- 屬性值會加上引號。<a href=foo> 會變成 <a href="foo">。
- 缺失的結尾標籤會被補上。<li>one<li>two 會變成兩個獨立的清單項目,而非一個含有迷途子節點的元素。
- 隱含元素會被插入。直接放在 <table> 內的 <tr> 在輸出中會被加上外層 <tbody>,即使來源中原本並沒有。
- <pre>、<textarea>、<script> 與 <style> 內的文字會依 HTML 解析規則按字面保留。本工具刻意不對原始文字內容執行自訂詞法處理,以避免天真的格式化工具切開原始文字或改變 DOM 的意義。
重點在於:輸出的是瀏覽器對輸入的看法,而非作者原本的來源。
輸入限制與輸出範圍
兩個硬性限制規範了工具接受與輸出的內容:
| 邊界 | 數值 | 在邊界時的行為 |
|---|---|---|
| 原始輸入 | 500,000 UTF-16 程式碼單位 | 剛好 500,000 予以接受;500,001 於解析前以明確訊息拒絕。 |
| 標準化輸出 | 1,000,000 程式碼單位 | 剛好 1,000,000 予以接受;1,000,001 於回傳前以明確訊息拒絕。 |
這些限制在流程中的固定點進行檢查,原始輸入長度在解析前量測,完整 body 序列化長度在結果公開前量測。輸入與輸出皆不會被切片、取樣、部分序列化或靜默降級。解析或移除註解後的空 body 為合法的零長度輸出;這並非失敗。
兩個刻意排除在結果之外的範圍:
- 文件外殼。Doctype、<html>、<head>、<title>、<meta>、<link> 與 <style> 不屬於 body.innerHTML 的一部分,因此不會出現。當必須保留完整頁面外殼時,請使用具備文件感知能力的編輯器。
- 僅位於 head 的中繼資料。放在 <head> 中的標籤會留在原處,除非 HTML 解析器的標準復原規則將特定 token 移入 body。請勿依賴本工具反映 head 的編輯結果。
何時應改用真正的淨化器
產品說明明確指出:腳本、事件屬性、URL、iframe、樣式以及其他主動式標記都會被保留。HTML Cleaner 會保留腳本、內聯事件處理器(例如 onerror)、javascript: URL、iframe、內聯樣式與未知元素。它不會重寫 URL 配置、強制執行內容政策或套用白名單。當結果停留在文字框內時處於非啟用狀態,但將該結果複製到 innerHTML、CMS、電子郵件模板或其他執行環境,可能會重新啟用其行為。
HTML Cleaner 看起來能做、實際上卻做不到的工作:
- 在將所見即所得編輯器的貼上輸出儲存為使用者內容前進行清理。請使用針對目的地環境的淨化器。
- 從使用者提交的 HTML 中移除 onclick。請使用具備明確屬性白名單的淨化器。
- 在轉寄前從電子郵件 HTML 中移除 iframe 或 script。請使用針對電子郵件用戶端設定的淨化器。
- 防禦貼上的 XSS 攻擊承載。淨化器是唯一對此有助益的工具。
一個實務上的做法是先使用 HTML Cleaner 檢視瀏覽器看到的內容,再於發布前將檢視過的 body 送入一個持續維護的淨化器。兩個工具負責不同任務,不可互換。有關安全邊界的背景,MDN 參考文件 DOMParser.parseFromString 說明了解析期間會停用腳本,但 iframe 與 img 元素所引用的資源仍可能被請求。MDN 參考文件 Element.innerHTML 則涵蓋片段序列化以及將解析後標記寫入即時文件的注入風險。
Verifying the Output Against the Spec
Because HTML normalization is browser-defined rather than tool-defined, two reasonable checks before you trust the output:
- Cross-check with the WHATWG HTML Living Standard. The parser's tree-construction rules, including tokenization, implied elements, and attribute serialization, are defined there. If the output surprises you, the parser is almost always doing what the spec requires.
- Confirm body scope. If you pasted a full document and the doctype or head is missing, that is by design: the tool returns body.innerHTML only. A document-aware editor is the right next step if you need the shell preserved.
Two things the tool does not promise:
- Indentation, line wrapping, attribute sorting, or stable byte-for-byte output across browser versions. Different browser versions may serialize the same parsed tree differently. If you need byte stability, run a separate deterministic formatter on the result.
- Source whitespace preservation inside pre, textarea, script, and style. Those follow HTML parsing rules and are not touched by a custom lexical pass, which avoids a naive formatter accidentally splitting raw-text content or changing DOM meaning.
For routine review or test-fixture work, the canonical browser serialization from HTML Cleaner is enough. To compare the cleaned output against the original side by side, run them through a browser-based text diff checker that highlights added, removed, and unchanged regions in your browser. For byte-stable output, validation, or security-critical publishing, route the result through a tool built for that specific job.
If you're weighing options, How to Change a Web Icon in HTML covers this in detail.