前端實現(xiàn)文本對比,并高亮顯示差異!
你有沒有想過,常見的代碼差異對比是如何都實現(xiàn)的呢?其實這里面涉及到非常復雜的文本對比算法,本文就來看看如何通過現(xiàn)有工具庫 jsdiff + diff2html 實現(xiàn)文本對比,并高亮顯示差異!
圖片
文本對比
文本對比可以借助 jsdiff 來實現(xiàn),jsdiff 是一個 JavaScript 庫,用于實現(xiàn)文本差異比較。這個庫提供了多種方法來計算和展示兩個文本之間的差異,可以用于多種文本差異比較的場景,比如版本控制、文檔比較、代碼編輯器中的變更高亮等。
jsdiff 基于 Myers 在 1986 年提出的 "An O(ND) Difference Algorithm and its Variations" 算法實現(xiàn)。
jsdiff 是一個非常熱門的工具庫,其 npm 周下載量高達 4000 萬,很多知名前端工具庫都依賴它:
圖片
Github:https://github.com/kpdecker/jsdiff
以下是 jsdiff 提供的 API:
- diffChars - 對兩個文本進行字符級別的差異比較。
- diffWords - 對兩個文本進行單詞級別的差異比較,忽略空白字符。
- diffWordsWithSpace - 對兩個文本進行單詞級別的差異比較,考慮空白字符作為分隔符。
- diffLines - 對兩個文本按行進行差異比較。
- diffSentences - 對兩個文本按句子進行差異比較。
- diffCss - 專門用于比較 CSS 代碼的差異。
- diffJson - 比較兩個 JSON 對象的差異,首先將它們序列化為格式化的 JSON 文本,然后逐行比較。
- diffArrays - 比較兩個數(shù)組,檢查數(shù)組元素的嚴格等同性。
- createTwoFilesPatch - 創(chuàng)建一個包含兩個文件差異的補丁。
- createPatch - 創(chuàng)建一個補丁,通常用于一個文件的前后變化。
- applyPatch - 應用一個給定的補丁到源文本上。
- applyPatches - 應用一個或多個補丁到相應的文件內(nèi)容上。
- parsePatch - 解析一個補丁字符串為結構化的數(shù)據(jù)。
- reversePatch - 反轉一個補丁,使得應用此補丁會撤銷原始的更改。
- convertChangesToXML - 將差異對象轉換為 XML 格式。
- convertChangesToDMP - 將差異對象轉換為 Google 的 diff-match-patch 庫的格式。
在使用 jsdiff 時,首先需要通過以下命令來安裝:
npm install diff --save
安裝完成之后就可以選擇合適的 API 直接使用了。對于文章最開始的例子,就可以借助 createTwoFilesPatch API 來對比兩個文件的差異,它的參數(shù)如下:
createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options)
- oldFileName: 舊文件的文件名。
- newFileName: 新文件的文件名。
- oldStr: 原始字符串值
- newStr: 新的字符串值
- oldHeader: 可選,允許在舊文件的頭部添加額外的信息。
- newHeader: 可選,用于在新文件的頭部添加額外的信息。
- options: 一個包含選項的對象,可以用來自定義補丁的生成方式:
context: 描述應該包含多少行上下文。設置為 Number.MAX_SAFE_INTEGER 或 Infinity 可以包含整個文件內(nèi)容在一個塊(hunk)中。
ignoreWhitespace: 與 diffLines 中的用法相同,用于忽略空白字符差異。默認為 false。
stripTrailingCr: 與 diffLines 中的用法相同,用于在執(zhí)行差異比較之前去除所有尾隨的回車符(\r)。這有助于在比較 UNIX 和 Windows 文本文件時得到有用的差異結果。默認為 false。
代碼如下:
import * as Diff from 'diff';
const oldFile = `{
"projectName": "ExampleProject",
"version": "1.0.0",
"author": "John Doe",
"dependencies": {
"libraryA": "^1.2.3",
"libraryB": "^3.4.5"
},
"devDependencies": {
"toolX": "^0.9.8"
},
"scripts": {
"start": "node index.js"
}
}`;
const newFile = `{
"projectName": "ExampleProject",
"version": "1.0.1",
"author": "Jane Doe",
"dependencies": {
"libraryA": "^1.2.3",
"libraryC": "^7.8.9"
},
"devDependencies": {
"toolX": "^0.9.8",
"toolY": "^2.3.4"
},
"scripts": {
"start": "node app.js",
"test": "npm test"
}
}`;
const diff = Diff.createTwoFilesPatch("舊文件", "新文件", oldFile, newFile);
這里的對比結果 diff 結果如下:
圖片
對比結果有點丑,下面會進行優(yōu)化。
除了 jsdiff,還有一個基于 jsdiff 開發(fā)的 React 庫:react-diff-viewer。它提供了一種簡單易用的方式來展示兩個文本或對象之間的差異,不僅可以對文本進行對比,還可以輸出漂亮的差異對比結果。
圖片
Github:https://github.com/praneshr/react-diff-viewer
高亮顯示差異
如果使用 jsdiff 進行對比,對比結果可能沒那么美觀,可以借助 diff2html 來美化。
diff2html 是一個用于將差異(diff)結果轉換成 HTML 格式的工具,它通常用于在網(wǎng)頁上展示文件或文本內(nèi)容之間的差異。這個庫提供了一種方便的方式來生成美觀的差異比較視圖,使得用戶可以輕松地查看和理解兩個版本之間的變化。
Github:https://github.com/rtfpessoa/diff2html
首先需要進行安裝:
npm install diff2html --save
然后導入使用即可:
import * as Diff2Html from "diff2html";
const outputHtml = Diff2Html.html(diff, {
inputFormat: "diff",
showFiles: true,
matching: "lines",
highlight: true,
outputFormat: "side-by-side",
});
這里的 diff 就是上一步中生成的 diff 結果。
美化后對比如下,更美觀了:
圖片
更多配置可以在其文檔中進行探索。