若想了解同一段文字在某個版本以不同字型呈現時的閱讀效果,請將兩個版本貼到 Text Diff Checker,點選「Compare lines」,然後查看逐行輸出:每一行新增會以加號標記,每一行刪除會以減號標記,而沒有變動的每一行則使用中性前綴。這個工具完全在您的瀏覽器中執行一個確定性的最長公共子序列(LCS)演算法,所以工作過程中兩端的內容都不會上傳到任何伺服器。每邊最多可接受 500 行以及 200,000 個 UTF-16 字碼單元,這樣的容量足以應付段落、設定檔區塊、文稿草稿,或是想在更換字型或格式後進行比對的短碼片段。比較的單位是整行,而非字元或單字,這代表一行若有修改,會顯示為一處刪除與一處新增,而不會以字元層級的方式標示差異。這種較粗略的單位是有意為之:當一端是襯線字、另一端是等寬字、無襯線字或經過樣式化的 Unicode 時,它能讓 diff 結果保持易讀,因為視覺樣式並不會改變 diff 判斷「兩行是否相等」的依據——只有底層字串本身才會。

how to see text in different fonts
如何以不同字型檢視文字並比較版本

為何基於行的 Diff 能協助您比較不同字型的版本

比較同一段文字的兩個版本,幾乎從來不只是為了排版本身。大多數讀者搜尋「see text in different fonts」的原因,是他們有一個版本以某種方式呈現、另一個版本以另一種方式呈現,並想確認底層用字是否仍然一致,或精準指出哪些行已經不再一致。以行為單位的 diff 很適合這項工作,因為它完全忽略視覺樣式,只回報實際字串內容的變動。這種分離很重要:字型切換——例如把預設的無襯線內文字型換成襯線標題字型——可能會因為連字、字距與字型可用性而隱藏或顯示某些字元,但只要字元本身被保留下來,就不會改變底層那一行。

diff 檢視還能提供一般並排字型預覽無法給您的東西。字型預覽顯示每個版本「看起來」如何;行 diff 則用白話明確告訴您,兩個版本是否逐行說著相同的內容。對於已被重新輸入、機器轉換、從其他程式匯出,或透過 Unicode 產生器加上粗體、斜體、草書或刪除線等樣式的文字,快速做一次行 diff 是確認樣式變動是否動到實質內容、或默默把字母換成了視覺相似的 Unicode 字元的最快方式。

整個比對過程中,兩端的內容都會停留在您的分頁中。Text Diff Checker 不會呼叫任何第三方程式庫或服務,關閉或重新整理頁面後也不會保留任何紀錄。這種純在本機運作的特性在您比較的內容屬於私密性質(例如草稿、設定檔片段、帳號識別碼清單)時特別實用,因為逐列產生結果的過程中,沒有任何資料會離開瀏覽器。

Text Diff Checker 實際比較的內容

比對機制建立於一個確定性的最長公共子序列(LCS)演算法,將每一行視為不可分割的權杖。只有當兩行的字串完全相同時才視為相符,差異比對涵蓋大小寫、前導空格、結尾空格、Tab 鍵、標點符號以及每一個 Unicode 字碼點。演算法會將換行邊界正規化以便分析——CRLF、單獨的 CR 與 LF 都能識別,且 CRLF 算作一個邊界——但會完整保留每一行內部的內容。

這套規則比許多讀者預期的更為嚴格。同一行中任何位置只要有一個字元被修改,整行就會被視為不相等:原始行會被回報為刪除,新行則被回報為新增。即使乍看之下相同,視覺相似的字元、不同的 Unicode 正規化形式,或行內隱藏的空白,都會被標示為變動。比較的單位是整行,而非字元或單字,這是刻意的設計。

元素是否納入行相等的判定?若不同會發生什麼事?
大小寫是"Hello" 與 "hello" 會以一處刪除與一處新增的方式顯示。
前導空格是" item" 與 "item" 不會被視為同一行。
結尾空格是"end" 與 "end " 會被回報為不同的行。
Tab vs. 多個空格是在行內會被視為不同的字碼點。
標點符號是"it's" 與 "its" 會形成一個 delete-plus-add 配對。
Unicode 正規化是預組字符與分解字符形式不會被默默視為相等。
換行邊界(CRLF / LF / CR)分析時予以正規化不會被視為變動;行內的內容會被保留。
非空文字中的空行是空行是有效的權杖,會參與比對。

有關 String.prototype.split 如何處理邊界字元——以及具型陣列如何在固定大小的儲存空間中保存計算後的數量——的參考資料,記載於 MDN 的 String split 以及 typed arrays。底層 JavaScript split 使用的相同邊界規則,會直接影響 diff 如何判斷某行的結尾與下一行的開頭。

如何比較以不同字型呈現的兩個文字版本

  1. 將原始文字貼入左側方框,將以不同字型呈現的版本貼入右側方框。兩個方框都接受最多 500 行以及 200,000 個 UTF-16 字碼單元的純文字;任一邊超過上限會在執行比對前被拒絕,因此不會出現默默截斷的情況。
  2. 選擇 Compare lines。工具會為兩組行陣列建立一個有界限的動態規劃 LCS 長度矩陣,使用精確的行相等判定以及一個確定性的優先規則(當剩餘子序列長度相等時偏好視為新增)向前走訪矩陣一次,然後依來源順序輸出各列。
  3. 檢視輸出結果。兩版本都存在的行會保留中性前綴;只存在於右側的行以加號開頭,代表新增;只存在於左側的行以減號開頭,代表刪除。檢視區底部的摘要會回報新增、刪除與不變的行的數量,這些數字衍生自您所看到的同一批列。

