利用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;"> </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 */