jsdiff.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * Javascript Diff Algorithm
  3. * By John Resig (http://ejohn.org/)
  4. * Modified by Chu Alan "sprite"
  5. * diffstring2 random colors removed by Richard Bondi for use with jsdifflib
  6. *
  7. * Released under the MIT license.
  8. *
  9. * More Info:
  10. * http://ejohn.org/projects/javascript-diff-algorithm/
  11. *
  12. */
  13. function escape_jsdiff(s) {
  14. var n = s;
  15. n = n.replace(/&/g, "&");
  16. n = n.replace(/</g, "&lt;");
  17. n = n.replace(/>/g, "&gt;");
  18. n = n.replace(/"/g, "&quot;");
  19. return n;
  20. }
  21. function diffString( o, n ) {
  22. o = o.replace(/\s+$/, '');
  23. n = n.replace(/\s+$/, '');
  24. var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) );
  25. var str = "";
  26. var oSpace = o.match(/\s+/g);
  27. if (oSpace == null) {
  28. oSpace = ["\n"];
  29. } else {
  30. oSpace.push("\n");
  31. }
  32. var nSpace = n.match(/\s+/g);
  33. if (nSpace == null) {
  34. nSpace = ["\n"];
  35. } else {
  36. nSpace.push("\n");
  37. }
  38. if (out.n.length == 0) {
  39. for (var i = 0; i < out.o.length; i++) {
  40. str += '<del>' + escape_jsdiff(out.o[i]) + oSpace[i] + "</del>";
  41. }
  42. } else {
  43. if (out.n[0].text == null) {
  44. for (n = 0; n < out.o.length && out.o[n].text == null; n++) {
  45. str += '<del>' + escape_jsdiff(out.o[n]) + oSpace[n] + "</del>";
  46. }
  47. }
  48. for ( var i = 0; i < out.n.length; i++ ) {
  49. if (out.n[i].text == null) {
  50. str += '<ins>' + escape_jsdiff(out.n[i]) + nSpace[i] + "</ins>";
  51. } else {
  52. var pre = "";
  53. for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
  54. pre += '<del>' + escape_jsdiff(out.o[n]) + oSpace[n] + "</del>";
  55. }
  56. str += " " + out.n[i].text + nSpace[i] + pre;
  57. }
  58. }
  59. }
  60. return str;
  61. }
  62. function randomColor() {
  63. return "rgb(" + (Math.random() * 100) + "%, " +
  64. (Math.random() * 100) + "%, " +
  65. (Math.random() * 100) + "%)";
  66. }
  67. function diffString2( o, n ) {
  68. o = o.replace(/\s+$/, '');
  69. n = n.replace(/\s+$/, '');
  70. var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) );
  71. var oSpace = o.match(/\s+/g);
  72. if (oSpace == null) {
  73. oSpace = ["\n"];
  74. } else {
  75. oSpace.push("\n");
  76. }
  77. var nSpace = n.match(/\s+/g);
  78. if (nSpace == null) {
  79. nSpace = ["\n"];
  80. } else {
  81. nSpace.push("\n");
  82. }
  83. var os = "";
  84. var colors = new Array();
  85. for (var i = 0; i < out.o.length; i++) {
  86. colors[i] = randomColor();
  87. if (out.o[i].text != null) {
  88. os += escape_jsdiff(out.o[i].text) + oSpace[i];
  89. } else {
  90. os += "<del>" + escape_jsdiff(out.o[i]) + oSpace[i] + "</del>";
  91. }
  92. }
  93. var ns = "";
  94. for (var i = 0; i < out.n.length; i++) {
  95. if (out.n[i].text != null) {
  96. ns += escape_jsdiff(out.n[i].text) + nSpace[i];
  97. } else {
  98. ns += "<ins>" + escape_jsdiff(out.n[i]) + nSpace[i] + "</ins>";
  99. }
  100. }
  101. return { o : os , n : ns };
  102. }
  103. function diff( o, n ) {
  104. var ns = new Object();
  105. var os = new Object();
  106. for ( var i = 0; i < n.length; i++ ) {
  107. if ( ns[ n[i] ] == null )
  108. ns[ n[i] ] = { rows: new Array(), o: null };
  109. ns[ n[i] ].rows.push( i );
  110. }
  111. for ( var i = 0; i < o.length; i++ ) {
  112. if ( os[ o[i] ] == null )
  113. os[ o[i] ] = { rows: new Array(), n: null };
  114. os[ o[i] ].rows.push( i );
  115. }
  116. for ( var i in ns ) {
  117. if ( ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1 ) {
  118. n[ ns[i].rows[0] ] = { text: n[ ns[i].rows[0] ], row: os[i].rows[0] };
  119. o[ os[i].rows[0] ] = { text: o[ os[i].rows[0] ], row: ns[i].rows[0] };
  120. }
  121. }
  122. for ( var i = 0; i < n.length - 1; i++ ) {
  123. if ( n[i].text != null && n[i+1].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&
  124. n[i+1] == o[ n[i].row + 1 ] ) {
  125. n[i+1] = { text: n[i+1], row: n[i].row + 1 };
  126. o[n[i].row+1] = { text: o[n[i].row+1], row: i + 1 };
  127. }
  128. }
  129. for ( var i = n.length - 1; i > 0; i-- ) {
  130. if ( n[i].text != null && n[i-1].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&
  131. n[i-1] == o[ n[i].row - 1 ] ) {
  132. n[i-1] = { text: n[i-1], row: n[i].row - 1 };
  133. o[n[i].row-1] = { text: o[n[i].row-1], row: i - 1 };
  134. }
  135. }
  136. return { o: o, n: n };
  137. }