UNPKG

3.1 kBJavaScriptView Raw
1'use strict';
2
3var htmlparser = require('htmlparser2');
4var isObject = require('isobject');
5
6/**
7 * @see https://github.com/fb55/htmlparser2/wiki/Parser-options
8 */
9var defaultOptions = {lowerCaseTags: false, lowerCaseAttributeNames: false};
10
11var defaultDirectives = [{name: '!doctype', start: '<', end: '>'}];
12
13/**
14 * Parse html to PostHTMLTree
15 * @param {String} html
16 * @param {Object} [options=defaultOptions]
17 * @return {PostHTMLTree}
18 */
19function postHTMLParser(html, options) {
20 var bufArray = [],
21 results = [];
22
23 bufArray.last = function() {
24 return this[this.length - 1];
25 };
26
27 function parserDirective(name, data) {
28 var directives = options.directives || defaultDirectives;
29 var last = bufArray.last();
30
31 for (var i = 0; i < directives.length; i++) {
32 var directive = directives[i];
33 var directiveText = directive.start + data + directive.end;
34
35 if (name.toLowerCase() === directive.name) {
36 if (!last) {
37 results.push(directiveText);
38 return;
39 }
40
41 last.content || (last.content = []);
42 last.content.push(directiveText);
43 }
44 }
45 }
46
47 var parser = new htmlparser.Parser({
48 onprocessinginstruction: parserDirective,
49 oncomment: function(data) {
50 var comment = '<!--' + data + '-->',
51 last = bufArray.last();
52
53 if (!last) {
54 results.push(comment);
55 return;
56 }
57
58 last.content || (last.content = []);
59 last.content.push(comment);
60 },
61 onopentag: function(tag, attrs) {
62 var buf = { tag: tag };
63
64 if (Object.keys(attrs).length) {
65 buf.attrs = attrs;
66 }
67
68 bufArray.push(buf);
69 },
70 onclosetag: function() {
71 var buf = bufArray.pop();
72
73 if (!bufArray.length) {
74 results.push(buf);
75 return;
76 }
77
78 var last = bufArray.last();
79 if (!Array.isArray(last.content)) {
80 last.content = [];
81 }
82
83 last.content.push(buf);
84 },
85 ontext: function(text) {
86 var last = bufArray.last();
87 if (!last) {
88 results.push(text);
89 return;
90 }
91
92 last.content || (last.content = []);
93 last.content.push(text);
94 }
95 }, options || defaultOptions);
96
97 parser.write(html);
98 parser.end();
99
100 return results;
101}
102
103function parserWrapper() {
104 var option;
105
106 function parser(html) {
107 var opt = option || defaultOptions;
108 return postHTMLParser(html, opt);
109 }
110
111 if (arguments.length === 1 && isObject(arguments[0])) {
112 option = arguments[0];
113 return parser;
114 }
115
116 option = arguments[1];
117 return parser(arguments[0]);
118}
119
120module.exports = parserWrapper;
121module.exports.defaultOptions = defaultOptions;
122module.exports.defaultDirectives = defaultDirectives;