對大約 50,000 字元的來源進行 HTML 跳脫作業時,就不再是快速貼上就能完成的工作,因為輸出長度會增加、瀏覽器會短暫暫停,而且編碼模式的選擇會讓結果大小產生明顯的差距。HTML 實體編碼器 / 解碼器可在瀏覽器中處理多達 500,000 個 JavaScript 字元,所有超過 ASCII 126 的字碼點可以選擇以可讀文字的形式直接通過,或轉換為大寫十六進位數值參照,而非 ASCII 模式會讓包含重音符號、CJK 字元或表情符號的文件輸出長度大幅超過來源長度。這個單一的擴展特性——當你切換到非 ASCII 選項時輸出長度會膨脹——正是區分小型跳脫作業與大型跳脫作業的最大差異,也是為什麼在貼上之前模式選擇很重要。這也是為什麼在輸入很長時,先執行一個小型代表性樣本是最有用的習慣:它能在來源擴展到五十萬字元之前,提前發現未預期的內容並確認下游的期望。

html escape large text
大型文字的 HTML 跳脫:規模改變了什麼

規模對 HTML 跳脫的影響

一旦貼上的內容從幾百個字擴展到小型文件,有三件事會表現得不同。首先,一旦選擇了非 ASCII 模式,輸出長度就不再大致等於輸入長度,因為每個重音字元、CJK 字元或表情符號都會從一個字元擴展為多字元參照。其次,解碼模式會對瀏覽器的 HTML 解析器造成更大的負載,因為它會委派給 WHATWG 具名字元參照表,而非使用小型固定對映表;含有大量參照的極長貼上內容,會在解析器走查表格時短暫暫停 UI。第三,錯誤的模式選擇所造成的實際成本會隨貼上規模而增加,因為重新編碼一個 300,000 字元的區塊明顯比重編碼一個段落要來得費力。事先了解這三項壓力,正是讓大型文字編碼感覺可控而非意外的原因。

在基本與非 ASCII 模式之間選擇

當來源不再是段落時,兩種編碼模式的表現差異極大,下表摘要說明了長貼上的實際差異。

面向基本編碼非 ASCII 編碼
跳脫的字元& < > " '同樣的五個語法字元,加上所有超過 ASCII 126 的字碼點
純 ASCII 文字的輸出長度與輸入相同,在出現引號處略長與輸入相同,在出現引號處略長
含重音或表情符號文字的輸出長度與輸入相同每個非 ASCII 字元會變成多字元的十六進位參照,因此長度會大幅增加
結果的可讀性高;一般詞彙保持可讀在 ASCII 範圍之外偏低
適用時機當你需要為 HTML 文位元組點或屬性產生乾淨、可讀的跳脫結果時當舊有工作流程、傳輸方式或教學範例明確要求數值參照時

MDN 的字元參照詞彙表建議避免不必要的參照,因為現代的 UTF-8 HTML 能直接承載 Unicode,這與基本模式對保留集以外每個字元所採用的推理相同。僅在外部系統或舊有管線明確要求數值參照,或你正在建構參照形式本身就是重點的比較或教學範例時,才使用非 ASCII 模式。對於一篇典型的 200,000 字元、含少量重音的文章,基本模式能讓檔案大小接近原始長度;同篇文章使用非 ASCII 模式時,輸出會遠超過來源長度,並應在重複使用前以小型樣本進行測量。

如何編碼大型文字區塊

  1. 開啟 HTML 實體編碼器 / 解碼器並選擇編碼方向。選擇「基本」以獲得保留一般 ASCII 文字可讀性的輸出;僅在下游系統或傳輸方式明確要求為超過 ASCII 126 的字碼點產生數值參照時,才選擇「非 ASCII」。
  2. 先貼上一小段代表性樣本——一兩個段落,其中包含你在完整區塊中預期會出現的任何重音、表情符號或帶引號的 HTML 屬性內容——然後執行轉換。這是最便宜確認模式選擇的時機。
  3. 檢查結果中的五個保留字元:& 符號應只以 & 形式出現、小於符號為 <、大於符號為 >、雙引號為 "、撇號為 '。確認一般詞彙、數字、空格、定位字元和換行仍能正常閱讀。
  4. 若使用非 ASCII 模式,請抽樣檢查一個重音字元或表情符號,確認參照為大寫十六進位,例如 É 對應 É、😀 對應 😀,而非一對損壞的代理參照。編碼器會逐一走訪 Unicode 字碼點而非 UTF-16 程式碼單位,因此輔助平面的表情符號應以單一參照呈現。
  5. 將完整的大型區塊貼入輸入區域,再次執行轉換,並且僅在確認接收情境——HTML 文位元組點、屬性值、程式碼範例或說明頁面——之後才複製結果。若區塊接近輸入上限,請在安全邊界處切分而非截斷。

