@matrixreq/htmldiff 1.6.0 → 2.0.1
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/README.md +76 -8
- package/js/constants.d.ts +3 -0
- package/js/constants.js +6 -0
- package/js/core/atomicTags.d.ts +10 -0
- package/js/core/atomicTags.js +28 -0
- package/js/core/diff.d.ts +2 -0
- package/js/core/diff.js +15 -0
- package/js/core/matching.d.ts +27 -0
- package/js/core/matching.js +207 -0
- package/js/core/operations.d.ts +10 -0
- package/js/core/operations.js +76 -0
- package/js/core/rendering.d.ts +25 -0
- package/js/core/rendering.js +212 -0
- package/js/core/tokens.d.ts +11 -0
- package/js/core/tokens.js +256 -0
- package/js/htmldiff.d.ts +0 -15
- package/js/htmldiff.js +14 -1351
- package/js/tables/Cell.d.ts +24 -0
- package/js/tables/Cell.js +115 -0
- package/js/tables/ColumnAligner.d.ts +11 -0
- package/js/tables/ColumnAligner.js +83 -0
- package/js/tables/MergedCells.d.ts +11 -0
- package/js/tables/MergedCells.js +171 -0
- package/js/tables/Row.d.ts +22 -0
- package/js/tables/Row.js +49 -0
- package/js/tables/RowAligner.d.ts +12 -0
- package/js/tables/RowAligner.js +107 -0
- package/js/tables/SequenceAligner.d.ts +47 -0
- package/js/tables/SequenceAligner.js +125 -0
- package/js/tables/Table.d.ts +27 -0
- package/js/tables/Table.js +166 -0
- package/js/tables/TableAligner.d.ts +9 -0
- package/js/tables/TableAligner.js +69 -0
- package/js/tables/TableMerger.d.ts +16 -0
- package/js/tables/TableMerger.js +216 -0
- package/js/tables/TableRedlining.d.ts +10 -0
- package/js/tables/TableRedlining.js +65 -0
- package/js/tables/TableVersion.d.ts +32 -0
- package/js/tables/TableVersion.js +128 -0
- package/js/tables/constants.d.ts +6 -0
- package/js/tables/constants.js +8 -0
- package/js/tables/helpers.d.ts +4 -0
- package/js/tables/helpers.js +23 -0
- package/js/tables/html.d.ts +32 -0
- package/js/tables/html.js +114 -0
- package/js/tables/index.d.ts +2 -0
- package/js/tables/index.js +5 -0
- package/js/tables/similarity.d.ts +10 -0
- package/js/tables/similarity.js +107 -0
- package/package.json +21 -14
- package/test/calculate_operations.spec.js +0 -278
- package/test/config.js +0 -2
- package/test/diff.spec.js +0 -318
- package/test/edge_cases.spec.js +0 -41
- package/test/find_matching_blocks.spec.js +0 -168
- package/test/from_port_source.spec.js +0 -30
- package/test/html_to_tokens.spec.js +0 -249
- package/test/inner_diff.spec.js +0 -333
- package/test/mocha.opts +0 -3
- package/test/module.spec.js +0 -11
- package/test/pain_games.spec.js +0 -18
- package/test/render_operations.spec.js +0 -178
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
describe('findMatchingBlocks', function(){
|
|
2
|
-
var diff, cut, res, createToken, tokenize, createSegment, htmlToTokens;
|
|
3
|
-
|
|
4
|
-
beforeEach(function(){
|
|
5
|
-
diff = require('../js/htmldiff');
|
|
6
|
-
createSegment = diff.findMatchingBlocks.createSegment;
|
|
7
|
-
htmlToTokens = diff.htmlToTokens;
|
|
8
|
-
createToken = diff.findMatchingBlocks.createToken;
|
|
9
|
-
tokenize = function(tokens){
|
|
10
|
-
return tokens.map(function(token){
|
|
11
|
-
return createToken(token);
|
|
12
|
-
});
|
|
13
|
-
};
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
describe('createMap', function(){
|
|
17
|
-
beforeEach(function(){
|
|
18
|
-
cut = diff.findMatchingBlocks.createMap;
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it('should be a function', function(){
|
|
22
|
-
expect(cut).is.a('function');
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
describe('When the items exist in the search target', function(){
|
|
26
|
-
beforeEach(function(){
|
|
27
|
-
res = cut(tokenize(['a', 'apple', 'has', 'a', 'worm']));
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('should find "a" twice', function(){
|
|
31
|
-
expect(res['a'].length).to.equal(2);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('should find "a" at 0', function(){
|
|
35
|
-
expect(res['a'][0]).to.equal(0);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('should find "a" at 3', function(){
|
|
39
|
-
expect(res['a'][1]).to.equal(3);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('should find "has" at 2', function(){
|
|
43
|
-
expect(res['has'][0]).to.equal(2);
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
describe('findBestMatch', function(){
|
|
49
|
-
var invoke;
|
|
50
|
-
|
|
51
|
-
beforeEach(function(){
|
|
52
|
-
cut = diff.findMatchingBlocks.findBestMatch;
|
|
53
|
-
invoke = function(before, after){
|
|
54
|
-
var segment = createSegment(before, after, 0, 0);
|
|
55
|
-
|
|
56
|
-
res = cut(segment);
|
|
57
|
-
};
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
describe('When there is a match', function(){
|
|
61
|
-
beforeEach(function(){
|
|
62
|
-
var before = tokenize(['a', 'dog', 'bites']);
|
|
63
|
-
var after = tokenize(['a', 'dog', 'bites', 'a', 'man']);
|
|
64
|
-
invoke(before, after);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('should match the match', function(){
|
|
68
|
-
expect(res).to.exist;
|
|
69
|
-
expect(res.startInBefore).equal(0);
|
|
70
|
-
expect(res.startInAfter).equal(0);
|
|
71
|
-
expect(res.length).equal(3);
|
|
72
|
-
expect(res.endInBefore).equal(2);
|
|
73
|
-
expect(res.endInAfter).equal(2);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
describe('When the match is surrounded', function(){
|
|
77
|
-
beforeEach(function(){
|
|
78
|
-
before = tokenize(['dog', 'bites']);
|
|
79
|
-
after = tokenize(['the', 'dog', 'bites', 'a', 'man']);
|
|
80
|
-
invoke(before, after);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('should match with appropriate indexing', function(){
|
|
84
|
-
expect(res).to.exist;
|
|
85
|
-
expect(res.startInBefore).to.equal(0);
|
|
86
|
-
expect(res.startInAfter).to.equal(1);
|
|
87
|
-
expect(res.endInBefore).to.equal(1);
|
|
88
|
-
expect(res.endInAfter).to.equal(2);
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
describe('When there is no match', function(){
|
|
94
|
-
beforeEach(function(){
|
|
95
|
-
var before = tokenize(['the', 'rat', 'sqeaks']);
|
|
96
|
-
var after = tokenize(['a', 'dog', 'bites', 'a', 'man']);
|
|
97
|
-
invoke(before, after);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it('should return nothing', function(){
|
|
101
|
-
expect(res).to.not.exist;
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
describe('findMatchingBlocks', function(){
|
|
107
|
-
var segment;
|
|
108
|
-
|
|
109
|
-
beforeEach(function(){
|
|
110
|
-
cut = diff.findMatchingBlocks;
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('should be a function', function(){
|
|
114
|
-
expect(cut).is.a('function');
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
describe('When called with a single match', function(){
|
|
118
|
-
beforeEach(function(){
|
|
119
|
-
var before = htmlToTokens('a dog bites');
|
|
120
|
-
var after = htmlToTokens('when a dog bites it hurts');
|
|
121
|
-
segment = createSegment(before, after, 0, 0);
|
|
122
|
-
|
|
123
|
-
res = cut(segment);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it('should return a match', function(){
|
|
127
|
-
expect(res.length).to.equal(1);
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
describe('When called with multiple matches', function(){
|
|
132
|
-
beforeEach(function(){
|
|
133
|
-
var before = htmlToTokens('the dog bit a man');
|
|
134
|
-
var after = htmlToTokens('the large brown dog bit a tall man');
|
|
135
|
-
segment = createSegment(before, after, 0, 0);
|
|
136
|
-
res = cut(segment);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it('should return 3 matches', function(){
|
|
140
|
-
expect(res.length).to.equal(3);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it('should match "the"', function(){
|
|
144
|
-
expect(res[0].startInBefore).eql(0);
|
|
145
|
-
expect(res[0].startInAfter).eql(0);
|
|
146
|
-
expect(res[0].endInBefore).eql(0);
|
|
147
|
-
expect(res[0].endInAfter).eql(0);
|
|
148
|
-
expect(res[0].length).eql(1);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
it('should match "dog bit a"', function(){
|
|
152
|
-
expect(res[1].startInBefore).eql(1);
|
|
153
|
-
expect(res[1].startInAfter).eql(5);
|
|
154
|
-
expect(res[1].endInBefore).eql(7);
|
|
155
|
-
expect(res[1].endInAfter).eql(11);
|
|
156
|
-
expect(res[1].length).eql(7);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it('should match "man"', function(){
|
|
160
|
-
expect(res[2].startInBefore).eql(8);
|
|
161
|
-
expect(res[2].startInAfter).eql(14);
|
|
162
|
-
expect(res[2].endInBefore).eql(8);
|
|
163
|
-
expect(res[2].endInAfter).eql(14);
|
|
164
|
-
expect(res[2].length).eql(1);
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
});
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
describe('The specs from the ruby source project', function(){
|
|
2
|
-
var cut;
|
|
3
|
-
|
|
4
|
-
beforeEach(function(){
|
|
5
|
-
cut = require('../js/htmldiff');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
it('should diff text', function(){
|
|
9
|
-
var diff = cut('a word is here', 'a nother word is there');
|
|
10
|
-
expect(diff).equal('a<ins data-operation-index="1"> nother</ins> word is ' +
|
|
11
|
-
'<del data-operation-index="3">here</del><ins data-operation-index="3">' +
|
|
12
|
-
'there</ins>');
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('should insert a letter and a space', function(){
|
|
16
|
-
var diff = cut('a c', 'a b c');
|
|
17
|
-
expect(diff).equal('a <ins data-operation-index="1">b </ins>c');
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should remove a letter and a space', function(){
|
|
21
|
-
var diff = cut('a b c', 'a c');
|
|
22
|
-
diff.should == 'a <del data-operation-index="1">b </del>c';
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('should change a letter', function(){
|
|
26
|
-
var diff = cut('a b c', 'a d c');
|
|
27
|
-
expect(diff).equal('a <del data-operation-index="1">b</del>' +
|
|
28
|
-
'<ins data-operation-index="1">d</ins> c');
|
|
29
|
-
});
|
|
30
|
-
});
|
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
describe('htmlToTokens', function(){
|
|
2
|
-
var cut, res, diff, createToken, tokenize;
|
|
3
|
-
|
|
4
|
-
beforeEach(function(){
|
|
5
|
-
diff = require('../js/htmldiff')
|
|
6
|
-
cut = diff.htmlToTokens;
|
|
7
|
-
|
|
8
|
-
createToken = diff.findMatchingBlocks.createToken;
|
|
9
|
-
tokenize = function(tokens){
|
|
10
|
-
return tokens.map(function(token){
|
|
11
|
-
return createToken(token);
|
|
12
|
-
});
|
|
13
|
-
};
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('should be a function', function(){
|
|
17
|
-
expect(cut).is.a('function');
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
describe('when called with text', function(){
|
|
21
|
-
beforeEach(function(){
|
|
22
|
-
res = cut('this is a test');
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('should return 4', function(){
|
|
26
|
-
expect(res.length).to.equal(7);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
describe('when called with html', function(){
|
|
31
|
-
beforeEach(function(){
|
|
32
|
-
res = cut('<p>this is a <strong>test</strong></p>');
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('should return 11', function(){
|
|
36
|
-
expect(res.length).to.equal(11);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should remove any html comments', function(){
|
|
40
|
-
res = cut('<p> this is <!-- a comment! --> </p>');
|
|
41
|
-
expect(res.length).to.equal(8);
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should identify contiguous whitespace as a single token', function(){
|
|
46
|
-
expect(cut('a b')).to.eql(tokenize(['a', ' ', 'b']));
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('should identify a single space as a single token', function(){
|
|
50
|
-
expect(cut(' a b ')).to.eql(tokenize([' ', 'a', ' ', 'b', ' ']));
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('should identify self closing tags as tokens', function(){
|
|
54
|
-
expect(cut('<p>hello</br>goodbye</p>')).eql(
|
|
55
|
-
tokenize(['<p>', 'hello', '</br>', 'goodbye', '</p>']));
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
describe('when encountering atomic tags', function(){
|
|
59
|
-
it('should identify an image tag as a single token', function(){
|
|
60
|
-
expect(cut('<p><img src="1.jpg"><img src="2.jpg"></p>')).eql(
|
|
61
|
-
tokenize(['<p>', '<img src="1.jpg">', '<img src="2.jpg">', '</p>']));
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('should identify an iframe tag as a single token', function(){
|
|
65
|
-
expect(cut('<p><iframe src="sample.html"></iframe></p>')).eql(
|
|
66
|
-
tokenize(['<p>', '<iframe src="sample.html"></iframe>', '</p>']));
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('should identify an object tag as a single token', function(){
|
|
70
|
-
var cutResult = cut('<p><object><param name="1" /><param name="2" /></object></p>');
|
|
71
|
-
var tokenizeResult = tokenize(
|
|
72
|
-
['<p>', '<object><param name="1" /><param name="2" /></object>','</p>']);
|
|
73
|
-
expect(cutResult).eql(tokenizeResult);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('should identify a math tag as a single token', function(){
|
|
77
|
-
var cutResult = cut('<p><math xmlns="http://www.w3.org/1998/Math/MathML">' +
|
|
78
|
-
'<mi>π<!-- π --></mi>' +
|
|
79
|
-
'<mo>⁢<!-- ⁢ --></mo>' +
|
|
80
|
-
'<msup><mi>r</mi><mn>2</mn></msup></math></p>');
|
|
81
|
-
var tokenizeResult = tokenize([
|
|
82
|
-
'<p>',
|
|
83
|
-
'<math xmlns="http://www.w3.org/1998/Math/MathML">' +
|
|
84
|
-
'<mi>π<!-- π --></mi>' +
|
|
85
|
-
'<mo>⁢<!-- ⁢ --></mo>' +
|
|
86
|
-
'<msup><mi>r</mi><mn>2</mn></msup></math>',
|
|
87
|
-
'</p>'
|
|
88
|
-
]);
|
|
89
|
-
expect(cutResult).eql(tokenizeResult);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('should identify an svg tag as a single token', function(){
|
|
93
|
-
var cutResult = cut('<p><svg width="100" height="100">' +
|
|
94
|
-
'<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" ' +
|
|
95
|
-
'fill="yellow" /></svg></p>');
|
|
96
|
-
var tokenizeResult = tokenize([
|
|
97
|
-
'<p>',
|
|
98
|
-
'<svg width="100" height="100">' +
|
|
99
|
-
'<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />' +
|
|
100
|
-
'</svg>',
|
|
101
|
-
'</p>'
|
|
102
|
-
]);
|
|
103
|
-
expect(cutResult).eql(tokenizeResult);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it('should identify a script tag as a single token', function(){
|
|
107
|
-
expect(cut('<p><script>console.log("hi");</script></p>')).eql(
|
|
108
|
-
tokenize(['<p>', '<script>console.log("hi");</script>', '</p>']));
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
it('should identify tags with data-htmldiff-id attribute as single token', () => {
|
|
114
|
-
expect(
|
|
115
|
-
cut('<div><customtag data-htmldiff-id="1">hello</br>goodbye</customtag>' +
|
|
116
|
-
'<custom-tag data-htmldiff-id="2">some stuff</custom-tag>' +
|
|
117
|
-
'</div>')
|
|
118
|
-
).eql(tokenize(
|
|
119
|
-
[
|
|
120
|
-
'<div>',
|
|
121
|
-
'<customtag data-htmldiff-id="1">hello</br>goodbye</customtag>',
|
|
122
|
-
'<custom-tag data-htmldiff-id="2">some stuff</custom-tag>',
|
|
123
|
-
'</div>'
|
|
124
|
-
]
|
|
125
|
-
));
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
describe('nested atomic tags wrapping', function(){
|
|
129
|
-
it('should keep a data-htmldiff-id wrapper with nested same-tag children as one token', function(){
|
|
130
|
-
var atomic = '<span data-htmldiff-id="u1">' +
|
|
131
|
-
'<span class="tooltip"><span class="avatar">AB</span></span>' +
|
|
132
|
-
'Name</span>';
|
|
133
|
-
expect(cut('<div>' + atomic + '</div>')).eql(
|
|
134
|
-
tokenize(['<div>', atomic, '</div>']));
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('should not close early on the first inner closing tag', function(){
|
|
138
|
-
var atomic = '<span data-htmldiff-id="1"><span>a</span><span>b</span></span>';
|
|
139
|
-
expect(cut(atomic)).eql(tokenize([atomic]));
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it('should not treat a stray ">" in script content as a tag boundary', function(){
|
|
143
|
-
var atomic = '<script>if (a > b) { return a > 0; }</script>';
|
|
144
|
-
expect(cut('<p>' + atomic + '</p>')).eql(
|
|
145
|
-
tokenize(['<p>', atomic, '</p>']));
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it('should ignore self-closing same-named children when counting depth', function(){
|
|
149
|
-
var atomic = '<span data-htmldiff-id="1">x<span/>y</span>';
|
|
150
|
-
expect(cut(atomic)).eql(tokenize([atomic]));
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it('should ignore self-closing same-named children written with a space (<span />)', function(){
|
|
154
|
-
var atomic = '<span data-htmldiff-id="1">x<span />y</span>';
|
|
155
|
-
expect(cut(atomic)).eql(tokenize([atomic]));
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
it('should key a wrapper by its own data-htmldiff-id, not a nested child one', function(){
|
|
159
|
-
var atomic = '<strong data-htmldiff-id="s1">' +
|
|
160
|
-
'<em data-htmldiff-id="e1">C</em></strong>';
|
|
161
|
-
expect(cut(atomic)[0].key).eql('s1');
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
it('should not key an unkeyed atomic tag by a nested child data-htmldiff-id', function(){
|
|
165
|
-
var atomic = '<a><em data-htmldiff-id="e1">C</em></a>';
|
|
166
|
-
expect(cut(atomic)[0].key).eql('<a>');
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
it('should not bump depth on differently-named tags that share a prefix', function(){
|
|
170
|
-
// a tag must not be matched by an atomic tag named "a" appearing as <article>.
|
|
171
|
-
var atomic = '<a href="x"><article>hi</article></a>';
|
|
172
|
-
expect(cut(atomic)).eql(tokenize([atomic]));
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
describe('tags sharing a prefix with atomic tag names', function(){
|
|
177
|
-
it('should not treat <abbr> as the atomic tag a', function(){
|
|
178
|
-
expect(cut('<abbr>x</abbr> tail')).eql(
|
|
179
|
-
tokenize(['<abbr>', 'x', '</abbr>', ' ', 'tail']));
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it('should not treat <article> as the atomic tag a', function(){
|
|
183
|
-
expect(cut('<article>hi</article>')).eql(
|
|
184
|
-
tokenize(['<article>', 'hi', '</article>']));
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
describe('self-closing atomic tags', function(){
|
|
189
|
-
it('should end a self-closing data-htmldiff-id tag without swallowing trailing content', function(){
|
|
190
|
-
expect(cut('<div data-htmldiff-id="s"/>x old')).eql(
|
|
191
|
-
tokenize(['<div data-htmldiff-id="s"/>', 'x', ' ', 'old']));
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it('should end a self-closing name-based atomic tag without swallowing trailing content', function(){
|
|
195
|
-
expect(cut('<svg/>tail')).eql(tokenize(['<svg/>', 'tail']));
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
describe('quoted attribute values containing tag delimiters', function(){
|
|
200
|
-
it('should not end a tag on ">" inside a double-quoted attribute value', function(){
|
|
201
|
-
expect(cut('<p class="a>b">text</p>')).eql(
|
|
202
|
-
tokenize(['<p class="a>b">', 'text', '</p>']));
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
it('should not end a tag on ">" inside a single-quoted attribute value', function(){
|
|
206
|
-
expect(cut("<p class='a>b'>x</p>")).eql(
|
|
207
|
-
tokenize(["<p class='a>b'>", 'x', '</p>']));
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
it('should not end a void atomic tag on ">" inside an attribute value', function(){
|
|
211
|
-
expect(cut('<img data-htmldiff-id="1" alt="a > b"> tail')).eql(
|
|
212
|
-
tokenize(['<img data-htmldiff-id="1" alt="a > b">', ' ', 'tail']));
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
it('should not treat "/>" inside an attribute value as self-closing', function(){
|
|
216
|
-
var atomic = '<span data-htmldiff-id="1" data-x="y/>z">c</span>';
|
|
217
|
-
expect(cut(atomic)).eql(tokenize([atomic]));
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
it('should keep an atomic tag with ">" in an attribute as one token', function(){
|
|
221
|
-
expect(cut('<div data-htmldiff-id="1" title="a > b">x</div> tail')).eql(
|
|
222
|
-
tokenize(['<div data-htmldiff-id="1" title="a > b">x</div>',
|
|
223
|
-
' ', 'tail']));
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
it('should not treat apostrophes in atomic text content as quotes', function(){
|
|
227
|
-
expect(cut("<div data-htmldiff-id='1'>it's ok</div> tail")).eql(
|
|
228
|
-
tokenize(["<div data-htmldiff-id='1'>it's ok</div>", ' ', 'tail']));
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
it('should not treat apostrophes in comments inside atomic tags as quotes', function(){
|
|
232
|
-
expect(cut("<math><mi>x<!-- don't --></mi></math> tail")).eql(
|
|
233
|
-
tokenize(["<math><mi>x<!-- don't --></mi></math>", ' ', 'tail']));
|
|
234
|
-
});
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
describe('void atomic tags', function(){
|
|
238
|
-
it('should end a void data-htmldiff-id tag written without a slash', function(){
|
|
239
|
-
expect(cut('<img data-htmldiff-id="1" src="a.jpg"> tail')).eql(
|
|
240
|
-
tokenize(['<img data-htmldiff-id="1" src="a.jpg">', ' ', 'tail']));
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it('should end a void data-htmldiff-id br tag without swallowing trailing content', function(){
|
|
244
|
-
expect(cut('<br data-htmldiff-id="x">y')).eql(
|
|
245
|
-
tokenize(['<br data-htmldiff-id="x">', 'y']));
|
|
246
|
-
});
|
|
247
|
-
});
|
|
248
|
-
});
|
|
249
|
-
});
|