diff --git a/src/diff/line.js b/src/diff/line.js
index f9b4f499..5852f75e 100644
--- a/src/diff/line.js
+++ b/src/diff/line.js
@@ -12,22 +12,60 @@ lineDiff.tokenize = function(value) {
}
// Merge the content and line separators into single tokens
- for (let i = 0; i < linesAndNewlines.length; i++) {
- let line = linesAndNewlines[i];
-
- if (i % 2 && !this.options.newlineIsToken) {
- retLines[retLines.length - 1] += line;
- } else {
- if (this.options.ignoreWhitespace) {
- line = line.trim();
+ if (this.options.ignoreWhitespace) {
+ for (let i = 0; i < linesAndNewlines.length; i++) {
+ let line = linesAndNewlines[i];
+
+ if (i % 2 && !this.options.newlineIsToken) {
+ let last = retLines[retLines.length - 1];
+ last.key += line;
+ last.payload += line;
+ } else {
+ retLines.push({ key: line.trim(), payload: line });
+ }
+ }
+ } else {
+ for (let i = 0; i < linesAndNewlines.length; i++) {
+ let line = linesAndNewlines[i];
+
+ if (i % 2 && !this.options.newlineIsToken) {
+ retLines[retLines.length - 1] += line;
+ } else {
+ retLines.push(line);
}
- retLines.push(line);
}
}
return retLines;
};
+lineDiff.removeEmpty = function(array) {
+ if (this.options.ignoreWhitespace) {
+ return array.filter(v => v.key);
+ }
+ return array.filter(v => v);
+};
+
+lineDiff.equals = function(left, right) {
+ if (this.options.ignoreWhitespace) {
+ // Special case handle for when one terminal is ignored (i.e. whitespace).
+ // For this case we merge the terminal into the prior string and drop the change.
+ // This is only available for string mode.
+ if (left === '') {
+ return Diff.prototype.equals.call(this, left, right.trim());
+ }
+ return Diff.prototype.equals.call(this, left.key, right.key);
+ }
+ return Diff.prototype.equals.call(this, left, right);
+};
+
+lineDiff.join = function(result) {
+ if (this.options.ignoreWhitespace) {
+ return result.map(v => v.payload).join('');
+ }
+ return result.join('');
+};
+
export function diffLines(oldStr, newStr, callback) { return lineDiff.diff(oldStr, newStr, callback); }
export function diffTrimmedLines(oldStr, newStr, callback) {
let options = generateOptions(callback, {ignoreWhitespace: true});
diff --git a/test/diff/line.js b/test/diff/line.js
index 5c2c7657..48d96f15 100644
--- a/test/diff/line.js
+++ b/test/diff/line.js
@@ -64,17 +64,52 @@ describe('diff/line', function() {
});
it('should ignore leading and trailing whitespace', function() {
- const diffResult = diffTrimmedLines(
+ const diffResult1 = diffTrimmedLines(
'line\nvalue \nline',
'line\nvalue\nline');
- expect(convertChangesToXML(diffResult)).to.equal('line\nvalue\nline');
+ expect(convertChangesToXML(diffResult1)).to.equal('line\nvalue\nline');
+
+ const diffResult2 = diffTrimmedLines(
+ 'line\nvalue\nline',
+ 'line\nvalue \nline');
+ expect(convertChangesToXML(diffResult2)).to.equal('line\nvalue \nline');
+
+ const diffResult3 = diffTrimmedLines(
+ 'line\n value\nline',
+ 'line\nvalue\nline');
+ expect(convertChangesToXML(diffResult3)).to.equal('line\nvalue\nline');
+
+ const diffResult4 = diffTrimmedLines(
+ 'line\nvalue\nline',
+ 'line\n value\nline');
+ expect(convertChangesToXML(diffResult4)).to.equal('line\n value\nline');
+ });
+
+ it('should keep leading and trailing whitespace in the output', function() {
+ function stringify(value) {
+ return JSON.stringify(value, null, 2);
+ }
+ const diffResult = diffTrimmedLines(
+ stringify([10, 20, 30]),
+ stringify({ data: [10, 42, 30] }));
+ expect(convertChangesToXML(diffResult)).to.equal([
+ '[\n',
+ '{\n',
+ ' "data": [\n',
+ ' 10,\n',
+ ' 20,\n',
+ ' 42,\n',
+ ' 30\n',
+ '] ]\n',
+ '}'
+ ].join('').replace(/"/g, '"'));
});
it('should handle windows line endings', function() {
const diffResult = diffTrimmedLines(
'line\r\nold value \r\nline',
'line\r\nnew value\r\nline');
- expect(convertChangesToXML(diffResult)).to.equal('line\r\nold value\r\nnew value\r\nline');
+ expect(convertChangesToXML(diffResult)).to.equal('line\r\nold value \r\nnew value\r\nline');
});
});