htmlparser3
Based on htmlparser2 and supports htmlparser2's all features, but also support parsing jsx
syntax。
With this, you can create your own template engine
conveniently!
example
parse with Node.js: https://github.com/abell123456/htmlparser3/tree/master/demo/build-with-node
parse with React.js: https://github.com/abell123456/htmlparser3/tree/master/demo/react-parser
DEMO
const html = `
<Switch condition={"5"}>
<div>555</div>
<Case is={a>b} />
<span>111</span>
<Case is="2" />
<span>222</span>
<Default/>
<span>I am showed now!</span>
</Switch>
`;
var parser = require('htmlparser3');
var fs = require('fs');
var ast = parser.parseDOM(html, {
xmlMode: true
});
console.log('ast[0]:', ast[0]); // AST
ast[0].children.forEach(item => {
console.log(item);
});
printAttrs(ast[0]);
// console.log('attr:', ast[0].attribs);
function printAttrs(ast) {
if(ast.attrs && ast.attrs.length) {
ast.attrs.forEach(attr => {
console.log('attr:', attr);
});
}
if(ast.children && ast.children.length) {
ast.children.forEach(child => {
printAttrs(child);
});
}
}
Output:
{
type: 'tag',
name: 'Switch',
attrs: [ { name: 'condition', value: '{"5"}', expression: '{"5"}' } ],
children:
[ { data: '\n ',
type: 'text',
next: [Object],
prev: null,
parent: [Circular] },
{ type: 'tag',
name: 'div',
attrs: [],
children: [Object],
next: [Object],
prev: [Object],
parent: [Circular] },
{ data: '\n ',
type: 'text',
next: [Object],
prev: [Object],
parent: [Circular] },
{ type: 'tag',
name: 'Case',
attrs: [Object],
children: [],
next: [Object],
prev: [Object],
parent: [Circular] },
{ data: '\n ',
type: 'text',
next: [Object],
prev: [Object],
parent: [Circular] },
{ type: 'tag',
name: 'span',
attrs: [],
children: [Object],
next: [Object],
prev: [Object],
parent: [Circular] },
{ data: '\n ',
type: 'text',
next: [Object],
prev: [Object],
parent: [Circular] },
{ type: 'tag',
name: 'Case',
attrs: [Object],
children: [],
next: [Object],
prev: [Object],
parent: [Circular] },
{ data: '\n ',
type: 'text',
next: [Object],
prev: [Object],
parent: [Circular] },
{ type: 'tag',
name: 'span',
attrs: [],
children: [Object],
next: [Object],
prev: [Object],
parent: [Circular] },
{ data: '\n ',
type: 'text',
next: [Object],
prev: [Object],
parent: [Circular] },
{ type: 'tag',
name: 'Default',
attrs: [],
children: [],
next: [Object],
prev: [Object],
parent: [Circular] },
{ data: '\n ',
type: 'text',
next: [Object],
prev: [Object],
parent: [Circular] },
{ type: 'tag',
name: 'span',
attrs: [],
children: [Object],
next: [Object],
prev: [Object],
parent: [Circular] },
{ data: '\n',
type: 'text',
next: null,
prev: [Object],
parent: [Circular] } ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: null },
prev: null,
parent: null }
{ data: '\n ',
type: 'text',
next:
{ type: 'tag',
name: 'div',
attrs: [],
children: [ [Object] ],
next:
{ data: '\n ',
type: 'text',
next: [Object],
prev: [Circular],
parent: [Object] },
prev: [Circular],
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
prev: null,
parent:
{ type: 'tag',
name: 'Switch',
attrs: [ [Object] ],
children:
[ [Circular],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object] ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: null },
prev: null,
parent: null } }
{ type: 'tag',
name: 'div',
attrs: [],
children:
[ { data: '555',
type: 'text',
next: null,
prev: null,
parent: [Circular] } ],
next:
{ data: '\n ',
type: 'text',
next:
{ type: 'tag',
name: 'Case',
attrs: [Object],
children: [],
next: [Object],
prev: [Circular],
parent: [Object] },
prev: [Circular],
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
prev:
{ data: '\n ',
type: 'text',
next: [Circular],
prev: null,
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [ [Object] ],
children:
[ [Object],
[Circular],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object] ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: null },
prev: null,
parent: null } }
{ data: '\n ',
type: 'text',
next:
{ type: 'tag',
name: 'Case',
attrs: [ [Object] ],
children: [],
next:
{ data: '\n ',
type: 'text',
next: [Object],
prev: [Circular],
parent: [Object] },
prev: [Circular],
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
prev:
{ type: 'tag',
name: 'div',
attrs: [],
children: [ [Object] ],
next: [Circular],
prev:
{ data: '\n ',
type: 'text',
next: [Circular],
prev: null,
parent: [Object] },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [ [Object] ],
children:
[ [Object],
[Object],
[Circular],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object] ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: null },
prev: null,
parent: null } }
{ type: 'tag',
name: 'Case',
attrs: [ { name: 'is', value: '{a>b}', expression: '{a>b}' } ],
children: [],
next:
{ data: '\n ',
type: 'text',
next:
{ type: 'tag',
name: 'span',
attrs: [],
children: [Object],
next: [Object],
prev: [Circular],
parent: [Object] },
prev: [Circular],
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
prev:
{ data: '\n ',
type: 'text',
next: [Circular],
prev:
{ type: 'tag',
name: 'div',
attrs: [],
children: [Object],
next: [Circular],
prev: [Object],
parent: [Object] },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [ [Object] ],
children:
[ [Object],
[Object],
[Object],
[Circular],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object] ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: null },
prev: null,
parent: null } }
{ data: '\n ',
type: 'text',
next:
{ type: 'tag',
name: 'span',
attrs: [],
children: [ [Object] ],
next:
{ data: '\n ',
type: 'text',
next: [Object],
prev: [Circular],
parent: [Object] },
prev: [Circular],
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
prev:
{ type: 'tag',
name: 'Case',
attrs: [ [Object] ],
children: [],
next: [Circular],
prev:
{ data: '\n ',
type: 'text',
next: [Circular],
prev: [Object],
parent: [Object] },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [ [Object] ],
children:
[ [Object],
[Object],
[Object],
[Object],
[Circular],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object] ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: null },
prev: null,
parent: null } }
{ type: 'tag',
name: 'span',
attrs: [],
children:
[ { data: '111',
type: 'text',
next: null,
prev: null,
parent: [Circular] } ],
next:
{ data: '\n ',
type: 'text',
next:
{ type: 'tag',
name: 'Case',
attrs: [Object],
children: [],
next: [Object],
prev: [Circular],
parent: [Object] },
prev: [Circular],
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
prev:
{ data: '\n ',
type: 'text',
next: [Circular],
prev:
{ type: 'tag',
name: 'Case',
attrs: [Object],
children: [],
next: [Circular],
prev: [Object],
parent: [Object] },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [ [Object] ],
children:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Circular],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object] ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: null },
prev: null,
parent: null } }
{ data: '\n ',
type: 'text',
next:
{ type: 'tag',
name: 'Case',
attrs: [ [Object] ],
children: [],
next:
{ data: '\n ',
type: 'text',
next: [Object],
prev: [Circular],
parent: [Object] },
prev: [Circular],
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
prev:
{ type: 'tag',
name: 'span',
attrs: [],
children: [ [Object] ],
next: [Circular],
prev:
{ data: '\n ',
type: 'text',
next: [Circular],
prev: [Object],
parent: [Object] },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [ [Object] ],
children:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Circular],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object] ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: null },
prev: null,
parent: null } }
{ type: 'tag',
name: 'Case',
attrs: [ { name: 'is', value: '2' } ],
children: [],
next:
{ data: '\n ',
type: 'text',
next:
{ type: 'tag',
name: 'span',
attrs: [],
children: [Object],
next: [Object],
prev: [Circular],
parent: [Object] },
prev: [Circular],
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
prev:
{ data: '\n ',
type: 'text',
next: [Circular],
prev:
{ type: 'tag',
name: 'span',
attrs: [],
children: [Object],
next: [Circular],
prev: [Object],
parent: [Object] },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [ [Object] ],
children:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Circular],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object] ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: null },
prev: null,
parent: null } }
{ data: '\n ',
type: 'text',
next:
{ type: 'tag',
name: 'span',
attrs: [],
children: [ [Object] ],
next:
{ data: '\n ',
type: 'text',
next: [Object],
prev: [Circular],
parent: [Object] },
prev: [Circular],
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
prev:
{ type: 'tag',
name: 'Case',
attrs: [ [Object] ],
children: [],
next: [Circular],
prev:
{ data: '\n ',
type: 'text',
next: [Circular],
prev: [Object],
parent: [Object] },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [ [Object] ],
children:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Circular],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object] ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: null },
prev: null,
parent: null } }
{ type: 'tag',
name: 'span',
attrs: [],
children:
[ { data: '222',
type: 'text',
next: null,
prev: null,
parent: [Circular] } ],
next:
{ data: '\n ',
type: 'text',
next:
{ type: 'tag',
name: 'Default',
attrs: [],
children: [],
next: [Object],
prev: [Circular],
parent: [Object] },
prev: [Circular],
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
prev:
{ data: '\n ',
type: 'text',
next: [Circular],
prev:
{ type: 'tag',
name: 'Case',
attrs: [Object],
children: [],
next: [Circular],
prev: [Object],
parent: [Object] },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [ [Object] ],
children:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Circular],
[Object],
[Object],
[Object],
[Object],
[Object] ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: null },
prev: null,
parent: null } }
{ data: '\n ',
type: 'text',
next:
{ type: 'tag',
name: 'Default',
attrs: [],
children: [],
next:
{ data: '\n ',
type: 'text',
next: [Object],
prev: [Circular],
parent: [Object] },
prev: [Circular],
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
prev:
{ type: 'tag',
name: 'span',
attrs: [],
children: [ [Object] ],
next: [Circular],
prev:
{ data: '\n ',
type: 'text',
next: [Circular],
prev: [Object],
parent: [Object] },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [ [Object] ],
children:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Circular],
[Object],
[Object],
[Object],
[Object] ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: null },
prev: null,
parent: null } }
{ type: 'tag',
name: 'Default',
attrs: [],
children: [],
next:
{ data: '\n ',
type: 'text',
next:
{ type: 'tag',
name: 'span',
attrs: [],
children: [Object],
next: [Object],
prev: [Circular],
parent: [Object] },
prev: [Circular],
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
prev:
{ data: '\n ',
type: 'text',
next: [Circular],
prev:
{ type: 'tag',
name: 'span',
attrs: [],
children: [Object],
next: [Circular],
prev: [Object],
parent: [Object] },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [ [Object] ],
children:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Circular],
[Object],
[Object],
[Object] ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: null },
prev: null,
parent: null } }
{ data: '\n ',
type: 'text',
next:
{ type: 'tag',
name: 'span',
attrs: [],
children: [ [Object] ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: [Object] },
prev: [Circular],
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
prev:
{ type: 'tag',
name: 'Default',
attrs: [],
children: [],
next: [Circular],
prev:
{ data: '\n ',
type: 'text',
next: [Circular],
prev: [Object],
parent: [Object] },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [ [Object] ],
children:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Circular],
[Object],
[Object] ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: null },
prev: null,
parent: null } }
{ type: 'tag',
name: 'span',
attrs: [],
children:
[ { data: 'I am showed now!',
type: 'text',
next: null,
prev: null,
parent: [Circular] } ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
prev:
{ data: '\n ',
type: 'text',
next: [Circular],
prev:
{ type: 'tag',
name: 'Default',
attrs: [],
children: [],
next: [Circular],
prev: [Object],
parent: [Object] },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [ [Object] ],
children:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Circular],
[Object] ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: null },
prev: null,
parent: null } }
{ data: '\n',
type: 'text',
next: null,
prev:
{ type: 'tag',
name: 'span',
attrs: [],
children: [ [Object] ],
next: [Circular],
prev:
{ data: '\n ',
type: 'text',
next: [Circular],
prev: [Object],
parent: [Object] },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [Object],
children: [Object],
next: [Object],
prev: null,
parent: null } },
parent:
{ type: 'tag',
name: 'Switch',
attrs: [ [Object] ],
children:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Circular] ],
next:
{ data: '\n',
type: 'text',
next: null,
prev: [Circular],
parent: null },
prev: null,
parent: null }
}
新特性
-
支持
JSX {}
格式的表达式定义; -
使用自定制
domhandler3
替换默认domhandler
,支持更多方便的钩子函数及功能定制; -
属性部分由原来的对象格式转变为:
数组
,并增添是否是表达式的判断属性; -
表达式解析优化,支持:
{alert(0)}{console.log(1)}
两个标签并列书写,支持:{'<div>hello world<div>'}
;