node-html-parser 6.1.13 → 7.0.1
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/CHANGELOG.md +30 -0
- package/README.md +50 -11
- package/dist/index.js +8 -9
- package/dist/main.js +147 -53
- package/dist/matcher.js +26 -26
- package/dist/nodes/comment.js +22 -46
- package/dist/nodes/html.d.ts +33 -13
- package/dist/nodes/html.js +561 -653
- package/dist/nodes/node.js +18 -29
- package/dist/nodes/text.js +61 -100
- package/dist/valid.js +3 -4
- package/dist/void-tag.js +13 -15
- package/package.json +2 -1
package/dist/nodes/html.js
CHANGED
|
@@ -1,141 +1,89 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __extends = (this && this.__extends) || (function () {
|
|
3
|
-
var extendStatics = function (d, b) {
|
|
4
|
-
extendStatics = Object.setPrototypeOf ||
|
|
5
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
|
-
return extendStatics(d, b);
|
|
8
|
-
};
|
|
9
|
-
return function (d, b) {
|
|
10
|
-
if (typeof b !== "function" && b !== null)
|
|
11
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
12
|
-
extendStatics(d, b);
|
|
13
|
-
function __() { this.constructor = d; }
|
|
14
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
|
-
};
|
|
16
|
-
})();
|
|
17
|
-
var __assign = (this && this.__assign) || function () {
|
|
18
|
-
__assign = Object.assign || function(t) {
|
|
19
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
20
|
-
s = arguments[i];
|
|
21
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
22
|
-
t[p] = s[p];
|
|
23
|
-
}
|
|
24
|
-
return t;
|
|
25
|
-
};
|
|
26
|
-
return __assign.apply(this, arguments);
|
|
27
|
-
};
|
|
28
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
29
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
30
|
-
if (ar || !(i in from)) {
|
|
31
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
32
|
-
ar[i] = from[i];
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
36
|
-
};
|
|
37
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
38
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
39
4
|
};
|
|
40
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
6
|
exports.parse = exports.base_parse = void 0;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
7
|
+
const css_select_1 = require("css-select");
|
|
8
|
+
const he_1 = __importDefault(require("he"));
|
|
9
|
+
const back_1 = __importDefault(require("../back"));
|
|
10
|
+
const matcher_1 = __importDefault(require("../matcher"));
|
|
11
|
+
const void_tag_1 = __importDefault(require("../void-tag"));
|
|
12
|
+
const comment_1 = __importDefault(require("./comment"));
|
|
13
|
+
const node_1 = __importDefault(require("./node"));
|
|
14
|
+
const text_1 = __importDefault(require("./text"));
|
|
15
|
+
const type_1 = __importDefault(require("./type"));
|
|
51
16
|
function decode(val) {
|
|
52
17
|
// clone string
|
|
53
18
|
return JSON.parse(JSON.stringify(he_1.default.decode(val)));
|
|
54
19
|
}
|
|
55
20
|
// https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
function addToKBlockElement() {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
var addToSet = function (array) {
|
|
68
|
-
for (var index = 0; index < array.length; index++) {
|
|
69
|
-
var element = array[index];
|
|
21
|
+
const Htags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup'];
|
|
22
|
+
const Dtags = ['details', 'dialog', 'dd', 'div', 'dt'];
|
|
23
|
+
const Ftags = ['fieldset', 'figcaption', 'figure', 'footer', 'form'];
|
|
24
|
+
const tableTags = ['table', 'td', 'tr'];
|
|
25
|
+
const htmlTags = ['address', 'article', 'aside', 'blockquote', 'br', 'hr', 'li', 'main', 'nav', 'ol', 'p', 'pre', 'section', 'ul'];
|
|
26
|
+
const kBlockElements = new Set();
|
|
27
|
+
function addToKBlockElement(...args) {
|
|
28
|
+
const addToSet = (array) => {
|
|
29
|
+
for (let index = 0; index < array.length; index++) {
|
|
30
|
+
const element = array[index];
|
|
70
31
|
kBlockElements.add(element);
|
|
71
32
|
kBlockElements.add(element.toUpperCase());
|
|
72
33
|
}
|
|
73
34
|
};
|
|
74
|
-
for (
|
|
75
|
-
var arg = args_1[_a];
|
|
35
|
+
for (const arg of args)
|
|
76
36
|
addToSet(arg);
|
|
77
|
-
}
|
|
78
37
|
}
|
|
79
38
|
addToKBlockElement(Htags, Dtags, Ftags, tableTags, htmlTags);
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (
|
|
83
|
-
|
|
39
|
+
class DOMTokenList {
|
|
40
|
+
_validate(c) {
|
|
41
|
+
if (/\s/.test(c)) {
|
|
42
|
+
throw new Error(`DOMException in DOMTokenList.add: The token '${c}' contains HTML space characters, which are not valid in tokens.`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
constructor(valuesInit = [], afterUpdate = () => null) {
|
|
84
46
|
this._set = new Set(valuesInit);
|
|
85
47
|
this._afterUpdate = afterUpdate;
|
|
86
48
|
}
|
|
87
|
-
|
|
88
|
-
if (/\s/.test(c)) {
|
|
89
|
-
throw new Error("DOMException in DOMTokenList.add: The token '".concat(c, "' contains HTML space characters, which are not valid in tokens."));
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
DOMTokenList.prototype.add = function (c) {
|
|
49
|
+
add(c) {
|
|
93
50
|
this._validate(c);
|
|
94
51
|
this._set.add(c);
|
|
95
52
|
this._afterUpdate(this); // eslint-disable-line @typescript-eslint/no-unsafe-call
|
|
96
|
-
}
|
|
97
|
-
|
|
53
|
+
}
|
|
54
|
+
replace(c1, c2) {
|
|
98
55
|
this._validate(c2);
|
|
99
56
|
this._set.delete(c1);
|
|
100
57
|
this._set.add(c2);
|
|
101
58
|
this._afterUpdate(this); // eslint-disable-line @typescript-eslint/no-unsafe-call
|
|
102
|
-
}
|
|
103
|
-
|
|
59
|
+
}
|
|
60
|
+
remove(c) {
|
|
104
61
|
this._set.delete(c) && this._afterUpdate(this); // eslint-disable-line @typescript-eslint/no-unsafe-call
|
|
105
|
-
}
|
|
106
|
-
|
|
62
|
+
}
|
|
63
|
+
toggle(c) {
|
|
107
64
|
this._validate(c);
|
|
108
65
|
if (this._set.has(c))
|
|
109
66
|
this._set.delete(c);
|
|
110
67
|
else
|
|
111
68
|
this._set.add(c);
|
|
112
69
|
this._afterUpdate(this); // eslint-disable-line @typescript-eslint/no-unsafe-call
|
|
113
|
-
}
|
|
114
|
-
|
|
70
|
+
}
|
|
71
|
+
contains(c) {
|
|
115
72
|
return this._set.has(c);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
enumerable: false,
|
|
122
|
-
configurable: true
|
|
123
|
-
});
|
|
124
|
-
DOMTokenList.prototype.values = function () {
|
|
73
|
+
}
|
|
74
|
+
get length() {
|
|
75
|
+
return this._set.size;
|
|
76
|
+
}
|
|
77
|
+
values() {
|
|
125
78
|
return this._set.values();
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
enumerable: false,
|
|
132
|
-
configurable: true
|
|
133
|
-
});
|
|
134
|
-
DOMTokenList.prototype.toString = function () {
|
|
79
|
+
}
|
|
80
|
+
get value() {
|
|
81
|
+
return Array.from(this._set.values());
|
|
82
|
+
}
|
|
83
|
+
toString() {
|
|
135
84
|
return Array.from(this._set.values()).join(' ');
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
}());
|
|
85
|
+
}
|
|
86
|
+
}
|
|
139
87
|
/**
|
|
140
88
|
* HTMLElement, which contains a set of children.
|
|
141
89
|
*
|
|
@@ -145,8 +93,22 @@ var DOMTokenList = /** @class */ (function () {
|
|
|
145
93
|
* @class HTMLElement
|
|
146
94
|
* @extends {Node}
|
|
147
95
|
*/
|
|
148
|
-
|
|
149
|
-
|
|
96
|
+
class HTMLElement extends node_1.default {
|
|
97
|
+
/**
|
|
98
|
+
* Quote attribute values
|
|
99
|
+
* @param attr attribute value
|
|
100
|
+
* @returns {string} quoted value
|
|
101
|
+
*/
|
|
102
|
+
quoteAttribute(attr) {
|
|
103
|
+
if (attr == null) {
|
|
104
|
+
return 'null';
|
|
105
|
+
}
|
|
106
|
+
return JSON.stringify(attr.replace(/"/g, '"'))
|
|
107
|
+
.replace(/\\t/g, '\t')
|
|
108
|
+
.replace(/\\n/g, '\n')
|
|
109
|
+
.replace(/\\r/g, '\r')
|
|
110
|
+
.replace(/\\/g, '');
|
|
111
|
+
}
|
|
150
112
|
/**
|
|
151
113
|
* Creates an instance of HTMLElement.
|
|
152
114
|
* @param keyAttrs id and class attribute
|
|
@@ -154,278 +116,220 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
154
116
|
*
|
|
155
117
|
* @memberof HTMLElement
|
|
156
118
|
*/
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (_parseOptions === void 0) { _parseOptions = {}; }
|
|
162
|
-
var _this = _super.call(this, parentNode, range) || this;
|
|
163
|
-
_this.rawAttrs = rawAttrs;
|
|
164
|
-
_this.voidTag = voidTag;
|
|
119
|
+
constructor(tagName, keyAttrs, rawAttrs = '', parentNode = null, range, voidTag = new void_tag_1.default(), _parseOptions = {}) {
|
|
120
|
+
super(parentNode, range);
|
|
121
|
+
this.rawAttrs = rawAttrs;
|
|
122
|
+
this.voidTag = voidTag;
|
|
165
123
|
/**
|
|
166
124
|
* Node Type declaration.
|
|
167
125
|
*/
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
126
|
+
this.nodeType = type_1.default.ELEMENT_NODE;
|
|
127
|
+
this.rawTagName = tagName;
|
|
128
|
+
this.rawAttrs = rawAttrs || '';
|
|
129
|
+
this.id = keyAttrs.id || '';
|
|
130
|
+
this.childNodes = [];
|
|
131
|
+
this._parseOptions = _parseOptions;
|
|
132
|
+
this.classList = new DOMTokenList(keyAttrs.class ? keyAttrs.class.split(/\s+/) : [], (classList) => this.setAttribute('class', classList.toString()) // eslint-disable-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
|
175
133
|
);
|
|
176
134
|
if (keyAttrs.id) {
|
|
177
135
|
if (!rawAttrs) {
|
|
178
|
-
|
|
136
|
+
this.rawAttrs = `id="${keyAttrs.id}"`;
|
|
179
137
|
}
|
|
180
138
|
}
|
|
181
139
|
if (keyAttrs.class) {
|
|
182
140
|
if (!rawAttrs) {
|
|
183
|
-
|
|
184
|
-
if (
|
|
185
|
-
|
|
141
|
+
const cls = `class="${this.classList.toString()}"`;
|
|
142
|
+
if (this.rawAttrs) {
|
|
143
|
+
this.rawAttrs += ` ${cls}`;
|
|
186
144
|
}
|
|
187
145
|
else {
|
|
188
|
-
|
|
146
|
+
this.rawAttrs = cls;
|
|
189
147
|
}
|
|
190
148
|
}
|
|
191
149
|
}
|
|
192
|
-
return _this;
|
|
193
150
|
}
|
|
194
|
-
/**
|
|
195
|
-
* Quote attribute values
|
|
196
|
-
* @param attr attribute value
|
|
197
|
-
* @returns {string} quoted value
|
|
198
|
-
*/
|
|
199
|
-
HTMLElement.prototype.quoteAttribute = function (attr) {
|
|
200
|
-
if (attr == null) {
|
|
201
|
-
return 'null';
|
|
202
|
-
}
|
|
203
|
-
return JSON.stringify(attr.replace(/"/g, '"')).replace(/\\t/g, '\t').replace(/\\n/g, '\n').replace(/\\r/g, '\r').replace(/\\/g, '');
|
|
204
|
-
};
|
|
205
151
|
/**
|
|
206
152
|
* Remove Child element from childNodes array
|
|
207
153
|
* @param {HTMLElement} node node to remove
|
|
208
154
|
*/
|
|
209
|
-
|
|
210
|
-
this.childNodes = this.childNodes.filter(
|
|
155
|
+
removeChild(node) {
|
|
156
|
+
this.childNodes = this.childNodes.filter((child) => {
|
|
211
157
|
return child !== node;
|
|
212
158
|
});
|
|
213
159
|
return this;
|
|
214
|
-
}
|
|
160
|
+
}
|
|
215
161
|
/**
|
|
216
162
|
* Exchanges given child with new child
|
|
217
163
|
* @param {HTMLElement} oldNode node to exchange
|
|
218
164
|
* @param {HTMLElement} newNode new node
|
|
219
165
|
*/
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
this.childNodes = children.map(
|
|
166
|
+
exchangeChild(oldNode, newNode) {
|
|
167
|
+
const children = this.childNodes;
|
|
168
|
+
this.childNodes = children.map((child) => {
|
|
223
169
|
if (child === oldNode) {
|
|
224
170
|
return newNode;
|
|
225
171
|
}
|
|
226
172
|
return child;
|
|
227
173
|
});
|
|
228
174
|
return this;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
return
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
});
|
|
282
|
-
Object.defineProperty(HTMLElement.prototype, "text", {
|
|
283
|
-
/**
|
|
284
|
-
* Get unescaped text value of current node and its children.
|
|
285
|
-
* @return {string} text content
|
|
286
|
-
*/
|
|
287
|
-
get: function () {
|
|
288
|
-
return decode(this.rawText);
|
|
289
|
-
},
|
|
290
|
-
enumerable: false,
|
|
291
|
-
configurable: true
|
|
292
|
-
});
|
|
293
|
-
Object.defineProperty(HTMLElement.prototype, "structuredText", {
|
|
294
|
-
/**
|
|
295
|
-
* Get structured Text (with '\n' etc.)
|
|
296
|
-
* @return {string} structured text
|
|
297
|
-
*/
|
|
298
|
-
get: function () {
|
|
299
|
-
var currentBlock = [];
|
|
300
|
-
var blocks = [currentBlock];
|
|
301
|
-
function dfs(node) {
|
|
302
|
-
if (node.nodeType === type_1.default.ELEMENT_NODE) {
|
|
303
|
-
if (kBlockElements.has(node.rawTagName)) {
|
|
304
|
-
if (currentBlock.length > 0) {
|
|
305
|
-
blocks.push((currentBlock = []));
|
|
306
|
-
}
|
|
307
|
-
node.childNodes.forEach(dfs);
|
|
308
|
-
if (currentBlock.length > 0) {
|
|
309
|
-
blocks.push((currentBlock = []));
|
|
310
|
-
}
|
|
175
|
+
}
|
|
176
|
+
get tagName() {
|
|
177
|
+
return this.rawTagName ? this.rawTagName.toUpperCase() : this.rawTagName;
|
|
178
|
+
}
|
|
179
|
+
set tagName(newname) {
|
|
180
|
+
this.rawTagName = newname.toLowerCase();
|
|
181
|
+
}
|
|
182
|
+
get localName() {
|
|
183
|
+
return this.rawTagName.toLowerCase();
|
|
184
|
+
}
|
|
185
|
+
get isVoidElement() {
|
|
186
|
+
return this.voidTag.isVoidElement(this.localName);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Get escpaed (as-it) text value of current node and its children.
|
|
190
|
+
* @return {string} text content
|
|
191
|
+
*/
|
|
192
|
+
get rawText() {
|
|
193
|
+
// https://github.com/taoqf/node-html-parser/issues/249
|
|
194
|
+
if (/^br$/i.test(this.rawTagName)) {
|
|
195
|
+
return '\n';
|
|
196
|
+
}
|
|
197
|
+
return this.childNodes.reduce((pre, cur) => {
|
|
198
|
+
return (pre += cur.rawText);
|
|
199
|
+
}, '');
|
|
200
|
+
}
|
|
201
|
+
get textContent() {
|
|
202
|
+
return decode(this.rawText);
|
|
203
|
+
}
|
|
204
|
+
set textContent(val) {
|
|
205
|
+
const content = [new text_1.default(val, this)];
|
|
206
|
+
this.childNodes = content;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Get unescaped text value of current node and its children.
|
|
210
|
+
* @return {string} text content
|
|
211
|
+
*/
|
|
212
|
+
get text() {
|
|
213
|
+
return decode(this.rawText);
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Get structured Text (with '\n' etc.)
|
|
217
|
+
* @return {string} structured text
|
|
218
|
+
*/
|
|
219
|
+
get structuredText() {
|
|
220
|
+
let currentBlock = [];
|
|
221
|
+
const blocks = [currentBlock];
|
|
222
|
+
function dfs(node) {
|
|
223
|
+
if (node.nodeType === type_1.default.ELEMENT_NODE) {
|
|
224
|
+
if (kBlockElements.has(node.rawTagName)) {
|
|
225
|
+
if (currentBlock.length > 0) {
|
|
226
|
+
blocks.push((currentBlock = []));
|
|
311
227
|
}
|
|
312
|
-
|
|
313
|
-
|
|
228
|
+
node.childNodes.forEach(dfs);
|
|
229
|
+
if (currentBlock.length > 0) {
|
|
230
|
+
blocks.push((currentBlock = []));
|
|
314
231
|
}
|
|
315
232
|
}
|
|
316
|
-
else
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
233
|
+
else {
|
|
234
|
+
node.childNodes.forEach(dfs);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else if (node.nodeType === type_1.default.TEXT_NODE) {
|
|
238
|
+
if (node.isWhitespace) {
|
|
239
|
+
// Whitespace node, postponed output
|
|
240
|
+
currentBlock.prependWhitespace = true;
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
let text = node.trimmedText;
|
|
244
|
+
if (currentBlock.prependWhitespace) {
|
|
245
|
+
text = ` ${text}`;
|
|
246
|
+
currentBlock.prependWhitespace = false;
|
|
328
247
|
}
|
|
248
|
+
currentBlock.push(text);
|
|
329
249
|
}
|
|
330
250
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
})
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
HTMLElement.prototype.toString = function () {
|
|
343
|
-
var tag = this.rawTagName;
|
|
251
|
+
}
|
|
252
|
+
dfs(this);
|
|
253
|
+
return blocks
|
|
254
|
+
.map((block) => {
|
|
255
|
+
return block.join('').replace(/\s{2,}/g, ' '); // Normalize each line's whitespace
|
|
256
|
+
})
|
|
257
|
+
.join('\n')
|
|
258
|
+
.replace(/\s+$/, ''); // trimRight;
|
|
259
|
+
}
|
|
260
|
+
toString() {
|
|
261
|
+
const tag = this.rawTagName;
|
|
344
262
|
if (tag) {
|
|
345
|
-
|
|
263
|
+
const attrs = this.rawAttrs ? ` ${this.rawAttrs}` : '';
|
|
346
264
|
return this.voidTag.formatNode(tag, attrs, this.innerHTML);
|
|
347
265
|
}
|
|
348
266
|
return this.innerHTML;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
enumerable: false,
|
|
366
|
-
configurable: true
|
|
367
|
-
});
|
|
368
|
-
HTMLElement.prototype.set_content = function (content, options) {
|
|
369
|
-
if (options === void 0) { options = {}; }
|
|
267
|
+
}
|
|
268
|
+
get innerHTML() {
|
|
269
|
+
return this.childNodes
|
|
270
|
+
.map((child) => {
|
|
271
|
+
return child.toString();
|
|
272
|
+
})
|
|
273
|
+
.join('');
|
|
274
|
+
}
|
|
275
|
+
set innerHTML(content) {
|
|
276
|
+
const r = parse(content, this._parseOptions);
|
|
277
|
+
const nodes = r.childNodes.length ? r.childNodes : [new text_1.default(content, this)];
|
|
278
|
+
resetParent(nodes, this);
|
|
279
|
+
resetParent(this.childNodes, null);
|
|
280
|
+
this.childNodes = nodes;
|
|
281
|
+
}
|
|
282
|
+
set_content(content, options = {}) {
|
|
370
283
|
if (content instanceof node_1.default) {
|
|
371
284
|
content = [content];
|
|
372
285
|
}
|
|
373
286
|
else if (typeof content == 'string') {
|
|
374
|
-
options =
|
|
375
|
-
|
|
287
|
+
options = Object.assign(Object.assign({}, this._parseOptions), options);
|
|
288
|
+
const r = parse(content, options);
|
|
376
289
|
content = r.childNodes.length ? r.childNodes : [new text_1.default(r.innerHTML, this)];
|
|
377
290
|
}
|
|
378
291
|
resetParent(this.childNodes, null);
|
|
379
292
|
resetParent(content, this);
|
|
380
293
|
this.childNodes = content;
|
|
381
294
|
return this;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
nodes[_i] = arguments[_i];
|
|
388
|
-
}
|
|
389
|
-
var parent = this.parentNode;
|
|
390
|
-
var content = nodes
|
|
391
|
-
.map(function (node) {
|
|
295
|
+
}
|
|
296
|
+
replaceWith(...nodes) {
|
|
297
|
+
const parent = this.parentNode;
|
|
298
|
+
const content = nodes
|
|
299
|
+
.map((node) => {
|
|
392
300
|
if (node instanceof node_1.default) {
|
|
393
301
|
return [node];
|
|
394
302
|
}
|
|
395
303
|
else if (typeof node == 'string') {
|
|
396
|
-
|
|
397
|
-
return r.childNodes.length ? r.childNodes : [new text_1.default(node,
|
|
304
|
+
const r = parse(node, this._parseOptions);
|
|
305
|
+
return r.childNodes.length ? r.childNodes : [new text_1.default(node, this)];
|
|
398
306
|
}
|
|
399
307
|
return [];
|
|
400
308
|
})
|
|
401
309
|
.flat();
|
|
402
|
-
|
|
403
|
-
return child ===
|
|
310
|
+
const idx = parent.childNodes.findIndex((child) => {
|
|
311
|
+
return child === this;
|
|
404
312
|
});
|
|
405
313
|
resetParent([this], null);
|
|
406
|
-
parent.childNodes =
|
|
314
|
+
parent.childNodes = [...parent.childNodes.slice(0, idx), ...resetParent(content, parent), ...parent.childNodes.slice(idx + 1)];
|
|
407
315
|
return this;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
},
|
|
413
|
-
enumerable: false,
|
|
414
|
-
configurable: true
|
|
415
|
-
});
|
|
316
|
+
}
|
|
317
|
+
get outerHTML() {
|
|
318
|
+
return this.toString();
|
|
319
|
+
}
|
|
416
320
|
/**
|
|
417
321
|
* Trim element from right (in block) after seeing pattern in a TextNode.
|
|
418
322
|
* @param {RegExp} pattern pattern to find
|
|
419
323
|
* @return {HTMLElement} reference to current node
|
|
420
324
|
*/
|
|
421
|
-
|
|
422
|
-
for (
|
|
423
|
-
|
|
325
|
+
trimRight(pattern) {
|
|
326
|
+
for (let i = 0; i < this.childNodes.length; i++) {
|
|
327
|
+
const childNode = this.childNodes[i];
|
|
424
328
|
if (childNode.nodeType === type_1.default.ELEMENT_NODE) {
|
|
425
329
|
childNode.trimRight(pattern);
|
|
426
330
|
}
|
|
427
331
|
else {
|
|
428
|
-
|
|
332
|
+
const index = childNode.rawText.search(pattern);
|
|
429
333
|
if (index > -1) {
|
|
430
334
|
childNode.rawText = childNode.rawText.substr(0, index);
|
|
431
335
|
// trim all following nodes.
|
|
@@ -434,49 +338,44 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
434
338
|
}
|
|
435
339
|
}
|
|
436
340
|
return this;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
write('#text');
|
|
461
|
-
}
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Get DOM structure
|
|
344
|
+
* @return {string} structure
|
|
345
|
+
*/
|
|
346
|
+
get structure() {
|
|
347
|
+
const res = [];
|
|
348
|
+
let indention = 0;
|
|
349
|
+
function write(str) {
|
|
350
|
+
res.push(' '.repeat(indention) + str);
|
|
351
|
+
}
|
|
352
|
+
function dfs(node) {
|
|
353
|
+
const idStr = node.id ? `#${node.id}` : '';
|
|
354
|
+
const 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
|
|
355
|
+
write(`${node.rawTagName}${idStr}${classStr}`);
|
|
356
|
+
indention++;
|
|
357
|
+
node.childNodes.forEach((childNode) => {
|
|
358
|
+
if (childNode.nodeType === type_1.default.ELEMENT_NODE) {
|
|
359
|
+
dfs(childNode);
|
|
360
|
+
}
|
|
361
|
+
else if (childNode.nodeType === type_1.default.TEXT_NODE) {
|
|
362
|
+
if (!childNode.isWhitespace) {
|
|
363
|
+
write('#text');
|
|
462
364
|
}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
configurable: true
|
|
471
|
-
});
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
indention--;
|
|
368
|
+
}
|
|
369
|
+
dfs(this);
|
|
370
|
+
return res.join('\n');
|
|
371
|
+
}
|
|
472
372
|
/**
|
|
473
373
|
* Remove whitespaces in this sub tree.
|
|
474
374
|
* @return {HTMLElement} pointer to this
|
|
475
375
|
*/
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
this.childNodes.forEach(function (node) {
|
|
376
|
+
removeWhitespace() {
|
|
377
|
+
let o = 0;
|
|
378
|
+
this.childNodes.forEach((node) => {
|
|
480
379
|
if (node.nodeType === type_1.default.TEXT_NODE) {
|
|
481
380
|
if (node.isWhitespace) {
|
|
482
381
|
return;
|
|
@@ -486,47 +385,56 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
486
385
|
else if (node.nodeType === type_1.default.ELEMENT_NODE) {
|
|
487
386
|
node.removeWhitespace();
|
|
488
387
|
}
|
|
489
|
-
|
|
388
|
+
this.childNodes[o++] = node;
|
|
490
389
|
});
|
|
491
390
|
this.childNodes.length = o;
|
|
391
|
+
// remove whitespace between attributes
|
|
392
|
+
const attrs = Object.keys(this.rawAttributes)
|
|
393
|
+
.map((key) => {
|
|
394
|
+
const val = this.rawAttributes[key];
|
|
395
|
+
return `${key}=${JSON.stringify(val)}`;
|
|
396
|
+
})
|
|
397
|
+
.join(' ');
|
|
398
|
+
this.rawAttrs = attrs;
|
|
399
|
+
delete this._rawAttrs;
|
|
492
400
|
return this;
|
|
493
|
-
}
|
|
401
|
+
}
|
|
494
402
|
/**
|
|
495
403
|
* Query CSS selector to find matching nodes.
|
|
496
404
|
* @param {string} selector Simplified CSS selector
|
|
497
405
|
* @return {HTMLElement[]} matching elements
|
|
498
406
|
*/
|
|
499
|
-
|
|
407
|
+
querySelectorAll(selector) {
|
|
500
408
|
return (0, css_select_1.selectAll)(selector, this, {
|
|
501
409
|
xmlMode: true,
|
|
502
410
|
adapter: matcher_1.default,
|
|
503
411
|
});
|
|
504
|
-
}
|
|
412
|
+
}
|
|
505
413
|
/**
|
|
506
414
|
* Query CSS Selector to find matching node.
|
|
507
415
|
* @param {string} selector Simplified CSS selector
|
|
508
416
|
* @return {(HTMLElement|null)} matching node
|
|
509
417
|
*/
|
|
510
|
-
|
|
418
|
+
querySelector(selector) {
|
|
511
419
|
return (0, css_select_1.selectOne)(selector, this, {
|
|
512
420
|
xmlMode: true,
|
|
513
421
|
adapter: matcher_1.default,
|
|
514
422
|
});
|
|
515
|
-
}
|
|
423
|
+
}
|
|
516
424
|
/**
|
|
517
425
|
* find elements by their tagName
|
|
518
426
|
* @param {string} tagName the tagName of the elements to select
|
|
519
427
|
*/
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
428
|
+
getElementsByTagName(tagName) {
|
|
429
|
+
const upperCasedTagName = tagName.toUpperCase();
|
|
430
|
+
const re = [];
|
|
431
|
+
const stack = [];
|
|
432
|
+
let currentNodeReference = this;
|
|
433
|
+
let index = 0;
|
|
526
434
|
// index turns to undefined once the stack is empty and the first condition occurs
|
|
527
435
|
// which happens once all relevant children are searched through
|
|
528
436
|
while (index !== undefined) {
|
|
529
|
-
|
|
437
|
+
let child;
|
|
530
438
|
// make it work with sparse arrays
|
|
531
439
|
do {
|
|
532
440
|
child = currentNodeReference.childNodes[index++];
|
|
@@ -550,20 +458,20 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
550
458
|
}
|
|
551
459
|
}
|
|
552
460
|
return re;
|
|
553
|
-
}
|
|
461
|
+
}
|
|
554
462
|
/**
|
|
555
463
|
* find element by it's id
|
|
556
464
|
* @param {string} id the id of the element to select
|
|
557
465
|
* @returns {HTMLElement | null} the element with the given id or null if not found
|
|
558
466
|
*/
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
467
|
+
getElementById(id) {
|
|
468
|
+
const stack = [];
|
|
469
|
+
let currentNodeReference = this;
|
|
470
|
+
let index = 0;
|
|
563
471
|
// index turns to undefined once the stack is empty and the first condition occurs
|
|
564
472
|
// which happens once all relevant children are searched through
|
|
565
473
|
while (index !== undefined) {
|
|
566
|
-
|
|
474
|
+
let child;
|
|
567
475
|
// make it work with sparse arrays
|
|
568
476
|
do {
|
|
569
477
|
child = currentNodeReference.childNodes[index++];
|
|
@@ -578,7 +486,6 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
578
486
|
if (child.id === id) {
|
|
579
487
|
return child;
|
|
580
488
|
}
|
|
581
|
-
;
|
|
582
489
|
// if children are existing push the current status to the stack and keep searching for elements in the level below
|
|
583
490
|
if (child.childNodes.length > 0) {
|
|
584
491
|
stack.push(index);
|
|
@@ -588,25 +495,25 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
588
495
|
}
|
|
589
496
|
}
|
|
590
497
|
return null;
|
|
591
|
-
}
|
|
498
|
+
}
|
|
592
499
|
/**
|
|
593
500
|
* 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.
|
|
594
501
|
* @param selector a DOMString containing a selector list
|
|
595
502
|
* @returns {HTMLElement | null} the element with the given id or null if not found
|
|
596
503
|
*/
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
504
|
+
closest(selector) {
|
|
505
|
+
const mapChild = new Map();
|
|
506
|
+
let el = this;
|
|
507
|
+
let old = null;
|
|
601
508
|
function findOne(test, elems) {
|
|
602
|
-
|
|
603
|
-
for (
|
|
604
|
-
|
|
605
|
-
if (test(
|
|
606
|
-
elem =
|
|
509
|
+
let elem = null;
|
|
510
|
+
for (let i = 0, l = elems.length; i < l && !elem; i++) {
|
|
511
|
+
const el = elems[i];
|
|
512
|
+
if (test(el)) {
|
|
513
|
+
elem = el;
|
|
607
514
|
}
|
|
608
515
|
else {
|
|
609
|
-
|
|
516
|
+
const child = mapChild.get(el);
|
|
610
517
|
if (child) {
|
|
611
518
|
elem = findOne(test, [child]);
|
|
612
519
|
}
|
|
@@ -621,14 +528,17 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
621
528
|
}
|
|
622
529
|
el = this;
|
|
623
530
|
while (el) {
|
|
624
|
-
|
|
531
|
+
const e = (0, css_select_1.selectOne)(selector, el, {
|
|
625
532
|
xmlMode: true,
|
|
626
|
-
adapter:
|
|
627
|
-
|
|
533
|
+
adapter: Object.assign(Object.assign({}, matcher_1.default), { getChildren(node) {
|
|
534
|
+
const child = mapChild.get(node);
|
|
628
535
|
return child && [child];
|
|
629
|
-
},
|
|
536
|
+
},
|
|
537
|
+
getSiblings(node) {
|
|
630
538
|
return [node];
|
|
631
|
-
},
|
|
539
|
+
},
|
|
540
|
+
findOne,
|
|
541
|
+
findAll() {
|
|
632
542
|
return [];
|
|
633
543
|
} }),
|
|
634
544
|
});
|
|
@@ -638,105 +548,67 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
638
548
|
el = el.parentNode;
|
|
639
549
|
}
|
|
640
550
|
return null;
|
|
641
|
-
}
|
|
551
|
+
}
|
|
642
552
|
/**
|
|
643
553
|
* Append a child node to childNodes
|
|
644
554
|
* @param {Node} node node to append
|
|
645
555
|
* @return {Node} node appended
|
|
646
556
|
*/
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
node.remove();
|
|
650
|
-
this.childNodes.push(node);
|
|
651
|
-
node.parentNode = this;
|
|
557
|
+
appendChild(node) {
|
|
558
|
+
this.append(node);
|
|
652
559
|
return node;
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
},
|
|
662
|
-
enumerable: false,
|
|
663
|
-
configurable: true
|
|
664
|
-
});
|
|
665
|
-
Object.defineProperty(HTMLElement.prototype, "lastChild", {
|
|
666
|
-
/**
|
|
667
|
-
* Get last child node
|
|
668
|
-
* @return {Node | undefined} last child node; or undefined if none
|
|
669
|
-
*/
|
|
670
|
-
get: function () {
|
|
671
|
-
return (0, back_1.default)(this.childNodes);
|
|
672
|
-
},
|
|
673
|
-
enumerable: false,
|
|
674
|
-
configurable: true
|
|
675
|
-
});
|
|
676
|
-
Object.defineProperty(HTMLElement.prototype, "attrs", {
|
|
677
|
-
/**
|
|
678
|
-
* Get attributes
|
|
679
|
-
* @access private
|
|
680
|
-
* @return {Object} parsed and unescaped attributes
|
|
681
|
-
*/
|
|
682
|
-
get: function () {
|
|
683
|
-
if (this._attrs) {
|
|
684
|
-
return this._attrs;
|
|
685
|
-
}
|
|
686
|
-
this._attrs = {};
|
|
687
|
-
var attrs = this.rawAttributes;
|
|
688
|
-
for (var key in attrs) {
|
|
689
|
-
var val = attrs[key] || '';
|
|
690
|
-
this._attrs[key.toLowerCase()] = decode(val);
|
|
691
|
-
}
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Get attributes
|
|
563
|
+
* @access private
|
|
564
|
+
* @return {Object} parsed and unescaped attributes
|
|
565
|
+
*/
|
|
566
|
+
get attrs() {
|
|
567
|
+
if (this._attrs) {
|
|
692
568
|
return this._attrs;
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
}
|
|
569
|
+
}
|
|
570
|
+
this._attrs = {};
|
|
571
|
+
const attrs = this.rawAttributes;
|
|
572
|
+
for (const key in attrs) {
|
|
573
|
+
const val = attrs[key] || '';
|
|
574
|
+
this._attrs[key.toLowerCase()] = decode(val);
|
|
575
|
+
}
|
|
576
|
+
return this._attrs;
|
|
577
|
+
}
|
|
578
|
+
get attributes() {
|
|
579
|
+
const ret_attrs = {};
|
|
580
|
+
const attrs = this.rawAttributes;
|
|
581
|
+
for (const key in attrs) {
|
|
582
|
+
const val = attrs[key] || '';
|
|
583
|
+
ret_attrs[key] = decode(val);
|
|
584
|
+
}
|
|
585
|
+
return ret_attrs;
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Get escaped (as-is) attributes
|
|
589
|
+
* @return {Object} parsed attributes
|
|
590
|
+
*/
|
|
591
|
+
get rawAttributes() {
|
|
592
|
+
if (this._rawAttrs) {
|
|
593
|
+
return this._rawAttrs;
|
|
594
|
+
}
|
|
595
|
+
const attrs = {};
|
|
596
|
+
if (this.rawAttrs) {
|
|
597
|
+
const re = /([a-zA-Z()[\]#@$.?:][a-zA-Z0-9-._:()[\]#]*)(?:\s*=\s*((?:'[^']*')|(?:"[^"]*")|\S+))?/g;
|
|
598
|
+
let match;
|
|
599
|
+
while ((match = re.exec(this.rawAttrs))) {
|
|
600
|
+
const key = match[1];
|
|
601
|
+
let val = match[2] || null;
|
|
602
|
+
if (val && (val[0] === `'` || val[0] === `"`))
|
|
603
|
+
val = val.slice(1, val.length - 1);
|
|
604
|
+
attrs[key] = attrs[key] || val;
|
|
730
605
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
HTMLElement.prototype.removeAttribute = function (key) {
|
|
738
|
-
var _this = this;
|
|
739
|
-
var attrs = this.rawAttributes;
|
|
606
|
+
}
|
|
607
|
+
this._rawAttrs = attrs;
|
|
608
|
+
return attrs;
|
|
609
|
+
}
|
|
610
|
+
removeAttribute(key) {
|
|
611
|
+
const attrs = this.rawAttributes;
|
|
740
612
|
delete attrs[key];
|
|
741
613
|
// Update this.attribute
|
|
742
614
|
if (this._attrs) {
|
|
@@ -744,11 +616,11 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
744
616
|
}
|
|
745
617
|
// Update rawString
|
|
746
618
|
this.rawAttrs = Object.keys(attrs)
|
|
747
|
-
.map(
|
|
748
|
-
|
|
619
|
+
.map((name) => {
|
|
620
|
+
const val = this.quoteAttribute(attrs[name]);
|
|
749
621
|
if (val === 'null' || val === '""')
|
|
750
622
|
return name;
|
|
751
|
-
return
|
|
623
|
+
return `${name}=${val}`;
|
|
752
624
|
})
|
|
753
625
|
.join(' ');
|
|
754
626
|
// Update this.id
|
|
@@ -756,30 +628,29 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
756
628
|
this.id = '';
|
|
757
629
|
}
|
|
758
630
|
return this;
|
|
759
|
-
}
|
|
760
|
-
|
|
631
|
+
}
|
|
632
|
+
hasAttribute(key) {
|
|
761
633
|
return key.toLowerCase() in this.attrs;
|
|
762
|
-
}
|
|
634
|
+
}
|
|
763
635
|
/**
|
|
764
636
|
* Get an attribute
|
|
765
637
|
* @return {string | undefined} value of the attribute; or undefined if not exist
|
|
766
638
|
*/
|
|
767
|
-
|
|
639
|
+
getAttribute(key) {
|
|
768
640
|
return this.attrs[key.toLowerCase()];
|
|
769
|
-
}
|
|
641
|
+
}
|
|
770
642
|
/**
|
|
771
643
|
* Set an attribute value to the HTMLElement
|
|
772
644
|
* @param {string} key The attribute name
|
|
773
645
|
* @param {string} value The value to set, or null / undefined to remove an attribute
|
|
774
646
|
*/
|
|
775
|
-
|
|
776
|
-
var _this = this;
|
|
647
|
+
setAttribute(key, value) {
|
|
777
648
|
if (arguments.length < 2) {
|
|
778
649
|
throw new Error("Failed to execute 'setAttribute' on 'Element'");
|
|
779
650
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
for (
|
|
651
|
+
const k2 = key.toLowerCase();
|
|
652
|
+
const attrs = this.rawAttributes;
|
|
653
|
+
for (const k in attrs) {
|
|
783
654
|
if (k.toLowerCase() === k2) {
|
|
784
655
|
key = k;
|
|
785
656
|
break;
|
|
@@ -792,11 +663,11 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
792
663
|
}
|
|
793
664
|
// Update rawString
|
|
794
665
|
this.rawAttrs = Object.keys(attrs)
|
|
795
|
-
.map(
|
|
796
|
-
|
|
666
|
+
.map((name) => {
|
|
667
|
+
const val = this.quoteAttribute(attrs[name]);
|
|
797
668
|
if (val === 'null' || val === '""')
|
|
798
669
|
return name;
|
|
799
|
-
return
|
|
670
|
+
return `${name}=${val}`;
|
|
800
671
|
})
|
|
801
672
|
.join(' ');
|
|
802
673
|
// Update this.id
|
|
@@ -804,13 +675,12 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
804
675
|
this.id = value;
|
|
805
676
|
}
|
|
806
677
|
return this;
|
|
807
|
-
}
|
|
678
|
+
}
|
|
808
679
|
/**
|
|
809
680
|
* Replace all the attributes of the HTMLElement by the provided attributes
|
|
810
681
|
* @param {Attributes} attributes the new attribute set
|
|
811
682
|
*/
|
|
812
|
-
|
|
813
|
-
var _this = this;
|
|
683
|
+
setAttributes(attributes) {
|
|
814
684
|
// Invalidate current this.attributes
|
|
815
685
|
if (this._attrs) {
|
|
816
686
|
delete this._attrs;
|
|
@@ -821,151 +691,181 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
821
691
|
}
|
|
822
692
|
// Update rawString
|
|
823
693
|
this.rawAttrs = Object.keys(attributes)
|
|
824
|
-
.map(
|
|
825
|
-
|
|
694
|
+
.map((name) => {
|
|
695
|
+
const val = attributes[name];
|
|
826
696
|
if (val === 'null' || val === '""')
|
|
827
697
|
return name;
|
|
828
|
-
return
|
|
698
|
+
return `${name}=${this.quoteAttribute(String(val))}`;
|
|
829
699
|
})
|
|
830
700
|
.join(' ');
|
|
831
701
|
return this;
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
var _a, _b, _c;
|
|
835
|
-
var _this = this;
|
|
702
|
+
}
|
|
703
|
+
insertAdjacentHTML(where, html) {
|
|
836
704
|
if (arguments.length < 2) {
|
|
837
705
|
throw new Error('2 arguments required');
|
|
838
706
|
}
|
|
839
|
-
|
|
707
|
+
const p = parse(html, this._parseOptions);
|
|
840
708
|
if (where === 'afterend') {
|
|
841
|
-
|
|
842
|
-
return child === _this;
|
|
843
|
-
});
|
|
844
|
-
resetParent(p.childNodes, this.parentNode);
|
|
845
|
-
(_a = this.parentNode.childNodes).splice.apply(_a, __spreadArray([idx + 1, 0], p.childNodes, false));
|
|
709
|
+
this.after(...p.childNodes);
|
|
846
710
|
}
|
|
847
711
|
else if (where === 'afterbegin') {
|
|
848
|
-
|
|
849
|
-
(_b = this.childNodes).unshift.apply(_b, p.childNodes);
|
|
712
|
+
this.prepend(...p.childNodes);
|
|
850
713
|
}
|
|
851
714
|
else if (where === 'beforeend') {
|
|
852
|
-
p.childNodes
|
|
853
|
-
_this.appendChild(n);
|
|
854
|
-
});
|
|
715
|
+
this.append(...p.childNodes);
|
|
855
716
|
}
|
|
856
717
|
else if (where === 'beforebegin') {
|
|
857
|
-
|
|
858
|
-
return child === _this;
|
|
859
|
-
});
|
|
860
|
-
resetParent(p.childNodes, this.parentNode);
|
|
861
|
-
(_c = this.parentNode.childNodes).splice.apply(_c, __spreadArray([idx, 0], p.childNodes, false));
|
|
718
|
+
this.before(...p.childNodes);
|
|
862
719
|
}
|
|
863
720
|
else {
|
|
864
|
-
throw new Error(
|
|
721
|
+
throw new Error(`The value provided ('${where}') is not one of 'beforebegin', 'afterbegin', 'beforeend', or 'afterend'`);
|
|
865
722
|
}
|
|
866
723
|
return this;
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
724
|
+
}
|
|
725
|
+
/** Prepend nodes or strings to this node's children. */
|
|
726
|
+
prepend(...insertable) {
|
|
727
|
+
const nodes = resolveInsertable(insertable);
|
|
728
|
+
resetParent(nodes, this);
|
|
729
|
+
this.childNodes.unshift(...nodes);
|
|
730
|
+
}
|
|
731
|
+
/** Append nodes or strings to this node's children. */
|
|
732
|
+
append(...insertable) {
|
|
733
|
+
const nodes = resolveInsertable(insertable);
|
|
734
|
+
resetParent(nodes, this);
|
|
735
|
+
this.childNodes.push(...nodes);
|
|
736
|
+
}
|
|
737
|
+
/** Insert nodes or strings before this node. */
|
|
738
|
+
before(...insertable) {
|
|
739
|
+
const nodes = resolveInsertable(insertable);
|
|
740
|
+
const siblings = this.parentNode.childNodes;
|
|
741
|
+
resetParent(nodes, this.parentNode);
|
|
742
|
+
siblings.splice(siblings.indexOf(this), 0, ...nodes);
|
|
743
|
+
}
|
|
744
|
+
/** Insert nodes or strings after this node. */
|
|
745
|
+
after(...insertable) {
|
|
746
|
+
const nodes = resolveInsertable(insertable);
|
|
747
|
+
const siblings = this.parentNode.childNodes;
|
|
748
|
+
resetParent(nodes, this.parentNode);
|
|
749
|
+
siblings.splice(siblings.indexOf(this) + 1, 0, ...nodes);
|
|
750
|
+
}
|
|
751
|
+
get nextSibling() {
|
|
752
|
+
if (this.parentNode) {
|
|
753
|
+
const children = this.parentNode.childNodes;
|
|
754
|
+
let i = 0;
|
|
755
|
+
while (i < children.length) {
|
|
756
|
+
const child = children[i++];
|
|
757
|
+
if (this === child)
|
|
758
|
+
return children[i] || null;
|
|
882
759
|
}
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
if (child instanceof HTMLElement) {
|
|
897
|
-
return child || null;
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
else if (this === child) {
|
|
901
|
-
find = true;
|
|
760
|
+
return null;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
get nextElementSibling() {
|
|
764
|
+
if (this.parentNode) {
|
|
765
|
+
const children = this.parentNode.childNodes;
|
|
766
|
+
let i = 0;
|
|
767
|
+
let find = false;
|
|
768
|
+
while (i < children.length) {
|
|
769
|
+
const child = children[i++];
|
|
770
|
+
if (find) {
|
|
771
|
+
if (child instanceof HTMLElement) {
|
|
772
|
+
return child || null;
|
|
902
773
|
}
|
|
903
774
|
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
},
|
|
907
|
-
enumerable: false,
|
|
908
|
-
configurable: true
|
|
909
|
-
});
|
|
910
|
-
Object.defineProperty(HTMLElement.prototype, "previousSibling", {
|
|
911
|
-
get: function () {
|
|
912
|
-
if (this.parentNode) {
|
|
913
|
-
var children = this.parentNode.childNodes;
|
|
914
|
-
var i = children.length;
|
|
915
|
-
while (i > 0) {
|
|
916
|
-
var child = children[--i];
|
|
917
|
-
if (this === child)
|
|
918
|
-
return children[i - 1] || null;
|
|
775
|
+
else if (this === child) {
|
|
776
|
+
find = true;
|
|
919
777
|
}
|
|
920
|
-
return null;
|
|
921
778
|
}
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
779
|
+
return null;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
get previousSibling() {
|
|
783
|
+
if (this.parentNode) {
|
|
784
|
+
const children = this.parentNode.childNodes;
|
|
785
|
+
let i = children.length;
|
|
786
|
+
while (i > 0) {
|
|
787
|
+
const child = children[--i];
|
|
788
|
+
if (this === child)
|
|
789
|
+
return children[i - 1] || null;
|
|
790
|
+
}
|
|
791
|
+
return null;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
get previousElementSibling() {
|
|
795
|
+
if (this.parentNode) {
|
|
796
|
+
const children = this.parentNode.childNodes;
|
|
797
|
+
let i = children.length;
|
|
798
|
+
let find = false;
|
|
799
|
+
while (i > 0) {
|
|
800
|
+
const child = children[--i];
|
|
801
|
+
if (find) {
|
|
802
|
+
if (child instanceof HTMLElement) {
|
|
803
|
+
return child || null;
|
|
941
804
|
}
|
|
942
805
|
}
|
|
943
|
-
|
|
806
|
+
else if (this === child) {
|
|
807
|
+
find = true;
|
|
808
|
+
}
|
|
944
809
|
}
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
}
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
810
|
+
return null;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
/** Get all childNodes of type {@link HTMLElement}. */
|
|
814
|
+
get children() {
|
|
815
|
+
const children = [];
|
|
816
|
+
for (const childNode of this.childNodes) {
|
|
817
|
+
if (childNode instanceof HTMLElement) {
|
|
818
|
+
children.push(childNode);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
return children;
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Get the first child node.
|
|
825
|
+
* @return The first child or undefined if none exists.
|
|
826
|
+
*/
|
|
827
|
+
get firstChild() {
|
|
828
|
+
return this.childNodes[0];
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Get the first child node of type {@link HTMLElement}.
|
|
832
|
+
* @return The first child element or undefined if none exists.
|
|
833
|
+
*/
|
|
834
|
+
get firstElementChild() {
|
|
835
|
+
return this.children[0];
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* Get the last child node.
|
|
839
|
+
* @return The last child or undefined if none exists.
|
|
840
|
+
*/
|
|
841
|
+
get lastChild() {
|
|
842
|
+
return (0, back_1.default)(this.childNodes);
|
|
843
|
+
}
|
|
956
844
|
/**
|
|
957
|
-
*
|
|
845
|
+
* Get the last child node of type {@link HTMLElement}.
|
|
846
|
+
* @return The last child element or undefined if none exists.
|
|
958
847
|
*/
|
|
959
|
-
|
|
848
|
+
get lastElementChild() {
|
|
849
|
+
return this.children[this.children.length - 1];
|
|
850
|
+
}
|
|
851
|
+
get childElementCount() {
|
|
852
|
+
return this.children.length;
|
|
853
|
+
}
|
|
854
|
+
get classNames() {
|
|
855
|
+
return this.classList.toString();
|
|
856
|
+
}
|
|
857
|
+
/** Clone this Node */
|
|
858
|
+
clone() {
|
|
960
859
|
return parse(this.toString(), this._parseOptions).firstChild;
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
}(node_1.default));
|
|
860
|
+
}
|
|
861
|
+
}
|
|
964
862
|
exports.default = HTMLElement;
|
|
863
|
+
// #xB7 | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x203F-#x2040] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
|
|
965
864
|
// https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
865
|
+
const kMarkupPattern = /<!--[\s\S]*?-->|<(\/?)([a-zA-Z][-.:0-9_a-zA-Z@\xB7\xC0-\xD6\xD8-\xF6\u00F8-\u03A1\u03A3-\u03D9\u03DB-\u03EF\u03F7-\u03FF\u0400-\u04FF\u0500-\u052F\u1D00-\u1D2B\u1D6B-\u1D77\u1D79-\u1D9A\u1E00-\u1E9B\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2126\u212A-\u212B\u2132\u214E\u2160-\u2188\u2C60-\u2C7F\uA722-\uA787\uA78B-\uA78E\uA790-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA7FF\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64-\uAB65\uFB00-\uFB06\uFB13-\uFB17\uFF21-\uFF3A\uFF41-\uFF5A\x37F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]*)((?:\s+[^>]*?(?:(?:'[^']*')|(?:"[^"]*"))?)*)\s*(\/?)>/gu;
|
|
866
|
+
// const kMarkupPattern = /<!--[\s\S]*?-->|<(\/?)([a-zA-Z][-.:0-9_a-zA-Z]*)((?:\s+[^>]*?(?:(?:'[^']*')|(?:"[^"]*"))?)*)\s*(\/?)>/g;
|
|
867
|
+
const kAttributePattern = /(?:^|\s)(id|class)\s*=\s*((?:'[^']*')|(?:"[^"]*")|\S+)/gi;
|
|
868
|
+
const kElementsClosedByOpening = {
|
|
969
869
|
li: { li: true, LI: true },
|
|
970
870
|
LI: { li: true, LI: true },
|
|
971
871
|
p: { p: true, div: true, P: true, DIV: true },
|
|
@@ -989,7 +889,7 @@ var kElementsClosedByOpening = {
|
|
|
989
889
|
h6: { h6: true, H6: true },
|
|
990
890
|
H6: { h6: true, H6: true },
|
|
991
891
|
};
|
|
992
|
-
|
|
892
|
+
const kElementsClosedByClosing = {
|
|
993
893
|
li: { ul: true, ol: true, UL: true, OL: true },
|
|
994
894
|
LI: { ul: true, ol: true, UL: true, OL: true },
|
|
995
895
|
a: { div: true, DIV: true },
|
|
@@ -1005,55 +905,54 @@ var kElementsClosedByClosing = {
|
|
|
1005
905
|
th: { tr: true, table: true, TR: true, TABLE: true },
|
|
1006
906
|
TH: { tr: true, table: true, TR: true, TABLE: true },
|
|
1007
907
|
};
|
|
1008
|
-
|
|
908
|
+
const frameflag = 'documentfragmentcontainer';
|
|
1009
909
|
/**
|
|
1010
910
|
* Parses HTML and returns a root element
|
|
1011
911
|
* Parse a chuck of HTML source.
|
|
1012
912
|
* @param {string} data html
|
|
1013
913
|
* @return {HTMLElement} root element
|
|
1014
914
|
*/
|
|
1015
|
-
function base_parse(data, options) {
|
|
915
|
+
function base_parse(data, options = {}) {
|
|
1016
916
|
var _a, _b;
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
var elements = options.blockTextElements || {
|
|
917
|
+
const voidTag = new void_tag_1.default((_a = options === null || options === void 0 ? void 0 : options.voidTag) === null || _a === void 0 ? void 0 : _a.closingSlash, (_b = options === null || options === void 0 ? void 0 : options.voidTag) === null || _b === void 0 ? void 0 : _b.tags);
|
|
918
|
+
const elements = options.blockTextElements || {
|
|
1020
919
|
script: true,
|
|
1021
920
|
noscript: true,
|
|
1022
921
|
style: true,
|
|
1023
922
|
pre: true,
|
|
1024
923
|
};
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
924
|
+
const element_names = Object.keys(elements);
|
|
925
|
+
const kBlockTextElements = element_names.map((it) => new RegExp(`^${it}$`, 'i'));
|
|
926
|
+
const kIgnoreElements = element_names.filter((it) => Boolean(elements[it])).map((it) => new RegExp(`^${it}$`, 'i'));
|
|
1028
927
|
function element_should_be_ignore(tag) {
|
|
1029
|
-
return kIgnoreElements.some(
|
|
928
|
+
return kIgnoreElements.some((it) => it.test(tag));
|
|
1030
929
|
}
|
|
1031
930
|
function is_block_text_element(tag) {
|
|
1032
|
-
return kBlockTextElements.some(
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
931
|
+
return kBlockTextElements.some((it) => it.test(tag));
|
|
932
|
+
}
|
|
933
|
+
const createRange = (startPos, endPos) => [startPos - frameFlagOffset, endPos - frameFlagOffset];
|
|
934
|
+
const root = new HTMLElement(null, {}, '', null, [0, data.length], voidTag, options);
|
|
935
|
+
let currentParent = root;
|
|
936
|
+
const stack = [root];
|
|
937
|
+
let lastTextPos = -1;
|
|
938
|
+
let noNestedTagIndex = undefined;
|
|
939
|
+
let match;
|
|
1041
940
|
// https://github.com/taoqf/node-html-parser/issues/38
|
|
1042
|
-
data =
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
941
|
+
data = `<${frameflag}>${data}</${frameflag}>`;
|
|
942
|
+
const { lowerCaseTagName, fixNestedATags } = options;
|
|
943
|
+
const dataEndPos = data.length - (frameflag.length + 2);
|
|
944
|
+
const frameFlagOffset = frameflag.length + 2;
|
|
1046
945
|
while ((match = kMarkupPattern.exec(data))) {
|
|
1047
946
|
// Note: Object destructuring here consistently tests as higher performance than array destructuring
|
|
1048
947
|
// eslint-disable-next-line prefer-const
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
948
|
+
let { 0: matchText, 1: leadingSlash, 2: tagName, 3: attributes, 4: closingSlash } = match;
|
|
949
|
+
const matchLength = matchText.length;
|
|
950
|
+
const tagStartPos = kMarkupPattern.lastIndex - matchLength;
|
|
951
|
+
const tagEndPos = kMarkupPattern.lastIndex;
|
|
1053
952
|
// Add TextNode if content
|
|
1054
953
|
if (lastTextPos > -1) {
|
|
1055
954
|
if (lastTextPos + matchLength < tagEndPos) {
|
|
1056
|
-
|
|
955
|
+
const text = data.substring(lastTextPos, tagStartPos);
|
|
1057
956
|
currentParent.appendChild(new text_1.default(text, currentParent, createRange(lastTextPos, tagStartPos)));
|
|
1058
957
|
}
|
|
1059
958
|
}
|
|
@@ -1066,7 +965,7 @@ function base_parse(data, options) {
|
|
|
1066
965
|
if (matchText[1] === '!') {
|
|
1067
966
|
if (options.comment) {
|
|
1068
967
|
// Only keep what is in between <!-- and -->
|
|
1069
|
-
|
|
968
|
+
const text = data.substring(tagStartPos + 4, tagEndPos - 3);
|
|
1070
969
|
currentParent.appendChild(new comment_1.default(text, currentParent, createRange(tagStartPos, tagEndPos)));
|
|
1071
970
|
}
|
|
1072
971
|
continue;
|
|
@@ -1078,13 +977,13 @@ function base_parse(data, options) {
|
|
|
1078
977
|
// Handle opening tags (ie. <this> not </that>)
|
|
1079
978
|
if (!leadingSlash) {
|
|
1080
979
|
/* Populate attributes */
|
|
1081
|
-
|
|
1082
|
-
for (
|
|
1083
|
-
|
|
1084
|
-
|
|
980
|
+
const attrs = {};
|
|
981
|
+
for (let attMatch; (attMatch = kAttributePattern.exec(attributes));) {
|
|
982
|
+
const { 1: key, 2: val } = attMatch;
|
|
983
|
+
const isQuoted = val[0] === `'` || val[0] === `"`;
|
|
1085
984
|
attrs[key.toLowerCase()] = isQuoted ? val.slice(1, val.length - 1) : val;
|
|
1086
985
|
}
|
|
1087
|
-
|
|
986
|
+
const parentTagName = currentParent.rawTagName;
|
|
1088
987
|
if (!closingSlash && kElementsClosedByOpening[parentTagName]) {
|
|
1089
988
|
if (kElementsClosedByOpening[parentTagName][tagName]) {
|
|
1090
989
|
stack.pop();
|
|
@@ -1099,23 +998,23 @@ function base_parse(data, options) {
|
|
|
1099
998
|
}
|
|
1100
999
|
noNestedTagIndex = stack.length;
|
|
1101
1000
|
}
|
|
1102
|
-
|
|
1103
|
-
|
|
1001
|
+
const tagEndPos = kMarkupPattern.lastIndex;
|
|
1002
|
+
const tagStartPos = tagEndPos - matchLength;
|
|
1104
1003
|
currentParent = currentParent.appendChild(
|
|
1105
1004
|
// Initialize range (end position updated later for closed tags)
|
|
1106
|
-
new HTMLElement(tagName, attrs, attributes.slice(1), null, createRange(
|
|
1005
|
+
new HTMLElement(tagName, attrs, attributes.slice(1), null, createRange(tagStartPos, tagEndPos), voidTag, options));
|
|
1107
1006
|
stack.push(currentParent);
|
|
1108
1007
|
if (is_block_text_element(tagName)) {
|
|
1109
1008
|
// Find closing tag
|
|
1110
|
-
|
|
1111
|
-
|
|
1009
|
+
const closeMarkup = `</${tagName}>`;
|
|
1010
|
+
const closeIndex = lowerCaseTagName
|
|
1112
1011
|
? data.toLocaleLowerCase().indexOf(closeMarkup, kMarkupPattern.lastIndex)
|
|
1113
1012
|
: data.indexOf(closeMarkup, kMarkupPattern.lastIndex);
|
|
1114
|
-
|
|
1013
|
+
const textEndPos = closeIndex === -1 ? dataEndPos : closeIndex;
|
|
1115
1014
|
if (element_should_be_ignore(tagName)) {
|
|
1116
|
-
|
|
1015
|
+
const text = data.substring(tagEndPos, textEndPos);
|
|
1117
1016
|
if (text.length > 0 && /\S/.test(text)) {
|
|
1118
|
-
currentParent.appendChild(new text_1.default(text, currentParent, createRange(
|
|
1017
|
+
currentParent.appendChild(new text_1.default(text, currentParent, createRange(tagEndPos, textEndPos)));
|
|
1119
1018
|
}
|
|
1120
1019
|
}
|
|
1121
1020
|
if (closeIndex === -1) {
|
|
@@ -1141,7 +1040,7 @@ function base_parse(data, options) {
|
|
|
1141
1040
|
break;
|
|
1142
1041
|
}
|
|
1143
1042
|
else {
|
|
1144
|
-
|
|
1043
|
+
const parentTagName = currentParent.tagName;
|
|
1145
1044
|
// Trying to close current tag, and move on
|
|
1146
1045
|
if (kElementsClosedByClosing[parentTagName]) {
|
|
1147
1046
|
if (kElementsClosedByClosing[parentTagName][tagName]) {
|
|
@@ -1163,21 +1062,20 @@ exports.base_parse = base_parse;
|
|
|
1163
1062
|
* Parses HTML and returns a root element
|
|
1164
1063
|
* Parse a chuck of HTML source.
|
|
1165
1064
|
*/
|
|
1166
|
-
function parse(data, options) {
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
var _loop_1 = function () {
|
|
1065
|
+
function parse(data, options = {}) {
|
|
1066
|
+
const stack = base_parse(data, options);
|
|
1067
|
+
const [root] = stack;
|
|
1068
|
+
while (stack.length > 1) {
|
|
1171
1069
|
// Handle each error elements.
|
|
1172
|
-
|
|
1173
|
-
|
|
1070
|
+
const last = stack.pop();
|
|
1071
|
+
const oneBefore = (0, back_1.default)(stack);
|
|
1174
1072
|
if (last.parentNode && last.parentNode.parentNode) {
|
|
1175
1073
|
if (last.parentNode === oneBefore && last.tagName === oneBefore.tagName) {
|
|
1176
1074
|
// Pair error case <h3> <h3> handle : Fixes to <h3> </h3>
|
|
1177
1075
|
// this is wrong, becouse this will put the H3 outside the current right position which should be inside the current Html Element, see issue 152 for more info
|
|
1178
1076
|
if (options.parseNoneClosedTags !== true) {
|
|
1179
1077
|
oneBefore.removeChild(last);
|
|
1180
|
-
last.childNodes.forEach(
|
|
1078
|
+
last.childNodes.forEach((child) => {
|
|
1181
1079
|
oneBefore.parentNode.appendChild(child);
|
|
1182
1080
|
});
|
|
1183
1081
|
stack.pop();
|
|
@@ -1189,7 +1087,7 @@ function parse(data, options) {
|
|
|
1189
1087
|
// eslint-disable-next-line no-lonely-if
|
|
1190
1088
|
if (options.parseNoneClosedTags !== true) {
|
|
1191
1089
|
oneBefore.removeChild(last);
|
|
1192
|
-
last.childNodes.forEach(
|
|
1090
|
+
last.childNodes.forEach((child) => {
|
|
1193
1091
|
oneBefore.appendChild(child);
|
|
1194
1092
|
});
|
|
1195
1093
|
}
|
|
@@ -1198,9 +1096,6 @@ function parse(data, options) {
|
|
|
1198
1096
|
else {
|
|
1199
1097
|
// If it's final element just skip.
|
|
1200
1098
|
}
|
|
1201
|
-
};
|
|
1202
|
-
while (stack.length > 1) {
|
|
1203
|
-
_loop_1();
|
|
1204
1099
|
}
|
|
1205
1100
|
// response.childNodes.forEach((node) => {
|
|
1206
1101
|
// if (node instanceof HTMLElement) {
|
|
@@ -1210,8 +1105,21 @@ function parse(data, options) {
|
|
|
1210
1105
|
return root;
|
|
1211
1106
|
}
|
|
1212
1107
|
exports.parse = parse;
|
|
1108
|
+
/**
|
|
1109
|
+
* Resolves a list of {@link NodeInsertable} to a list of nodes,
|
|
1110
|
+
* and removes nodes from any potential parent.
|
|
1111
|
+
*/
|
|
1112
|
+
function resolveInsertable(insertable) {
|
|
1113
|
+
return insertable.map((val) => {
|
|
1114
|
+
if (typeof val === 'string') {
|
|
1115
|
+
return new text_1.default(val);
|
|
1116
|
+
}
|
|
1117
|
+
val.remove();
|
|
1118
|
+
return val;
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1213
1121
|
function resetParent(nodes, parent) {
|
|
1214
|
-
return nodes.map(
|
|
1122
|
+
return nodes.map((node) => {
|
|
1215
1123
|
node.parentNode = parent;
|
|
1216
1124
|
return node;
|
|
1217
1125
|
});
|