Skip to content

Commit 4a0ba65

Browse files
committed
Add line diff that is newline character aware
Fixes #68
1 parent cf6f569 commit 4a0ba65

File tree

3 files changed

+29
-2
lines changed

3 files changed

+29
-2
lines changed

Diff for: README.md

+4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ or
3939

4040
Returns a list of change objects (See below).
4141

42+
* `JsDiff.diffLinesNL(oldStr, newStr[, callback])` - diffs two blocks of text, comparing line by line. This differs from `diffLines` in that the newline character is treated as a distinct token. This allows for changes to the newline structure to occur independently of the line content and to be treated as such. In general this is the more human friendly form of `diffLines` and `diffLines` is better suited for patches and other computer friendly output.
43+
44+
Returns a list of change objects (See below).
45+
4246
* `JsDiff.diffSentences(oldStr, newStr[, callback])` - diffs two blocks of text, comparing sentence by sentence.
4347

4448
Returns a list of change objects (See below).

Diff for: src/diff/line.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
import Diff from './base';
22

3+
function tokenize(value) {
4+
return value.split(/(\n|\r\n)/);
5+
}
6+
7+
// Treats new line characters as separate, significant tokens
8+
export const nlTokenLineDiff = new Diff();
9+
nlTokenLineDiff.tokenize = tokenize;
10+
11+
// Inlines new line characters into the diff result, thus, `restaurant\n` is different than `restaruant`
312
export const lineDiff = new Diff();
13+
14+
// Operates in a similar fashion to lineDiff, but whitespace other thing the the newline character is trimmed
415
export const trimmedLineDiff = new Diff();
516
trimmedLineDiff.ignoreTrim = true;
617

718
lineDiff.tokenize = trimmedLineDiff.tokenize = function(value) {
819
let retLines = [],
9-
linesAndNewlines = value.split(/(\n|\r\n)/);
20+
linesAndNewlines = tokenize(value);
1021

1122
// Ignore the final empty token that occurs if the string ends with a new line
1223
if (!linesAndNewlines[linesAndNewlines.length - 1]) {
@@ -32,3 +43,4 @@ lineDiff.tokenize = trimmedLineDiff.tokenize = function(value) {
3243

3344
export function diffLines(oldStr, newStr, callback) { return lineDiff.diff(oldStr, newStr, callback); }
3445
export function diffTrimmedLines(oldStr, newStr, callback) { return trimmedLineDiff.diff(oldStr, newStr, callback); }
46+
export function diffLinesNL(oldStr, newStr, callback) { return nlTokenLineDiff.diff(oldStr, newStr, callback); }

Diff for: test/diff/line.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {diffLines, diffTrimmedLines} from '../../lib/diff/line';
1+
import {diffLines, diffTrimmedLines, diffLinesNL} from '../../lib/diff/line';
22
import {convertChangesToXML} from '../../lib/convert/xml';
33

44
import {expect} from 'chai';
@@ -77,4 +77,15 @@ describe('diff/line', function() {
7777
expect(convertChangesToXML(diffResult)).to.equal('line\r\n<del>old value\r\n</del><ins>new value\r\n</ins>line');
7878
});
7979
});
80+
81+
describe('#diffLinesNL', function() {
82+
expect(diffLinesNL('restaurant', 'restaurant\n')).to.eql([
83+
{value: 'restaurant', count: 1},
84+
{value: '\n', count: 1, added: true, removed: undefined}
85+
]);
86+
expect(diffLinesNL('restaurant', 'restaurant\nhello')).to.eql([
87+
{value: 'restaurant', count: 1},
88+
{value: '\nhello', count: 2, added: true, removed: undefined}
89+
]);
90+
});
8091
});

0 commit comments

Comments
 (0)