|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536 |
- /* global console */
- var test = require('tape');
- var HTML = require('../index');
-
-
- test('parse', function (t) {
- var html = '<div class="oh"><p></p></div>';
- var parsed = HTML.parse(html);
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {
- class: 'oh'
- },
- voidElement: false,
- children: [
- {
- type: 'tag',
- name: 'p',
- attrs: {},
- children: [],
- voidElement: false
- }
- ]
- }]);
- t.equal(html, HTML.stringify(parsed));
-
- html = '<div class="oh"><p>hi</p></div>';
- parsed = HTML.parse(html);
-
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {
- class: 'oh'
- },
- voidElement: false,
- children: [
- {
- type: 'tag',
- name: 'p',
- attrs: {},
- voidElement: false,
- children: [
- {
- type: 'text',
- content: 'hi'
- }
- ]
- }
- ]
- }]);
- t.equal(html, HTML.stringify(parsed));
-
- html = '<div>oh <strong>hello</strong> there! How are <span>you</span>?</div>';
- parsed = HTML.parse(html);
-
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {},
- voidElement: false,
- children: [
- {
- type: 'text',
- content: 'oh '
- },
- {
- type: 'tag',
- name: 'strong',
- attrs: {},
- voidElement: false,
- children: [
- {
- type: 'text',
- content: 'hello'
- }
- ]
- },
- {
- type: 'text',
- content: ' there! How are '
- },
- {
- type: 'tag',
- name: 'span',
- attrs: {},
- voidElement: false,
- children: [
- {
- type: 'text',
- content: 'you'
- }
- ]
- },
- {
- type: 'text',
- content: '?'
- }
- ]
- }]);
- t.equal(html, HTML.stringify(parsed));
-
- html = '<div class="handles multiple classes" and="attributes"></div>';
- parsed = HTML.parse(html);
-
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {
- class: 'handles multiple classes',
- and: 'attributes'
- },
- voidElement: false,
- children: []
- }]);
- t.equal(html, HTML.stringify(parsed));
-
- html = '<div class=\'handles\' other=47 and="attributes"></div>';
- parsed = HTML.parse(html);
-
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {
- class: 'handles',
- other: '47',
- and: 'attributes'
- },
- voidElement: false,
- children: []
- }]);
- t.equal(HTML.stringify(parsed), '<div class="handles" other="47" and="attributes"></div>');
-
- html = '<div-custom class="oh"><my-component some="thing"><p>should be ignored</p></my-component></div-custom>';
- parsed = HTML.parse(html, {
- components: {
- 'my-component': 'something'
- }
- });
-
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div-custom',
- attrs: {
- class: 'oh'
- },
- voidElement: false,
- children: [
- {
- type: 'component',
- name: 'my-component',
- attrs: {
- some: 'thing'
- },
- voidElement: false,
- children: []
- }
- ]
- }], 'should not include children of registered components in AST');
-
- html = '<div><my-component thing="one">ok</my-component><my-component thing="two">ok</my-component></div>';
- parsed = HTML.parse(html, {
- components: {
- 'my-component': 'something'
- }
- });
-
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {},
- voidElement: false,
- children: [
- {
- type: 'component',
- name: 'my-component',
- attrs: {
- thing: 'one'
- },
- voidElement: false,
- children: []
- },
- {
- type: 'component',
- name: 'my-component',
- attrs: {
- thing: 'two'
- },
- voidElement: false,
- children: []
- }
- ]
- }]);
-
- html = '<div><img></div>';
- parsed = HTML.parse(html);
-
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {},
- voidElement: false,
- children: [
- {
- type: 'tag',
- name: 'img',
- attrs: {},
- voidElement: true,
- children: []
- }
- ]
- }], 'should handle unclosed void elements');
- t.equal(HTML.stringify(parsed), '<div><img/></div>');
-
- html = '<div></div><img>';
- parsed = HTML.parse(html);
-
- t.deepEqual(parsed, [
- {
- type: 'tag',
- name: 'div',
- attrs: {},
- voidElement: false,
- children: []
- },
- {
- type: 'tag',
- name: 'img',
- attrs: {},
- voidElement: true,
- children: []
- }
- ], 'should handle multiple root nodes');
- t.equal(HTML.stringify(parsed), '<div></div><img/>');
-
- html = '<div><void-web-component/></div>';
- parsed = HTML.parse(html);
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {},
- voidElement: false,
- children: [
- {
- type: 'tag',
- name: 'void-web-component',
- attrs: {},
- voidElement: true,
- children: []
- }
- ]
- }], 'should handle custom void tags if self-closing');
-
- html = '<div><void-registered-component/></div>';
- parsed = HTML.parse(html, {components: {'void-registered-component': true}});
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {},
- voidElement: false,
- children: [
- {
- type: 'component',
- name: 'void-registered-component',
- attrs: {},
- voidElement: true,
- children: []
- }
- ]
- }], 'should handle registered void tags if self-closing');
-
-
- html = '<div> 9 <input type="text"/> 10 </div>';
- parsed = HTML.parse(html);
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {},
- voidElement: false,
- children: [
- { type: 'text', content: ' 9 ' },
- {
- type: 'tag',
- name: 'input',
- attrs: {
- type: 'text'
- },
- children: [],
- voidElement: true,
- },
- { type: 'text', content: ' 10 ' },
- ]
- }], 'should not give voidElements children');
-
- html = '<div></div>\n';
- parsed = HTML.parse(html);
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {},
- voidElement: false,
- children: []
- }], 'should not explode on trailing whitespace');
-
- html = '<div>Hi</div> There ';
- parsed = HTML.parse(html);
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {},
- voidElement: false,
- children: [
- { type: 'text', content: 'Hi' }
- ]
- },{
- type: 'text', content: ' There '
- }], 'should handle trailing text nodes at the top-level');
-
- html = '<div>Hi</div> There <span>something</span> <a></a>else ';
- parsed = HTML.parse(html);
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {},
- voidElement: false,
- children: [
- { type: 'text', content: 'Hi' }
- ]
- },{
- type: 'text', content: ' There '
- },{
- type: 'tag',
- name: 'span',
- attrs: {},
- voidElement: false,
- children: [
- { type: 'text', content: 'something' }
- ]
- },{
- type: 'text',
- content: ' '
- },
- {
- type: 'tag',
- name: 'a',
- attrs: {},
- voidElement: false,
- children: []
- },{
- type: 'text', content: 'else '
- }], 'should handle text nodes in the middle of tags at the top-level');
-
- html = '\n<div> <span>Hi!</span> </div>\n';
- parsed = HTML.parse(html);
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {},
- voidElement: false,
- children: [
- { type: 'text', content: ' '},
- {
- type: 'tag',
- name: 'span',
- attrs: {},
- voidElement: false,
- children: [
- { type: 'text', content: 'Hi!' }
- ]
- },
- { type: 'text', content: ' '}
- ]
- }], 'should trim whitespace from the beginning and end of the parsed nodes');
-
- html = '<div>Hi</div>\n\n <span>There</span> \t <div>\n\t</div>';
- parsed = HTML.parse(html);
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {},
- voidElement: false,
- children: [
- { type: 'text', content: 'Hi' }
- ]
- },{
- type: 'text',
- content: ' '
- },
- {
- type: 'tag',
- name: 'span',
- attrs: {},
- voidElement: false,
- children: [
- { type: 'text', content: 'There' }
- ]
- },{
- type: 'text',
- content: ' '
- },{
- type: 'tag',
- name: 'div',
- attrs: {},
- voidElement: false,
- children: [
- { type: 'text', content: ' ' }
- ]
- }], 'should collapse whitespace');
- // See https://www.w3.org/TR/html4/struct/text.html#h-9.1
-
- html = '<div>Hi</div>\n\n <span>There</span> \t <iframe>\n\t</iframe>';
- parsed = HTML.parse(html, { ignoreWhitespace: true });
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {},
- voidElement: false,
- children: [
- { type: 'text', content: 'Hi' }
- ]
- },{
- type: 'tag',
- name: 'span',
- attrs: {},
- voidElement: false,
- children: [
- { type: 'text', content: 'There' }
- ]
- },{
- type: 'tag',
- name: 'iframe',
- attrs: {},
- voidElement: false,
- children: []
- }], 'should remove text nodes that are nothing but whitespace if the ignoreWhitespace option is passed');
-
- html = '<!--\n\t<style type="text/css">\n\t\t.header {\n\t\t\tfont-size: 14px;\n\t\t}\n\t</style>\n\n-->\n<div>Hi</div>';
- parsed = HTML.parse(html);
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {},
- voidElement: false,
- children: [
- { type: 'text', content: 'Hi'}
- ]
- }], 'should ignore HTML comments');
-
- html = '<div>Hi <!-- I\'m a nested comment! with a <span></span> -->there<strong>!</strong></div><span><!--test--></span>';
- parsed = HTML.parse(html);
- t.deepEqual(parsed, [{
- type: 'tag',
- name: 'div',
- attrs: {},
- voidElement: false,
- children: [
- { type: 'text', content: 'Hi '},
- { type: 'text', content: 'there'},
- {
- type: 'tag',
- name: 'strong',
- attrs: {},
- voidElement: false,
- children: [{ type: 'text', content: '!'}]
- }
- ]
- },{
- type: 'tag',
- name: 'span',
- attrs: {},
- voidElement: false,
- children: []
- }], 'should ignore nested HTML comments');
-
- html = 'Hello, world!';
- parsed = HTML.parse(html);
- t.deepEqual(parsed, [{
- type: 'text',
- content: 'Hello, world!'
- }], 'should handle just text');
- t.end();
- });
-
- test('simple speed sanity check', function (t) {
- var i = 100000;
- var groupSize = 1000;
- var waitLoopSize = 10000000;
- var groups = i / groupSize;
- var html = '<html><head><title>Some page</title></head><body class="hey there"><img src="someURL"><h3>Hey, we need content</h3><br></body></html>';
-
- var parse = HTML.parse;
- var times = [];
- var count;
- var waitCount;
- var total = 0;
- var start, stepAverage;
-
- console.log('running ' + i + ' iterations...');
-
- while(i--) {
- count = groupSize;
- // grab groups
- if (i % count === 0) {
- start = Date.now();
- while(count--) {
- parse(html);
- }
- var diff = Date.now() - start;
- stepAverage = diff/groupSize;
- console.log('group ' + (groups - (i / groupSize)) + ': ' + stepAverage);
- times.push(stepAverage);
- total += stepAverage;
- waitCount = waitLoopSize;
- // forcing a bit of a pause between tests
- while(waitCount--) {}
- }
-
- }
-
- // trim off first
- // it's always a slower outlier
- // with higher variability that
- // makes it harder to find differences
- times.shift();
-
- var max = Math.max.apply(null, times);
- var min = Math.min.apply(null, times);
- var average = total / times.length;
-
- console.log('max', max);
- console.log('min', min);
- console.log('avg', average);
-
- t.end();
- });
|