如果您真正的目的是想看自訂字型檔案在選定像素大小下呈現的效果——這項工作超出了本文涵蓋的逐行比對範圍——請在同一個分頁中將該檔案載入 Font Previewer。若想更完整地了解如何在不安裝任何軟體的情況下在本機預覽字型,可參考 how to preview fonts locally in your browser 教學,其中涵蓋了工作流程中的這一部分。

閱讀輸出:加號、減號與不變

整個輸出就是這個單一、依順序排列的檢視結果。它不是獨立的 unified-diff 檔案,也沒有可以自動套用的 patch。每一列都是來自其中一個輸入的完整一行,依來源順序排列,並以一個字元的前綴標示該列的類型:

前綴列類型意義
(中性,無前綴)不變在 LCS 的同一位置上,兩側出現了相同的行。
+新增此行只存在於右側(修改後)版本。
−刪除此行只存在於左側(原始)版本。

檢視區底部的摘要會回報新增、刪除與不變的數量,這些數字衍生自最終的列類型——可視化呈現與摘要數字一定來自同一個結果,所以兩者不會產生矛盾。由於演算法在重複行可能對應多個最佳 LCS 對齊時,採用了明確的優先規則,因此同樣的輸入內容總會產生相同的確定性結果列。

這種確定性正是當您要檢查字型替換是否默默改動了任何字元時,輸出結果值得信賴的原因。使用相同的左右輸入內容執行兩次,會得到位元層級完全相同的列;今天看到的變動,明天在同一個瀏覽器上也會看到相同的變動。編輯任一邊都會清除先前的比對結果,因此每次重新執行都會從乾淨的列集合開始。

行 Diff 不適用的情境

行 diff 刻意採用較粗略的單位,因此在某些情境下它並不是合適的工具。Text Diff Checker 不會加上行號、不會偵測被搬移的區塊、不會忽略空白、不會摺疊字母大小寫、不會剖析程式語言,也不會標示字元層級的編輯。它同樣不會合併衝突,也不會回寫任何一邊的來源。輸出是一個供人檢視的說明性檢視結果,並非適合自動套用的 unified-diff 檔案。

在貼上內容之前,有兩個實際的限制值得留意。首先,兩邊的上限為 500 行以及 200,000 個 UTF-16 字碼單元。任何超過上限的內容都會在建立動態規劃表格之前被拒絕,因此非常龐大的檔案需要採用其他做法。其次,LCS 演算法的運算量與兩邊行數的乘積成正比。這道上限正是讓瀏覽器在您貼入較長輸入時仍能保持回應順暢的關鍵;也因此這個工具被定位為適用於短而專注的比對,而非整份文件的差異比對。

若是針對原始碼儲存庫、版本控管的文字,或任何需要歷史紀錄、檔名、重新命名、修補檔、作者資訊、衝突解決的情境,請使用 Git。對於非常龐大的檔案,請使用串流式或原生差異工具,而非把檔案內容貼到網頁中。若要查看同一行內部的字元層級差異,diff 檢視只能告訴您該行已變動——若要檢視那一行內部的字元差異,您需要使用其他工具,例如以選定像素大小直接並排顯示的字型預覽。

有一項針對「不同字型」這個使用情境的特別提醒:這個工具在它所規範的規則下回報的是精確的字串相等,而非視覺或語意上的等價。即使兩行視覺上相似,只要有任何字元(包含空格)不同,仍會被標示為 delete-plus-add 配對。請務必檢視實際的輸出,並在檢視完成之前保留兩個來源版本。

Preparing Your Text for a Clean Comparison

The diff is only as clean as the text you paste in. A few habits make the output easier to read and reduce false-positive change rows:

  • Normalize line endings on both sides before pasting, especially if one version was exported on Windows and the other on macOS or Linux. The tool already recognizes CRLF, CR, and LF, but mixing boundary styles with stray ones — for example, a CR inside a line — can shift how lines are counted.
  • Decide whether trailing whitespace matters for your use case before pasting. If it does not, run both sides through a whitespace cleaner first; if it does, leave the spaces untouched so the diff reflects reality.
  • Collapse empty-line runs to a single blank line on both sides when blank-line density is not part of what you want to inspect. A quick pass through an empty-line remover on each side removes that source of noise before the comparison runs.
  • Keep capitalization, punctuation, and any Unicode styling exactly as you want them to be compared. Remember that a bold or italic Unicode character is a different code point from its plain counterpart, so styled and unstyled text will not match line for line even when the words are the same.

If your real question is "show me what this phrase looks like in a font I have not installed," load the font file into the Font Previewer and type the phrase at the size you want. The Text Diff Checker is the right tool when your question is "show me whether the strings on the left and the right are actually the same line by line." For a deeper look at the line-by-line reading approach, the guide on reading difficult texts with a line diff walks through the same workflow with extra focus on the reader's point of view.