add CodeMirror's merge.js addon + modify imported diff code for compatibility

This commit is contained in:
Raymond Hill 2018-03-11 10:59:02 -04:00
parent 2aa704651d
commit caef7d00bb
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
3 changed files with 1289 additions and 141 deletions

113
src/lib/codemirror/addon/merge/merge.css vendored Normal file
View File

@ -0,0 +1,113 @@
.CodeMirror-merge {
position: relative;
border: 1px solid #ddd;
white-space: pre;
}
.CodeMirror-merge, .CodeMirror-merge .CodeMirror {
height: 350px;
}
.CodeMirror-merge-2pane .CodeMirror-merge-pane { width: 47%; }
.CodeMirror-merge-2pane .CodeMirror-merge-gap { width: 6%; }
.CodeMirror-merge-3pane .CodeMirror-merge-pane { width: 31%; }
.CodeMirror-merge-3pane .CodeMirror-merge-gap { width: 3.5%; }
.CodeMirror-merge-pane {
display: inline-block;
white-space: normal;
vertical-align: top;
}
.CodeMirror-merge-pane-rightmost {
position: absolute;
right: 0px;
z-index: 1;
}
.CodeMirror-merge-gap {
z-index: 2;
display: inline-block;
height: 100%;
-moz-box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
position: relative;
background: #f8f8f8;
}
.CodeMirror-merge-scrolllock-wrap {
position: absolute;
bottom: 0; left: 50%;
}
.CodeMirror-merge-scrolllock {
position: relative;
left: -50%;
cursor: pointer;
color: #555;
line-height: 1;
}
.CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right {
position: absolute;
left: 0; top: 0;
right: 0; bottom: 0;
line-height: 1;
}
.CodeMirror-merge-copy {
position: absolute;
cursor: pointer;
color: #44c;
z-index: 3;
}
.CodeMirror-merge-copy-reverse {
position: absolute;
cursor: pointer;
color: #44c;
}
.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; }
.CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; }
.CodeMirror-merge-r-inserted, .CodeMirror-merge-l-inserted {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==);
background-position: bottom left;
background-repeat: repeat-x;
}
.CodeMirror-merge-r-deleted, .CodeMirror-merge-l-deleted {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==);
background-position: bottom left;
background-repeat: repeat-x;
}
.CodeMirror-merge-r-chunk { background: #ffffe0; }
.CodeMirror-merge-r-chunk-start { border-top: 1px solid #ee8; }
.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #ee8; }
.CodeMirror-merge-r-connect { fill: #ffffe0; stroke: #ee8; stroke-width: 1px; }
.CodeMirror-merge-l-chunk { background: #eef; }
.CodeMirror-merge-l-chunk-start { border-top: 1px solid #88e; }
.CodeMirror-merge-l-chunk-end { border-bottom: 1px solid #88e; }
.CodeMirror-merge-l-connect { fill: #eef; stroke: #88e; stroke-width: 1px; }
.CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; }
.CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; }
.CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; }
.CodeMirror-merge-collapsed-widget:before {
content: "(...)";
}
.CodeMirror-merge-collapsed-widget {
cursor: pointer;
color: #88b;
background: #eef;
border: 1px solid #ddf;
font-size: 90%;
padding: 0 3px;
border-radius: 4px;
}
.CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt { display: none; }

1001
src/lib/codemirror/addon/merge/merge.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,55 @@
/* vim: set shiftwidth=2 tabstop=2 noexpandtab textwidth=80 wrap : */ /*******************************************************************************
"use strict";
module.exports = diff; Key portions of code below was borrowed from:
https://github.com/Swatinem/diff
function diff(a, b, eql) { License is LGPL3 (thanks!) as per:
if (!eql) https://github.com/Swatinem/diff/blob/b58391504759/README.md
eql = function (a, b) { return a === b; };
var d = new Diff(a, b, eql); I chose to pick this implementation over
https://github.com/google/diff-match-patch as suggested by CodeMirror
because:
- Code is clean and simple to read -- useful when unfamiliar with the diff
algorithm, this makes changing the code easier if/when needed.
- Smaller -- diff_match_patch comes with an extended API most of which is
of no use to the current project.
- diff_match_patch uncompressed: 74.7 KB
- Swatinem's diff uncompressed: 3.66 KB
- I can easily adapt Swatinem's diff to deal with arrays of strings, which
is best suited for the current project -- it natively work with arrays.
I removed portions of code which are of no use for the current project.
I modified the diff script generator (Diff.prototype.editscript) since I
need to generate a script which is compatible with the output of the
diff_match_patch, as expected by CodeMirror.
**/
'use strict';
(function(context) {
// CodeMirror expect these globals:
context.DIFF_INSERT = 1;
context.DIFF_DELETE = -1;
context.DIFF_EQUAL = 0;
context.diff_match_patch = function(){};
context.diff_match_patch.prototype.diff_main = function(a, b) {
if ( a === b ) { return [ [ 0, a ] ]; }
var aa = a.match(/\n|[^\n]+\n?/g) || [];
var bb = b.match(/\n|[^\n]+\n?/g) || [];
var d = new Diff(aa, bb, eqlDefault);
return d.editscript(); return d.editscript();
} };
diff.Diff = Diff; function eqlDefault(a, b) { return a === b; }
function Diff(a, b, eql) { function Diff(a, b, eql) {
this.a = a; this.a = a;
this.b = b; this.b = b;
this.eql = eql; this.eql = eql;
@ -26,14 +62,9 @@ function Diff(a, b, eql) {
this.up = {}; this.up = {};
this.lcs(0, a.length, 0, b.length); this.lcs(0, a.length, 0, b.length);
} }
Diff.NOOP = 'nop'; Diff.prototype.editscript = function Diff_editscript() {
Diff.DELETE = 'del';
Diff.INSERT = 'ins';
Diff.REPLACE = 'rep';
Diff.prototype.editscript = function Diff_editscript() {
var moda = this.moda, modb = this.modb; var moda = this.moda, modb = this.modb;
var astart = 0, aend = moda.length; var astart = 0, aend = moda.length;
var bstart = 0, bend = modb.length; var bstart = 0, bend = modb.length;
@ -41,28 +72,29 @@ Diff.prototype.editscript = function Diff_editscript() {
while (astart < aend || bstart < bend) { while (astart < aend || bstart < bend) {
if (astart < aend && bstart < bend) { if (astart < aend && bstart < bend) {
if (!moda[astart] && !modb[bstart]) { if (!moda[astart] && !modb[bstart]) {
result.push(Diff.NOOP); result.push([ 0, this.a[astart] ]);
astart++; bstart++; astart++; bstart++;
continue; continue;
} else if (moda[astart] && modb[bstart]) { } else if (moda[astart] && modb[bstart]) {
result.push(Diff.REPLACE); result.push([ -1, this.a[astart] ]);
result.push([ 1, this.b[bstart] ]);
astart++; bstart++; astart++; bstart++;
continue; continue;
} }
} }
if (astart < aend && (bstart >= bend || moda[astart])) { if (astart < aend && (bstart >= bend || moda[astart])) {
result.push(Diff.DELETE); result.push([ -1, this.a[astart] ]);
astart++; astart++;
} }
if (bstart < bend && (astart >= aend || modb[bstart])) { if (bstart < bend && (astart >= aend || modb[bstart])) {
result.push(Diff.INSERT); result.push([ 1, this.b[bstart] ]);
bstart++; bstart++;
} }
} }
return result; return result;
}; };
Diff.prototype.lcs = function Diff_lcs(astart, aend, bstart, bend) { Diff.prototype.lcs = function Diff_lcs(astart, aend, bstart, bend) {
var a = this.a, b = this.b, eql = this.eql; var a = this.a, b = this.b, eql = this.eql;
// separate common head // separate common head
while (astart < aend && bstart < bend && eql(a[astart], b[bstart])) { while (astart < aend && bstart < bend && eql(a[astart], b[bstart])) {
@ -91,9 +123,9 @@ Diff.prototype.lcs = function Diff_lcs(astart, aend, bstart, bend) {
this.lcs(astart, snake.x, bstart, snake.y); this.lcs(astart, snake.x, bstart, snake.y);
this.lcs(snake.u, aend, snake.v, bend); this.lcs(snake.u, aend, snake.v, bend);
} }
}; };
Diff.prototype.snake = function Diff_snake(astart, aend, bstart, bend) { Diff.prototype.snake = function Diff_snake(astart, aend, bstart, bend) {
var a = this.a, b = this.b, eql = this.eql; var a = this.a, b = this.b, eql = this.eql;
var N = aend - astart, var N = aend - astart,
@ -169,5 +201,7 @@ Diff.prototype.snake = function Diff_snake(astart, aend, bstart, bend) {
} }
} }
} }
}; };
return Diff;
})(self);