node-html-parser 6.1.15-0 → 7.0.2
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 +33 -0
- package/README.md +5 -6
- package/dist/index.js +8 -9
- package/dist/main.js +70 -26
- package/dist/matcher.js +26 -26
- package/dist/nodes/comment.js +22 -46
- package/dist/nodes/html.d.ts +3 -1
- package/dist/nodes/html.js +579 -725
- 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 +3 -2
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,279 +116,226 @@ 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
|
-
|
|
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
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
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
|
+
get id() {
|
|
189
|
+
return this._id;
|
|
190
|
+
}
|
|
191
|
+
set id(newid) {
|
|
192
|
+
this.setAttribute('id', newid);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get escpaed (as-it) text value of current node and its children.
|
|
196
|
+
* @return {string} text content
|
|
197
|
+
*/
|
|
198
|
+
get rawText() {
|
|
199
|
+
// https://github.com/taoqf/node-html-parser/issues/249
|
|
200
|
+
if (/^br$/i.test(this.rawTagName)) {
|
|
201
|
+
return '\n';
|
|
202
|
+
}
|
|
203
|
+
return this.childNodes.reduce((pre, cur) => {
|
|
204
|
+
return (pre += cur.rawText);
|
|
205
|
+
}, '');
|
|
206
|
+
}
|
|
207
|
+
get textContent() {
|
|
208
|
+
return decode(this.rawText);
|
|
209
|
+
}
|
|
210
|
+
set textContent(val) {
|
|
211
|
+
const content = [new text_1.default(val, this)];
|
|
212
|
+
this.childNodes = content;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Get unescaped text value of current node and its children.
|
|
216
|
+
* @return {string} text content
|
|
217
|
+
*/
|
|
218
|
+
get text() {
|
|
219
|
+
return decode(this.rawText);
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Get structured Text (with '\n' etc.)
|
|
223
|
+
* @return {string} structured text
|
|
224
|
+
*/
|
|
225
|
+
get structuredText() {
|
|
226
|
+
let currentBlock = [];
|
|
227
|
+
const blocks = [currentBlock];
|
|
228
|
+
function dfs(node) {
|
|
229
|
+
if (node.nodeType === type_1.default.ELEMENT_NODE) {
|
|
230
|
+
if (kBlockElements.has(node.rawTagName)) {
|
|
231
|
+
if (currentBlock.length > 0) {
|
|
232
|
+
blocks.push((currentBlock = []));
|
|
311
233
|
}
|
|
312
|
-
|
|
313
|
-
|
|
234
|
+
node.childNodes.forEach(dfs);
|
|
235
|
+
if (currentBlock.length > 0) {
|
|
236
|
+
blocks.push((currentBlock = []));
|
|
314
237
|
}
|
|
315
238
|
}
|
|
316
|
-
else
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
239
|
+
else {
|
|
240
|
+
node.childNodes.forEach(dfs);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
else if (node.nodeType === type_1.default.TEXT_NODE) {
|
|
244
|
+
if (node.isWhitespace) {
|
|
245
|
+
// Whitespace node, postponed output
|
|
246
|
+
currentBlock.prependWhitespace = true;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
let text = node.trimmedText;
|
|
250
|
+
if (currentBlock.prependWhitespace) {
|
|
251
|
+
text = ` ${text}`;
|
|
252
|
+
currentBlock.prependWhitespace = false;
|
|
328
253
|
}
|
|
254
|
+
currentBlock.push(text);
|
|
329
255
|
}
|
|
330
256
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
})
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
HTMLElement.prototype.toString = function () {
|
|
343
|
-
var tag = this.rawTagName;
|
|
257
|
+
}
|
|
258
|
+
dfs(this);
|
|
259
|
+
return blocks
|
|
260
|
+
.map((block) => {
|
|
261
|
+
return block.join('').replace(/\s{2,}/g, ' '); // Normalize each line's whitespace
|
|
262
|
+
})
|
|
263
|
+
.join('\n')
|
|
264
|
+
.replace(/\s+$/, ''); // trimRight;
|
|
265
|
+
}
|
|
266
|
+
toString() {
|
|
267
|
+
const tag = this.rawTagName;
|
|
344
268
|
if (tag) {
|
|
345
|
-
|
|
269
|
+
const attrs = this.rawAttrs ? ` ${this.rawAttrs}` : '';
|
|
346
270
|
return this.voidTag.formatNode(tag, attrs, this.innerHTML);
|
|
347
271
|
}
|
|
348
272
|
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 = {}; }
|
|
273
|
+
}
|
|
274
|
+
get innerHTML() {
|
|
275
|
+
return this.childNodes
|
|
276
|
+
.map((child) => {
|
|
277
|
+
return child.toString();
|
|
278
|
+
})
|
|
279
|
+
.join('');
|
|
280
|
+
}
|
|
281
|
+
set innerHTML(content) {
|
|
282
|
+
const r = parse(content, this._parseOptions);
|
|
283
|
+
const nodes = r.childNodes.length ? r.childNodes : [new text_1.default(content, this)];
|
|
284
|
+
resetParent(nodes, this);
|
|
285
|
+
resetParent(this.childNodes, null);
|
|
286
|
+
this.childNodes = nodes;
|
|
287
|
+
}
|
|
288
|
+
set_content(content, options = {}) {
|
|
370
289
|
if (content instanceof node_1.default) {
|
|
371
290
|
content = [content];
|
|
372
291
|
}
|
|
373
292
|
else if (typeof content == 'string') {
|
|
374
|
-
options =
|
|
375
|
-
|
|
293
|
+
options = Object.assign(Object.assign({}, this._parseOptions), options);
|
|
294
|
+
const r = parse(content, options);
|
|
376
295
|
content = r.childNodes.length ? r.childNodes : [new text_1.default(r.innerHTML, this)];
|
|
377
296
|
}
|
|
378
297
|
resetParent(this.childNodes, null);
|
|
379
298
|
resetParent(content, this);
|
|
380
299
|
this.childNodes = content;
|
|
381
300
|
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) {
|
|
301
|
+
}
|
|
302
|
+
replaceWith(...nodes) {
|
|
303
|
+
const parent = this.parentNode;
|
|
304
|
+
const content = nodes
|
|
305
|
+
.map((node) => {
|
|
392
306
|
if (node instanceof node_1.default) {
|
|
393
307
|
return [node];
|
|
394
308
|
}
|
|
395
309
|
else if (typeof node == 'string') {
|
|
396
|
-
|
|
397
|
-
return r.childNodes.length ? r.childNodes : [new text_1.default(node,
|
|
310
|
+
const r = parse(node, this._parseOptions);
|
|
311
|
+
return r.childNodes.length ? r.childNodes : [new text_1.default(node, this)];
|
|
398
312
|
}
|
|
399
313
|
return [];
|
|
400
314
|
})
|
|
401
315
|
.flat();
|
|
402
|
-
|
|
403
|
-
return child ===
|
|
316
|
+
const idx = parent.childNodes.findIndex((child) => {
|
|
317
|
+
return child === this;
|
|
404
318
|
});
|
|
405
319
|
resetParent([this], null);
|
|
406
|
-
resetParent(content, parent);
|
|
407
|
-
parent.childNodes = __spreadArray(__spreadArray(__spreadArray([], parent.childNodes.slice(0, idx), true), content, true), parent.childNodes.slice(idx + 1), true);
|
|
320
|
+
parent.childNodes = [...parent.childNodes.slice(0, idx), ...resetParent(content, parent), ...parent.childNodes.slice(idx + 1)];
|
|
408
321
|
return this;
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
},
|
|
414
|
-
enumerable: false,
|
|
415
|
-
configurable: true
|
|
416
|
-
});
|
|
322
|
+
}
|
|
323
|
+
get outerHTML() {
|
|
324
|
+
return this.toString();
|
|
325
|
+
}
|
|
417
326
|
/**
|
|
418
327
|
* Trim element from right (in block) after seeing pattern in a TextNode.
|
|
419
328
|
* @param {RegExp} pattern pattern to find
|
|
420
329
|
* @return {HTMLElement} reference to current node
|
|
421
330
|
*/
|
|
422
|
-
|
|
423
|
-
for (
|
|
424
|
-
|
|
331
|
+
trimRight(pattern) {
|
|
332
|
+
for (let i = 0; i < this.childNodes.length; i++) {
|
|
333
|
+
const childNode = this.childNodes[i];
|
|
425
334
|
if (childNode.nodeType === type_1.default.ELEMENT_NODE) {
|
|
426
335
|
childNode.trimRight(pattern);
|
|
427
336
|
}
|
|
428
337
|
else {
|
|
429
|
-
|
|
338
|
+
const index = childNode.rawText.search(pattern);
|
|
430
339
|
if (index > -1) {
|
|
431
340
|
childNode.rawText = childNode.rawText.substr(0, index);
|
|
432
341
|
// trim all following nodes.
|
|
@@ -435,49 +344,44 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
435
344
|
}
|
|
436
345
|
}
|
|
437
346
|
return this;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
write('#text');
|
|
462
|
-
}
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Get DOM structure
|
|
350
|
+
* @return {string} structure
|
|
351
|
+
*/
|
|
352
|
+
get structure() {
|
|
353
|
+
const res = [];
|
|
354
|
+
let indention = 0;
|
|
355
|
+
function write(str) {
|
|
356
|
+
res.push(' '.repeat(indention) + str);
|
|
357
|
+
}
|
|
358
|
+
function dfs(node) {
|
|
359
|
+
const idStr = node._id ? `#${node._id}` : '';
|
|
360
|
+
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
|
|
361
|
+
write(`${node.rawTagName}${idStr}${classStr}`);
|
|
362
|
+
indention++;
|
|
363
|
+
node.childNodes.forEach((childNode) => {
|
|
364
|
+
if (childNode.nodeType === type_1.default.ELEMENT_NODE) {
|
|
365
|
+
dfs(childNode);
|
|
366
|
+
}
|
|
367
|
+
else if (childNode.nodeType === type_1.default.TEXT_NODE) {
|
|
368
|
+
if (!childNode.isWhitespace) {
|
|
369
|
+
write('#text');
|
|
463
370
|
}
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
configurable: true
|
|
472
|
-
});
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
indention--;
|
|
374
|
+
}
|
|
375
|
+
dfs(this);
|
|
376
|
+
return res.join('\n');
|
|
377
|
+
}
|
|
473
378
|
/**
|
|
474
379
|
* Remove whitespaces in this sub tree.
|
|
475
380
|
* @return {HTMLElement} pointer to this
|
|
476
381
|
*/
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
this.childNodes.forEach(function (node) {
|
|
382
|
+
removeWhitespace() {
|
|
383
|
+
let o = 0;
|
|
384
|
+
this.childNodes.forEach((node) => {
|
|
481
385
|
if (node.nodeType === type_1.default.TEXT_NODE) {
|
|
482
386
|
if (node.isWhitespace) {
|
|
483
387
|
return;
|
|
@@ -487,54 +391,56 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
487
391
|
else if (node.nodeType === type_1.default.ELEMENT_NODE) {
|
|
488
392
|
node.removeWhitespace();
|
|
489
393
|
}
|
|
490
|
-
|
|
394
|
+
this.childNodes[o++] = node;
|
|
491
395
|
});
|
|
492
396
|
this.childNodes.length = o;
|
|
493
397
|
// remove whitespace between attributes
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
398
|
+
const attrs = Object.keys(this.rawAttributes)
|
|
399
|
+
.map((key) => {
|
|
400
|
+
const val = this.rawAttributes[key];
|
|
401
|
+
return `${key}=${JSON.stringify(val)}`;
|
|
402
|
+
})
|
|
403
|
+
.join(' ');
|
|
498
404
|
this.rawAttrs = attrs;
|
|
499
405
|
delete this._rawAttrs;
|
|
500
406
|
return this;
|
|
501
|
-
}
|
|
407
|
+
}
|
|
502
408
|
/**
|
|
503
409
|
* Query CSS selector to find matching nodes.
|
|
504
410
|
* @param {string} selector Simplified CSS selector
|
|
505
411
|
* @return {HTMLElement[]} matching elements
|
|
506
412
|
*/
|
|
507
|
-
|
|
413
|
+
querySelectorAll(selector) {
|
|
508
414
|
return (0, css_select_1.selectAll)(selector, this, {
|
|
509
415
|
xmlMode: true,
|
|
510
416
|
adapter: matcher_1.default,
|
|
511
417
|
});
|
|
512
|
-
}
|
|
418
|
+
}
|
|
513
419
|
/**
|
|
514
420
|
* Query CSS Selector to find matching node.
|
|
515
421
|
* @param {string} selector Simplified CSS selector
|
|
516
422
|
* @return {(HTMLElement|null)} matching node
|
|
517
423
|
*/
|
|
518
|
-
|
|
424
|
+
querySelector(selector) {
|
|
519
425
|
return (0, css_select_1.selectOne)(selector, this, {
|
|
520
426
|
xmlMode: true,
|
|
521
427
|
adapter: matcher_1.default,
|
|
522
428
|
});
|
|
523
|
-
}
|
|
429
|
+
}
|
|
524
430
|
/**
|
|
525
431
|
* find elements by their tagName
|
|
526
432
|
* @param {string} tagName the tagName of the elements to select
|
|
527
433
|
*/
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
434
|
+
getElementsByTagName(tagName) {
|
|
435
|
+
const upperCasedTagName = tagName.toUpperCase();
|
|
436
|
+
const re = [];
|
|
437
|
+
const stack = [];
|
|
438
|
+
let currentNodeReference = this;
|
|
439
|
+
let index = 0;
|
|
534
440
|
// index turns to undefined once the stack is empty and the first condition occurs
|
|
535
441
|
// which happens once all relevant children are searched through
|
|
536
442
|
while (index !== undefined) {
|
|
537
|
-
|
|
443
|
+
let child;
|
|
538
444
|
// make it work with sparse arrays
|
|
539
445
|
do {
|
|
540
446
|
child = currentNodeReference.childNodes[index++];
|
|
@@ -558,20 +464,20 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
558
464
|
}
|
|
559
465
|
}
|
|
560
466
|
return re;
|
|
561
|
-
}
|
|
467
|
+
}
|
|
562
468
|
/**
|
|
563
469
|
* find element by it's id
|
|
564
470
|
* @param {string} id the id of the element to select
|
|
565
471
|
* @returns {HTMLElement | null} the element with the given id or null if not found
|
|
566
472
|
*/
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
473
|
+
getElementById(id) {
|
|
474
|
+
const stack = [];
|
|
475
|
+
let currentNodeReference = this;
|
|
476
|
+
let index = 0;
|
|
571
477
|
// index turns to undefined once the stack is empty and the first condition occurs
|
|
572
478
|
// which happens once all relevant children are searched through
|
|
573
479
|
while (index !== undefined) {
|
|
574
|
-
|
|
480
|
+
let child;
|
|
575
481
|
// make it work with sparse arrays
|
|
576
482
|
do {
|
|
577
483
|
child = currentNodeReference.childNodes[index++];
|
|
@@ -583,10 +489,9 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
583
489
|
continue;
|
|
584
490
|
}
|
|
585
491
|
if (child.nodeType === type_1.default.ELEMENT_NODE) {
|
|
586
|
-
if (child.
|
|
492
|
+
if (child._id === id) {
|
|
587
493
|
return child;
|
|
588
494
|
}
|
|
589
|
-
;
|
|
590
495
|
// if children are existing push the current status to the stack and keep searching for elements in the level below
|
|
591
496
|
if (child.childNodes.length > 0) {
|
|
592
497
|
stack.push(index);
|
|
@@ -596,25 +501,25 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
596
501
|
}
|
|
597
502
|
}
|
|
598
503
|
return null;
|
|
599
|
-
}
|
|
504
|
+
}
|
|
600
505
|
/**
|
|
601
506
|
* 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.
|
|
602
507
|
* @param selector a DOMString containing a selector list
|
|
603
508
|
* @returns {HTMLElement | null} the element with the given id or null if not found
|
|
604
509
|
*/
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
510
|
+
closest(selector) {
|
|
511
|
+
const mapChild = new Map();
|
|
512
|
+
let el = this;
|
|
513
|
+
let old = null;
|
|
609
514
|
function findOne(test, elems) {
|
|
610
|
-
|
|
611
|
-
for (
|
|
612
|
-
|
|
613
|
-
if (test(
|
|
614
|
-
elem =
|
|
515
|
+
let elem = null;
|
|
516
|
+
for (let i = 0, l = elems.length; i < l && !elem; i++) {
|
|
517
|
+
const el = elems[i];
|
|
518
|
+
if (test(el)) {
|
|
519
|
+
elem = el;
|
|
615
520
|
}
|
|
616
521
|
else {
|
|
617
|
-
|
|
522
|
+
const child = mapChild.get(el);
|
|
618
523
|
if (child) {
|
|
619
524
|
elem = findOne(test, [child]);
|
|
620
525
|
}
|
|
@@ -629,14 +534,17 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
629
534
|
}
|
|
630
535
|
el = this;
|
|
631
536
|
while (el) {
|
|
632
|
-
|
|
537
|
+
const e = (0, css_select_1.selectOne)(selector, el, {
|
|
633
538
|
xmlMode: true,
|
|
634
|
-
adapter:
|
|
635
|
-
|
|
539
|
+
adapter: Object.assign(Object.assign({}, matcher_1.default), { getChildren(node) {
|
|
540
|
+
const child = mapChild.get(node);
|
|
636
541
|
return child && [child];
|
|
637
|
-
},
|
|
542
|
+
},
|
|
543
|
+
getSiblings(node) {
|
|
638
544
|
return [node];
|
|
639
|
-
},
|
|
545
|
+
},
|
|
546
|
+
findOne,
|
|
547
|
+
findAll() {
|
|
640
548
|
return [];
|
|
641
549
|
} }),
|
|
642
550
|
});
|
|
@@ -646,80 +554,67 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
646
554
|
el = el.parentNode;
|
|
647
555
|
}
|
|
648
556
|
return null;
|
|
649
|
-
}
|
|
557
|
+
}
|
|
650
558
|
/**
|
|
651
559
|
* Append a child node to childNodes
|
|
652
560
|
* @param {Node} node node to append
|
|
653
561
|
* @return {Node} node appended
|
|
654
562
|
*/
|
|
655
|
-
|
|
563
|
+
appendChild(node) {
|
|
656
564
|
this.append(node);
|
|
657
565
|
return node;
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
if (this._attrs) {
|
|
667
|
-
return this._attrs;
|
|
668
|
-
}
|
|
669
|
-
this._attrs = {};
|
|
670
|
-
var attrs = this.rawAttributes;
|
|
671
|
-
for (var key in attrs) {
|
|
672
|
-
var val = attrs[key] || '';
|
|
673
|
-
this._attrs[key.toLowerCase()] = decode(val);
|
|
674
|
-
}
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Get attributes
|
|
569
|
+
* @access private
|
|
570
|
+
* @return {Object} parsed and unescaped attributes
|
|
571
|
+
*/
|
|
572
|
+
get attrs() {
|
|
573
|
+
if (this._attrs) {
|
|
675
574
|
return this._attrs;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
}
|
|
575
|
+
}
|
|
576
|
+
this._attrs = {};
|
|
577
|
+
const attrs = this.rawAttributes;
|
|
578
|
+
for (const key in attrs) {
|
|
579
|
+
const val = attrs[key] || '';
|
|
580
|
+
this._attrs[key.toLowerCase()] = decode(val);
|
|
581
|
+
}
|
|
582
|
+
return this._attrs;
|
|
583
|
+
}
|
|
584
|
+
get attributes() {
|
|
585
|
+
const ret_attrs = {};
|
|
586
|
+
const attrs = this.rawAttributes;
|
|
587
|
+
for (const key in attrs) {
|
|
588
|
+
const val = attrs[key] || '';
|
|
589
|
+
ret_attrs[key] = decode(val);
|
|
590
|
+
}
|
|
591
|
+
return ret_attrs;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Get escaped (as-is) attributes
|
|
595
|
+
* @return {Object} parsed attributes
|
|
596
|
+
*/
|
|
597
|
+
get rawAttributes() {
|
|
598
|
+
if (this._rawAttrs) {
|
|
599
|
+
return this._rawAttrs;
|
|
600
|
+
}
|
|
601
|
+
const attrs = {};
|
|
602
|
+
if (this.rawAttrs) {
|
|
603
|
+
const re = /([a-zA-Z()[\]#@$.?:][a-zA-Z0-9-._:()[\]#]*)(?:\s*=\s*((?:'[^']*')|(?:"[^"]*")|\S+))?/g;
|
|
604
|
+
let match;
|
|
605
|
+
while ((match = re.exec(this.rawAttrs))) {
|
|
606
|
+
const key = match[1];
|
|
607
|
+
let val = match[2] || null;
|
|
608
|
+
if (val && (val[0] === `'` || val[0] === `"`))
|
|
609
|
+
val = val.slice(1, val.length - 1);
|
|
610
|
+
attrs[key] = attrs[key] || val;
|
|
713
611
|
}
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
HTMLElement.prototype.removeAttribute = function (key) {
|
|
721
|
-
var _this = this;
|
|
722
|
-
var attrs = this.rawAttributes;
|
|
612
|
+
}
|
|
613
|
+
this._rawAttrs = attrs;
|
|
614
|
+
return attrs;
|
|
615
|
+
}
|
|
616
|
+
removeAttribute(key) {
|
|
617
|
+
const attrs = this.rawAttributes;
|
|
723
618
|
delete attrs[key];
|
|
724
619
|
// Update this.attribute
|
|
725
620
|
if (this._attrs) {
|
|
@@ -727,42 +622,41 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
727
622
|
}
|
|
728
623
|
// Update rawString
|
|
729
624
|
this.rawAttrs = Object.keys(attrs)
|
|
730
|
-
.map(
|
|
731
|
-
|
|
625
|
+
.map((name) => {
|
|
626
|
+
const val = this.quoteAttribute(attrs[name]);
|
|
732
627
|
if (val === 'null' || val === '""')
|
|
733
628
|
return name;
|
|
734
|
-
return
|
|
629
|
+
return `${name}=${val}`;
|
|
735
630
|
})
|
|
736
631
|
.join(' ');
|
|
737
|
-
// Update this.
|
|
632
|
+
// Update this._id
|
|
738
633
|
if (key === 'id') {
|
|
739
|
-
this.
|
|
634
|
+
this._id = '';
|
|
740
635
|
}
|
|
741
636
|
return this;
|
|
742
|
-
}
|
|
743
|
-
|
|
637
|
+
}
|
|
638
|
+
hasAttribute(key) {
|
|
744
639
|
return key.toLowerCase() in this.attrs;
|
|
745
|
-
}
|
|
640
|
+
}
|
|
746
641
|
/**
|
|
747
642
|
* Get an attribute
|
|
748
643
|
* @return {string | undefined} value of the attribute; or undefined if not exist
|
|
749
644
|
*/
|
|
750
|
-
|
|
645
|
+
getAttribute(key) {
|
|
751
646
|
return this.attrs[key.toLowerCase()];
|
|
752
|
-
}
|
|
647
|
+
}
|
|
753
648
|
/**
|
|
754
649
|
* Set an attribute value to the HTMLElement
|
|
755
650
|
* @param {string} key The attribute name
|
|
756
651
|
* @param {string} value The value to set, or null / undefined to remove an attribute
|
|
757
652
|
*/
|
|
758
|
-
|
|
759
|
-
var _this = this;
|
|
653
|
+
setAttribute(key, value) {
|
|
760
654
|
if (arguments.length < 2) {
|
|
761
655
|
throw new Error("Failed to execute 'setAttribute' on 'Element'");
|
|
762
656
|
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
for (
|
|
657
|
+
const k2 = key.toLowerCase();
|
|
658
|
+
const attrs = this.rawAttributes;
|
|
659
|
+
for (const k in attrs) {
|
|
766
660
|
if (k.toLowerCase() === k2) {
|
|
767
661
|
key = k;
|
|
768
662
|
break;
|
|
@@ -775,25 +669,24 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
775
669
|
}
|
|
776
670
|
// Update rawString
|
|
777
671
|
this.rawAttrs = Object.keys(attrs)
|
|
778
|
-
.map(
|
|
779
|
-
|
|
672
|
+
.map((name) => {
|
|
673
|
+
const val = this.quoteAttribute(attrs[name]);
|
|
780
674
|
if (val === 'null' || val === '""')
|
|
781
675
|
return name;
|
|
782
|
-
return
|
|
676
|
+
return `${name}=${val}`;
|
|
783
677
|
})
|
|
784
678
|
.join(' ');
|
|
785
|
-
// Update this.
|
|
679
|
+
// Update this._id
|
|
786
680
|
if (key === 'id') {
|
|
787
|
-
this.
|
|
681
|
+
this._id = value;
|
|
788
682
|
}
|
|
789
683
|
return this;
|
|
790
|
-
}
|
|
684
|
+
}
|
|
791
685
|
/**
|
|
792
686
|
* Replace all the attributes of the HTMLElement by the provided attributes
|
|
793
687
|
* @param {Attributes} attributes the new attribute set
|
|
794
688
|
*/
|
|
795
|
-
|
|
796
|
-
var _this = this;
|
|
689
|
+
setAttributes(attributes) {
|
|
797
690
|
// Invalidate current this.attributes
|
|
798
691
|
if (this._attrs) {
|
|
799
692
|
delete this._attrs;
|
|
@@ -804,243 +697,185 @@ var HTMLElement = /** @class */ (function (_super) {
|
|
|
804
697
|
}
|
|
805
698
|
// Update rawString
|
|
806
699
|
this.rawAttrs = Object.keys(attributes)
|
|
807
|
-
.map(
|
|
808
|
-
|
|
700
|
+
.map((name) => {
|
|
701
|
+
const val = attributes[name];
|
|
809
702
|
if (val === 'null' || val === '""')
|
|
810
703
|
return name;
|
|
811
|
-
return
|
|
704
|
+
return `${name}=${this.quoteAttribute(String(val))}`;
|
|
812
705
|
})
|
|
813
706
|
.join(' ');
|
|
707
|
+
// Update this._id
|
|
708
|
+
if ('id' in attributes) {
|
|
709
|
+
this._id = attributes['id'];
|
|
710
|
+
}
|
|
814
711
|
return this;
|
|
815
|
-
}
|
|
816
|
-
|
|
712
|
+
}
|
|
713
|
+
insertAdjacentHTML(where, html) {
|
|
817
714
|
if (arguments.length < 2) {
|
|
818
715
|
throw new Error('2 arguments required');
|
|
819
716
|
}
|
|
820
|
-
|
|
717
|
+
const p = parse(html, this._parseOptions);
|
|
821
718
|
if (where === 'afterend') {
|
|
822
|
-
this.after
|
|
719
|
+
this.after(...p.childNodes);
|
|
823
720
|
}
|
|
824
721
|
else if (where === 'afterbegin') {
|
|
825
|
-
this.prepend
|
|
722
|
+
this.prepend(...p.childNodes);
|
|
826
723
|
}
|
|
827
724
|
else if (where === 'beforeend') {
|
|
828
|
-
this.append
|
|
725
|
+
this.append(...p.childNodes);
|
|
829
726
|
}
|
|
830
727
|
else if (where === 'beforebegin') {
|
|
831
|
-
this.before
|
|
728
|
+
this.before(...p.childNodes);
|
|
832
729
|
}
|
|
833
730
|
else {
|
|
834
|
-
throw new Error(
|
|
731
|
+
throw new Error(`The value provided ('${where}') is not one of 'beforebegin', 'afterbegin', 'beforeend', or 'afterend'`);
|
|
835
732
|
}
|
|
836
733
|
return this;
|
|
837
|
-
}
|
|
734
|
+
}
|
|
838
735
|
/** Prepend nodes or strings to this node's children. */
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
var insertable = [];
|
|
842
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
843
|
-
insertable[_i] = arguments[_i];
|
|
844
|
-
}
|
|
845
|
-
var nodes = resolveInsertable(insertable);
|
|
736
|
+
prepend(...insertable) {
|
|
737
|
+
const nodes = resolveInsertable(insertable);
|
|
846
738
|
resetParent(nodes, this);
|
|
847
|
-
|
|
848
|
-
}
|
|
739
|
+
this.childNodes.unshift(...nodes);
|
|
740
|
+
}
|
|
849
741
|
/** Append nodes or strings to this node's children. */
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
var insertable = [];
|
|
853
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
854
|
-
insertable[_i] = arguments[_i];
|
|
855
|
-
}
|
|
856
|
-
var nodes = resolveInsertable(insertable);
|
|
742
|
+
append(...insertable) {
|
|
743
|
+
const nodes = resolveInsertable(insertable);
|
|
857
744
|
resetParent(nodes, this);
|
|
858
|
-
|
|
859
|
-
}
|
|
745
|
+
this.childNodes.push(...nodes);
|
|
746
|
+
}
|
|
860
747
|
/** Insert nodes or strings before this node. */
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
insertable[_i] = arguments[_i];
|
|
865
|
-
}
|
|
866
|
-
var nodes = resolveInsertable(insertable);
|
|
867
|
-
var siblings = this.parentNode.childNodes;
|
|
748
|
+
before(...insertable) {
|
|
749
|
+
const nodes = resolveInsertable(insertable);
|
|
750
|
+
const siblings = this.parentNode.childNodes;
|
|
868
751
|
resetParent(nodes, this.parentNode);
|
|
869
|
-
siblings.splice
|
|
870
|
-
}
|
|
752
|
+
siblings.splice(siblings.indexOf(this), 0, ...nodes);
|
|
753
|
+
}
|
|
871
754
|
/** Insert nodes or strings after this node. */
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
insertable[_i] = arguments[_i];
|
|
876
|
-
}
|
|
877
|
-
var nodes = resolveInsertable(insertable);
|
|
878
|
-
var siblings = this.parentNode.childNodes;
|
|
755
|
+
after(...insertable) {
|
|
756
|
+
const nodes = resolveInsertable(insertable);
|
|
757
|
+
const siblings = this.parentNode.childNodes;
|
|
879
758
|
resetParent(nodes, this.parentNode);
|
|
880
|
-
siblings.splice
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
return children[i] || null;
|
|
891
|
-
}
|
|
892
|
-
return null;
|
|
759
|
+
siblings.splice(siblings.indexOf(this) + 1, 0, ...nodes);
|
|
760
|
+
}
|
|
761
|
+
get nextSibling() {
|
|
762
|
+
if (this.parentNode) {
|
|
763
|
+
const children = this.parentNode.childNodes;
|
|
764
|
+
let i = 0;
|
|
765
|
+
while (i < children.length) {
|
|
766
|
+
const child = children[i++];
|
|
767
|
+
if (this === child)
|
|
768
|
+
return children[i] || null;
|
|
893
769
|
}
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
if (child instanceof HTMLElement) {
|
|
908
|
-
return child || null;
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
else if (this === child) {
|
|
912
|
-
find = true;
|
|
770
|
+
return null;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
get nextElementSibling() {
|
|
774
|
+
if (this.parentNode) {
|
|
775
|
+
const children = this.parentNode.childNodes;
|
|
776
|
+
let i = 0;
|
|
777
|
+
let find = false;
|
|
778
|
+
while (i < children.length) {
|
|
779
|
+
const child = children[i++];
|
|
780
|
+
if (find) {
|
|
781
|
+
if (child instanceof HTMLElement) {
|
|
782
|
+
return child || null;
|
|
913
783
|
}
|
|
914
784
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
},
|
|
918
|
-
enumerable: false,
|
|
919
|
-
configurable: true
|
|
920
|
-
});
|
|
921
|
-
Object.defineProperty(HTMLElement.prototype, "previousSibling", {
|
|
922
|
-
get: function () {
|
|
923
|
-
if (this.parentNode) {
|
|
924
|
-
var children = this.parentNode.childNodes;
|
|
925
|
-
var i = children.length;
|
|
926
|
-
while (i > 0) {
|
|
927
|
-
var child = children[--i];
|
|
928
|
-
if (this === child)
|
|
929
|
-
return children[i - 1] || null;
|
|
785
|
+
else if (this === child) {
|
|
786
|
+
find = true;
|
|
930
787
|
}
|
|
931
|
-
return null;
|
|
932
788
|
}
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
789
|
+
return null;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
get previousSibling() {
|
|
793
|
+
if (this.parentNode) {
|
|
794
|
+
const children = this.parentNode.childNodes;
|
|
795
|
+
let i = children.length;
|
|
796
|
+
while (i > 0) {
|
|
797
|
+
const child = children[--i];
|
|
798
|
+
if (this === child)
|
|
799
|
+
return children[i - 1] || null;
|
|
800
|
+
}
|
|
801
|
+
return null;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
get previousElementSibling() {
|
|
805
|
+
if (this.parentNode) {
|
|
806
|
+
const children = this.parentNode.childNodes;
|
|
807
|
+
let i = children.length;
|
|
808
|
+
let find = false;
|
|
809
|
+
while (i > 0) {
|
|
810
|
+
const child = children[--i];
|
|
811
|
+
if (find) {
|
|
812
|
+
if (child instanceof HTMLElement) {
|
|
813
|
+
return child || null;
|
|
952
814
|
}
|
|
953
815
|
}
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
},
|
|
957
|
-
enumerable: false,
|
|
958
|
-
configurable: true
|
|
959
|
-
});
|
|
960
|
-
Object.defineProperty(HTMLElement.prototype, "children", {
|
|
961
|
-
/** Get all childNodes of type {@link HTMLElement}. */
|
|
962
|
-
get: function () {
|
|
963
|
-
var children = [];
|
|
964
|
-
for (var _i = 0, _a = this.childNodes; _i < _a.length; _i++) {
|
|
965
|
-
var childNode = _a[_i];
|
|
966
|
-
if (childNode instanceof HTMLElement) {
|
|
967
|
-
children.push(childNode);
|
|
816
|
+
else if (this === child) {
|
|
817
|
+
find = true;
|
|
968
818
|
}
|
|
969
819
|
}
|
|
970
|
-
return
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
configurable: true
|
|
1018
|
-
});
|
|
1019
|
-
Object.defineProperty(HTMLElement.prototype, "childElementCount", {
|
|
1020
|
-
get: function () {
|
|
1021
|
-
return this.children.length;
|
|
1022
|
-
},
|
|
1023
|
-
enumerable: false,
|
|
1024
|
-
configurable: true
|
|
1025
|
-
});
|
|
1026
|
-
Object.defineProperty(HTMLElement.prototype, "classNames", {
|
|
1027
|
-
get: function () {
|
|
1028
|
-
return this.classList.toString();
|
|
1029
|
-
},
|
|
1030
|
-
enumerable: false,
|
|
1031
|
-
configurable: true
|
|
1032
|
-
});
|
|
820
|
+
return null;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
/** Get all childNodes of type {@link HTMLElement}. */
|
|
824
|
+
get children() {
|
|
825
|
+
const children = [];
|
|
826
|
+
for (const childNode of this.childNodes) {
|
|
827
|
+
if (childNode instanceof HTMLElement) {
|
|
828
|
+
children.push(childNode);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
return children;
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Get the first child node.
|
|
835
|
+
* @return The first child or undefined if none exists.
|
|
836
|
+
*/
|
|
837
|
+
get firstChild() {
|
|
838
|
+
return this.childNodes[0];
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Get the first child node of type {@link HTMLElement}.
|
|
842
|
+
* @return The first child element or undefined if none exists.
|
|
843
|
+
*/
|
|
844
|
+
get firstElementChild() {
|
|
845
|
+
return this.children[0];
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Get the last child node.
|
|
849
|
+
* @return The last child or undefined if none exists.
|
|
850
|
+
*/
|
|
851
|
+
get lastChild() {
|
|
852
|
+
return (0, back_1.default)(this.childNodes);
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
855
|
+
* Get the last child node of type {@link HTMLElement}.
|
|
856
|
+
* @return The last child element or undefined if none exists.
|
|
857
|
+
*/
|
|
858
|
+
get lastElementChild() {
|
|
859
|
+
return this.children[this.children.length - 1];
|
|
860
|
+
}
|
|
861
|
+
get childElementCount() {
|
|
862
|
+
return this.children.length;
|
|
863
|
+
}
|
|
864
|
+
get classNames() {
|
|
865
|
+
return this.classList.toString();
|
|
866
|
+
}
|
|
1033
867
|
/** Clone this Node */
|
|
1034
|
-
|
|
868
|
+
clone() {
|
|
1035
869
|
return parse(this.toString(), this._parseOptions).firstChild;
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
}(node_1.default));
|
|
870
|
+
}
|
|
871
|
+
}
|
|
1039
872
|
exports.default = HTMLElement;
|
|
873
|
+
// #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]
|
|
1040
874
|
// https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
875
|
+
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;
|
|
876
|
+
// const kMarkupPattern = /<!--[\s\S]*?-->|<(\/?)([a-zA-Z][-.:0-9_a-zA-Z]*)((?:\s+[^>]*?(?:(?:'[^']*')|(?:"[^"]*"))?)*)\s*(\/?)>/g;
|
|
877
|
+
const kAttributePattern = /(?:^|\s)(id|class)\s*=\s*((?:'[^']*')|(?:"[^"]*")|\S+)/gi;
|
|
878
|
+
const kElementsClosedByOpening = {
|
|
1044
879
|
li: { li: true, LI: true },
|
|
1045
880
|
LI: { li: true, LI: true },
|
|
1046
881
|
p: { p: true, div: true, P: true, DIV: true },
|
|
@@ -1064,7 +899,7 @@ var kElementsClosedByOpening = {
|
|
|
1064
899
|
h6: { h6: true, H6: true },
|
|
1065
900
|
H6: { h6: true, H6: true },
|
|
1066
901
|
};
|
|
1067
|
-
|
|
902
|
+
const kElementsClosedByClosing = {
|
|
1068
903
|
li: { ul: true, ol: true, UL: true, OL: true },
|
|
1069
904
|
LI: { ul: true, ol: true, UL: true, OL: true },
|
|
1070
905
|
a: { div: true, DIV: true },
|
|
@@ -1080,55 +915,57 @@ var kElementsClosedByClosing = {
|
|
|
1080
915
|
th: { tr: true, table: true, TR: true, TABLE: true },
|
|
1081
916
|
TH: { tr: true, table: true, TR: true, TABLE: true },
|
|
1082
917
|
};
|
|
1083
|
-
|
|
918
|
+
const kElementsClosedByClosingExcept = {
|
|
919
|
+
p: { a: true, audio: true, del: true, ins: true, map: true, noscript: true, video: true },
|
|
920
|
+
};
|
|
921
|
+
const frameflag = 'documentfragmentcontainer';
|
|
1084
922
|
/**
|
|
1085
923
|
* Parses HTML and returns a root element
|
|
1086
924
|
* Parse a chuck of HTML source.
|
|
1087
925
|
* @param {string} data html
|
|
1088
926
|
* @return {HTMLElement} root element
|
|
1089
927
|
*/
|
|
1090
|
-
function base_parse(data, options) {
|
|
928
|
+
function base_parse(data, options = {}) {
|
|
1091
929
|
var _a, _b;
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
var elements = options.blockTextElements || {
|
|
930
|
+
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);
|
|
931
|
+
const elements = options.blockTextElements || {
|
|
1095
932
|
script: true,
|
|
1096
933
|
noscript: true,
|
|
1097
934
|
style: true,
|
|
1098
935
|
pre: true,
|
|
1099
936
|
};
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
937
|
+
const element_names = Object.keys(elements);
|
|
938
|
+
const kBlockTextElements = element_names.map((it) => new RegExp(`^${it}$`, 'i'));
|
|
939
|
+
const kIgnoreElements = element_names.filter((it) => Boolean(elements[it])).map((it) => new RegExp(`^${it}$`, 'i'));
|
|
1103
940
|
function element_should_be_ignore(tag) {
|
|
1104
|
-
return kIgnoreElements.some(
|
|
941
|
+
return kIgnoreElements.some((it) => it.test(tag));
|
|
1105
942
|
}
|
|
1106
943
|
function is_block_text_element(tag) {
|
|
1107
|
-
return kBlockTextElements.some(
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
944
|
+
return kBlockTextElements.some((it) => it.test(tag));
|
|
945
|
+
}
|
|
946
|
+
const createRange = (startPos, endPos) => [startPos - frameFlagOffset, endPos - frameFlagOffset];
|
|
947
|
+
const root = new HTMLElement(null, {}, '', null, [0, data.length], voidTag, options);
|
|
948
|
+
let currentParent = root;
|
|
949
|
+
const stack = [root];
|
|
950
|
+
let lastTextPos = -1;
|
|
951
|
+
let noNestedTagIndex = undefined;
|
|
952
|
+
let match;
|
|
1116
953
|
// https://github.com/taoqf/node-html-parser/issues/38
|
|
1117
|
-
data =
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
954
|
+
data = `<${frameflag}>${data}</${frameflag}>`;
|
|
955
|
+
const { lowerCaseTagName, fixNestedATags } = options;
|
|
956
|
+
const dataEndPos = data.length - (frameflag.length + 2);
|
|
957
|
+
const frameFlagOffset = frameflag.length + 2;
|
|
1121
958
|
while ((match = kMarkupPattern.exec(data))) {
|
|
1122
959
|
// Note: Object destructuring here consistently tests as higher performance than array destructuring
|
|
1123
960
|
// eslint-disable-next-line prefer-const
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
961
|
+
let { 0: matchText, 1: leadingSlash, 2: tagName, 3: attributes, 4: closingSlash } = match;
|
|
962
|
+
const matchLength = matchText.length;
|
|
963
|
+
const tagStartPos = kMarkupPattern.lastIndex - matchLength;
|
|
964
|
+
const tagEndPos = kMarkupPattern.lastIndex;
|
|
1128
965
|
// Add TextNode if content
|
|
1129
966
|
if (lastTextPos > -1) {
|
|
1130
967
|
if (lastTextPos + matchLength < tagEndPos) {
|
|
1131
|
-
|
|
968
|
+
const text = data.substring(lastTextPos, tagStartPos);
|
|
1132
969
|
currentParent.appendChild(new text_1.default(text, currentParent, createRange(lastTextPos, tagStartPos)));
|
|
1133
970
|
}
|
|
1134
971
|
}
|
|
@@ -1141,7 +978,7 @@ function base_parse(data, options) {
|
|
|
1141
978
|
if (matchText[1] === '!') {
|
|
1142
979
|
if (options.comment) {
|
|
1143
980
|
// Only keep what is in between <!-- and -->
|
|
1144
|
-
|
|
981
|
+
const text = data.substring(tagStartPos + 4, tagEndPos - 3);
|
|
1145
982
|
currentParent.appendChild(new comment_1.default(text, currentParent, createRange(tagStartPos, tagEndPos)));
|
|
1146
983
|
}
|
|
1147
984
|
continue;
|
|
@@ -1153,13 +990,13 @@ function base_parse(data, options) {
|
|
|
1153
990
|
// Handle opening tags (ie. <this> not </that>)
|
|
1154
991
|
if (!leadingSlash) {
|
|
1155
992
|
/* Populate attributes */
|
|
1156
|
-
|
|
1157
|
-
for (
|
|
1158
|
-
|
|
1159
|
-
|
|
993
|
+
const attrs = {};
|
|
994
|
+
for (let attMatch; (attMatch = kAttributePattern.exec(attributes));) {
|
|
995
|
+
const { 1: key, 2: val } = attMatch;
|
|
996
|
+
const isQuoted = val[0] === `'` || val[0] === `"`;
|
|
1160
997
|
attrs[key.toLowerCase()] = isQuoted ? val.slice(1, val.length - 1) : val;
|
|
1161
998
|
}
|
|
1162
|
-
|
|
999
|
+
const parentTagName = currentParent.rawTagName;
|
|
1163
1000
|
if (!closingSlash && kElementsClosedByOpening[parentTagName]) {
|
|
1164
1001
|
if (kElementsClosedByOpening[parentTagName][tagName]) {
|
|
1165
1002
|
stack.pop();
|
|
@@ -1174,23 +1011,23 @@ function base_parse(data, options) {
|
|
|
1174
1011
|
}
|
|
1175
1012
|
noNestedTagIndex = stack.length;
|
|
1176
1013
|
}
|
|
1177
|
-
|
|
1178
|
-
|
|
1014
|
+
const tagEndPos = kMarkupPattern.lastIndex;
|
|
1015
|
+
const tagStartPos = tagEndPos - matchLength;
|
|
1179
1016
|
currentParent = currentParent.appendChild(
|
|
1180
1017
|
// Initialize range (end position updated later for closed tags)
|
|
1181
|
-
new HTMLElement(tagName, attrs, attributes.slice(1), null, createRange(
|
|
1018
|
+
new HTMLElement(tagName, attrs, attributes.slice(1), null, createRange(tagStartPos, tagEndPos), voidTag, options));
|
|
1182
1019
|
stack.push(currentParent);
|
|
1183
1020
|
if (is_block_text_element(tagName)) {
|
|
1184
1021
|
// Find closing tag
|
|
1185
|
-
|
|
1186
|
-
|
|
1022
|
+
const closeMarkup = `</${tagName}>`;
|
|
1023
|
+
const closeIndex = lowerCaseTagName
|
|
1187
1024
|
? data.toLocaleLowerCase().indexOf(closeMarkup, kMarkupPattern.lastIndex)
|
|
1188
1025
|
: data.indexOf(closeMarkup, kMarkupPattern.lastIndex);
|
|
1189
|
-
|
|
1026
|
+
const textEndPos = closeIndex === -1 ? dataEndPos : closeIndex;
|
|
1190
1027
|
if (element_should_be_ignore(tagName)) {
|
|
1191
|
-
|
|
1028
|
+
const text = data.substring(tagEndPos, textEndPos);
|
|
1192
1029
|
if (text.length > 0 && /\S/.test(text)) {
|
|
1193
|
-
currentParent.appendChild(new text_1.default(text, currentParent, createRange(
|
|
1030
|
+
currentParent.appendChild(new text_1.default(text, currentParent, createRange(tagEndPos, textEndPos)));
|
|
1194
1031
|
}
|
|
1195
1032
|
}
|
|
1196
1033
|
if (closeIndex === -1) {
|
|
@@ -1216,7 +1053,7 @@ function base_parse(data, options) {
|
|
|
1216
1053
|
break;
|
|
1217
1054
|
}
|
|
1218
1055
|
else {
|
|
1219
|
-
|
|
1056
|
+
const parentTagName = currentParent.tagName;
|
|
1220
1057
|
// Trying to close current tag, and move on
|
|
1221
1058
|
if (kElementsClosedByClosing[parentTagName]) {
|
|
1222
1059
|
if (kElementsClosedByClosing[parentTagName][tagName]) {
|
|
@@ -1225,6 +1062,25 @@ function base_parse(data, options) {
|
|
|
1225
1062
|
continue;
|
|
1226
1063
|
}
|
|
1227
1064
|
}
|
|
1065
|
+
const openTag = currentParent.rawTagName ?
|
|
1066
|
+
currentParent.rawTagName.toLowerCase() :
|
|
1067
|
+
'';
|
|
1068
|
+
if (kElementsClosedByClosingExcept[openTag]) {
|
|
1069
|
+
const closingTag = tagName.toLowerCase();
|
|
1070
|
+
if (stack.length > 1) {
|
|
1071
|
+
const possibleContainer = stack[stack.length - 2];
|
|
1072
|
+
if (possibleContainer &&
|
|
1073
|
+
possibleContainer.rawTagName &&
|
|
1074
|
+
possibleContainer.rawTagName.toLowerCase() === closingTag &&
|
|
1075
|
+
!kElementsClosedByClosingExcept[openTag][closingTag]) {
|
|
1076
|
+
// Update range end for closed tag
|
|
1077
|
+
currentParent.range[1] = createRange(-1, Math.max(lastTextPos, tagEndPos))[1];
|
|
1078
|
+
stack.pop();
|
|
1079
|
+
currentParent = (0, back_1.default)(stack);
|
|
1080
|
+
continue;
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1228
1084
|
// Use aggressive strategy to handle unmatching markups.
|
|
1229
1085
|
break;
|
|
1230
1086
|
}
|
|
@@ -1238,22 +1094,22 @@ exports.base_parse = base_parse;
|
|
|
1238
1094
|
* Parses HTML and returns a root element
|
|
1239
1095
|
* Parse a chuck of HTML source.
|
|
1240
1096
|
*/
|
|
1241
|
-
function parse(data, options) {
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
var stack = base_parse(data, options);
|
|
1245
|
-
var root = stack[0];
|
|
1097
|
+
function parse(data, options = {}) {
|
|
1098
|
+
const stack = base_parse(data, options);
|
|
1099
|
+
const [root] = stack;
|
|
1246
1100
|
while (stack.length > 1) {
|
|
1247
1101
|
// Handle each error elements.
|
|
1248
|
-
|
|
1249
|
-
|
|
1102
|
+
const last = stack.pop();
|
|
1103
|
+
const oneBefore = (0, back_1.default)(stack);
|
|
1250
1104
|
if (last.parentNode && last.parentNode.parentNode) {
|
|
1251
1105
|
if (last.parentNode === oneBefore && last.tagName === oneBefore.tagName) {
|
|
1252
1106
|
// Pair error case <h3> <h3> handle : Fixes to <h3> </h3>
|
|
1253
1107
|
// 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
|
|
1254
1108
|
if (options.parseNoneClosedTags !== true) {
|
|
1255
1109
|
oneBefore.removeChild(last);
|
|
1256
|
-
|
|
1110
|
+
last.childNodes.forEach((child) => {
|
|
1111
|
+
oneBefore.parentNode.appendChild(child);
|
|
1112
|
+
});
|
|
1257
1113
|
stack.pop();
|
|
1258
1114
|
}
|
|
1259
1115
|
}
|
|
@@ -1263,7 +1119,9 @@ function parse(data, options) {
|
|
|
1263
1119
|
// eslint-disable-next-line no-lonely-if
|
|
1264
1120
|
if (options.parseNoneClosedTags !== true) {
|
|
1265
1121
|
oneBefore.removeChild(last);
|
|
1266
|
-
|
|
1122
|
+
last.childNodes.forEach((child) => {
|
|
1123
|
+
oneBefore.appendChild(child);
|
|
1124
|
+
});
|
|
1267
1125
|
}
|
|
1268
1126
|
}
|
|
1269
1127
|
}
|
|
@@ -1276,7 +1134,6 @@ function parse(data, options) {
|
|
|
1276
1134
|
// node.parentNode = null;
|
|
1277
1135
|
// }
|
|
1278
1136
|
// });
|
|
1279
|
-
resetParent(root.childNodes, root, true);
|
|
1280
1137
|
return root;
|
|
1281
1138
|
}
|
|
1282
1139
|
exports.parse = parse;
|
|
@@ -1285,7 +1142,7 @@ exports.parse = parse;
|
|
|
1285
1142
|
* and removes nodes from any potential parent.
|
|
1286
1143
|
*/
|
|
1287
1144
|
function resolveInsertable(insertable) {
|
|
1288
|
-
return insertable.map(
|
|
1145
|
+
return insertable.map((val) => {
|
|
1289
1146
|
if (typeof val === 'string') {
|
|
1290
1147
|
return new text_1.default(val);
|
|
1291
1148
|
}
|
|
@@ -1293,12 +1150,9 @@ function resolveInsertable(insertable) {
|
|
|
1293
1150
|
return val;
|
|
1294
1151
|
});
|
|
1295
1152
|
}
|
|
1296
|
-
function resetParent(nodes, parent
|
|
1297
|
-
|
|
1298
|
-
nodes.forEach(function (node) {
|
|
1153
|
+
function resetParent(nodes, parent) {
|
|
1154
|
+
return nodes.map((node) => {
|
|
1299
1155
|
node.parentNode = parent;
|
|
1300
|
-
|
|
1301
|
-
resetParent(node.childNodes, node, true);
|
|
1302
|
-
}
|
|
1156
|
+
return node;
|
|
1303
1157
|
});
|
|
1304
1158
|
}
|