diff --git a/js/htmldiff.js b/js/htmldiff.js index 6acce60..7310ba0 100644 --- a/js/htmldiff.js +++ b/js/htmldiff.js @@ -823,7 +823,11 @@ data.status = notes[index].isWrappable; } var status = notes[index].isWrappable; - if (status !== data.status){ + + // Handling atomic tags wrapping independently + // each atomic tag is wrapped with their own ins/del tags + var isAtomic = isStartOfAtomicTag(token); + if (status !== data.status || (isAtomic && index > data.lastIndex) || data.lastWasAtomic){ data.list.push({ isWrappable: data.status, tokens: tokens.slice(data.lastIndex, index) @@ -831,6 +835,9 @@ data.lastIndex = index; data.status = status; } + // tracking if the last token was an atomic tag + // if so then we break the segment and wrap them + data.lastWasAtomic = isAtomic; if (index === tokens.length - 1){ data.list.push({ isWrappable: data.status, @@ -838,7 +845,7 @@ }); } return data; - }, {list: [], status: null, lastIndex: 0}).list; + }, {list: [], status: null, lastIndex: 0, lastWasAtomic: false}).list; return segments.map(mapFn).join(''); }; diff --git a/package.json b/package.json index ccd3ca5..ca27589 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@matrixreq/htmldiff", "description": "Diff and markup HTML with and tags", "companyname": "Matrix Requirements", - "version": "1.2.0", + "version": "1.3.0", "keywords": [ "diff", "html", diff --git a/test/diff.spec.js b/test/diff.spec.js index 96004a7..f511270 100644 --- a/test/diff.spec.js +++ b/test/diff.spec.js @@ -206,5 +206,54 @@ describe('Diff', function(){ }); }); }); // describe('iframe Differences') - + + describe('Adjacent atomic tag combining', function(){ + it('should wrap each inserted atomic tag independently when multiple are inserted', function(){ + var result = cut('', ''); + expect(result).to.equal( + '' + + '' + ); + }); + + it('should wrap each deleted atomic tag independently when multiple are deleted', function(){ + var result = cut('', ''); + expect(result).to.equal( + '' + + '' + ); + }); + + it('should not merge atomic tag with adjacent text in same ins/del', function(){ + var result = cut('hello world', 'helloworld'); + expect(result).to.equal('helloworld'); + }); + + it('should wrap inserted content inside the tag, not in a standalone ins', function(){ + var result = cut('', 'hello'); + expect(result).to.equal( + 'hello' + ); + }); + + it('should mark non-atomic container tags with data-diff-node rather than wrapping with ins', function(){ + var result = cut('', '
  • content
  • '); + expect(result).to.equal( + '
  • ' + + '
    ' + + 'content' + + '
    ' + + '
  • ' + ); + }); + + it('should keep adjacent inserted tags as separate segments', function(){ + var result = cut('', 'helloworld'); + expect(result).to.equal( + 'hello' + + 'world' + ); + }); + }); // describe('Adjacent atomic tag combining') + }); // describe('Diff') \ No newline at end of file diff --git a/test/render_operations.spec.js b/test/render_operations.spec.js index 2ea6b7b..1e179b8 100644 --- a/test/render_operations.spec.js +++ b/test/render_operations.spec.js @@ -163,14 +163,15 @@ describe('renderOperations', function(){ 'new
    text'); }); - it('should wrap atomic tags', function(){ + it('should wrap atomic tags independently', function(){ var before = tokenize(['old', '', ' ', 'text']); var after = tokenize(['new', ' ', 'text']); res = cut(before, after); expect(res).to.equal( - 'old' + + 'old' + + '' + 'new text'); }); });