1 |
|
2 | var JsonML, cheerio, htmlBeautify, htmlparser2;
|
3 |
|
4 | htmlparser2 = require('htmlparser2');
|
5 |
|
6 | cheerio = require('cheerio');
|
7 |
|
8 | htmlBeautify = require('js-beautify').html;
|
9 |
|
10 | JsonML = (function() {
|
11 | function JsonML() {}
|
12 |
|
13 | JsonML.prototype.stringifyListMode = true;
|
14 |
|
15 | JsonML.prototype.stringify = function(object, replacer, indent) {
|
16 | var element, html, j, len;
|
17 | html = '';
|
18 | if (this.stringifyListMode) {
|
19 | for (j = 0, len = object.length; j < len; j++) {
|
20 | element = object[j];
|
21 | html += this.stringifyElement(element, replacer);
|
22 | }
|
23 | } else {
|
24 | html += this.stringifyElement(object, replacer);
|
25 | }
|
26 | if (indent > 0) {
|
27 | html = htmlBeautify(html, {
|
28 | indent_size: indent,
|
29 | unformatted: ['code', 'pre', 'em', 'strong', 'span']
|
30 | });
|
31 | html = html.replace(/^\s*/g, '').replace(/(\r\n|\n){2,}/g, '\n');
|
32 | }
|
33 | return html;
|
34 | };
|
35 |
|
36 | JsonML.prototype.stringifyElement = function(element, replacer) {
|
37 | var attributes, elementList, i, j, len, list, name, node, ref;
|
38 | if (typeof element === 'string') {
|
39 | node = element;
|
40 | } else {
|
41 | if (typeof element[0] !== 'string') {
|
42 | throw new TypeError('Invalid tagName "' + element[0] + '"');
|
43 | }
|
44 | name = element.shift();
|
45 | if (((ref = element[0]) != null ? ref.toString() : void 0) === '[object Object]') {
|
46 | attributes = element.shift();
|
47 | }
|
48 | elementList = element != null ? element : [];
|
49 | node = cheerio('<' + name + '/>');
|
50 | if (attributes != null) {
|
51 | node.attr(attributes);
|
52 | }
|
53 | for (i = j = 0, len = elementList.length; j < len; i = ++j) {
|
54 | list = elementList[i];
|
55 | node.append(this.stringifyElement(list));
|
56 | }
|
57 | }
|
58 | if (replacer != null) {
|
59 | node = replacer(node);
|
60 | }
|
61 | return node;
|
62 | };
|
63 |
|
64 | JsonML.prototype.parse = function(html, trim) {
|
65 | var nodes, object;
|
66 | if (trim == null) {
|
67 | trim = true;
|
68 | }
|
69 | nodes = htmlparser2.parseDOM(html, {
|
70 | xmlMode: true
|
71 | });
|
72 | object = this.parseElementList(nodes, trim);
|
73 | return object;
|
74 | };
|
75 |
|
76 | JsonML.prototype.parseElementList = function(nodes, trim) {
|
77 | var canConcat, element, elementList, i, j, len, node;
|
78 | if (trim == null) {
|
79 | trim = true;
|
80 | }
|
81 | i = -1;
|
82 | elementList = [];
|
83 | for (j = 0, len = nodes.length; j < len; j++) {
|
84 | node = nodes[j];
|
85 | element = this.parseElement(node, trim);
|
86 | if (typeof element === 'string') {
|
87 | if (trim) {
|
88 | element = element.trim();
|
89 | }
|
90 | if (element === ' ' && trim) {
|
91 | element = '';
|
92 | }
|
93 | }
|
94 | if ((element != null ? element.length : void 0) === 0) {
|
95 | continue;
|
96 | }
|
97 | canConcat = typeof elementList[i] === 'string' && typeof element === 'string';
|
98 | if (canConcat) {
|
99 | elementList[i] += element;
|
100 | } else {
|
101 | if (element != null) {
|
102 | elementList.push(element);
|
103 | }
|
104 | i++;
|
105 | }
|
106 | }
|
107 | return elementList;
|
108 | };
|
109 |
|
110 | JsonML.prototype.parseElement = function(node, trim) {
|
111 | var attribs, child, children, data, element, elementList, j, len, name, type;
|
112 | if (trim == null) {
|
113 | trim = true;
|
114 | }
|
115 | type = node.type, data = node.data, name = node.name, attribs = node.attribs, children = node.children;
|
116 | switch (type) {
|
117 | case 'directive':
|
118 | return '<' + data + '>';
|
119 | case 'comment':
|
120 | return '<!--' + data + '-->';
|
121 | case 'text':
|
122 | return data;
|
123 | case 'tag':
|
124 | case 'script':
|
125 | case 'style':
|
126 | elementList = this.parseElementList(children, trim);
|
127 | element = [];
|
128 | if (name != null) {
|
129 | element.push(name);
|
130 | }
|
131 | if (Object.keys(attribs).length) {
|
132 | element.push(attribs);
|
133 | }
|
134 | for (j = 0, len = elementList.length; j < len; j++) {
|
135 | child = elementList[j];
|
136 | element.push(child);
|
137 | }
|
138 | return element;
|
139 | default:
|
140 | throw new TypeError(type + ' is Invalid node type');
|
141 | }
|
142 | };
|
143 |
|
144 | return JsonML;
|
145 |
|
146 | })();
|
147 |
|
148 | module.exports = new JsonML;
|
149 |
|
150 | module.exports.JsonML = JsonML;
|