@matrixreq/htmldiff 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/js/htmldiff.js CHANGED
@@ -823,7 +823,11 @@
823
823
  data.status = notes[index].isWrappable;
824
824
  }
825
825
  var status = notes[index].isWrappable;
826
- if (status !== data.status){
826
+
827
+ // Handling atomic tags wrapping independently
828
+ // each atomic tag is wrapped with their own ins/del tags
829
+ var isAtomic = isStartOfAtomicTag(token);
830
+ if (status !== data.status || (isAtomic && index > data.lastIndex) || data.lastWasAtomic){
827
831
  data.list.push({
828
832
  isWrappable: data.status,
829
833
  tokens: tokens.slice(data.lastIndex, index)
@@ -831,6 +835,9 @@
831
835
  data.lastIndex = index;
832
836
  data.status = status;
833
837
  }
838
+ // tracking if the last token was an atomic tag
839
+ // if so then we break the segment and wrap them
840
+ data.lastWasAtomic = isAtomic;
834
841
  if (index === tokens.length - 1){
835
842
  data.list.push({
836
843
  isWrappable: data.status,
@@ -838,7 +845,7 @@
838
845
  });
839
846
  }
840
847
  return data;
841
- }, {list: [], status: null, lastIndex: 0}).list;
848
+ }, {list: [], status: null, lastIndex: 0, lastWasAtomic: false}).list;
842
849
 
843
850
  return segments.map(mapFn).join('');
844
851
  };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@matrixreq/htmldiff",
3
3
  "description": "Diff and markup HTML with <ins> and <del> tags",
4
4
  "companyname": "Matrix Requirements",
5
- "version": "1.2.0",
5
+ "version": "1.3.0",
6
6
  "keywords": [
7
7
  "diff",
8
8
  "html",
package/test/diff.spec.js CHANGED
@@ -206,5 +206,54 @@ describe('Diff', function(){
206
206
  });
207
207
  });
208
208
  }); // describe('iframe Differences')
209
-
209
+
210
+ describe('Adjacent atomic tag combining', function(){
211
+ it('should wrap each inserted atomic tag independently when multiple are inserted', function(){
212
+ var result = cut('', '<iframe src="a.html"></iframe><iframe src="b.html"></iframe>');
213
+ expect(result).to.equal(
214
+ '<ins data-operation-index="0"><iframe src="a.html"></iframe></ins>' +
215
+ '<ins data-operation-index="0"><iframe src="b.html"></iframe></ins>'
216
+ );
217
+ });
218
+
219
+ it('should wrap each deleted atomic tag independently when multiple are deleted', function(){
220
+ var result = cut('<iframe src="a.html"></iframe><iframe src="b.html"></iframe>', '');
221
+ expect(result).to.equal(
222
+ '<del data-operation-index="0"><iframe src="a.html"></iframe></del>' +
223
+ '<del data-operation-index="0"><iframe src="b.html"></iframe></del>'
224
+ );
225
+ });
226
+
227
+ it('should not merge atomic tag with adjacent text in same ins/del', function(){
228
+ var result = cut('hello world', 'hello<iframe src="a.html"></iframe>world');
229
+ expect(result).to.equal('hello<ins data-operation-index="1"><iframe src="a.html"></iframe></ins>world');
230
+ });
231
+
232
+ it('should wrap inserted <b> content inside the tag, not in a standalone ins', function(){
233
+ var result = cut('', '<b>hello</b>');
234
+ expect(result).to.equal(
235
+ '<b data-diff-node="ins" data-operation-index="0"><ins data-operation-index="0">hello</ins></b>'
236
+ );
237
+ });
238
+
239
+ it('should mark non-atomic container tags with data-diff-node rather than wrapping with ins', function(){
240
+ var result = cut('', '<li><div>content</div></li>');
241
+ expect(result).to.equal(
242
+ '<li data-diff-node="ins" data-operation-index="0">' +
243
+ '<div data-diff-node="ins" data-operation-index="0">' +
244
+ '<ins data-operation-index="0">content</ins>' +
245
+ '</div>' +
246
+ '</li>'
247
+ );
248
+ });
249
+
250
+ it('should keep adjacent inserted <b> tags as separate segments', function(){
251
+ var result = cut('', '<b>hello</b><b>world</b>');
252
+ expect(result).to.equal(
253
+ '<b data-diff-node="ins" data-operation-index="0"><ins data-operation-index="0">hello</ins></b>' +
254
+ '<b data-diff-node="ins" data-operation-index="0"><ins data-operation-index="0">world</ins></b>'
255
+ );
256
+ });
257
+ }); // describe('Adjacent atomic tag combining')
258
+
210
259
  }); // describe('Diff')
@@ -163,14 +163,15 @@ describe('renderOperations', function(){
163
163
  '<ins data-operation-index="0">new<br/></ins> text');
164
164
  });
165
165
 
166
- it('should wrap atomic tags', function(){
166
+ it('should wrap atomic tags independently', function(){
167
167
  var before = tokenize(['old', '<iframe src="source.html"></iframe>', ' ', 'text']);
168
168
  var after = tokenize(['new', ' ', 'text']);
169
169
 
170
170
  res = cut(before, after);
171
171
 
172
172
  expect(res).to.equal(
173
- '<del data-operation-index="0">old<iframe src="source.html"></iframe></del>' +
173
+ '<del data-operation-index="0">old</del>' +
174
+ '<del data-operation-index="0"><iframe src="source.html"></iframe></del>' +
174
175
  '<ins data-operation-index="0">new</ins> text');
175
176
  });
176
177
  });