在 500,000 字元限制內作業

編碼器將輸入上限設為 500,000 個 JavaScript 字元,以確保作業在本機執行並保持回應速度;這對大多數文件已相當充裕,但對極長的手稿、串接的記錄檔或貼上的多檔匯出內容仍可能不足。實際的工作流程是在安全邊界處——段落結尾、JSON 物件結尾、程式碼區塊結尾、HTML 元素結尾——切分來源,而不是在字串中間切斷,以相同模式編碼每個區塊,然後在貼入目標 HTML 之前串接結果。先對小型樣本執行轉換能一次達成兩件事:確認編碼模式會產生下游系統所預期的參照,並提前發現任何不尋常的內容——控制字元、雜散的空位元組、來源中格式錯誤的 & 符號,或未預期的非 ASCII 字串——避免這些內容擴展到五十萬字元。頁面不會儲存歷史記錄、不會擷取遠端參照表,也不會傳輸輸入資料,因此你編碼的每個區塊只會保留在瀏覽器中,並在關閉分頁時消失。

為何解碼輸出需要特別留意

解碼模式比小型編碼表更為廣泛,因為它會要求瀏覽器的 HTML 解析器套用完整的 WHATWG 具名字元參照表,包括舊有別名與解析為多個字碼點的參照,因此幾乎任何你丟進去的參照序列都會以可讀文字的形式回傳。這樣的廣度在大規模時也是一道安全界線:像 <script>alert(1)</script> 這樣的參照序列會解碼為字面的 <script>alert(1)</script> 字元,雖然該工具本身並不會執行此字串,但若將其複製到不安全的 innerHTML 接收端,它會重新變成在頁面中執行的即時標記。應將每個解碼後的值視為不受信任的資料,在實際輸出邊界處套用依情境而定的跳脫,而不是信任解碼器已將途中任何內容中和。解碼結果會放置於純文字唯讀文字區中,因此無法在工具本身內執行,但一旦離開頁面,責任便回到你身上;貼上的內容越大,就越容易遺漏某個需要處理的雜散序列。

當 HTML 跳脫不夠用時

HTML 語法跳脫並不等同於安全地建構 URL 參數、JavaScript 字串常值、CSS 值、SQL 查詢或 HTTP 標頭;在大規模下,混淆這些情境的成本會隨貼上規模而倍增。URL 需要由 URL 編碼器處理百分比編碼;JavaScript 字串需要其本身的引號與反斜線處理;CSS 值則位於另一個解析器中;XML 的預定義實體集遠小於 HTML,且解析參照的方式不同,因此能在 HTML 中解析的參照在 XML 中可能會失敗。此工具無法取代框架的自動跳脫、可信任的樣板引擎、清理器或內容安全政策,而且並不會因為輸入龐大就能取代這些控制項。請將此編碼器用於為 HTML 文位元組點或屬性準備文字的特定工作,在最終輸出邊界將結果交給適當的依情境處理層,並在目標格式不是 HTML 時改用專用工具——例如用於百分比編碼的 URL 解碼器,或用於位元組層級作業的 UTF-8 編碼器 / 解碼器。WHATWG HTML 動態標準具名字元參照清單是解碼器所使用的底層表格,而 MDN 的字元參照詞彙表則說明在現代 UTF-8 HTML 中何時需要或不需要參照。

如需更深入的探討,請參閱 ROT13 解碼器範例:什麼會改變,什麼保持不變。

如需更深入的探討,請參閱 在 Mac 上不使用終端機進行二進位轉文字。