Skip to content

Commit 1b186fd

Browse files
committed
Fix kpdecker#241: diffTrimmedLines now keep whitespaces in the output
1 parent 305a2b3 commit 1b186fd

File tree

2 files changed

+85
-12
lines changed

2 files changed

+85
-12
lines changed

Diff for: src/diff/line.js

+47-9
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,60 @@ lineDiff.tokenize = function(value) {
1212
}
1313

1414
// Merge the content and line separators into single tokens
15-
for (let i = 0; i < linesAndNewlines.length; i++) {
16-
let line = linesAndNewlines[i];
17-
18-
if (i % 2 && !this.options.newlineIsToken) {
19-
retLines[retLines.length - 1] += line;
20-
} else {
21-
if (this.options.ignoreWhitespace) {
22-
line = line.trim();
15+
if (this.options.ignoreWhitespace) {
16+
for (let i = 0; i < linesAndNewlines.length; i++) {
17+
let line = linesAndNewlines[i];
18+
19+
if (i % 2 && !this.options.newlineIsToken) {
20+
let last = retLines[retLines.length - 1];
21+
last.key += line;
22+
last.payload += line;
23+
} else {
24+
retLines.push({ key: line.trim(), payload: line });
25+
}
26+
}
27+
} else {
28+
for (let i = 0; i < linesAndNewlines.length; i++) {
29+
let line = linesAndNewlines[i];
30+
31+
if (i % 2 && !this.options.newlineIsToken) {
32+
retLines[retLines.length - 1] += line;
33+
} else {
34+
retLines.push(line);
2335
}
24-
retLines.push(line);
2536
}
2637
}
2738

2839
return retLines;
2940
};
3041

42+
lineDiff.removeEmpty = function(array) {
43+
if (this.options.ignoreWhitespace) {
44+
return array.filter(v => v.key);
45+
}
46+
return array.filter(v => v);
47+
};
48+
49+
lineDiff.equals = function(left, right) {
50+
if (this.options.ignoreWhitespace) {
51+
// Special case handle for when one terminal is ignored (i.e. whitespace).
52+
// For this case we merge the terminal into the prior string and drop the change.
53+
// This is only available for string mode.
54+
if (left === '') {
55+
return Diff.prototype.equals.call(this, left, right.trim());
56+
}
57+
return Diff.prototype.equals.call(this, left.key, right.key);
58+
}
59+
return Diff.prototype.equals.call(this, left, right);
60+
};
61+
62+
lineDiff.join = function(result) {
63+
if (this.options.ignoreWhitespace) {
64+
return result.map(v => v.payload).join('');
65+
}
66+
return result.join('');
67+
};
68+
3169
export function diffLines(oldStr, newStr, callback) { return lineDiff.diff(oldStr, newStr, callback); }
3270
export function diffTrimmedLines(oldStr, newStr, callback) {
3371
let options = generateOptions(callback, {ignoreWhitespace: true});

Diff for: test/diff/line.js

+38-3
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,52 @@ describe('diff/line', function() {
6464
});
6565

6666
it('should ignore leading and trailing whitespace', function() {
67-
const diffResult = diffTrimmedLines(
67+
const diffResult1 = diffTrimmedLines(
6868
'line\nvalue \nline',
6969
'line\nvalue\nline');
70-
expect(convertChangesToXML(diffResult)).to.equal('line\nvalue\nline');
70+
expect(convertChangesToXML(diffResult1)).to.equal('line\nvalue\nline');
71+
72+
const diffResult2 = diffTrimmedLines(
73+
'line\nvalue\nline',
74+
'line\nvalue \nline');
75+
expect(convertChangesToXML(diffResult2)).to.equal('line\nvalue \nline');
76+
77+
const diffResult3 = diffTrimmedLines(
78+
'line\n value\nline',
79+
'line\nvalue\nline');
80+
expect(convertChangesToXML(diffResult3)).to.equal('line\nvalue\nline');
81+
82+
const diffResult4 = diffTrimmedLines(
83+
'line\nvalue\nline',
84+
'line\n value\nline');
85+
expect(convertChangesToXML(diffResult4)).to.equal('line\n value\nline');
86+
});
87+
88+
it('should keep leading and trailing whitespace in the output', function() {
89+
function stringify(value) {
90+
return JSON.stringify(value, null, 2);
91+
}
92+
const diffResult = diffTrimmedLines(
93+
stringify([10, 20, 30]),
94+
stringify({ data: [10, 42, 30] }));
95+
expect(convertChangesToXML(diffResult)).to.equal([
96+
'<del>[\n</del>',
97+
'<ins>{\n',
98+
' "data": [\n</ins>',
99+
' 10,\n',
100+
'<del> 20,\n</del>',
101+
'<ins> 42,\n</ins>',
102+
' 30\n',
103+
'<del>]</del><ins> ]\n',
104+
'}</ins>'
105+
].join('').replace(/"/g, '&quot;'));
71106
});
72107

73108
it('should handle windows line endings', function() {
74109
const diffResult = diffTrimmedLines(
75110
'line\r\nold value \r\nline',
76111
'line\r\nnew value\r\nline');
77-
expect(convertChangesToXML(diffResult)).to.equal('line\r\n<del>old value\r\n</del><ins>new value\r\n</ins>line');
112+
expect(convertChangesToXML(diffResult)).to.equal('line\r\n<del>old value \r\n</del><ins>new value\r\n</ins>line');
78113
});
79114
});
80115

0 commit comments

Comments
 (0)