一個基於 DOMParser 建構的 HTML 清理工具替代方案,透過瀏覽器的 text/html tokenizer 解析片段,可選擇性地移除註解節點,並僅將解析後的 body 序列化為靜態文字。不同於一般會重新調整縮排或聲稱能清理內容的線上美化工具,這個方法刻意只做三件事:讓瀏覽器的 HTML 解析器自行進行結構修復、將序列化結果顯示在唯讀 textarea 中以避免任何內容被注入到實際頁面中,以及明確聲明並未強制執行任何安全邊界。如果你曾經把片段貼進某個「清理工具」,並懷疑來回轉換是否改動了你關心的內容,這種由解析器驅動的替代方案之所以吸引人,在於你所看見的變更,就是瀏覽器本身會進行的變更。這個工具絕不會將輸入上傳到 Lizely、絕不會執行解析後的腳本、絕不會產生即時 HTML 預覽,也絕不會聲稱輸出內容可安全地注入到其他位置。代價是誠實:它會保留腳本、事件處理常式、iframe 與 img 的 URL、樣式以及未知元素,與解析後的結果完全一致,因為這些都不在其唯一的可選刪除規則範圍內。

html cleaner alternative
基於瀏覽器解析器的 HTML 清理工具替代方案

瀏覽器型 HTML 清理工具替代方案有何不同

你在搜尋結果中找到的大多數 HTML 清理工具大致可分為三類:以正規表示式驅動、僅重新縮排而不進行解析的格式化工具、致力於產生漂亮輸出的源碼感知美化工具,以及試圖移除危險節點的清理工具。瀏覽器解析器的方法不屬於其中任何一類。它使用與每個你載入的網頁相同的 text/html 解析器,然後要求該解析器回傳其對 body 的標準化檢視。重點不是產生最容易閱讀的輸出,而是產生瀏覽器今天解析你片段時會產生的輸出。

這點很重要,原因有二。第一,它讓你能對「我的片段在瀏覽器中實際看起來是什麼樣子?」以及「我是不是忘了關閉某個標籤?」這類問題得到一個確定性的答案。第二,它讓限制變得顯而易見。解析器在設計上就是寬容的,因此格式錯誤的輸入會被修復,而不是像 XML 那樣回傳錯誤,序列化器也只輸出 body 標記,永遠不會輸出 document shell 或僅 head 的中繼資料。如果你想要位元完全一致、美化過或清理過的輸出,這一層是錯的——你需要的是承諾不同的其他工具。

對於特別希望不經上傳步驟、純粹在本地端使用的替代方案的開發者來說,這類工具值得與託管式格式化工具相互比較。HTML Cleaner 頁面詳細記錄了它真正兌現了哪些承諾,以及明確拒絕了哪些承諾。

清理工具的範圍:body 標記、註解,僅此而已

HTML Cleaner 有一個刻意收窄的合約。原始輸入會以 text/html 模式通過 DOMParser、可選的切換開關決定是否從解析後的 body 中移除 Comment 節點,結果會從 body.innerHTML 序列化到唯讀 textarea。這就是整個流程。沒有白名單、沒有政策引擎、沒有 URL 重寫器、沒有屬性移除器,也沒有腳本移除器。

正因為合約很窄,下表值得仔細閱讀。每一列都描述的是實際行為,而非行銷說法。

行為HTML Cleaner 實際做了什麼
完全在瀏覽器中執行是——不會上傳到 Lizely
解析輸入內容以 text/html 模式使用 DOMParser
移除註解節點可選,單一切換開關
移除 script 或 style 區塊否——按解析結果保留
移除事件處理常式屬性(onclick、onerror)否——保留
重寫 javascript: URL否——保留
移除 iframe、img、form、SVG、MathML否——保留
產生即時預覽否——僅有唯讀 textarea
執行解析後的腳本否——DOMParser document 沒有 browsing context
下載遠端資源可能——iframe 與 img 參照可能會擷取
重新縮排或美化排版否——僅使用瀏覽器的標準序列化
保留 doctype、head、title、meta否——僅輸出 body
原始輸入上限500,000 UTF-16 code units,在解析前檢查
標準化後輸出上限1,000,000 UTF-16 code units,在回傳前檢查
適用於不受信任的 HTML否——請使用具備目的地感知的清理工具

最下面那一列是最重要的。若結果包含 script 標籤或 onerror 屬性,當下游應用程式將其注入到實際頁面時將會是危險的。這個解析器在建構上就是停用腳本的,textarea 也是靜態的,但若把輸出複製到 innerHTML、CMS 內容欄位、email 樣板或任何其他執行環境中,就會在那些地方啟動。MDN 的 innerHTML reference 也記錄了相同的注入風險。

如何標準化並清理 HTML 片段

把這個工具當作快速的標準化與註解移除步驟,而非清理工具。下方流程對應工具頁面上已驗證的操作步驟。

  1. 將 HTML 片段或完整文件貼入輸入區域,然後決定是否要移除 HTML 註解節點。
  2. 觸發標準化。工具會以 text/html 模式使用 DOMParser 解析,若切換開關為開啟則移除 Comment 節點,並序列化 body.innerHTML。
  3. 在唯讀輸出區域中檢閱僅含 body 的文字,並讀取工具所顯示的註解移除數量。
  4. 只有在你也決定目的地是否需要真正的 HTML 清理工具之後,才複製完整結果。

