⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 diff.js

📁 Joomla!是一套获得过多个奖项的内容管理系统(Content Management System, CMS)。Joomla!采用PHP+MySQL数据库开发
💻 JS
📖 第 1 页 / 共 3 页
字号:
// Diff_Match_Patch v1.3// Computes the difference between two texts to create a patch.// Applies the patch onto another text, allowing for errors.// Copyright (C) 2006 Neil Fraser// http://neil.fraser.name/software/diff_match_patch/// This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License// as published by the Free Software Foundation.// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License (www.gnu.org) for more details.// Constants.// Redefine these in your program to override the defaults.// Number of seconds to map a diff before giving up.  (0 for infinity)var DIFF_TIMEOUT = 1.0;// Cost of an empty edit operation in terms of edit characters.var DIFF_EDIT_COST = 4;// Tweak the relative importance (0.0 = accuracy, 1.0 = proximity)var MATCH_BALANCE = 0.5;// At what point is no match declared (0.0 = perfection, 1.0 = very loose)var MATCH_THRESHOLD = 0.5;// The min and max cutoffs used when computing text lengths.var MATCH_MINLENGTH = 100;var MATCH_MAXLENGTH = 1000;// Chunk size for context length.var PATCH_MARGIN = 4;  ////////////////////////////////////////////////////////////////////// //  Diff                                                            ////////////////////////////////////////////////////////////////////////// The data structure representing a diff is an array of tuples:// [[-1, "Hello"], [1, "Goodbye"], [0, " world."]]// which means: delete "Hello", add "Goodbye" and keep " world."function diff_main(text1, text2, checklines) {  // Find the differences between two texts.  Return an array of changes.  // If checklines is present and false, then don't run a line-level diff first to identify the changed areas.  // Check for equality (speedup)  if (text1 == text2)    return [[0, text1]];  if (typeof checklines == 'undefined')    checklines = true;  var a;  // Trim off common prefix (speedup)  a = diff_prefix(text1, text2);  text1 = a[0];  text2 = a[1];  var commonprefix = a[2];  // Trim off common suffix (speedup)  a = diff_suffix(text1, text2);  text1 = a[0];  text2 = a[1];  var commonsuffix = a[2];  var diff, i;  var longtext = text1.length > text2.length ? text1 : text2;  var shorttext = text1.length > text2.length ? text2 : text1;  if (!text1) {  // Just add some text (speedup)    diff = [[1, text2]];  } else if (!text2) { // Just delete some text (speedup)    diff = [[-1, text1]];  } else if ((i = longtext.indexOf(shorttext)) != -1) {    // Shorter text is inside the longer text (speedup)    diff = [[1, longtext.substring(0, i)], [0, shorttext], [1, longtext.substring(i+shorttext.length)]];    // Swap insertions for deletions if diff is reversed.    if (text1.length > text2.length)      diff[0][0] = diff[2][0] = -1;  } else {    longtext = shorttext = null; // Garbage collect    // Check to see if the problem can be split in two.    var hm = diff_halfmatch(text1, text2);    if (hm) {      // A half-match was found, sort out the return data.      var text1_a = hm[0];      var text1_b = hm[1];      var text2_a = hm[2];      var text2_b = hm[3];      var mid_common = hm[4];      // Send both pairs off for separate processing.      var diff_a = diff_main(text1_a, text2_a, checklines);      var diff_b = diff_main(text1_b, text2_b, checklines);      // Merge the results.      diff = diff_a.concat([[0, mid_common]], diff_b);    } else {      // Perform a real diff.      if (checklines && text1.length + text2.length < 250)        checklines = false; // Too trivial for the overhead.      if (checklines) {        // Scan the text on a line-by-line basis first.        a = diff_lines2chars(text1, text2);        text1 = a[0];        text2 = a[1];        var linearray = a[2];      }      diff = diff_map(text1, text2);      if (!diff) // No acceptable result.        diff = [[-1, text1], [1, text2]];      if (checklines) {        diff_chars2lines(diff, linearray); // Convert the diff back to original text.        diff_cleanup_semantic(diff); // Eliminate freak matches (e.g. blank lines)        // Rediff any replacement blocks, this time on character-by-character basis.        diff.push([0, '']);  // Add a dummy entry at the end.        var pointer = 0;        var count_delete = 0;        var count_insert = 0;        var text_delete = '';        var text_insert = '';        while(pointer < diff.length) {          if (diff[pointer][0] == 1) {            count_insert++;            text_insert += diff[pointer][1];          } else if (diff[pointer][0] == -1) {            count_delete++;            text_delete += diff[pointer][1];          } else {  // Upon reaching an equality, check for prior redundancies.            if (count_delete >= 1 && count_insert >= 1) {              // Delete the offending records and add the merged ones.              a = diff_main(text_delete, text_insert, false);              diff.splice(pointer - count_delete - count_insert, count_delete + count_insert);              pointer = pointer - count_delete - count_insert;              for (i=a.length-1; i>=0; i--)                diff.splice(pointer, 0, a[i]);              pointer = pointer + a.length;            }            count_insert = 0;            count_delete = 0;            text_delete = '';            text_insert = '';          }          pointer++;        }        diff.pop();  // Remove the dummy entry at the end.      }    }  }  if (commonprefix)    diff.unshift([0, commonprefix]);  if (commonsuffix)    diff.push([0, commonsuffix]);  diff_cleanup_merge(diff);  return diff;}function diff_lines2chars(text1, text2) {  // Split text into an array of strings.  // Reduce the texts to a string of hashes where each character represents one line.  var linearray = new Array();  // linearray[4] == "Hello\n"  var linehash = new Object();  // linehash["Hello\n"] == 4  // "\x00" is a valid JavaScript character, but the Venkman debugger doesn't like it (bug 335098)  // So we'll insert a junk entry to avoid generating a null character.  linearray.push('');  function diff_lines2chars_munge(text) {    // My first ever closure!    var i, line;    var chars = '';    while (text) {      i = text.indexOf('\n');      if (i == -1)        i = text.length;      line = text.substring(0, i+1);      text = text.substring(i+1);      if (linehash.hasOwnProperty ? linehash.hasOwnProperty(line) : (linehash[line] !== undefined)) {        chars += String.fromCharCode(linehash[line]);      } else {        linearray.push(line);        linehash[line] = linearray.length - 1;        chars += String.fromCharCode(linearray.length - 1);      }    }    return chars;  }  var chars1 = diff_lines2chars_munge(text1);  var chars2 = diff_lines2chars_munge(text2);  return [chars1, chars2, linearray];}function diff_chars2lines(diff, linearray) {  // Rehydrate the text in a diff from a string of line hashes to real lines of text.  var chars, text;  for (var x=0; x<diff.length; x++) {    chars = diff[x][1];    text = '';    for (var y=0; y<chars.length; y++)      text += linearray[chars.charCodeAt(y)];    diff[x][1] = text;  }}function diff_map(text1, text2) {  // Explore the intersection points between the two texts.  var now = new Date();  var ms_end = now.getTime() + DIFF_TIMEOUT * 1000; // Don't run for too long.  var max = (text1.length + text2.length) / 2;  var v_map1 = new Array();  var v_map2 = new Array();  var v1 = new Object();  var v2 = new Object();  v1[1] = 0;  v2[1] = 0;  var x, y;  var footstep; // Used to track overlapping paths.  var footsteps = new Object();  var done = false;  var hasOwnProperty = !!(footsteps.hasOwnProperty);  // If the total number of characters is odd, then the front path will collide with the reverse path.  var front = (text1.length + text2.length) % 2;  for (var d=0; d<max; d++) {    now = new Date();    if (DIFF_TIMEOUT > 0 && now.getTime() > ms_end) // Timeout reached      return null;    // Walk the front path one step.    v_map1[d] = new Object();    for (var k=-d; k<=d; k+=2) {      if (k == -d || k != d && v1[k-1] < v1[k+1])        x = v1[k+1];      else        x = v1[k-1]+1;      y = x - k;      footstep = x+","+y;      if (front && (hasOwnProperty ? footsteps.hasOwnProperty(footstep) : (footsteps[footstep] !== undefined)))        done = true;      if (!front)        footsteps[footstep] = d;      while (!done && x < text1.length && y < text2.length && text1.charAt(x) == text2.charAt(y)) {        x++; y++;        footstep = x+","+y;        if (front && (hasOwnProperty ? footsteps.hasOwnProperty(footstep) : (footsteps[footstep] !== undefined)))          done = true;        if (!front)          footsteps[footstep] = d;      }      v1[k] = x;      v_map1[d][x+","+y] = true;      if (done) {        // Front path ran over reverse path.        v_map2 = v_map2.slice(0, footsteps[footstep]+1);        var a = diff_path1(v_map1, text1.substring(0, x), text2.substring(0, y));        return a.concat(diff_path2(v_map2, text1.substring(x), text2.substring(y)));      }    }    // Walk the reverse path one step.    v_map2[d] = new Object();    for (var k=-d; k<=d; k+=2) {      if (k == -d || k != d && v2[k-1] < v2[k+1])        x = v2[k+1];      else        x = v2[k-1]+1;      y = x - k;      footstep = (text1.length-x)+","+(text2.length-y);      if (!front && (hasOwnProperty ? footsteps.hasOwnProperty(footstep) : (footsteps[footstep] !== undefined)))        done = true;      if (front)        footsteps[footstep] = d;      while (!done && x < text1.length && y < text2.length && text1.charAt(text1.length-x-1) == text2.charAt(text2.length-y-1)) {        x++; y++;        footstep = (text1.length-x)+","+(text2.length-y);        if (!front && (hasOwnProperty ? footsteps.hasOwnProperty(footstep) : (footsteps[footstep] !== undefined)))          done = true;        if (front)          footsteps[footstep] = d;      }      v2[k] = x;      v_map2[d][x+","+y] = true;      if (done) {        // Reverse path ran over front path.        v_map1 = v_map1.slice(0, footsteps[footstep]+1);        var a = diff_path1(v_map1, text1.substring(0, text1.length-x), text2.substring(0, text2.length-y));        return a.concat(diff_path2(v_map2, text1.substring(text1.length-x), text2.substring(text2.length-y)));      }    }  }  // Number of diffs equals number of characters, no commonality at all.  return null;}function diff_path1(v_map, text1, text2) {  // Work from the middle back to the start to determine the path.  var path = [];  var x = text1.length;  var y = text2.length;  var last_op = null;  for (var d=v_map.length-2; d>=0; d--) {    while(1) {      if (v_map[d].hasOwnProperty ? v_map[d].hasOwnProperty((x-1)+","+y) : (v_map[d][(x-1)+","+y] !== undefined)) {        x--;        if (last_op === -1)          path[0][1] = text1.charAt(x) + path[0][1];        else          path.unshift([-1, text1.charAt(x)]);        last_op = -1;        break;      } else if (v_map[d].hasOwnProperty ? v_map[d].hasOwnProperty(x+","+(y-1)) : (v_map[d][x+","+(y-1)] !== undefined)) {        y--;        if (last_op === 1)          path[0][1] = text2.charAt(y) + path[0][1];        else          path.unshift([1, text2.charAt(y)]);        last_op = 1;        break;      } else {        x--;        y--;        //if (text1.charAt(x) != text2.charAt(y))        //  return alert("No diagonal.  Can't happen. (diff_path1)");        if (last_op === 0)          path[0][1] = text1.charAt(x) + path[0][1];        else          path.unshift([0, text1.charAt(x)]);        last_op = 0;      }    }  }  return path;}function diff_path2(v_map, text1, text2) {  // Work from the middle back to the end to determine the path.  var path = [];  var x = text1.length;  var y = text2.length;  var last_op = null;  for (var d=v_map.length-2; d>=0; d--) {    while(1) {      if (v_map[d].hasOwnProperty ? v_map[d].hasOwnProperty((x-1)+","+y) : (v_map[d][(x-1)+","+y] !== undefined)) {        x--;        if (last_op === -1)          path[path.length-1][1] += text1.charAt(text1.length-x-1);        else          path.push([-1, text1.charAt(text1.length-x-1)]);        last_op = -1;        break;      } else if (v_map[d].hasOwnProperty ? v_map[d].hasOwnProperty(x+","+(y-1)) : (v_map[d][x+","+(y-1)] !== undefined)) {        y--;        if (last_op === 1)          path[path.length-1][1] += text2.charAt(text2.length-y-1);        else          path.push([1, text2.charAt(text2.length-y-1)]);        last_op = 1;        break;      } else {        x--;        y--;        //if (text1.charAt(text1.length-x-1) != text2.charAt(text2.length-y-1))        //  return alert("No diagonal.  Can't happen. (diff_path2)");        if (last_op === 0)          path[path.length-1][1] += text1.charAt(text1.length-x-1);        else          path.push([0, text1.charAt(text1.length-x-1)]);        last_op = 0;      }    }  }  return path;}function diff_prefix(text1, text2) {  // Trim off common prefix  var pointermin = 0;  var pointermax = Math.min(text1.length, text2.length);  var pointermid = pointermax;  while(pointermin < pointermid) {    if (text1.substring(0, pointermid) == text2.substring(0, pointermid))      pointermin = pointermid;    else      pointermax = pointermid;    pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);  }  var commonprefix = text1.substring(0, pointermid);  text1 = text1.substring(pointermid);  text2 = text2.substring(pointermid);  return [text1, text2, commonprefix];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -