Skip to content

Commit a129da8

Browse files
committed
Merge pull request #47 from JamesGould123/master
Adding Diff Trimmed Lines
2 parents 5199cc4 + cb0c827 commit a129da8

File tree

4 files changed

+69
-15
lines changed

4 files changed

+69
-15
lines changed

Diff for: README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ or
3333

3434
Returns a list of change objects (See below).
3535

36+
* `JsDiff.diffTrimmedLines(oldStr, newStr[, callback])` - diffs two blocks of text, comparing line by line, ignoring leading and trailing whitespace.
37+
38+
Returns a list of change objects (See below).
39+
3640
* `JsDiff.diffSentences(oldStr, newStr[, callback])` - diffs two blocks of text, comparing sentence by sentence.
3741

3842
Returns a list of change objects (See below).
@@ -166,4 +170,3 @@ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
166170

167171

168172
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/kpdecker/jsdiff/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
169-

Diff for: diff.js

+33-13
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927
1616
*/
1717
(function(global, undefined) {
18+
1819
var JsDiff = (function() {
1920
/*jshint maxparams: 5*/
2021
/*istanbul ignore next*/
@@ -174,7 +175,7 @@
174175
editLength++;
175176
}
176177

177-
// Performs the length of edit iteration. Is a bit fugly as this has to support the
178+
// Performs the length of edit iteration. Is a bit fugly as this has to support the
178179
// sync and async mode which is never fun. Loops over execEditLength until a value
179180
// is produced.
180181
var editLength = 1;
@@ -256,25 +257,42 @@
256257
};
257258

258259
var LineDiff = new Diff();
259-
LineDiff.tokenize = function(value) {
260+
261+
var TrimmedLineDiff = new Diff();
262+
TrimmedLineDiff.ignoreTrim = true;
263+
264+
LineDiff.tokenize = TrimmedLineDiff.tokenize = function(value) {
260265
var retLines = [],
261266
lines = value.split(/^/m);
262-
263267
for(var i = 0; i < lines.length; i++) {
264268
var line = lines[i],
265-
lastLine = lines[i - 1];
269+
lastLine = lines[i - 1],
270+
lastLineLastChar = lastLine ? lastLine[lastLine.length - 1] : '';
266271

267272
// Merge lines that may contain windows new lines
268-
if (line === '\n' && lastLine && lastLine[lastLine.length - 1] === '\r') {
269-
retLines[retLines.length - 1] += '\n';
273+
if (line === '\n' && (lastLineLastChar === '\r' || lastLineLastChar === '\n')) {
274+
if (this.ignoreTrim || lastLineLastChar === '\n'){
275+
//to avoid merging to \n\n, remove \n and add \r\n.
276+
retLines[retLines.length - 1] = retLines[retLines.length - 1].slice(0,-1) + '\r\n';
277+
} else {
278+
retLines[retLines.length - 1] += '\n';
279+
}
270280
} else if (line) {
281+
if (this.ignoreTrim) {
282+
line = line.trim();
283+
//add a newline unless this is the last line.
284+
if (i < lines.length - 1) {
285+
line += '\n';
286+
}
287+
}
271288
retLines.push(line);
272289
}
273290
}
274291

275292
return retLines;
276293
};
277294

295+
278296
var SentenceDiff = new Diff();
279297
SentenceDiff.tokenize = function (value) {
280298
return removeEmpty(value.split(/(\S.+?[.!?])(?=\s+|$)/));
@@ -344,6 +362,8 @@
344362
diffWords: function(oldStr, newStr, callback) { return WordDiff.diff(oldStr, newStr, callback); },
345363
diffWordsWithSpace: function(oldStr, newStr, callback) { return WordWithSpaceDiff.diff(oldStr, newStr, callback); },
346364
diffLines: function(oldStr, newStr, callback) { return LineDiff.diff(oldStr, newStr, callback); },
365+
diffTrimmedLines: function(oldStr, newStr, callback) { return TrimmedLineDiff.diff(oldStr, newStr, callback); },
366+
347367
diffSentences: function(oldStr, newStr, callback) { return SentenceDiff.diff(oldStr, newStr, callback); },
348368

349369
diffCss: function(oldStr, newStr, callback) { return CssDiff.diff(oldStr, newStr, callback); },
@@ -447,7 +467,7 @@
447467
addEOFNL = false;
448468

449469
for (var i = (diffstr[0][0]==='I'?4:0); i < diffstr.length; i++) {
450-
if(diffstr[i][0] === '@') {
470+
if (diffstr[i][0] === '@') {
451471
var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/);
452472
diff.unshift({
453473
start:meh[3],
@@ -456,17 +476,17 @@
456476
newlength:meh[4],
457477
newlines:[]
458478
});
459-
} else if(diffstr[i][0] === '+') {
479+
} else if (diffstr[i][0] === '+') {
460480
diff[0].newlines.push(diffstr[i].substr(1));
461-
} else if(diffstr[i][0] === '-') {
481+
} else if (diffstr[i][0] === '-') {
462482
diff[0].oldlines.push(diffstr[i].substr(1));
463-
} else if(diffstr[i][0] === ' ') {
483+
} else if (diffstr[i][0] === ' ') {
464484
diff[0].newlines.push(diffstr[i].substr(1));
465485
diff[0].oldlines.push(diffstr[i].substr(1));
466-
} else if(diffstr[i][0] === '\\') {
486+
} else if (diffstr[i][0] === '\\') {
467487
if (diffstr[i-1][0] === '+') {
468488
remEOFNL = true;
469-
} else if(diffstr[i-1][0] === '-') {
489+
} else if (diffstr[i-1][0] === '-') {
470490
addEOFNL = true;
471491
}
472492
}
@@ -476,7 +496,7 @@
476496
for (var i = diff.length - 1; i >= 0; i--) {
477497
var d = diff[i];
478498
for (var j = 0; j < d.oldlength; j++) {
479-
if(str[d.start-1+j] !== d.oldlines[j]) {
499+
if (str[d.start-1+j] !== d.oldlines[j]) {
480500
return false;
481501
}
482502
}

Diff for: index.html

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ <h1>Diff</h1>
1111
<label><input type="radio" name="diff_type" value="diffChars" checked> Chars</label>
1212
<label><input type="radio" name="diff_type" value="diffWords"> Words</label>
1313
<label><input type="radio" name="diff_type" value="diffLines"> Lines</label>
14+
<label><input type="radio" name="diff_type" value="diffTrimmedLines"> Trimmed Lines</label>
1415
<label><input type="radio" name="diff_type" value="createPatch"> Patch</label>
1516
<label><input type="radio" name="diff_type" value="applyPatch"> Merge</label>
1617
</div>

Diff for: test/diffTest.js

+31-1
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ describe('#diffLines', function() {
185185
diff.convertChangesToXML(diffResult).should.equal('line\nvalue\nline');
186186
});
187187

188-
it('should handle shorespace', function() {
188+
it('should handle leading and trailing whitespace', function() {
189189
var diffResult = diff.diffLines(
190190
'line\nvalue \nline',
191191
'line\nvalue\nline');
@@ -200,6 +200,36 @@ describe('#diffLines', function() {
200200
});
201201
});
202202

203+
// Trimmed Line Diff
204+
describe('#TrimmedLineDiff', function() {
205+
it('should diff lines', function() {
206+
var diffResult = diff.diffTrimmedLines(
207+
'line\nold value\nline',
208+
'line\nnew value\nline');
209+
diff.convertChangesToXML(diffResult).should.equal('line\n<ins>new value\n</ins><del>old value\n</del>line');
210+
});
211+
it('should the same lines in diff', function() {
212+
var diffResult = diff.diffTrimmedLines(
213+
'line\nvalue\nline',
214+
'line\nvalue\nline');
215+
diff.convertChangesToXML(diffResult).should.equal('line\nvalue\nline');
216+
});
217+
218+
it('should ignore leading and trailing whitespace', function() {
219+
var diffResult = diff.diffTrimmedLines(
220+
'line\nvalue \nline',
221+
'line\nvalue\nline');
222+
diff.convertChangesToXML(diffResult).should.equal('line\nvalue\nline');
223+
});
224+
225+
it('should handle windows line endings', function() {
226+
var diffResult = diff.diffTrimmedLines(
227+
'line\r\nold value \r\nline',
228+
'line\r\nnew value\r\nline');
229+
diff.convertChangesToXML(diffResult).should.equal('line\r\n<ins>new value\r\n</ins><del>old value\r\n</del>line');
230+
});
231+
});
232+
203233
describe('#diffJson', function() {
204234
it('should accept objects', function() {
205235
diff.diffJson(

0 commit comments

Comments
 (0)