有兩個實務細節值得了解。第一,輸入上限是在解析前檢查的,因此過大的貼上內容會在最一開始就被拒絕,而不是在長時間解析後才被擋下。第二,編輯輸入內容或切換註解開關會清除先前的結果、註解數量、任何錯誤以及剪貼簿狀態——工具使用 generation guard,使早期複製所延遲取得的剪貼簿權限無法在編輯、重試或卸載後還原過時狀態。若瀏覽器拒絕寫入剪貼簿,完整輸出仍會保留在唯讀 textarea 中供手動選取。

瀏覽器解析器在標準化過程中修復了什麼

由於這個工具依賴瀏覽器的 HTML 解析器,它會繼承解析器所套用的所有修復規則。WHATWG HTML Living Standard 定義了 text/html 的 tokenization 與樹狀結構建構,而解析器在設計上就是寬容的。實際上,當你對片段進行來回轉換時,可以預期會發生以下幾類變更:

  • 元素名稱會被轉為小寫,因為在解析後的 DOM 中 HTML 元素名稱不區分大小寫。
  • 當原始標記省略引號時,序列化器會為屬性值加上引號,且部分屬性會在形式上被標準化。
  • 當 table 省略了隱含元素(例如 tbody)時,會被自動插入,因為樹狀結構建構需要它們。
  • 部分遺漏的結尾標籤會被修復,而不是回報為錯誤。
  • 當輸入順序違反 content model 時,標記會依照 HTML 樹狀結構建構規則重新排列。

序列化刻意限定在 body.innerHTML,因此完整的輸入文件可能包含 doctype、html、head、title、meta、link、style 與 body 等區段,但回傳的文字僅包含解析後 body 的子標記。Doctype 與 document shell 不會被複製。除非解析器的標準復原規則將特定 token 移入 body,否則僅 head 的中繼資料不會出現在輸出中。若必須保留完整的頁面 shell,那麼具備 document 感知的編輯器才是合適的工具。

位於 pre、textarea、script 與 style 中的文字遵循 HTML 解析規則,不會被自訂的詞法處理階段重新排版。這是刻意的設計:過於天真的格式化工具可能會意外切開 raw-text 內容或改變 DOM 語意。工具會回報 parser API 例外、缺少 body 輸出或無效的解析結果,但並不承諾嚴格的標準符合性,也未聲稱修復後的結構符合作者原本的意圖。

硬性限制與誠實的取捨

有三項限制值得預先規劃。輸入最多 500,000 UTF-16 code units,標準化後的輸出最多 1,000,000。原始輸入限制會在解析前檢查,完整 body 序列化會在回傳結果前進行測量。剛好等於上限的值會被接受;上限加 1 的值則會以明確的訊息失敗。不會進行切片、抽樣、部分序列化,也不會靜默切換到不同的清理政策。解析後或移除註解後的空白 body 是合法的零長度輸出。

DOMParser 會建立一個停用指令碼的獨立 document,結果只存在於唯讀 textarea 中,但瀏覽器在解析期間仍可能下載被解析後 iframe 或 img 元素所參照的資源。若貼上的 HTML 含有敏感的遠端資源 URL,且這些請求會向其他主機洩漏資訊,請避免這麼做。MDN 的 DOMParser.parseFromString reference 記錄了這項行為以及缺少 browsing context 的特性。

HTML 標準化並非常規的 pretty printer。DOMParser 與 innerHTML 會產生瀏覽器的標準序列化,但並不保證縮排、換行、屬性排序、原始空白保留,或在每個瀏覽器版本之間產生位元完全相同的輸出。若你需要壓縮輸出、美化輸出,或跨引擎產生完全相同的位元組,那些是屬於不同目標、需要不同工具的工作。

When HTML Cleaner Is the Wrong Tool

The tool fits a small, honest niche: see how a browser normalizes a fragment, remove comments from an otherwise unchanged parsed structure, or prepare body markup for manual review. It does not fit tasks where the reader's intent is something else.

  • Standards validation. The forgiving parser repairs malformed markup instead of rejecting it, so a strict validator is what you want when conformance is the goal.
  • Security sanitization. Active content is preserved, so a destination-aware sanitizer such as DOMPurify or a maintained server-side equivalent is the right layer for untrusted HTML.
  • Full document preservation. Doctype, head, title, meta, link, and style at the document level are outside the output, so a document-aware editor is required when the page shell must round-trip.
  • Pretty printing or minification. Canonical browser serialization is not the same as beautified or compact output; use a formatter or minifier for that.
  • Cross-browser byte identity. Two browsers are not guaranteed to produce byte-identical output for the same input.
  • Publish-time safety proof. Copying the output into innerHTML, a CMS, or an email template activates behavior in that context, so a separate sanitization pass is still needed.

For a related browser-first alternative with the same no-upload philosophy on a different input shape, see the text-to-html paragraphs API alternative walkthrough. Together they illustrate the same trade-off: a tool that does exactly one job in your browser, documents the boundary honestly, and refuses to claim guarantees it cannot keep.

If you're weighing options, How to Edit an HTML Page Online Without Software covers this in detail.