JQ 實現對比兩個文本的差異並高亮顯示差異部分

来源:https://www.cnblogs.com/zxf100/archive/2022/07/06/16452557.html
-Advertisement-
Play Games

利用jq對比兩段文本的差異,差異的內容用不同顏色表示出來。 線上參考demo:http://incaseofstairs.com/jsdiff/ 項目地址:https://github.com/kpdecker/jsdiff 先上效果圖: 左側第一列是原稿,第二列是需要對比稿,第三列是對比後的結果。 ...


利用jq對比兩段文本的差異,差異的內容用不同顏色表示出來。

線上參考demo:
http://incaseofstairs.com/jsdiff/

項目地址:
https://github.com/kpdecker/jsdiff

先上效果圖:

 

 左側第一列是原稿,第二列是需要對比稿,第三列是對比後的結果。

紅色文字刪除線表示對比稿相對原稿缺少的文字,綠色下劃線文字表示對比稿相對原稿新增的文字。

同時支持三種方式:Chars,以字元顯示差異;Words,以整句或段顯示對比差異;Lines以行顯示差異。

 

html源碼:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>比較文本差異</title>
    <style type="text/css">
        table { width: 100%; height: 600px; }
        tr { flex-direction: row; display: -webkit-flex; display: flex; height: 100%; -webkit-flex-wrap: wrap; flex-wrap: wrap; }
            tr td { width: 33%; border: 1px solid #000000; }
        del { background: #ff0000; }
        ins { background: #00ff21; }
    </style>
</head>
<body>

    <div id="settings">
        <h1>比較文本差異(只適合比較純文本且不帶html標簽)</h1>
        <label><input type="radio" name="diff_type" value="diffChars" checked> Chars</label>
        <label><input type="radio" name="diff_type" value="diffWords"> Words</label>
        <label><input type="radio" name="diff_type" value="diffLines"> Lines</label>
    </div>
    <a href="https://github.com/kpdecker/jsdiff" class="source">github.com/kpdecker/jsdiff</a>
    <table>
        <tr>
            <td contenteditable="true" id="a">restaurant</td>
            <td contenteditable="true" id="b">aura</td>
            <td><div id="result"></div></td>
        </tr>
    </table>

    <script src="/static/index/js/diff.js"></script>
    <script defer>
        var a = document.getElementById('a');
        var b = document.getElementById('b');
        var result = document.getElementById('result');

        function changed() {
            console.log('***********************************************');
            var oldContent = a.textContent;
            var content1 = b.textContent;

            //console.log("content1-----");
            //console.log(content1);

            //diffChars以字元顯示差異
            //diffWords以整句或段顯示對比差異
            //diffLines以行顯示差異
            //window.diffType
            var diff = JsDiff[window.diffType](oldContent, content1);
            var arr = new Array();
            for (var i = 0; i < diff.length; i++) {
                if (diff[i].added && diff[i + 1] && diff[i + 1].removed) {
                    var swap = diff[i];
                    diff[i] = diff[i + 1];
                    diff[i + 1] = swap;
                }
                console.log(diff[i]);
                var diffObj = diff[i];
                var content = diffObj.value;

                //可以考慮啟用,特別是後臺清理HTML標簽後的文本
                if (content.indexOf("\n") >= 0) {
                    //console.log("有換行符");
                    //替換為<br/>
                    var reg = new RegExp('\n', 'g');
                    content = content.replace(reg, '<br/>');
                }

                //var reg2 = new RegExp('##em2', 'g');
                //var reg3 = new RegExp('replace##', 'g');
                //content = content.replace(reg2, '');
                //content = content.replace(reg3, '');

                if (diffObj.removed) {
                    arr.push('<del title="刪除的部分">' + content + '</del>');
                } else if (diffObj.added) {
                    arr.push('<ins title="新增的部分">' + content + '</ins>');
                } else {
                    //沒有改動的部分
                    arr.push('<span title="沒有改動的部分">' + content + '</span>');
                }
            }
            var html = arr.join('');
            //var reg = new RegExp('##em2.replace##', 'g');
            //html = html.replace(reg, '<span style="text-indent:2em;display: inline-block;">&nbsp;</span>');
            //$("#" + newId+"_show").html(html);
            //$("#result").html(html);
            result.innerHTML = html;
        }
        //function changed() {
        //    var diff = JsDiff[window.diffType](a.textContent, b.textContent);
        //    var fragment = document.createDocumentFragment();
        //    for (var i=0; i < diff.length; i++) {
        //        if (diff[i].added && diff[i + 1] && diff[i + 1].removed) {
        //            var swap = diff[i];
        //            diff[i] = diff[i + 1];
        //            diff[i + 1] = swap;
        //        }
        //        var node;
        //        if (diff[i].removed) {
        //            node = document.createElement('del');
        //            node.appendChild(document.createTextNode(diff[i].value));
        //        } else if (diff[i].added) {
        //            node = document.createElement('ins');
        //            node.appendChild(document.createTextNode(diff[i].value));
        //        } else {
        //            node = document.createTextNode(diff[i].value);
        //        }
        //        fragment.appendChild(node);
        //    }
        //    result.textContent = '';
        //    result.appendChild(fragment);
        //}

        window.onload = function () {
            onDiffTypeChange(document.querySelector('#settings [name="diff_type"]:checked'));
            changed();
        };

        a.onpaste = a.onchange =
            b.onpaste = b.onchange = changed;

        if ('oninput' in a) {
            a.oninput = b.oninput = changed;
        } else {
            a.onkeyup = b.onkeyup = changed;
        }

        function onDiffTypeChange(radio) {
            window.diffType = radio.value;
            document.title = "Diff " + radio.value.slice(4);
        }

        var radio = document.getElementsByName('diff_type');
        for (var i = 0; i < radio.length; i++) {
            radio[i].onchange = function (e) {
                onDiffTypeChange(e.target);
                changed();
            }
        }
    </script>
</body>
</html>

 

JQ代碼

/*!

 diff v2.0.1

Software License Agreement (BSD License)

Copyright (c) 2009-2015, Kevin Decker <[email protected]>

All rights reserved.

Redistribution and use of this software in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above
  copyright notice, this list of conditions and the
  following disclaimer.

* Redistributions in binary form must reproduce the above
  copyright notice, this list of conditions and the
  following disclaimer in the documentation and/or other
  materials provided with the distribution.

* Neither the name of Kevin Decker nor the names of its
  contributors may be used to endorse or promote products
  derived from this software without specific prior
  written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@license
*/
(function webpackUniversalModuleDefinition(root, factory) {
    if(typeof exports === 'object' && typeof module === 'object')
        module.exports = factory();
    else if(typeof define === 'function' && define.amd)
        define(factory);
    else if(typeof exports === 'object')
        exports["JsDiff"] = factory();
    else
        root["JsDiff"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/     // The module cache
/******/     var installedModules = {};

/******/     // The require function
/******/     function __webpack_require__(moduleId) {

/******/         // Check if module is in cache
/******/         if(installedModules[moduleId])
/******/             return installedModules[moduleId].exports;

/******/         // Create a new module (and put it into the cache)
/******/         var module = installedModules[moduleId] = {
/******/             exports: {},
/******/             id: moduleId,
/******/             loaded: false
/******/         };

/******/         // Execute the module function
/******/         modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/         // Flag the module as loaded
/******/         module.loaded = true;

/******/         // Return the exports of the module
/******/         return module.exports;
/******/     }


/******/     // expose the modules object (__webpack_modules__)
/******/     __webpack_require__.m = modules;

/******/     // expose the module cache
/******/     __webpack_require__.c = installedModules;

/******/     // __webpack_public_path__
/******/     __webpack_require__.p = "";

/******/     // Load entry module and return exports
/******/     return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

    /* See LICENSE file for terms of use */

    /*
     * Text diff implementation.
     *
     * This library supports the following APIS:
     * JsDiff.diffChars: Character by character diff
     * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace
     * JsDiff.diffLines: Line based diff
     *
     * JsDiff.diffCss: Diff targeted at CSS content
     *
     * These methods are based on the implementation proposed in
     * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986).
     * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927
     */
    'use strict';

    exports.__esModule = true;
    // istanbul ignore next

    function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

    var _diffBase = __webpack_require__(1);

    var _diffBase2 = _interopRequireDefault(_diffBase);

    var _diffCharacter = __webpack_require__(3);

    var _diffWord = __webpack_require__(4);

    var _diffLine = __webpack_require__(5);

    var _diffSentence = __webpack_require__(6);

    var _diffCss = __webpack_require__(7);

    var _diffJson = __webpack_require__(8);

    var _patchApply = __webpack_require__(9);

    var _patchCreate = __webpack_require__(10);

    var _convertDmp = __webpack_require__(12);

    var _convertXml = __webpack_require__(13);

    exports.Diff = _diffBase2['default'];
    exports.diffChars = _diffCharacter.diffChars;
    exports.diffWords = _diffWord.diffWords;
    exports.diffWordsWithSpace = _diffWord.diffWordsWithSpace;
    exports.diffLines = _diffLine.diffLines;
    exports.diffTrimmedLines = _diffLine.diffTrimmedLines;
    exports.diffSentences = _diffSentence.diffSentences;
    exports.diffCss = _diffCss.diffCss;
    exports.diffJson = _diffJson.diffJson;
    exports.structuredPatch = _patchCreate.structuredPatch;
    exports.createTwoFilesPatch = _patchCreate.createTwoFilesPatch;
    exports.createPatch = _patchCreate.createPatch;
    exports.applyPatch = _patchApply.applyPatch;
    exports.convertChangesToDMP = _convertDmp.convertChangesToDMP;
    exports.convertChangesToXML = _convertXml.convertChangesToXML;
    exports.canonicalize = _diffJson.canonicalize;


/***/ },
/* 1 */
              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 近日,中國信通院、雲計算開源產業聯盟正式對外發佈《雲原生產品目錄》,騰訊雲原生資料庫TDSQL-C憑藉其超強性能、極致效率的彈性伸縮和完善的產品化解決方案體系,成功入圍目錄。 全球數字經濟進入高速發展期,在敏捷、高效、降本需求的驅動下,雲原生已經成為提升雲計算使用效能的關鍵支撐,正引領新一代軟體架構 ...
  • 機器規劃 環境準備 安裝JDK 1. 在所有機器上安裝jdk8 2. 配置好環境變數 vi /etc/profile JAVA_HOME=/usr/local/jdk1.8.0_152 PATH=$PATH:$JAVA_HOME/bin export JAVA_HOME export PATH so ...
  • 7月4日,國際權威機構IDC發佈的《2021年下半年中國關係型資料庫軟體市場跟蹤報告》顯示,騰訊雲資料庫在關係型資料庫軟體市場(公有雲模式)中,位列第二。 IDC報告顯示,2021下半年中國關係型資料庫軟體市場規模為15.8億美元,同比增長34.9%。其中,公有雲關係型資料庫規模8.7億美元,同比增 ...
  • #RDD(2) ##RDD轉換運算元 RDD根據數據處理方式的不同將運算元整體上分為Value類型、雙Value類型、Key-Value類型 ###value類型 ####map 函數簽名 def map[U:ClassTag](f:T=>U):RDD[U] 函數說明 將處理的數據逐條進行映射轉換,這裡 ...
  • ZEGO 提供 ZIM + RTC 服務聯動的場景解決方案,公開語聊房、秀場直播等業務場景搭建的示例源碼,幫助開發者能在極短的時間內搭建完美的業務場景。 ...
  • 目前正在做的一個項目需要用到地圖功能,在使用數據線連接到手機進行真機調試的時候,由於uniapp自帶了高德的SDK能夠獲取位置信息,但是在打包成apk後就不行了,原先地圖的位置顯示一片空白,這個時候,就需要我們去高德(或者百度)開放平臺去申請應用的key了,在這裡以高德地圖為例,步驟如下: 第一步: ...
  • 2022年6月,HMS Core機器學習服務面向開發者提供一項全新的開放能力——同聲傳譯,通過AI語音技術減少資源成本,加強溝通交流,旨在幫助開發者製作豐富多樣的同聲傳譯應用。 HMS Core同聲傳譯涵蓋了機器學習服務的語音識別、翻譯、語音合成等核心技術,首先把輸入的實時語音轉換成文字,然後再把文 ...
  • Android系統日誌和工具 我們經常需要查看設備裡面的各種日誌信息。所以有必要瞭解android系統裡面有哪些日誌,以及用什麼方式可以提取這些日誌。以我手頭的紅米note4xplus為例,其基本配置為高通msm8953,android7.0。我們可以看一下根文件系統: mido:/ # ls ac ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...