node-html-parser 4.1.5
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/.eslintignore +3 -0
- package/.eslintrc.json +226 -0
- package/.mocharc.yaml +1 -0
- package/.prettierrc +7 -0
- package/LICENSE +7 -0
- package/README.md +255 -0
- package/dist/back.d.ts +1 -0
- package/dist/back.js +6 -0
- package/dist/esm/back.js +3 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/matcher.js +101 -0
- package/dist/esm/nodes/comment.js +23 -0
- package/dist/esm/nodes/html.js +1048 -0
- package/dist/esm/nodes/node.js +25 -0
- package/dist/esm/nodes/text.js +95 -0
- package/dist/esm/nodes/type.js +7 -0
- package/dist/esm/parse.js +1 -0
- package/dist/esm/valid.js +9 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +21 -0
- package/dist/main.js +1542 -0
- package/dist/matcher.d.ts +6 -0
- package/dist/matcher.js +106 -0
- package/dist/nodes/comment.d.ts +18 -0
- package/dist/nodes/comment.js +51 -0
- package/dist/nodes/html.d.ts +206 -0
- package/dist/nodes/html.js +1188 -0
- package/dist/nodes/node.d.ts +18 -0
- package/dist/nodes/node.js +38 -0
- package/dist/nodes/text.d.ts +42 -0
- package/dist/nodes/text.js +139 -0
- package/dist/nodes/type.d.ts +6 -0
- package/dist/nodes/type.js +9 -0
- package/dist/parse.d.ts +1 -0
- package/dist/parse.js +5 -0
- package/dist/valid.d.ts +6 -0
- package/dist/valid.js +13 -0
- package/package.json +88 -0
package/dist/main.js
ADDED
|
@@ -0,0 +1,1542 @@
|
|
|
1
|
+
var __extends = (this && this.__extends) || (function () {
|
|
2
|
+
var extendStatics = function (d, b) {
|
|
3
|
+
extendStatics = Object.setPrototypeOf ||
|
|
4
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
5
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
6
|
+
return extendStatics(d, b);
|
|
7
|
+
};
|
|
8
|
+
return function (d, b) {
|
|
9
|
+
if (typeof b !== "function" && b !== null)
|
|
10
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
11
|
+
extendStatics(d, b);
|
|
12
|
+
function __() { this.constructor = d; }
|
|
13
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
14
|
+
};
|
|
15
|
+
})();
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
var __assign = (this && this.__assign) || function () {
|
|
20
|
+
__assign = Object.assign || function(t) {
|
|
21
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
22
|
+
s = arguments[i];
|
|
23
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
24
|
+
t[p] = s[p];
|
|
25
|
+
}
|
|
26
|
+
return t;
|
|
27
|
+
};
|
|
28
|
+
return __assign.apply(this, arguments);
|
|
29
|
+
};
|
|
30
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
31
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
32
|
+
if (ar || !(i in from)) {
|
|
33
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
34
|
+
ar[i] = from[i];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return to.concat(ar || from);
|
|
38
|
+
};
|
|
39
|
+
define("back", ["require", "exports"], function (require, exports) {
|
|
40
|
+
"use strict";
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
function arr_back(arr) {
|
|
43
|
+
return arr[arr.length - 1];
|
|
44
|
+
}
|
|
45
|
+
exports.default = arr_back;
|
|
46
|
+
});
|
|
47
|
+
define("nodes/type", ["require", "exports"], function (require, exports) {
|
|
48
|
+
"use strict";
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
var NodeType;
|
|
51
|
+
(function (NodeType) {
|
|
52
|
+
NodeType[NodeType["ELEMENT_NODE"] = 1] = "ELEMENT_NODE";
|
|
53
|
+
NodeType[NodeType["TEXT_NODE"] = 3] = "TEXT_NODE";
|
|
54
|
+
NodeType[NodeType["COMMENT_NODE"] = 8] = "COMMENT_NODE";
|
|
55
|
+
})(NodeType || (NodeType = {}));
|
|
56
|
+
exports.default = NodeType;
|
|
57
|
+
});
|
|
58
|
+
define("nodes/text", ["require", "exports", "he", "nodes/node", "nodes/type"], function (require, exports, he_1, node_1, type_1) {
|
|
59
|
+
"use strict";
|
|
60
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
61
|
+
node_1 = __importDefault(node_1);
|
|
62
|
+
type_1 = __importDefault(type_1);
|
|
63
|
+
/**
|
|
64
|
+
* TextNode to contain a text element in DOM tree.
|
|
65
|
+
* @param {string} value [description]
|
|
66
|
+
*/
|
|
67
|
+
var TextNode = /** @class */ (function (_super) {
|
|
68
|
+
__extends(TextNode, _super);
|
|
69
|
+
function TextNode(rawText, parentNode, range) {
|
|
70
|
+
var _this = _super.call(this, parentNode, range) || this;
|
|
71
|
+
/**
|
|
72
|
+
* Node Type declaration.
|
|
73
|
+
* @type {Number}
|
|
74
|
+
*/
|
|
75
|
+
_this.nodeType = type_1.default.TEXT_NODE;
|
|
76
|
+
_this._rawText = rawText;
|
|
77
|
+
return _this;
|
|
78
|
+
}
|
|
79
|
+
Object.defineProperty(TextNode.prototype, "rawText", {
|
|
80
|
+
get: function () {
|
|
81
|
+
return this._rawText;
|
|
82
|
+
},
|
|
83
|
+
/**
|
|
84
|
+
* Set rawText and invalidate trimmed caches
|
|
85
|
+
*/
|
|
86
|
+
set: function (text) {
|
|
87
|
+
this._rawText = text;
|
|
88
|
+
this._trimmedRawText = void 0;
|
|
89
|
+
this._trimmedText = void 0;
|
|
90
|
+
},
|
|
91
|
+
enumerable: false,
|
|
92
|
+
configurable: true
|
|
93
|
+
});
|
|
94
|
+
Object.defineProperty(TextNode.prototype, "trimmedRawText", {
|
|
95
|
+
/**
|
|
96
|
+
* Returns raw text with all whitespace trimmed except single leading/trailing non-breaking space
|
|
97
|
+
*/
|
|
98
|
+
get: function () {
|
|
99
|
+
if (this._trimmedRawText !== undefined)
|
|
100
|
+
return this._trimmedRawText;
|
|
101
|
+
this._trimmedRawText = trimText(this.rawText);
|
|
102
|
+
return this._trimmedRawText;
|
|
103
|
+
},
|
|
104
|
+
enumerable: false,
|
|
105
|
+
configurable: true
|
|
106
|
+
});
|
|
107
|
+
Object.defineProperty(TextNode.prototype, "trimmedText", {
|
|
108
|
+
/**
|
|
109
|
+
* Returns text with all whitespace trimmed except single leading/trailing non-breaking space
|
|
110
|
+
*/
|
|
111
|
+
get: function () {
|
|
112
|
+
if (this._trimmedText !== undefined)
|
|
113
|
+
return this._trimmedText;
|
|
114
|
+
this._trimmedText = trimText(this.text);
|
|
115
|
+
return this._trimmedText;
|
|
116
|
+
},
|
|
117
|
+
enumerable: false,
|
|
118
|
+
configurable: true
|
|
119
|
+
});
|
|
120
|
+
Object.defineProperty(TextNode.prototype, "text", {
|
|
121
|
+
/**
|
|
122
|
+
* Get unescaped text value of current node and its children.
|
|
123
|
+
* @return {string} text content
|
|
124
|
+
*/
|
|
125
|
+
get: function () {
|
|
126
|
+
return (0, he_1.decode)(this.rawText);
|
|
127
|
+
},
|
|
128
|
+
enumerable: false,
|
|
129
|
+
configurable: true
|
|
130
|
+
});
|
|
131
|
+
Object.defineProperty(TextNode.prototype, "isWhitespace", {
|
|
132
|
+
/**
|
|
133
|
+
* Detect if the node contains only white space.
|
|
134
|
+
* @return {boolean}
|
|
135
|
+
*/
|
|
136
|
+
get: function () {
|
|
137
|
+
return /^(\s| )*$/.test(this.rawText);
|
|
138
|
+
},
|
|
139
|
+
enumerable: false,
|
|
140
|
+
configurable: true
|
|
141
|
+
});
|
|
142
|
+
TextNode.prototype.toString = function () {
|
|
143
|
+
return this.rawText;
|
|
144
|
+
};
|
|
145
|
+
return TextNode;
|
|
146
|
+
}(node_1.default));
|
|
147
|
+
exports.default = TextNode;
|
|
148
|
+
/**
|
|
149
|
+
* Trim whitespace except single leading/trailing non-breaking space
|
|
150
|
+
*/
|
|
151
|
+
function trimText(text) {
|
|
152
|
+
var i = 0;
|
|
153
|
+
var startPos;
|
|
154
|
+
var endPos;
|
|
155
|
+
while (i >= 0 && i < text.length) {
|
|
156
|
+
if (/\S/.test(text[i])) {
|
|
157
|
+
if (startPos === undefined) {
|
|
158
|
+
startPos = i;
|
|
159
|
+
i = text.length;
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
endPos = i;
|
|
163
|
+
i = void 0;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (startPos === undefined)
|
|
167
|
+
i++;
|
|
168
|
+
else
|
|
169
|
+
i--;
|
|
170
|
+
}
|
|
171
|
+
if (startPos === undefined)
|
|
172
|
+
startPos = 0;
|
|
173
|
+
if (endPos === undefined)
|
|
174
|
+
endPos = text.length - 1;
|
|
175
|
+
var hasLeadingSpace = startPos > 0 && /[^\S\r\n]/.test(text[startPos - 1]);
|
|
176
|
+
var hasTrailingSpace = endPos < (text.length - 1) && /[^\S\r\n]/.test(text[endPos + 1]);
|
|
177
|
+
return (hasLeadingSpace ? ' ' : '') + text.slice(startPos, endPos + 1) + (hasTrailingSpace ? ' ' : '');
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
define("matcher", ["require", "exports", "nodes/type"], function (require, exports, type_2) {
|
|
181
|
+
"use strict";
|
|
182
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
183
|
+
type_2 = __importDefault(type_2);
|
|
184
|
+
function isTag(node) {
|
|
185
|
+
return node && node.nodeType === type_2.default.ELEMENT_NODE;
|
|
186
|
+
}
|
|
187
|
+
function getAttributeValue(elem, name) {
|
|
188
|
+
return isTag(elem) ? elem.getAttribute(name) : undefined;
|
|
189
|
+
}
|
|
190
|
+
function getName(elem) {
|
|
191
|
+
return ((elem && elem.rawTagName) || '').toLowerCase();
|
|
192
|
+
}
|
|
193
|
+
function getChildren(node) {
|
|
194
|
+
return node && node.childNodes;
|
|
195
|
+
}
|
|
196
|
+
function getParent(node) {
|
|
197
|
+
return node ? node.parentNode : null;
|
|
198
|
+
}
|
|
199
|
+
function getText(node) {
|
|
200
|
+
return node.text;
|
|
201
|
+
}
|
|
202
|
+
function removeSubsets(nodes) {
|
|
203
|
+
var idx = nodes.length;
|
|
204
|
+
var node;
|
|
205
|
+
var ancestor;
|
|
206
|
+
var replace;
|
|
207
|
+
// Check if each node (or one of its ancestors) is already contained in the
|
|
208
|
+
// array.
|
|
209
|
+
while (--idx > -1) {
|
|
210
|
+
node = ancestor = nodes[idx];
|
|
211
|
+
// Temporarily remove the node under consideration
|
|
212
|
+
nodes[idx] = null;
|
|
213
|
+
replace = true;
|
|
214
|
+
while (ancestor) {
|
|
215
|
+
if (nodes.indexOf(ancestor) > -1) {
|
|
216
|
+
replace = false;
|
|
217
|
+
nodes.splice(idx, 1);
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
ancestor = getParent(ancestor);
|
|
221
|
+
}
|
|
222
|
+
// If the node has been found to be unique, re-insert it.
|
|
223
|
+
if (replace) {
|
|
224
|
+
nodes[idx] = node;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return nodes;
|
|
228
|
+
}
|
|
229
|
+
function existsOne(test, elems) {
|
|
230
|
+
return elems.some(function (elem) {
|
|
231
|
+
return isTag(elem) ? test(elem) || existsOne(test, getChildren(elem)) : false;
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
function getSiblings(node) {
|
|
235
|
+
var parent = getParent(node);
|
|
236
|
+
return parent && getChildren(parent);
|
|
237
|
+
}
|
|
238
|
+
function hasAttrib(elem, name) {
|
|
239
|
+
return getAttributeValue(elem, name) !== undefined;
|
|
240
|
+
}
|
|
241
|
+
function findOne(test, elems) {
|
|
242
|
+
var elem = null;
|
|
243
|
+
for (var i = 0, l = elems.length; i < l && !elem; i++) {
|
|
244
|
+
var el = elems[i];
|
|
245
|
+
if (test(el)) {
|
|
246
|
+
elem = el;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
var childs = getChildren(el);
|
|
250
|
+
if (childs && childs.length > 0) {
|
|
251
|
+
elem = findOne(test, childs);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return elem;
|
|
256
|
+
}
|
|
257
|
+
function findAll(test, nodes) {
|
|
258
|
+
var result = [];
|
|
259
|
+
for (var i = 0, j = nodes.length; i < j; i++) {
|
|
260
|
+
if (!isTag(nodes[i]))
|
|
261
|
+
continue;
|
|
262
|
+
if (test(nodes[i]))
|
|
263
|
+
result.push(nodes[i]);
|
|
264
|
+
var childs = getChildren(nodes[i]);
|
|
265
|
+
if (childs)
|
|
266
|
+
result = result.concat(findAll(test, childs));
|
|
267
|
+
}
|
|
268
|
+
return result;
|
|
269
|
+
}
|
|
270
|
+
exports.default = {
|
|
271
|
+
isTag: isTag,
|
|
272
|
+
getAttributeValue: getAttributeValue,
|
|
273
|
+
getName: getName,
|
|
274
|
+
getChildren: getChildren,
|
|
275
|
+
getParent: getParent,
|
|
276
|
+
getText: getText,
|
|
277
|
+
removeSubsets: removeSubsets,
|
|
278
|
+
existsOne: existsOne,
|
|
279
|
+
getSiblings: getSiblings,
|
|
280
|
+
hasAttrib: hasAttrib,
|
|
281
|
+
findOne: findOne,
|
|
282
|
+
findAll: findAll
|
|
283
|
+
};
|
|
284
|
+
});
|
|
285
|
+
define("nodes/html", ["require", "exports", "he", "css-select", "nodes/node", "nodes/type", "nodes/text", "matcher", "back", "nodes/comment"], function (require, exports, he_2, css_select_1, node_2, type_3, text_1, matcher_1, back_1, comment_1) {
|
|
286
|
+
"use strict";
|
|
287
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
288
|
+
exports.parse = exports.base_parse = void 0;
|
|
289
|
+
he_2 = __importDefault(he_2);
|
|
290
|
+
node_2 = __importDefault(node_2);
|
|
291
|
+
type_3 = __importDefault(type_3);
|
|
292
|
+
text_1 = __importDefault(text_1);
|
|
293
|
+
matcher_1 = __importDefault(matcher_1);
|
|
294
|
+
back_1 = __importDefault(back_1);
|
|
295
|
+
comment_1 = __importDefault(comment_1);
|
|
296
|
+
function decode(val) {
|
|
297
|
+
// clone string
|
|
298
|
+
return JSON.parse(JSON.stringify(he_2.default.decode(val)));
|
|
299
|
+
}
|
|
300
|
+
// https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements
|
|
301
|
+
var Htags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup'];
|
|
302
|
+
var Dtags = ['details', 'dialog', 'dd', 'div', 'dt'];
|
|
303
|
+
var Ftags = ['fieldset', 'figcaption', 'figure', 'footer', 'form'];
|
|
304
|
+
var tableTags = ['table', 'td', 'tr'];
|
|
305
|
+
var htmlTags = ['address', 'article', 'aside', 'blockquote', 'br', 'hr', 'li', 'main', 'nav', 'ol', 'p', 'pre', 'section', 'ul'];
|
|
306
|
+
var kBlockElements = new Set();
|
|
307
|
+
function addToKBlockElement() {
|
|
308
|
+
var args = [];
|
|
309
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
310
|
+
args[_i] = arguments[_i];
|
|
311
|
+
}
|
|
312
|
+
var addToSet = function (array) {
|
|
313
|
+
for (var index = 0; index < array.length; index++) {
|
|
314
|
+
var element = array[index];
|
|
315
|
+
kBlockElements.add(element);
|
|
316
|
+
kBlockElements.add(element.toUpperCase());
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
for (var _a = 0, args_1 = args; _a < args_1.length; _a++) {
|
|
320
|
+
var arg = args_1[_a];
|
|
321
|
+
addToSet(arg);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
addToKBlockElement(Htags, Dtags, Ftags, tableTags, htmlTags);
|
|
325
|
+
var DOMTokenList = /** @class */ (function () {
|
|
326
|
+
function DOMTokenList(valuesInit, afterUpdate) {
|
|
327
|
+
if (valuesInit === void 0) { valuesInit = []; }
|
|
328
|
+
if (afterUpdate === void 0) { afterUpdate = function () { return null; }; }
|
|
329
|
+
this._set = new Set(valuesInit);
|
|
330
|
+
this._afterUpdate = afterUpdate;
|
|
331
|
+
}
|
|
332
|
+
DOMTokenList.prototype._validate = function (c) {
|
|
333
|
+
if (/\s/.test(c)) {
|
|
334
|
+
throw new Error("DOMException in DOMTokenList.add: The token '" + c + "' contains HTML space characters, which are not valid in tokens.");
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
DOMTokenList.prototype.add = function (c) {
|
|
338
|
+
this._validate(c);
|
|
339
|
+
this._set.add(c);
|
|
340
|
+
this._afterUpdate(this); // eslint-disable-line @typescript-eslint/no-unsafe-call
|
|
341
|
+
};
|
|
342
|
+
DOMTokenList.prototype.replace = function (c1, c2) {
|
|
343
|
+
this._validate(c2);
|
|
344
|
+
this._set.delete(c1);
|
|
345
|
+
this._set.add(c2);
|
|
346
|
+
this._afterUpdate(this); // eslint-disable-line @typescript-eslint/no-unsafe-call
|
|
347
|
+
};
|
|
348
|
+
DOMTokenList.prototype.remove = function (c) {
|
|
349
|
+
this._set.delete(c) && this._afterUpdate(this); // eslint-disable-line @typescript-eslint/no-unsafe-call
|
|
350
|
+
};
|
|
351
|
+
DOMTokenList.prototype.toggle = function (c) {
|
|
352
|
+
this._validate(c);
|
|
353
|
+
if (this._set.has(c))
|
|
354
|
+
this._set.delete(c);
|
|
355
|
+
else
|
|
356
|
+
this._set.add(c);
|
|
357
|
+
this._afterUpdate(this); // eslint-disable-line @typescript-eslint/no-unsafe-call
|
|
358
|
+
};
|
|
359
|
+
DOMTokenList.prototype.contains = function (c) {
|
|
360
|
+
return this._set.has(c);
|
|
361
|
+
};
|
|
362
|
+
Object.defineProperty(DOMTokenList.prototype, "length", {
|
|
363
|
+
get: function () {
|
|
364
|
+
return this._set.size;
|
|
365
|
+
},
|
|
366
|
+
enumerable: false,
|
|
367
|
+
configurable: true
|
|
368
|
+
});
|
|
369
|
+
DOMTokenList.prototype.values = function () {
|
|
370
|
+
return this._set.values();
|
|
371
|
+
};
|
|
372
|
+
Object.defineProperty(DOMTokenList.prototype, "value", {
|
|
373
|
+
get: function () {
|
|
374
|
+
return Array.from(this._set.values());
|
|
375
|
+
},
|
|
376
|
+
enumerable: false,
|
|
377
|
+
configurable: true
|
|
378
|
+
});
|
|
379
|
+
DOMTokenList.prototype.toString = function () {
|
|
380
|
+
return Array.from(this._set.values()).join(' ');
|
|
381
|
+
};
|
|
382
|
+
return DOMTokenList;
|
|
383
|
+
}());
|
|
384
|
+
/**
|
|
385
|
+
* HTMLElement, which contains a set of children.
|
|
386
|
+
*
|
|
387
|
+
* Note: this is a minimalist implementation, no complete tree
|
|
388
|
+
* structure provided (no parentNode, nextSibling,
|
|
389
|
+
* previousSibling etc).
|
|
390
|
+
* @class HTMLElement
|
|
391
|
+
* @extends {Node}
|
|
392
|
+
*/
|
|
393
|
+
var HTMLElement = /** @class */ (function (_super) {
|
|
394
|
+
__extends(HTMLElement, _super);
|
|
395
|
+
/**
|
|
396
|
+
* Creates an instance of HTMLElement.
|
|
397
|
+
* @param keyAttrs id and class attribute
|
|
398
|
+
* @param [rawAttrs] attributes in string
|
|
399
|
+
*
|
|
400
|
+
* @memberof HTMLElement
|
|
401
|
+
*/
|
|
402
|
+
function HTMLElement(tagName, keyAttrs, rawAttrs, parentNode, range) {
|
|
403
|
+
if (rawAttrs === void 0) { rawAttrs = ''; }
|
|
404
|
+
var _this = _super.call(this, parentNode, range) || this;
|
|
405
|
+
_this.rawAttrs = rawAttrs;
|
|
406
|
+
/**
|
|
407
|
+
* Node Type declaration.
|
|
408
|
+
*/
|
|
409
|
+
_this.nodeType = type_3.default.ELEMENT_NODE;
|
|
410
|
+
_this.rawTagName = tagName;
|
|
411
|
+
_this.rawAttrs = rawAttrs || '';
|
|
412
|
+
_this.id = keyAttrs.id || '';
|
|
413
|
+
_this.childNodes = [];
|
|
414
|
+
_this.classList = new DOMTokenList(keyAttrs.class ? keyAttrs.class.split(/\s+/) : [], function (classList) { return _this.setAttribute('class', classList.toString()); } // eslint-disable-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
|
415
|
+
);
|
|
416
|
+
if (keyAttrs.id) {
|
|
417
|
+
if (!rawAttrs) {
|
|
418
|
+
_this.rawAttrs = "id=\"" + keyAttrs.id + "\"";
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
if (keyAttrs.class) {
|
|
422
|
+
if (!rawAttrs) {
|
|
423
|
+
var cls = "class=\"" + _this.classList.toString() + "\"";
|
|
424
|
+
if (_this.rawAttrs) {
|
|
425
|
+
_this.rawAttrs += " " + cls;
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
_this.rawAttrs = cls;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return _this;
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Quote attribute values
|
|
436
|
+
* @param attr attribute value
|
|
437
|
+
* @returns {string} quoted value
|
|
438
|
+
*/
|
|
439
|
+
HTMLElement.prototype.quoteAttribute = function (attr) {
|
|
440
|
+
if (attr === null) {
|
|
441
|
+
return 'null';
|
|
442
|
+
}
|
|
443
|
+
return JSON.stringify(attr.replace(/"/g, '"'));
|
|
444
|
+
};
|
|
445
|
+
/**
|
|
446
|
+
* Remove current element
|
|
447
|
+
*/
|
|
448
|
+
HTMLElement.prototype.remove = function () {
|
|
449
|
+
var _this = this;
|
|
450
|
+
if (this.parentNode) {
|
|
451
|
+
var children = this.parentNode.childNodes;
|
|
452
|
+
this.parentNode.childNodes = children.filter(function (child) {
|
|
453
|
+
return _this !== child;
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
/**
|
|
458
|
+
* Remove Child element from childNodes array
|
|
459
|
+
* @param {HTMLElement} node node to remove
|
|
460
|
+
*/
|
|
461
|
+
HTMLElement.prototype.removeChild = function (node) {
|
|
462
|
+
this.childNodes = this.childNodes.filter(function (child) {
|
|
463
|
+
return child !== node;
|
|
464
|
+
});
|
|
465
|
+
};
|
|
466
|
+
/**
|
|
467
|
+
* Exchanges given child with new child
|
|
468
|
+
* @param {HTMLElement} oldNode node to exchange
|
|
469
|
+
* @param {HTMLElement} newNode new node
|
|
470
|
+
*/
|
|
471
|
+
HTMLElement.prototype.exchangeChild = function (oldNode, newNode) {
|
|
472
|
+
var children = this.childNodes;
|
|
473
|
+
this.childNodes = children.map(function (child) {
|
|
474
|
+
if (child === oldNode) {
|
|
475
|
+
return newNode;
|
|
476
|
+
}
|
|
477
|
+
return child;
|
|
478
|
+
});
|
|
479
|
+
};
|
|
480
|
+
Object.defineProperty(HTMLElement.prototype, "tagName", {
|
|
481
|
+
get: function () {
|
|
482
|
+
return this.rawTagName ? this.rawTagName.toUpperCase() : this.rawTagName;
|
|
483
|
+
},
|
|
484
|
+
enumerable: false,
|
|
485
|
+
configurable: true
|
|
486
|
+
});
|
|
487
|
+
Object.defineProperty(HTMLElement.prototype, "localName", {
|
|
488
|
+
get: function () {
|
|
489
|
+
return this.rawTagName.toLowerCase();
|
|
490
|
+
},
|
|
491
|
+
enumerable: false,
|
|
492
|
+
configurable: true
|
|
493
|
+
});
|
|
494
|
+
Object.defineProperty(HTMLElement.prototype, "rawText", {
|
|
495
|
+
/**
|
|
496
|
+
* Get escpaed (as-it) text value of current node and its children.
|
|
497
|
+
* @return {string} text content
|
|
498
|
+
*/
|
|
499
|
+
get: function () {
|
|
500
|
+
return this.childNodes.reduce(function (pre, cur) {
|
|
501
|
+
return (pre += cur.rawText);
|
|
502
|
+
}, '');
|
|
503
|
+
},
|
|
504
|
+
enumerable: false,
|
|
505
|
+
configurable: true
|
|
506
|
+
});
|
|
507
|
+
Object.defineProperty(HTMLElement.prototype, "textContent", {
|
|
508
|
+
get: function () {
|
|
509
|
+
return decode(this.rawText);
|
|
510
|
+
},
|
|
511
|
+
set: function (val) {
|
|
512
|
+
var content = [new text_1.default(val, this)];
|
|
513
|
+
this.childNodes = content;
|
|
514
|
+
},
|
|
515
|
+
enumerable: false,
|
|
516
|
+
configurable: true
|
|
517
|
+
});
|
|
518
|
+
Object.defineProperty(HTMLElement.prototype, "text", {
|
|
519
|
+
/**
|
|
520
|
+
* Get unescaped text value of current node and its children.
|
|
521
|
+
* @return {string} text content
|
|
522
|
+
*/
|
|
523
|
+
get: function () {
|
|
524
|
+
return decode(this.rawText);
|
|
525
|
+
},
|
|
526
|
+
enumerable: false,
|
|
527
|
+
configurable: true
|
|
528
|
+
});
|
|
529
|
+
Object.defineProperty(HTMLElement.prototype, "structuredText", {
|
|
530
|
+
/**
|
|
531
|
+
* Get structured Text (with '\n' etc.)
|
|
532
|
+
* @return {string} structured text
|
|
533
|
+
*/
|
|
534
|
+
get: function () {
|
|
535
|
+
var currentBlock = [];
|
|
536
|
+
var blocks = [currentBlock];
|
|
537
|
+
function dfs(node) {
|
|
538
|
+
if (node.nodeType === type_3.default.ELEMENT_NODE) {
|
|
539
|
+
if (kBlockElements.has(node.rawTagName)) {
|
|
540
|
+
if (currentBlock.length > 0) {
|
|
541
|
+
blocks.push((currentBlock = []));
|
|
542
|
+
}
|
|
543
|
+
node.childNodes.forEach(dfs);
|
|
544
|
+
if (currentBlock.length > 0) {
|
|
545
|
+
blocks.push((currentBlock = []));
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
else {
|
|
549
|
+
node.childNodes.forEach(dfs);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
else if (node.nodeType === type_3.default.TEXT_NODE) {
|
|
553
|
+
if (node.isWhitespace) {
|
|
554
|
+
// Whitespace node, postponed output
|
|
555
|
+
currentBlock.prependWhitespace = true;
|
|
556
|
+
}
|
|
557
|
+
else {
|
|
558
|
+
var text = node.trimmedText;
|
|
559
|
+
if (currentBlock.prependWhitespace) {
|
|
560
|
+
text = " " + text;
|
|
561
|
+
currentBlock.prependWhitespace = false;
|
|
562
|
+
}
|
|
563
|
+
currentBlock.push(text);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
dfs(this);
|
|
568
|
+
return blocks
|
|
569
|
+
.map(function (block) {
|
|
570
|
+
return block.join('').replace(/\s{2,}/g, ' '); // Normalize each line's whitespace
|
|
571
|
+
})
|
|
572
|
+
.join('\n')
|
|
573
|
+
.replace(/\s+$/, ''); // trimRight;
|
|
574
|
+
},
|
|
575
|
+
enumerable: false,
|
|
576
|
+
configurable: true
|
|
577
|
+
});
|
|
578
|
+
HTMLElement.prototype.toString = function () {
|
|
579
|
+
var tag = this.rawTagName;
|
|
580
|
+
if (tag) {
|
|
581
|
+
// const void_tags = new Set('area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr'.split('|'));
|
|
582
|
+
// const is_void = void_tags.has(tag);
|
|
583
|
+
var is_void = /^(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)$/i.test(tag);
|
|
584
|
+
var attrs = this.rawAttrs ? " " + this.rawAttrs : '';
|
|
585
|
+
if (is_void) {
|
|
586
|
+
return "<" + tag + attrs + ">";
|
|
587
|
+
}
|
|
588
|
+
return "<" + tag + attrs + ">" + this.innerHTML + "</" + tag + ">";
|
|
589
|
+
}
|
|
590
|
+
return this.innerHTML;
|
|
591
|
+
};
|
|
592
|
+
Object.defineProperty(HTMLElement.prototype, "innerHTML", {
|
|
593
|
+
get: function () {
|
|
594
|
+
return this.childNodes
|
|
595
|
+
.map(function (child) {
|
|
596
|
+
return child.toString();
|
|
597
|
+
})
|
|
598
|
+
.join('');
|
|
599
|
+
},
|
|
600
|
+
set: function (content) {
|
|
601
|
+
//const r = parse(content, global.options); // TODO global.options ?
|
|
602
|
+
var r = parse(content);
|
|
603
|
+
this.childNodes = r.childNodes.length ? r.childNodes : [new text_1.default(content, this)];
|
|
604
|
+
},
|
|
605
|
+
enumerable: false,
|
|
606
|
+
configurable: true
|
|
607
|
+
});
|
|
608
|
+
HTMLElement.prototype.set_content = function (content, options) {
|
|
609
|
+
if (options === void 0) { options = {}; }
|
|
610
|
+
if (content instanceof node_2.default) {
|
|
611
|
+
content = [content];
|
|
612
|
+
}
|
|
613
|
+
else if (typeof content == 'string') {
|
|
614
|
+
var r = parse(content, options);
|
|
615
|
+
content = r.childNodes.length ? r.childNodes : [new text_1.default(content, this)];
|
|
616
|
+
}
|
|
617
|
+
this.childNodes = content;
|
|
618
|
+
};
|
|
619
|
+
HTMLElement.prototype.replaceWith = function () {
|
|
620
|
+
var _this = this;
|
|
621
|
+
var nodes = [];
|
|
622
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
623
|
+
nodes[_i] = arguments[_i];
|
|
624
|
+
}
|
|
625
|
+
var content = nodes
|
|
626
|
+
.map(function (node) {
|
|
627
|
+
if (node instanceof node_2.default) {
|
|
628
|
+
return [node];
|
|
629
|
+
}
|
|
630
|
+
else if (typeof node == 'string') {
|
|
631
|
+
// const r = parse(content, global.options); // TODO global.options ?
|
|
632
|
+
var r = parse(node);
|
|
633
|
+
return r.childNodes.length ? r.childNodes : [new text_1.default(node, _this)];
|
|
634
|
+
}
|
|
635
|
+
return [];
|
|
636
|
+
})
|
|
637
|
+
.flat();
|
|
638
|
+
var idx = this.parentNode.childNodes.findIndex(function (child) {
|
|
639
|
+
return child === _this;
|
|
640
|
+
});
|
|
641
|
+
this.parentNode.childNodes = __spreadArray(__spreadArray(__spreadArray([], this.parentNode.childNodes.slice(0, idx), true), content, true), this.parentNode.childNodes.slice(idx + 1), true);
|
|
642
|
+
};
|
|
643
|
+
Object.defineProperty(HTMLElement.prototype, "outerHTML", {
|
|
644
|
+
get: function () {
|
|
645
|
+
return this.toString();
|
|
646
|
+
},
|
|
647
|
+
enumerable: false,
|
|
648
|
+
configurable: true
|
|
649
|
+
});
|
|
650
|
+
/**
|
|
651
|
+
* Trim element from right (in block) after seeing pattern in a TextNode.
|
|
652
|
+
* @param {RegExp} pattern pattern to find
|
|
653
|
+
* @return {HTMLElement} reference to current node
|
|
654
|
+
*/
|
|
655
|
+
HTMLElement.prototype.trimRight = function (pattern) {
|
|
656
|
+
for (var i = 0; i < this.childNodes.length; i++) {
|
|
657
|
+
var childNode = this.childNodes[i];
|
|
658
|
+
if (childNode.nodeType === type_3.default.ELEMENT_NODE) {
|
|
659
|
+
childNode.trimRight(pattern);
|
|
660
|
+
}
|
|
661
|
+
else {
|
|
662
|
+
var index = childNode.rawText.search(pattern);
|
|
663
|
+
if (index > -1) {
|
|
664
|
+
childNode.rawText = childNode.rawText.substr(0, index);
|
|
665
|
+
// trim all following nodes.
|
|
666
|
+
this.childNodes.length = i + 1;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
return this;
|
|
671
|
+
};
|
|
672
|
+
Object.defineProperty(HTMLElement.prototype, "structure", {
|
|
673
|
+
/**
|
|
674
|
+
* Get DOM structure
|
|
675
|
+
* @return {string} strucutre
|
|
676
|
+
*/
|
|
677
|
+
get: function () {
|
|
678
|
+
var res = [];
|
|
679
|
+
var indention = 0;
|
|
680
|
+
function write(str) {
|
|
681
|
+
res.push(' '.repeat(indention) + str);
|
|
682
|
+
}
|
|
683
|
+
function dfs(node) {
|
|
684
|
+
var idStr = node.id ? "#" + node.id : '';
|
|
685
|
+
var classStr = node.classList.length ? "." + node.classList.value.join('.') : ''; // eslint-disable-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/restrict-template-expressions, @typescript-eslint/no-unsafe-call
|
|
686
|
+
write("" + node.rawTagName + idStr + classStr);
|
|
687
|
+
indention++;
|
|
688
|
+
node.childNodes.forEach(function (childNode) {
|
|
689
|
+
if (childNode.nodeType === type_3.default.ELEMENT_NODE) {
|
|
690
|
+
dfs(childNode);
|
|
691
|
+
}
|
|
692
|
+
else if (childNode.nodeType === type_3.default.TEXT_NODE) {
|
|
693
|
+
if (!childNode.isWhitespace) {
|
|
694
|
+
write('#text');
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
});
|
|
698
|
+
indention--;
|
|
699
|
+
}
|
|
700
|
+
dfs(this);
|
|
701
|
+
return res.join('\n');
|
|
702
|
+
},
|
|
703
|
+
enumerable: false,
|
|
704
|
+
configurable: true
|
|
705
|
+
});
|
|
706
|
+
/**
|
|
707
|
+
* Remove whitespaces in this sub tree.
|
|
708
|
+
* @return {HTMLElement} pointer to this
|
|
709
|
+
*/
|
|
710
|
+
HTMLElement.prototype.removeWhitespace = function () {
|
|
711
|
+
var _this = this;
|
|
712
|
+
var o = 0;
|
|
713
|
+
this.childNodes.forEach(function (node) {
|
|
714
|
+
if (node.nodeType === type_3.default.TEXT_NODE) {
|
|
715
|
+
if (node.isWhitespace) {
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
node.rawText = node.trimmedRawText;
|
|
719
|
+
}
|
|
720
|
+
else if (node.nodeType === type_3.default.ELEMENT_NODE) {
|
|
721
|
+
node.removeWhitespace();
|
|
722
|
+
}
|
|
723
|
+
_this.childNodes[o++] = node;
|
|
724
|
+
});
|
|
725
|
+
this.childNodes.length = o;
|
|
726
|
+
return this;
|
|
727
|
+
};
|
|
728
|
+
/**
|
|
729
|
+
* Query CSS selector to find matching nodes.
|
|
730
|
+
* @param {string} selector Simplified CSS selector
|
|
731
|
+
* @return {HTMLElement[]} matching elements
|
|
732
|
+
*/
|
|
733
|
+
HTMLElement.prototype.querySelectorAll = function (selector) {
|
|
734
|
+
return (0, css_select_1.selectAll)(selector, this, {
|
|
735
|
+
xmlMode: true,
|
|
736
|
+
adapter: matcher_1.default,
|
|
737
|
+
});
|
|
738
|
+
// let matcher: Matcher;
|
|
739
|
+
// if (selector instanceof Matcher) {
|
|
740
|
+
// matcher = selector;
|
|
741
|
+
// matcher.reset();
|
|
742
|
+
// } else {
|
|
743
|
+
// if (selector.includes(',')) {
|
|
744
|
+
// const selectors = selector.split(',');
|
|
745
|
+
// return Array.from(selectors.reduce((pre, cur) => {
|
|
746
|
+
// const result = this.querySelectorAll(cur.trim());
|
|
747
|
+
// return result.reduce((p, c) => {
|
|
748
|
+
// return p.add(c);
|
|
749
|
+
// }, pre);
|
|
750
|
+
// }, new Set<HTMLElement>()));
|
|
751
|
+
// }
|
|
752
|
+
// matcher = new Matcher(selector);
|
|
753
|
+
// }
|
|
754
|
+
// interface IStack {
|
|
755
|
+
// 0: Node; // node
|
|
756
|
+
// 1: number; // children
|
|
757
|
+
// 2: boolean; // found flag
|
|
758
|
+
// }
|
|
759
|
+
// const stack = [] as IStack[];
|
|
760
|
+
// return this.childNodes.reduce((res, cur) => {
|
|
761
|
+
// stack.push([cur, 0, false]);
|
|
762
|
+
// while (stack.length) {
|
|
763
|
+
// const state = arr_back(stack); // get last element
|
|
764
|
+
// const el = state[0];
|
|
765
|
+
// if (state[1] === 0) {
|
|
766
|
+
// // Seen for first time.
|
|
767
|
+
// if (el.nodeType !== NodeType.ELEMENT_NODE) {
|
|
768
|
+
// stack.pop();
|
|
769
|
+
// continue;
|
|
770
|
+
// }
|
|
771
|
+
// const html_el = el as HTMLElement;
|
|
772
|
+
// state[2] = matcher.advance(html_el);
|
|
773
|
+
// if (state[2]) {
|
|
774
|
+
// if (matcher.matched) {
|
|
775
|
+
// res.push(html_el);
|
|
776
|
+
// res.push(...(html_el.querySelectorAll(selector)));
|
|
777
|
+
// // no need to go further.
|
|
778
|
+
// matcher.rewind();
|
|
779
|
+
// stack.pop();
|
|
780
|
+
// continue;
|
|
781
|
+
// }
|
|
782
|
+
// }
|
|
783
|
+
// }
|
|
784
|
+
// if (state[1] < el.childNodes.length) {
|
|
785
|
+
// stack.push([el.childNodes[state[1]++], 0, false]);
|
|
786
|
+
// } else {
|
|
787
|
+
// if (state[2]) {
|
|
788
|
+
// matcher.rewind();
|
|
789
|
+
// }
|
|
790
|
+
// stack.pop();
|
|
791
|
+
// }
|
|
792
|
+
// }
|
|
793
|
+
// return res;
|
|
794
|
+
// }, [] as HTMLElement[]);
|
|
795
|
+
};
|
|
796
|
+
/**
|
|
797
|
+
* Query CSS Selector to find matching node.
|
|
798
|
+
* @param {string} selector Simplified CSS selector
|
|
799
|
+
* @return {HTMLElement} matching node
|
|
800
|
+
*/
|
|
801
|
+
HTMLElement.prototype.querySelector = function (selector) {
|
|
802
|
+
return (0, css_select_1.selectOne)(selector, this, {
|
|
803
|
+
xmlMode: true,
|
|
804
|
+
adapter: matcher_1.default,
|
|
805
|
+
});
|
|
806
|
+
// let matcher: Matcher;
|
|
807
|
+
// if (selector instanceof Matcher) {
|
|
808
|
+
// matcher = selector;
|
|
809
|
+
// matcher.reset();
|
|
810
|
+
// } else {
|
|
811
|
+
// matcher = new Matcher(selector);
|
|
812
|
+
// }
|
|
813
|
+
// const stack = [] as { 0: Node; 1: 0 | 1; 2: boolean }[];
|
|
814
|
+
// for (const node of this.childNodes) {
|
|
815
|
+
// stack.push([node, 0, false]);
|
|
816
|
+
// while (stack.length) {
|
|
817
|
+
// const state = arr_back(stack);
|
|
818
|
+
// const el = state[0];
|
|
819
|
+
// if (state[1] === 0) {
|
|
820
|
+
// // Seen for first time.
|
|
821
|
+
// if (el.nodeType !== NodeType.ELEMENT_NODE) {
|
|
822
|
+
// stack.pop();
|
|
823
|
+
// continue;
|
|
824
|
+
// }
|
|
825
|
+
// state[2] = matcher.advance(el as HTMLElement);
|
|
826
|
+
// if (state[2]) {
|
|
827
|
+
// if (matcher.matched) {
|
|
828
|
+
// return el as HTMLElement;
|
|
829
|
+
// }
|
|
830
|
+
// }
|
|
831
|
+
// }
|
|
832
|
+
// if (state[1] < el.childNodes.length) {
|
|
833
|
+
// stack.push([el.childNodes[state[1]++], 0, false]);
|
|
834
|
+
// } else {
|
|
835
|
+
// if (state[2]) {
|
|
836
|
+
// matcher.rewind();
|
|
837
|
+
// }
|
|
838
|
+
// stack.pop();
|
|
839
|
+
// }
|
|
840
|
+
// }
|
|
841
|
+
// }
|
|
842
|
+
// return null;
|
|
843
|
+
};
|
|
844
|
+
/**
|
|
845
|
+
* traverses the Element and its parents (heading toward the document root) until it finds a node that matches the provided selector string. Will return itself or the matching ancestor. If no such element exists, it returns null.
|
|
846
|
+
* @param selector a DOMString containing a selector list
|
|
847
|
+
*/
|
|
848
|
+
HTMLElement.prototype.closest = function (selector) {
|
|
849
|
+
var mapChild = new Map();
|
|
850
|
+
var el = this;
|
|
851
|
+
var old = null;
|
|
852
|
+
function findOne(test, elems) {
|
|
853
|
+
var elem = null;
|
|
854
|
+
for (var i = 0, l = elems.length; i < l && !elem; i++) {
|
|
855
|
+
var el_1 = elems[i];
|
|
856
|
+
if (test(el_1)) {
|
|
857
|
+
elem = el_1;
|
|
858
|
+
}
|
|
859
|
+
else {
|
|
860
|
+
var child = mapChild.get(el_1);
|
|
861
|
+
if (child) {
|
|
862
|
+
elem = findOne(test, [child]);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
return elem;
|
|
867
|
+
}
|
|
868
|
+
while (el) {
|
|
869
|
+
mapChild.set(el, old);
|
|
870
|
+
old = el;
|
|
871
|
+
el = el.parentNode;
|
|
872
|
+
}
|
|
873
|
+
el = this;
|
|
874
|
+
while (el) {
|
|
875
|
+
var e = (0, css_select_1.selectOne)(selector, el, {
|
|
876
|
+
xmlMode: true,
|
|
877
|
+
adapter: __assign(__assign({}, matcher_1.default), { getChildren: function (node) {
|
|
878
|
+
var child = mapChild.get(node);
|
|
879
|
+
return child && [child];
|
|
880
|
+
}, getSiblings: function (node) {
|
|
881
|
+
return [node];
|
|
882
|
+
}, findOne: findOne, findAll: function () {
|
|
883
|
+
return [];
|
|
884
|
+
} }),
|
|
885
|
+
});
|
|
886
|
+
if (e) {
|
|
887
|
+
return e;
|
|
888
|
+
}
|
|
889
|
+
el = el.parentNode;
|
|
890
|
+
}
|
|
891
|
+
return null;
|
|
892
|
+
};
|
|
893
|
+
/**
|
|
894
|
+
* Append a child node to childNodes
|
|
895
|
+
* @param {Node} node node to append
|
|
896
|
+
* @return {Node} node appended
|
|
897
|
+
*/
|
|
898
|
+
HTMLElement.prototype.appendChild = function (node) {
|
|
899
|
+
// node.parentNode = this;
|
|
900
|
+
this.childNodes.push(node);
|
|
901
|
+
node.parentNode = this;
|
|
902
|
+
return node;
|
|
903
|
+
};
|
|
904
|
+
Object.defineProperty(HTMLElement.prototype, "firstChild", {
|
|
905
|
+
/**
|
|
906
|
+
* Get first child node
|
|
907
|
+
* @return {Node} first child node
|
|
908
|
+
*/
|
|
909
|
+
get: function () {
|
|
910
|
+
return this.childNodes[0];
|
|
911
|
+
},
|
|
912
|
+
enumerable: false,
|
|
913
|
+
configurable: true
|
|
914
|
+
});
|
|
915
|
+
Object.defineProperty(HTMLElement.prototype, "lastChild", {
|
|
916
|
+
/**
|
|
917
|
+
* Get last child node
|
|
918
|
+
* @return {Node} last child node
|
|
919
|
+
*/
|
|
920
|
+
get: function () {
|
|
921
|
+
return (0, back_1.default)(this.childNodes);
|
|
922
|
+
},
|
|
923
|
+
enumerable: false,
|
|
924
|
+
configurable: true
|
|
925
|
+
});
|
|
926
|
+
Object.defineProperty(HTMLElement.prototype, "attrs", {
|
|
927
|
+
/**
|
|
928
|
+
* Get attributes
|
|
929
|
+
* @access private
|
|
930
|
+
* @return {Object} parsed and unescaped attributes
|
|
931
|
+
*/
|
|
932
|
+
get: function () {
|
|
933
|
+
if (this._attrs) {
|
|
934
|
+
return this._attrs;
|
|
935
|
+
}
|
|
936
|
+
this._attrs = {};
|
|
937
|
+
var attrs = this.rawAttributes;
|
|
938
|
+
for (var key in attrs) {
|
|
939
|
+
var val = attrs[key] || '';
|
|
940
|
+
this._attrs[key.toLowerCase()] = decode(val);
|
|
941
|
+
}
|
|
942
|
+
return this._attrs;
|
|
943
|
+
},
|
|
944
|
+
enumerable: false,
|
|
945
|
+
configurable: true
|
|
946
|
+
});
|
|
947
|
+
Object.defineProperty(HTMLElement.prototype, "attributes", {
|
|
948
|
+
get: function () {
|
|
949
|
+
var ret_attrs = {};
|
|
950
|
+
var attrs = this.rawAttributes;
|
|
951
|
+
for (var key in attrs) {
|
|
952
|
+
var val = attrs[key] || '';
|
|
953
|
+
ret_attrs[key] = decode(val);
|
|
954
|
+
}
|
|
955
|
+
return ret_attrs;
|
|
956
|
+
},
|
|
957
|
+
enumerable: false,
|
|
958
|
+
configurable: true
|
|
959
|
+
});
|
|
960
|
+
Object.defineProperty(HTMLElement.prototype, "rawAttributes", {
|
|
961
|
+
/**
|
|
962
|
+
* Get escaped (as-it) attributes
|
|
963
|
+
* @return {Object} parsed attributes
|
|
964
|
+
*/
|
|
965
|
+
get: function () {
|
|
966
|
+
if (this._rawAttrs) {
|
|
967
|
+
return this._rawAttrs;
|
|
968
|
+
}
|
|
969
|
+
var attrs = {};
|
|
970
|
+
if (this.rawAttrs) {
|
|
971
|
+
var re = /([a-z()#][a-z0-9-_:()#]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|(\S+)))?/gi;
|
|
972
|
+
var match = void 0;
|
|
973
|
+
while ((match = re.exec(this.rawAttrs))) {
|
|
974
|
+
attrs[match[1]] = match[2] || match[3] || match[4] || null;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
this._rawAttrs = attrs;
|
|
978
|
+
return attrs;
|
|
979
|
+
},
|
|
980
|
+
enumerable: false,
|
|
981
|
+
configurable: true
|
|
982
|
+
});
|
|
983
|
+
HTMLElement.prototype.removeAttribute = function (key) {
|
|
984
|
+
var attrs = this.rawAttributes;
|
|
985
|
+
delete attrs[key];
|
|
986
|
+
// Update this.attribute
|
|
987
|
+
if (this._attrs) {
|
|
988
|
+
delete this._attrs[key];
|
|
989
|
+
}
|
|
990
|
+
// Update rawString
|
|
991
|
+
this.rawAttrs = Object.keys(attrs)
|
|
992
|
+
.map(function (name) {
|
|
993
|
+
var val = JSON.stringify(attrs[name]);
|
|
994
|
+
if (val === undefined || val === 'null') {
|
|
995
|
+
return name;
|
|
996
|
+
}
|
|
997
|
+
return name + "=" + val;
|
|
998
|
+
})
|
|
999
|
+
.join(' ');
|
|
1000
|
+
// Update this.id
|
|
1001
|
+
if (key === 'id') {
|
|
1002
|
+
this.id = '';
|
|
1003
|
+
}
|
|
1004
|
+
};
|
|
1005
|
+
HTMLElement.prototype.hasAttribute = function (key) {
|
|
1006
|
+
return key.toLowerCase() in this.attrs;
|
|
1007
|
+
};
|
|
1008
|
+
/**
|
|
1009
|
+
* Get an attribute
|
|
1010
|
+
* @return {string} value of the attribute
|
|
1011
|
+
*/
|
|
1012
|
+
HTMLElement.prototype.getAttribute = function (key) {
|
|
1013
|
+
return this.attrs[key.toLowerCase()];
|
|
1014
|
+
};
|
|
1015
|
+
/**
|
|
1016
|
+
* Set an attribute value to the HTMLElement
|
|
1017
|
+
* @param {string} key The attribute name
|
|
1018
|
+
* @param {string} value The value to set, or null / undefined to remove an attribute
|
|
1019
|
+
*/
|
|
1020
|
+
HTMLElement.prototype.setAttribute = function (key, value) {
|
|
1021
|
+
var _this = this;
|
|
1022
|
+
if (arguments.length < 2) {
|
|
1023
|
+
throw new Error("Failed to execute 'setAttribute' on 'Element'");
|
|
1024
|
+
}
|
|
1025
|
+
var k2 = key.toLowerCase();
|
|
1026
|
+
var attrs = this.rawAttributes;
|
|
1027
|
+
for (var k in attrs) {
|
|
1028
|
+
if (k.toLowerCase() === k2) {
|
|
1029
|
+
key = k;
|
|
1030
|
+
break;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
attrs[key] = String(value);
|
|
1034
|
+
// update this.attrs
|
|
1035
|
+
if (this._attrs) {
|
|
1036
|
+
this._attrs[k2] = decode(attrs[key]);
|
|
1037
|
+
}
|
|
1038
|
+
// Update rawString
|
|
1039
|
+
this.rawAttrs = Object.keys(attrs)
|
|
1040
|
+
.map(function (name) {
|
|
1041
|
+
var val = _this.quoteAttribute(attrs[name]);
|
|
1042
|
+
if (val === 'null' || val === '""')
|
|
1043
|
+
return name;
|
|
1044
|
+
return name + "=" + val;
|
|
1045
|
+
})
|
|
1046
|
+
.join(' ');
|
|
1047
|
+
// Update this.id
|
|
1048
|
+
if (key === 'id') {
|
|
1049
|
+
this.id = value;
|
|
1050
|
+
}
|
|
1051
|
+
};
|
|
1052
|
+
/**
|
|
1053
|
+
* Replace all the attributes of the HTMLElement by the provided attributes
|
|
1054
|
+
* @param {Attributes} attributes the new attribute set
|
|
1055
|
+
*/
|
|
1056
|
+
HTMLElement.prototype.setAttributes = function (attributes) {
|
|
1057
|
+
var _this = this;
|
|
1058
|
+
// Invalidate current this.attributes
|
|
1059
|
+
if (this._attrs) {
|
|
1060
|
+
delete this._attrs;
|
|
1061
|
+
}
|
|
1062
|
+
// Invalidate current this.rawAttributes
|
|
1063
|
+
if (this._rawAttrs) {
|
|
1064
|
+
delete this._rawAttrs;
|
|
1065
|
+
}
|
|
1066
|
+
// Update rawString
|
|
1067
|
+
this.rawAttrs = Object.keys(attributes)
|
|
1068
|
+
.map(function (name) {
|
|
1069
|
+
var val = attributes[name];
|
|
1070
|
+
if (val === 'null' || val === '""')
|
|
1071
|
+
return name;
|
|
1072
|
+
return name + "=" + _this.quoteAttribute(String(val));
|
|
1073
|
+
})
|
|
1074
|
+
.join(' ');
|
|
1075
|
+
};
|
|
1076
|
+
HTMLElement.prototype.insertAdjacentHTML = function (where, html) {
|
|
1077
|
+
var _a, _b, _c;
|
|
1078
|
+
var _this = this;
|
|
1079
|
+
if (arguments.length < 2) {
|
|
1080
|
+
throw new Error('2 arguments required');
|
|
1081
|
+
}
|
|
1082
|
+
var p = parse(html);
|
|
1083
|
+
if (where === 'afterend') {
|
|
1084
|
+
var idx = this.parentNode.childNodes.findIndex(function (child) {
|
|
1085
|
+
return child === _this;
|
|
1086
|
+
});
|
|
1087
|
+
(_a = this.parentNode.childNodes).splice.apply(_a, __spreadArray([idx + 1, 0], p.childNodes, false));
|
|
1088
|
+
p.childNodes.forEach(function (n) {
|
|
1089
|
+
if (n instanceof HTMLElement) {
|
|
1090
|
+
n.parentNode = _this.parentNode;
|
|
1091
|
+
}
|
|
1092
|
+
});
|
|
1093
|
+
}
|
|
1094
|
+
else if (where === 'afterbegin') {
|
|
1095
|
+
(_b = this.childNodes).unshift.apply(_b, p.childNodes);
|
|
1096
|
+
}
|
|
1097
|
+
else if (where === 'beforeend') {
|
|
1098
|
+
p.childNodes.forEach(function (n) {
|
|
1099
|
+
_this.appendChild(n);
|
|
1100
|
+
});
|
|
1101
|
+
}
|
|
1102
|
+
else if (where === 'beforebegin') {
|
|
1103
|
+
var idx = this.parentNode.childNodes.findIndex(function (child) {
|
|
1104
|
+
return child === _this;
|
|
1105
|
+
});
|
|
1106
|
+
(_c = this.parentNode.childNodes).splice.apply(_c, __spreadArray([idx, 0], p.childNodes, false));
|
|
1107
|
+
p.childNodes.forEach(function (n) {
|
|
1108
|
+
if (n instanceof HTMLElement) {
|
|
1109
|
+
n.parentNode = _this.parentNode;
|
|
1110
|
+
}
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
else {
|
|
1114
|
+
throw new Error("The value provided ('" + where + "') is not one of 'beforebegin', 'afterbegin', 'beforeend', or 'afterend'");
|
|
1115
|
+
}
|
|
1116
|
+
// if (!where || html === undefined || html === null) {
|
|
1117
|
+
// return;
|
|
1118
|
+
// }
|
|
1119
|
+
};
|
|
1120
|
+
Object.defineProperty(HTMLElement.prototype, "nextSibling", {
|
|
1121
|
+
get: function () {
|
|
1122
|
+
if (this.parentNode) {
|
|
1123
|
+
var children = this.parentNode.childNodes;
|
|
1124
|
+
var i = 0;
|
|
1125
|
+
while (i < children.length) {
|
|
1126
|
+
var child = children[i++];
|
|
1127
|
+
if (this === child)
|
|
1128
|
+
return children[i] || null;
|
|
1129
|
+
}
|
|
1130
|
+
return null;
|
|
1131
|
+
}
|
|
1132
|
+
},
|
|
1133
|
+
enumerable: false,
|
|
1134
|
+
configurable: true
|
|
1135
|
+
});
|
|
1136
|
+
Object.defineProperty(HTMLElement.prototype, "nextElementSibling", {
|
|
1137
|
+
get: function () {
|
|
1138
|
+
if (this.parentNode) {
|
|
1139
|
+
var children = this.parentNode.childNodes;
|
|
1140
|
+
var i = 0;
|
|
1141
|
+
var find = false;
|
|
1142
|
+
while (i < children.length) {
|
|
1143
|
+
var child = children[i++];
|
|
1144
|
+
if (find) {
|
|
1145
|
+
if (child instanceof HTMLElement) {
|
|
1146
|
+
return child || null;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
else if (this === child) {
|
|
1150
|
+
find = true;
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
return null;
|
|
1154
|
+
}
|
|
1155
|
+
},
|
|
1156
|
+
enumerable: false,
|
|
1157
|
+
configurable: true
|
|
1158
|
+
});
|
|
1159
|
+
Object.defineProperty(HTMLElement.prototype, "classNames", {
|
|
1160
|
+
get: function () {
|
|
1161
|
+
return this.classList.toString();
|
|
1162
|
+
},
|
|
1163
|
+
enumerable: false,
|
|
1164
|
+
configurable: true
|
|
1165
|
+
});
|
|
1166
|
+
return HTMLElement;
|
|
1167
|
+
}(node_2.default));
|
|
1168
|
+
exports.default = HTMLElement;
|
|
1169
|
+
// https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
|
|
1170
|
+
var kMarkupPattern = /<!--[^]*?(?=-->)-->|<(\/?)([a-z][-.:0-9_a-z]*)\s*((?=[/>]*?)|(?:.*?[\s\d/'"])|(?:.*?[\w]))(\/?)>/gi;
|
|
1171
|
+
// <(?<tag>[^\s]*)(.*)>(.*)</\k<tag>>
|
|
1172
|
+
// <([a-z][-.:0-9_a-z]*)\s*\/>
|
|
1173
|
+
// <(area|base|br|col|hr|img|input|link|meta|source)\s*(.*)\/?>
|
|
1174
|
+
// <(area|base|br|col|hr|img|input|link|meta|source)\s*(.*)\/?>|<(?<tag>[^\s]*)(.*)>(.*)</\k<tag>>
|
|
1175
|
+
var kAttributePattern = /(^|\s)(id|class)\s*=\s*("([^"]*)"|'([^']*)'|(\S+))/gi;
|
|
1176
|
+
var kSelfClosingElements = {
|
|
1177
|
+
area: true,
|
|
1178
|
+
AREA: true,
|
|
1179
|
+
base: true,
|
|
1180
|
+
BASE: true,
|
|
1181
|
+
br: true,
|
|
1182
|
+
BR: true,
|
|
1183
|
+
col: true,
|
|
1184
|
+
COL: true,
|
|
1185
|
+
hr: true,
|
|
1186
|
+
HR: true,
|
|
1187
|
+
img: true,
|
|
1188
|
+
IMG: true,
|
|
1189
|
+
input: true,
|
|
1190
|
+
INPUT: true,
|
|
1191
|
+
link: true,
|
|
1192
|
+
LINK: true,
|
|
1193
|
+
meta: true,
|
|
1194
|
+
META: true,
|
|
1195
|
+
source: true,
|
|
1196
|
+
SOURCE: true,
|
|
1197
|
+
embed: true,
|
|
1198
|
+
EMBED: true,
|
|
1199
|
+
param: true,
|
|
1200
|
+
PARAM: true,
|
|
1201
|
+
track: true,
|
|
1202
|
+
TRACK: true,
|
|
1203
|
+
wbr: true,
|
|
1204
|
+
WBR: true,
|
|
1205
|
+
};
|
|
1206
|
+
var kElementsClosedByOpening = {
|
|
1207
|
+
li: { li: true, LI: true },
|
|
1208
|
+
LI: { li: true, LI: true },
|
|
1209
|
+
p: { p: true, div: true, P: true, DIV: true },
|
|
1210
|
+
P: { p: true, div: true, P: true, DIV: true },
|
|
1211
|
+
b: { div: true, DIV: true },
|
|
1212
|
+
B: { div: true, DIV: true },
|
|
1213
|
+
td: { td: true, th: true, TD: true, TH: true },
|
|
1214
|
+
TD: { td: true, th: true, TD: true, TH: true },
|
|
1215
|
+
th: { td: true, th: true, TD: true, TH: true },
|
|
1216
|
+
TH: { td: true, th: true, TD: true, TH: true },
|
|
1217
|
+
h1: { h1: true, H1: true },
|
|
1218
|
+
H1: { h1: true, H1: true },
|
|
1219
|
+
h2: { h2: true, H2: true },
|
|
1220
|
+
H2: { h2: true, H2: true },
|
|
1221
|
+
h3: { h3: true, H3: true },
|
|
1222
|
+
H3: { h3: true, H3: true },
|
|
1223
|
+
h4: { h4: true, H4: true },
|
|
1224
|
+
H4: { h4: true, H4: true },
|
|
1225
|
+
h5: { h5: true, H5: true },
|
|
1226
|
+
H5: { h5: true, H5: true },
|
|
1227
|
+
h6: { h6: true, H6: true },
|
|
1228
|
+
H6: { h6: true, H6: true },
|
|
1229
|
+
};
|
|
1230
|
+
var kElementsClosedByClosing = {
|
|
1231
|
+
li: { ul: true, ol: true, UL: true, OL: true },
|
|
1232
|
+
LI: { ul: true, ol: true, UL: true, OL: true },
|
|
1233
|
+
a: { div: true, DIV: true },
|
|
1234
|
+
A: { div: true, DIV: true },
|
|
1235
|
+
b: { div: true, DIV: true },
|
|
1236
|
+
B: { div: true, DIV: true },
|
|
1237
|
+
i: { div: true, DIV: true },
|
|
1238
|
+
I: { div: true, DIV: true },
|
|
1239
|
+
p: { div: true, DIV: true },
|
|
1240
|
+
P: { div: true, DIV: true },
|
|
1241
|
+
td: { tr: true, table: true, TR: true, TABLE: true },
|
|
1242
|
+
TD: { tr: true, table: true, TR: true, TABLE: true },
|
|
1243
|
+
th: { tr: true, table: true, TR: true, TABLE: true },
|
|
1244
|
+
TH: { tr: true, table: true, TR: true, TABLE: true },
|
|
1245
|
+
};
|
|
1246
|
+
var frameflag = 'documentfragmentcontainer';
|
|
1247
|
+
/**
|
|
1248
|
+
* Parses HTML and returns a root element
|
|
1249
|
+
* Parse a chuck of HTML source.
|
|
1250
|
+
* @param {string} data html
|
|
1251
|
+
* @return {HTMLElement} root element
|
|
1252
|
+
*/
|
|
1253
|
+
function base_parse(data, options) {
|
|
1254
|
+
if (options === void 0) { options = { lowerCaseTagName: false, comment: false }; }
|
|
1255
|
+
var elements = options.blockTextElements || {
|
|
1256
|
+
script: true,
|
|
1257
|
+
noscript: true,
|
|
1258
|
+
style: true,
|
|
1259
|
+
pre: true,
|
|
1260
|
+
};
|
|
1261
|
+
var element_names = Object.keys(elements);
|
|
1262
|
+
var kBlockTextElements = element_names.map(function (it) { return new RegExp(it, 'i'); });
|
|
1263
|
+
var kIgnoreElements = element_names.filter(function (it) { return elements[it]; }).map(function (it) { return new RegExp(it, 'i'); });
|
|
1264
|
+
function element_should_be_ignore(tag) {
|
|
1265
|
+
return kIgnoreElements.some(function (it) { return it.test(tag); });
|
|
1266
|
+
}
|
|
1267
|
+
function is_block_text_element(tag) {
|
|
1268
|
+
return kBlockTextElements.some(function (it) { return it.test(tag); });
|
|
1269
|
+
}
|
|
1270
|
+
var createRange = function (startPos, endPos) { return [startPos - frameFlagOffset, endPos - frameFlagOffset]; };
|
|
1271
|
+
var root = new HTMLElement(null, {}, '', null, [0, data.length]);
|
|
1272
|
+
var currentParent = root;
|
|
1273
|
+
var stack = [root];
|
|
1274
|
+
var lastTextPos = -1;
|
|
1275
|
+
var noNestedTagIndex = undefined;
|
|
1276
|
+
var match;
|
|
1277
|
+
// https://github.com/taoqf/node-html-parser/issues/38
|
|
1278
|
+
data = "<" + frameflag + ">" + data + "</" + frameflag + ">";
|
|
1279
|
+
var dataEndPos = data.length - (frameflag.length + 2);
|
|
1280
|
+
var frameFlagOffset = frameflag.length + 2;
|
|
1281
|
+
while ((match = kMarkupPattern.exec(data))) {
|
|
1282
|
+
var tagStartPos = kMarkupPattern.lastIndex - match[0].length;
|
|
1283
|
+
var tagEndPos = kMarkupPattern.lastIndex;
|
|
1284
|
+
// Add TextNode if content
|
|
1285
|
+
if (lastTextPos > -1) {
|
|
1286
|
+
if (lastTextPos + match[0].length < tagEndPos) {
|
|
1287
|
+
var text = data.substring(lastTextPos, tagStartPos);
|
|
1288
|
+
currentParent.appendChild(new text_1.default(text, currentParent, createRange(lastTextPos, tagStartPos)));
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
lastTextPos = kMarkupPattern.lastIndex;
|
|
1292
|
+
// https://github.com/taoqf/node-html-parser/issues/38
|
|
1293
|
+
// Skip frameflag node
|
|
1294
|
+
if (match[2] === frameflag)
|
|
1295
|
+
continue;
|
|
1296
|
+
// Handle comments
|
|
1297
|
+
if (match[0][1] === '!') {
|
|
1298
|
+
if (options.comment) {
|
|
1299
|
+
// Only keep what is in between <!-- and -->
|
|
1300
|
+
var text = data.substring(tagStartPos + 4, tagEndPos - 3);
|
|
1301
|
+
currentParent.appendChild(new comment_1.default(text, currentParent, createRange(tagStartPos, tagEndPos)));
|
|
1302
|
+
}
|
|
1303
|
+
continue;
|
|
1304
|
+
}
|
|
1305
|
+
/* -- Handle tag matching -- */
|
|
1306
|
+
// Fix tag casing if necessary
|
|
1307
|
+
if (options.lowerCaseTagName)
|
|
1308
|
+
match[2] = match[2].toLowerCase();
|
|
1309
|
+
// Handle opening tags (ie. <this> not </that>)
|
|
1310
|
+
if (!match[1]) {
|
|
1311
|
+
/* Populate attributes */
|
|
1312
|
+
var attrs = {};
|
|
1313
|
+
for (var attMatch = void 0; (attMatch = kAttributePattern.exec(match[3]));) {
|
|
1314
|
+
attrs[attMatch[2].toLowerCase()] = attMatch[4] || attMatch[5] || attMatch[6];
|
|
1315
|
+
}
|
|
1316
|
+
var tagName = currentParent.rawTagName;
|
|
1317
|
+
if (!match[4] && kElementsClosedByOpening[tagName]) {
|
|
1318
|
+
if (kElementsClosedByOpening[tagName][match[2]]) {
|
|
1319
|
+
stack.pop();
|
|
1320
|
+
currentParent = (0, back_1.default)(stack);
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
// Prevent nested A tags by terminating the last A and starting a new one : see issue #144
|
|
1324
|
+
if (match[2] === 'a' || match[2] === 'A') {
|
|
1325
|
+
if (noNestedTagIndex !== undefined) {
|
|
1326
|
+
stack.splice(noNestedTagIndex);
|
|
1327
|
+
currentParent = (0, back_1.default)(stack);
|
|
1328
|
+
}
|
|
1329
|
+
noNestedTagIndex = stack.length;
|
|
1330
|
+
}
|
|
1331
|
+
var tagEndPos_1 = kMarkupPattern.lastIndex;
|
|
1332
|
+
var tagStartPos_1 = tagEndPos_1 - match[0].length;
|
|
1333
|
+
currentParent = currentParent.appendChild(
|
|
1334
|
+
// Initialize range (end position updated later for closed tags)
|
|
1335
|
+
new HTMLElement(match[2], attrs, match[3], null, createRange(tagStartPos_1, tagEndPos_1)));
|
|
1336
|
+
stack.push(currentParent);
|
|
1337
|
+
if (is_block_text_element(match[2])) {
|
|
1338
|
+
// Find closing tag
|
|
1339
|
+
var closeMarkup = "</" + match[2] + ">";
|
|
1340
|
+
var closeIndex = options.lowerCaseTagName
|
|
1341
|
+
? data.toLocaleLowerCase().indexOf(closeMarkup, kMarkupPattern.lastIndex)
|
|
1342
|
+
: data.indexOf(closeMarkup, kMarkupPattern.lastIndex);
|
|
1343
|
+
var textEndPos = closeIndex === -1 ? dataEndPos : closeIndex;
|
|
1344
|
+
if (element_should_be_ignore(match[2])) {
|
|
1345
|
+
var text = data.substring(tagEndPos_1, textEndPos);
|
|
1346
|
+
if (text.length > 0 && /\S/.test(text)) {
|
|
1347
|
+
currentParent.appendChild(new text_1.default(text, currentParent, createRange(tagEndPos_1, textEndPos)));
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
if (closeIndex === -1) {
|
|
1351
|
+
lastTextPos = kMarkupPattern.lastIndex = data.length + 1;
|
|
1352
|
+
}
|
|
1353
|
+
else {
|
|
1354
|
+
lastTextPos = kMarkupPattern.lastIndex = closeIndex + closeMarkup.length;
|
|
1355
|
+
// Cause to be treated as self-closing, because no close found
|
|
1356
|
+
match[1] = 'true';
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
// Handle closing tags or self-closed elements (ie </tag> or <br>)
|
|
1361
|
+
if (match[1] || match[4] || kSelfClosingElements[match[2]]) {
|
|
1362
|
+
while (true) {
|
|
1363
|
+
if (match[2] === 'a' || match[2] === 'A')
|
|
1364
|
+
noNestedTagIndex = undefined;
|
|
1365
|
+
if (currentParent.rawTagName === match[2]) {
|
|
1366
|
+
// Update range end for closed tag
|
|
1367
|
+
currentParent.range[1] = createRange(-1, Math.max(lastTextPos, tagEndPos))[1];
|
|
1368
|
+
stack.pop();
|
|
1369
|
+
currentParent = (0, back_1.default)(stack);
|
|
1370
|
+
break;
|
|
1371
|
+
}
|
|
1372
|
+
else {
|
|
1373
|
+
var tagName = currentParent.tagName;
|
|
1374
|
+
// Trying to close current tag, and move on
|
|
1375
|
+
if (kElementsClosedByClosing[tagName]) {
|
|
1376
|
+
if (kElementsClosedByClosing[tagName][match[2]]) {
|
|
1377
|
+
stack.pop();
|
|
1378
|
+
currentParent = (0, back_1.default)(stack);
|
|
1379
|
+
continue;
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
// Use aggressive strategy to handle unmatching markups.
|
|
1383
|
+
break;
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
return stack;
|
|
1389
|
+
}
|
|
1390
|
+
exports.base_parse = base_parse;
|
|
1391
|
+
/**
|
|
1392
|
+
* Parses HTML and returns a root element
|
|
1393
|
+
* Parse a chuck of HTML source.
|
|
1394
|
+
*/
|
|
1395
|
+
function parse(data, options) {
|
|
1396
|
+
if (options === void 0) { options = { lowerCaseTagName: false, comment: false }; }
|
|
1397
|
+
var stack = base_parse(data, options);
|
|
1398
|
+
var root = stack[0];
|
|
1399
|
+
var _loop_1 = function () {
|
|
1400
|
+
// Handle each error elements.
|
|
1401
|
+
var last = stack.pop();
|
|
1402
|
+
var oneBefore = (0, back_1.default)(stack);
|
|
1403
|
+
if (last.parentNode && last.parentNode.parentNode) {
|
|
1404
|
+
if (last.parentNode === oneBefore && last.tagName === oneBefore.tagName) {
|
|
1405
|
+
// Pair error case <h3> <h3> handle : Fixes to <h3> </h3>
|
|
1406
|
+
oneBefore.removeChild(last);
|
|
1407
|
+
last.childNodes.forEach(function (child) {
|
|
1408
|
+
oneBefore.parentNode.appendChild(child);
|
|
1409
|
+
});
|
|
1410
|
+
stack.pop();
|
|
1411
|
+
}
|
|
1412
|
+
else {
|
|
1413
|
+
// Single error <div> <h3> </div> handle: Just removes <h3>
|
|
1414
|
+
oneBefore.removeChild(last);
|
|
1415
|
+
last.childNodes.forEach(function (child) {
|
|
1416
|
+
oneBefore.appendChild(child);
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
else {
|
|
1421
|
+
// If it's final element just skip.
|
|
1422
|
+
}
|
|
1423
|
+
};
|
|
1424
|
+
while (stack.length > 1) {
|
|
1425
|
+
_loop_1();
|
|
1426
|
+
}
|
|
1427
|
+
// response.childNodes.forEach((node) => {
|
|
1428
|
+
// if (node instanceof HTMLElement) {
|
|
1429
|
+
// node.parentNode = null;
|
|
1430
|
+
// }
|
|
1431
|
+
// });
|
|
1432
|
+
return root;
|
|
1433
|
+
}
|
|
1434
|
+
exports.parse = parse;
|
|
1435
|
+
});
|
|
1436
|
+
define("nodes/node", ["require", "exports", "he"], function (require, exports, he_3) {
|
|
1437
|
+
"use strict";
|
|
1438
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1439
|
+
/**
|
|
1440
|
+
* Node Class as base class for TextNode and HTMLElement.
|
|
1441
|
+
*/
|
|
1442
|
+
var Node = /** @class */ (function () {
|
|
1443
|
+
function Node(parentNode, range) {
|
|
1444
|
+
if (parentNode === void 0) { parentNode = null; }
|
|
1445
|
+
this.parentNode = parentNode;
|
|
1446
|
+
this.childNodes = [];
|
|
1447
|
+
Object.defineProperty(this, 'range', {
|
|
1448
|
+
enumerable: false,
|
|
1449
|
+
writable: true,
|
|
1450
|
+
configurable: true,
|
|
1451
|
+
value: range !== null && range !== void 0 ? range : [-1, -1]
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
Object.defineProperty(Node.prototype, "innerText", {
|
|
1455
|
+
get: function () {
|
|
1456
|
+
return this.rawText;
|
|
1457
|
+
},
|
|
1458
|
+
enumerable: false,
|
|
1459
|
+
configurable: true
|
|
1460
|
+
});
|
|
1461
|
+
Object.defineProperty(Node.prototype, "textContent", {
|
|
1462
|
+
get: function () {
|
|
1463
|
+
return (0, he_3.decode)(this.rawText);
|
|
1464
|
+
},
|
|
1465
|
+
set: function (val) {
|
|
1466
|
+
this.rawText = (0, he_3.encode)(val);
|
|
1467
|
+
},
|
|
1468
|
+
enumerable: false,
|
|
1469
|
+
configurable: true
|
|
1470
|
+
});
|
|
1471
|
+
return Node;
|
|
1472
|
+
}());
|
|
1473
|
+
exports.default = Node;
|
|
1474
|
+
});
|
|
1475
|
+
define("nodes/comment", ["require", "exports", "nodes/node", "nodes/type"], function (require, exports, node_3, type_4) {
|
|
1476
|
+
"use strict";
|
|
1477
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1478
|
+
node_3 = __importDefault(node_3);
|
|
1479
|
+
type_4 = __importDefault(type_4);
|
|
1480
|
+
var CommentNode = /** @class */ (function (_super) {
|
|
1481
|
+
__extends(CommentNode, _super);
|
|
1482
|
+
function CommentNode(rawText, parentNode, range) {
|
|
1483
|
+
var _this = _super.call(this, parentNode, range) || this;
|
|
1484
|
+
_this.rawText = rawText;
|
|
1485
|
+
/**
|
|
1486
|
+
* Node Type declaration.
|
|
1487
|
+
* @type {Number}
|
|
1488
|
+
*/
|
|
1489
|
+
_this.nodeType = type_4.default.COMMENT_NODE;
|
|
1490
|
+
return _this;
|
|
1491
|
+
}
|
|
1492
|
+
Object.defineProperty(CommentNode.prototype, "text", {
|
|
1493
|
+
/**
|
|
1494
|
+
* Get unescaped text value of current node and its children.
|
|
1495
|
+
* @return {string} text content
|
|
1496
|
+
*/
|
|
1497
|
+
get: function () {
|
|
1498
|
+
return this.rawText;
|
|
1499
|
+
},
|
|
1500
|
+
enumerable: false,
|
|
1501
|
+
configurable: true
|
|
1502
|
+
});
|
|
1503
|
+
CommentNode.prototype.toString = function () {
|
|
1504
|
+
return "<!--" + this.rawText + "-->";
|
|
1505
|
+
};
|
|
1506
|
+
return CommentNode;
|
|
1507
|
+
}(node_3.default));
|
|
1508
|
+
exports.default = CommentNode;
|
|
1509
|
+
});
|
|
1510
|
+
define("parse", ["require", "exports", "nodes/html"], function (require, exports, html_1) {
|
|
1511
|
+
"use strict";
|
|
1512
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1513
|
+
exports.default = void 0;
|
|
1514
|
+
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return html_1.parse; } });
|
|
1515
|
+
});
|
|
1516
|
+
define("valid", ["require", "exports", "nodes/html"], function (require, exports, html_2) {
|
|
1517
|
+
"use strict";
|
|
1518
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1519
|
+
/**
|
|
1520
|
+
* Parses HTML and returns a root element
|
|
1521
|
+
* Parse a chuck of HTML source.
|
|
1522
|
+
*/
|
|
1523
|
+
function valid(data, options) {
|
|
1524
|
+
if (options === void 0) { options = { lowerCaseTagName: false, comment: false }; }
|
|
1525
|
+
var stack = (0, html_2.base_parse)(data, options);
|
|
1526
|
+
return Boolean(stack.length === 1);
|
|
1527
|
+
}
|
|
1528
|
+
exports.default = valid;
|
|
1529
|
+
});
|
|
1530
|
+
define("index", ["require", "exports", "nodes/comment", "nodes/html", "parse", "valid", "nodes/node", "nodes/text", "nodes/type"], function (require, exports, comment_2, html_3, parse_1, valid_1, node_4, text_2, type_5) {
|
|
1531
|
+
"use strict";
|
|
1532
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1533
|
+
exports.NodeType = exports.TextNode = exports.Node = exports.valid = exports.default = exports.parse = exports.HTMLElement = exports.CommentNode = void 0;
|
|
1534
|
+
Object.defineProperty(exports, "CommentNode", { enumerable: true, get: function () { return __importDefault(comment_2).default; } });
|
|
1535
|
+
Object.defineProperty(exports, "HTMLElement", { enumerable: true, get: function () { return __importDefault(html_3).default; } });
|
|
1536
|
+
Object.defineProperty(exports, "parse", { enumerable: true, get: function () { return __importDefault(parse_1).default; } });
|
|
1537
|
+
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(parse_1).default; } });
|
|
1538
|
+
Object.defineProperty(exports, "valid", { enumerable: true, get: function () { return __importDefault(valid_1).default; } });
|
|
1539
|
+
Object.defineProperty(exports, "Node", { enumerable: true, get: function () { return __importDefault(node_4).default; } });
|
|
1540
|
+
Object.defineProperty(exports, "TextNode", { enumerable: true, get: function () { return __importDefault(text_2).default; } });
|
|
1541
|
+
Object.defineProperty(exports, "NodeType", { enumerable: true, get: function () { return __importDefault(type_5).default; } });
|
|
1542
|
+
});
|