wikiparser-node 0.5.0 → 0.6.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/config/default.json +129 -66
- package/config/zhwiki.json +4 -4
- package/index.js +74 -65
- package/lib/element.js +125 -152
- package/lib/node.js +251 -223
- package/lib/ranges.js +2 -2
- package/lib/text.js +64 -64
- package/lib/title.js +8 -7
- package/mixin/hidden.js +2 -0
- package/mixin/sol.js +1 -2
- package/package.json +4 -3
- package/parser/brackets.js +8 -2
- package/parser/externalLinks.js +1 -1
- package/parser/hrAndDoubleUnderscore.js +4 -4
- package/parser/links.js +7 -7
- package/parser/table.js +12 -10
- package/src/arg.js +53 -48
- package/src/atom/index.js +7 -5
- package/src/attribute.js +91 -80
- package/src/charinsert.js +91 -0
- package/src/converter.js +22 -11
- package/src/converterFlags.js +72 -62
- package/src/converterRule.js +49 -49
- package/src/extLink.js +30 -28
- package/src/gallery.js +56 -32
- package/src/hasNowiki/index.js +42 -0
- package/src/hasNowiki/pre.js +40 -0
- package/src/heading.js +15 -11
- package/src/html.js +38 -38
- package/src/imageParameter.js +64 -48
- package/src/imagemap.js +205 -0
- package/src/imagemapLink.js +43 -0
- package/src/index.js +222 -124
- package/src/link/category.js +4 -8
- package/src/link/file.js +95 -59
- package/src/link/galleryImage.js +74 -10
- package/src/link/index.js +61 -39
- package/src/magicLink.js +21 -22
- package/src/nested/choose.js +24 -0
- package/src/nested/combobox.js +23 -0
- package/src/nested/index.js +88 -0
- package/src/nested/references.js +23 -0
- package/src/nowiki/comment.js +17 -17
- package/src/nowiki/dd.js +2 -2
- package/src/nowiki/doubleUnderscore.js +14 -14
- package/src/nowiki/index.js +12 -0
- package/src/onlyinclude.js +10 -8
- package/src/paramTag/index.js +83 -0
- package/src/paramTag/inputbox.js +42 -0
- package/src/parameter.js +32 -18
- package/src/syntax.js +9 -1
- package/src/table/index.js +33 -32
- package/src/table/td.js +51 -57
- package/src/table/tr.js +6 -6
- package/src/tagPair/ext.js +58 -40
- package/src/tagPair/include.js +1 -1
- package/src/tagPair/index.js +21 -20
- package/src/transclude.js +158 -143
- package/tool/index.js +720 -439
- package/util/base.js +17 -0
- package/util/debug.js +1 -1
- package/util/diff.js +1 -1
- package/util/string.js +20 -20
package/lib/node.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {typeError
|
|
3
|
+
const {typeError} = require('../util/debug'),
|
|
4
4
|
{text} = require('../util/string'),
|
|
5
5
|
assert = require('assert/strict'),
|
|
6
6
|
EventEmitter = require('events'),
|
|
@@ -21,11 +21,11 @@ class AstNode {
|
|
|
21
21
|
* @throws `RangeError` 指定位置不存在子节点
|
|
22
22
|
*/
|
|
23
23
|
#verifyChild = (i, addition = 0) => {
|
|
24
|
-
if (
|
|
24
|
+
if (!Number.isInteger(i)) {
|
|
25
25
|
this.typeError('verifyChild', 'Number');
|
|
26
26
|
}
|
|
27
27
|
const {childNodes: {length}} = this;
|
|
28
|
-
if (i < -length || i >= length + addition
|
|
28
|
+
if (i < -length || i >= length + addition) {
|
|
29
29
|
throw new RangeError(`不存在第 ${i} 个子节点!`);
|
|
30
30
|
}
|
|
31
31
|
};
|
|
@@ -45,17 +45,6 @@ class AstNode {
|
|
|
45
45
|
return this.#parentNode;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
/** 是否具有根节点 */
|
|
49
|
-
get isConnected() {
|
|
50
|
-
return this.getRootNode().type === 'root';
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** 不是自身的根节点 */
|
|
54
|
-
get ownerDocument() {
|
|
55
|
-
const root = this.getRootNode();
|
|
56
|
-
return root.type === 'root' && root !== this ? root : undefined;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
48
|
/**
|
|
60
49
|
* 后一个兄弟节点
|
|
61
50
|
* @complexity `n`
|
|
@@ -96,6 +85,17 @@ class AstNode {
|
|
|
96
85
|
return childNodes?.slice(0, i)?.findLast(({type}) => type !== 'text');
|
|
97
86
|
}
|
|
98
87
|
|
|
88
|
+
/** 是否具有根节点 */
|
|
89
|
+
get isConnected() {
|
|
90
|
+
return this.getRootNode().type === 'root';
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** 不是自身的根节点 */
|
|
94
|
+
get ownerDocument() {
|
|
95
|
+
const root = this.getRootNode();
|
|
96
|
+
return root.type === 'root' && root !== this ? root : undefined;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
99
|
/**
|
|
100
100
|
* 后方是否还有其他节点(不含后代)
|
|
101
101
|
* @returns {boolean}
|
|
@@ -113,9 +113,14 @@ class AstNode {
|
|
|
113
113
|
return nextSibling === undefined && parentNode?.eof;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
constructor() {
|
|
117
|
+
Object.defineProperty(this, 'childNodes', {writable: false});
|
|
118
|
+
Object.freeze(this.childNodes);
|
|
119
|
+
}
|
|
120
|
+
|
|
116
121
|
/**
|
|
117
122
|
* 标记仅用于代码调试的方法
|
|
118
|
-
* @param {string} method
|
|
123
|
+
* @param {string} method
|
|
119
124
|
* @throws `Error`
|
|
120
125
|
*/
|
|
121
126
|
debugOnly(method = 'debugOnly') {
|
|
@@ -124,7 +129,7 @@ class AstNode {
|
|
|
124
129
|
|
|
125
130
|
/**
|
|
126
131
|
* 抛出`TypeError`
|
|
127
|
-
* @param {string} method
|
|
132
|
+
* @param {string} method
|
|
128
133
|
* @param {...string} types 可接受的参数类型
|
|
129
134
|
*/
|
|
130
135
|
typeError(method, ...types) {
|
|
@@ -146,17 +151,12 @@ class AstNode {
|
|
|
146
151
|
}
|
|
147
152
|
for (const key of keys) {
|
|
148
153
|
Object.defineProperty(this, key, {
|
|
149
|
-
writable: false, enumerable: Boolean(this[key]), configurable: !permanent,
|
|
154
|
+
writable: false, enumerable: !permanent && Boolean(this[key]), configurable: !permanent,
|
|
150
155
|
});
|
|
151
156
|
}
|
|
152
157
|
return this;
|
|
153
158
|
}
|
|
154
159
|
|
|
155
|
-
constructor() {
|
|
156
|
-
Object.defineProperty(this, 'childNodes', {writable: false});
|
|
157
|
-
Object.freeze(this.childNodes);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
160
|
/**
|
|
161
161
|
* 是否是全同节点
|
|
162
162
|
* @param {this} node 待比较的节点
|
|
@@ -174,32 +174,6 @@ class AstNode {
|
|
|
174
174
|
return true;
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
/**
|
|
178
|
-
* 是否具有某属性
|
|
179
|
-
* @param {PropertyKey} key 属性键
|
|
180
|
-
*/
|
|
181
|
-
hasAttribute(key) {
|
|
182
|
-
const type = typeof key;
|
|
183
|
-
return type === 'string' || type === 'number' || type === 'symbol'
|
|
184
|
-
? key in this
|
|
185
|
-
: this.typeError('hasAttribute', 'String', 'Number', 'Symbol');
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* 获取属性值。除非用于私有属性,否则总是返回字符串。
|
|
190
|
-
* @template {string} T
|
|
191
|
-
* @param {T} key 属性键
|
|
192
|
-
* @returns {TokenAttribute<T>}
|
|
193
|
-
*/
|
|
194
|
-
getAttribute(key) {
|
|
195
|
-
if (key === 'optional') {
|
|
196
|
-
return [...this.#optional];
|
|
197
|
-
} else if (key === 'verifyChild') {
|
|
198
|
-
return this.#verifyChild;
|
|
199
|
-
}
|
|
200
|
-
return this.hasAttribute(key) ? String(this[key]) : undefined;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
177
|
/** 获取所有属性键 */
|
|
204
178
|
getAttributeNames() {
|
|
205
179
|
const names = Object.getOwnPropertyNames(this);
|
|
@@ -211,38 +185,6 @@ class AstNode {
|
|
|
211
185
|
return this.getAttributeNames().length > 0;
|
|
212
186
|
}
|
|
213
187
|
|
|
214
|
-
/**
|
|
215
|
-
* 设置属性
|
|
216
|
-
* @template {string} T
|
|
217
|
-
* @param {T} key 属性键
|
|
218
|
-
* @param {TokenAttribute<T>} value 属性值
|
|
219
|
-
* @throws `RangeError` 禁止手动指定的属性
|
|
220
|
-
*/
|
|
221
|
-
setAttribute(key, value) {
|
|
222
|
-
if (key === 'parentNode') {
|
|
223
|
-
if (externalUse('setAttribute')) {
|
|
224
|
-
throw new RangeError(`禁止手动指定 ${key} 属性!`);
|
|
225
|
-
}
|
|
226
|
-
this.#parentNode = value;
|
|
227
|
-
} else if (this.hasAttribute(key)) {
|
|
228
|
-
const descriptor = Object.getOwnPropertyDescriptor(this, key);
|
|
229
|
-
if (!descriptor || !descriptor.writable && externalUse('setAttribute')) {
|
|
230
|
-
throw new RangeError(`禁止手动指定 ${key} 属性!`);
|
|
231
|
-
} else if (this.#optional.includes(key)) {
|
|
232
|
-
descriptor.enumerable = Boolean(value);
|
|
233
|
-
}
|
|
234
|
-
const oldValue = this[key],
|
|
235
|
-
frozen = oldValue !== null && typeof oldValue === 'object' && Object.isFrozen(oldValue);
|
|
236
|
-
Object.defineProperty(this, key, {...descriptor, value});
|
|
237
|
-
if (frozen && value !== null && typeof value === 'object') {
|
|
238
|
-
Object.freeze(value);
|
|
239
|
-
}
|
|
240
|
-
} else {
|
|
241
|
-
this[key] = value;
|
|
242
|
-
}
|
|
243
|
-
return this;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
188
|
/**
|
|
247
189
|
* 移除某属性
|
|
248
190
|
* @param {PropertyKey} key 属性键
|
|
@@ -274,116 +216,55 @@ class AstNode {
|
|
|
274
216
|
}
|
|
275
217
|
|
|
276
218
|
/**
|
|
277
|
-
*
|
|
278
|
-
* @param {
|
|
279
|
-
* @returns {string}
|
|
280
|
-
* @complexity `n`
|
|
281
|
-
*/
|
|
282
|
-
text(separator = '') {
|
|
283
|
-
return text(this.childNodes, separator);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/** 是否具有子节点 */
|
|
287
|
-
hasChildNodes() {
|
|
288
|
-
return this.childNodes.length > 0;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* 是自身或后代节点
|
|
293
|
-
* @param {this} node 待检测节点
|
|
294
|
-
* @returns {boolean}
|
|
295
|
-
* @complexity `n`
|
|
219
|
+
* 是否具有某属性
|
|
220
|
+
* @param {PropertyKey} key 属性键
|
|
296
221
|
*/
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
222
|
+
hasAttribute(key) {
|
|
223
|
+
const type = typeof key;
|
|
224
|
+
return type === 'string' || type === 'number' || type === 'symbol'
|
|
225
|
+
? key in this
|
|
226
|
+
: this.typeError('hasAttribute', 'String', 'Number', 'Symbol');
|
|
301
227
|
}
|
|
302
228
|
|
|
303
229
|
/**
|
|
304
|
-
*
|
|
305
|
-
* @
|
|
306
|
-
* @param {
|
|
307
|
-
* @
|
|
230
|
+
* 获取属性值。除非用于私有属性,否则总是返回字符串。
|
|
231
|
+
* @template {string} T
|
|
232
|
+
* @param {T} key 属性键
|
|
233
|
+
* @returns {TokenAttribute<T>}
|
|
308
234
|
*/
|
|
309
|
-
|
|
310
|
-
if (
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
} else if (typeof types !== 'string' || typeof listener !== 'function') {
|
|
315
|
-
this.typeError('addEventListener', 'String', 'Function');
|
|
316
|
-
} else {
|
|
317
|
-
this.#events[options?.once ? 'once' : 'on'](types, listener);
|
|
235
|
+
getAttribute(key) {
|
|
236
|
+
if (key === 'optional') {
|
|
237
|
+
return [...this.#optional];
|
|
238
|
+
} else if (key === 'verifyChild') {
|
|
239
|
+
return this.#verifyChild;
|
|
318
240
|
}
|
|
241
|
+
return this.hasAttribute(key) ? String(this[key]) : undefined;
|
|
319
242
|
}
|
|
320
243
|
|
|
321
244
|
/**
|
|
322
|
-
*
|
|
323
|
-
* @
|
|
324
|
-
* @param {
|
|
245
|
+
* 设置属性
|
|
246
|
+
* @template {string} T
|
|
247
|
+
* @param {T} key 属性键
|
|
248
|
+
* @param {TokenAttribute<T>} value 属性值
|
|
325
249
|
*/
|
|
326
|
-
|
|
327
|
-
if (
|
|
328
|
-
|
|
329
|
-
|
|
250
|
+
setAttribute(key, value) {
|
|
251
|
+
if (key === 'parentNode') {
|
|
252
|
+
this.#parentNode = value;
|
|
253
|
+
} else if (Object.hasOwn(this, key)) {
|
|
254
|
+
const descriptor = Object.getOwnPropertyDescriptor(this, key);
|
|
255
|
+
if (this.#optional.includes(key)) {
|
|
256
|
+
descriptor.enumerable = Boolean(value);
|
|
330
257
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* 移除事件的所有监听
|
|
340
|
-
* @param {string|string[]} types 事件类型
|
|
341
|
-
*/
|
|
342
|
-
removeAllEventListeners(types) {
|
|
343
|
-
if (Array.isArray(types)) {
|
|
344
|
-
for (const type of types) {
|
|
345
|
-
this.removeAllEventListeners(type);
|
|
258
|
+
const oldValue = this[key],
|
|
259
|
+
frozen = oldValue !== null && typeof oldValue === 'object' && Object.isFrozen(oldValue);
|
|
260
|
+
Object.defineProperty(this, key, {...descriptor, value});
|
|
261
|
+
if (frozen && value !== null && typeof value === 'object') {
|
|
262
|
+
Object.freeze(value);
|
|
346
263
|
}
|
|
347
|
-
} else if (types !== undefined && typeof types !== 'string') {
|
|
348
|
-
this.typeError('removeAllEventListeners', 'String');
|
|
349
264
|
} else {
|
|
350
|
-
this
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* 列举事件监听
|
|
356
|
-
* @param {string} type 事件类型
|
|
357
|
-
* @returns {AstListener[]}
|
|
358
|
-
*/
|
|
359
|
-
listEventListeners(type) {
|
|
360
|
-
return typeof type === 'string' ? this.#events.listeners(type) : this.typeError('listEventListeners', 'String');
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
/**
|
|
364
|
-
* 触发事件
|
|
365
|
-
* @param {AstEvent} e 事件对象
|
|
366
|
-
* @param {any} data 事件数据
|
|
367
|
-
*/
|
|
368
|
-
dispatchEvent(e, data) {
|
|
369
|
-
if (!(e instanceof Event)) {
|
|
370
|
-
this.typeError('dispatchEvent', 'Event');
|
|
371
|
-
} else if (!e.target) { // 初始化
|
|
372
|
-
Object.defineProperty(e, 'target', {value: this, enumerable: true});
|
|
373
|
-
|
|
374
|
-
/** 终止冒泡 */
|
|
375
|
-
e.stopPropagation = function() {
|
|
376
|
-
Object.defineProperty(this, 'bubbles', {value: false});
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
|
-
Object.defineProperties(e, { // 每次bubble更新
|
|
380
|
-
prevTarget: {value: e.currentTarget, enumerable: true, configurable: true},
|
|
381
|
-
currentTarget: {value: this, enumerable: true, configurable: true},
|
|
382
|
-
});
|
|
383
|
-
this.#events.emit(e.type, e, data);
|
|
384
|
-
if (e.bubbles && this.parentNode) {
|
|
385
|
-
this.parentNode.dispatchEvent(e, data);
|
|
265
|
+
this[key] = value;
|
|
386
266
|
}
|
|
267
|
+
return this;
|
|
387
268
|
}
|
|
388
269
|
|
|
389
270
|
/**
|
|
@@ -396,34 +277,8 @@ class AstNode {
|
|
|
396
277
|
[node] = childNodes.splice(i, 1),
|
|
397
278
|
e = new Event('remove', {bubbles: true});
|
|
398
279
|
node.setAttribute('parentNode');
|
|
399
|
-
this.setAttribute('childNodes', childNodes)
|
|
400
|
-
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
/**
|
|
404
|
-
* 获取子节点的位置
|
|
405
|
-
* @param {this} node 子节点
|
|
406
|
-
* @complexity `n`
|
|
407
|
-
* @throws `RangeError` 找不到子节点
|
|
408
|
-
*/
|
|
409
|
-
#getChildIndex(node) {
|
|
410
|
-
const {childNodes} = this,
|
|
411
|
-
i = childNodes.indexOf(node);
|
|
412
|
-
if (i === -1) {
|
|
413
|
-
Parser.error('找不到子节点!', node);
|
|
414
|
-
throw new RangeError('找不到子节点!');
|
|
415
|
-
}
|
|
416
|
-
return i;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
/**
|
|
420
|
-
* 移除子节点
|
|
421
|
-
* @template {this} T
|
|
422
|
-
* @param {T} node 子节点
|
|
423
|
-
* @complexity `n`
|
|
424
|
-
*/
|
|
425
|
-
removeChild(node) {
|
|
426
|
-
this.removeAt(this.#getChildIndex(node));
|
|
280
|
+
this.setAttribute('childNodes', childNodes);
|
|
281
|
+
this.dispatchEvent(e, {position: i, removed: node});
|
|
427
282
|
return node;
|
|
428
283
|
}
|
|
429
284
|
|
|
@@ -453,8 +308,35 @@ class AstNode {
|
|
|
453
308
|
childNodes.splice(j, 1);
|
|
454
309
|
}
|
|
455
310
|
childNodes.splice(i, 0, node);
|
|
456
|
-
this.setAttribute('childNodes', childNodes)
|
|
457
|
-
|
|
311
|
+
this.setAttribute('childNodes', childNodes);
|
|
312
|
+
this.dispatchEvent(e, {position: i < 0 ? i + this.childNodes.length - 1 : i, inserted: node});
|
|
313
|
+
return node;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* 获取子节点的位置
|
|
318
|
+
* @param {this} node 子节点
|
|
319
|
+
* @complexity `n`
|
|
320
|
+
* @throws `RangeError` 找不到子节点
|
|
321
|
+
*/
|
|
322
|
+
#getChildIndex(node) {
|
|
323
|
+
const {childNodes} = this,
|
|
324
|
+
i = childNodes.indexOf(node);
|
|
325
|
+
if (i === -1) {
|
|
326
|
+
Parser.error('找不到子节点!', node);
|
|
327
|
+
throw new RangeError('找不到子节点!');
|
|
328
|
+
}
|
|
329
|
+
return i;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* 移除子节点
|
|
334
|
+
* @template {this} T
|
|
335
|
+
* @param {T} node 子节点
|
|
336
|
+
* @complexity `n`
|
|
337
|
+
*/
|
|
338
|
+
removeChild(node) {
|
|
339
|
+
this.removeAt(this.#getChildIndex(node));
|
|
458
340
|
return node;
|
|
459
341
|
}
|
|
460
342
|
|
|
@@ -476,7 +358,7 @@ class AstNode {
|
|
|
476
358
|
* @complexity `n`
|
|
477
359
|
*/
|
|
478
360
|
insertBefore(child, reference) {
|
|
479
|
-
return reference === undefined ? this.
|
|
361
|
+
return reference === undefined ? this.insertAt(child) : this.insertAt(child, this.#getChildIndex(reference));
|
|
480
362
|
}
|
|
481
363
|
|
|
482
364
|
/**
|
|
@@ -552,6 +434,156 @@ class AstNode {
|
|
|
552
434
|
this.remove();
|
|
553
435
|
}
|
|
554
436
|
|
|
437
|
+
/**
|
|
438
|
+
* 可见部分
|
|
439
|
+
* @param {string} separator 子节点间的连接符
|
|
440
|
+
* @returns {string}
|
|
441
|
+
* @complexity `n`
|
|
442
|
+
*/
|
|
443
|
+
text(separator = '') {
|
|
444
|
+
return text(this.childNodes, separator);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/** 是否具有子节点 */
|
|
448
|
+
hasChildNodes() {
|
|
449
|
+
return this.childNodes.length > 0;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* 是自身或后代节点
|
|
454
|
+
* @param {this} node 待检测节点
|
|
455
|
+
* @returns {boolean}
|
|
456
|
+
* @complexity `n`
|
|
457
|
+
*/
|
|
458
|
+
contains(node) {
|
|
459
|
+
return node instanceof AstNode
|
|
460
|
+
? node === this || this.childNodes.some(child => child.contains(node))
|
|
461
|
+
: this.typeError('contains', 'AstNode');
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* 添加事件监听
|
|
466
|
+
* @param {string|string[]} types 事件类型
|
|
467
|
+
* @param {AstListener} listener 监听函数
|
|
468
|
+
* @param {{once: boolean}} options 选项
|
|
469
|
+
*/
|
|
470
|
+
addEventListener(types, listener, options) {
|
|
471
|
+
if (Array.isArray(types)) {
|
|
472
|
+
for (const type of types) {
|
|
473
|
+
this.addEventListener(type, listener, options);
|
|
474
|
+
}
|
|
475
|
+
} else if (typeof types === 'string' && typeof listener === 'function') {
|
|
476
|
+
this.#events[options?.once ? 'once' : 'on'](types, listener);
|
|
477
|
+
} else {
|
|
478
|
+
this.typeError('addEventListener', 'String', 'Function');
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* 移除事件监听
|
|
484
|
+
* @param {string|string[]} types 事件类型
|
|
485
|
+
* @param {AstListener} listener 监听函数
|
|
486
|
+
*/
|
|
487
|
+
removeEventListener(types, listener) {
|
|
488
|
+
if (Array.isArray(types)) {
|
|
489
|
+
for (const type of types) {
|
|
490
|
+
this.removeEventListener(type, listener);
|
|
491
|
+
}
|
|
492
|
+
} else if (typeof types === 'string' && typeof listener === 'function') {
|
|
493
|
+
this.#events.off(types, listener);
|
|
494
|
+
} else {
|
|
495
|
+
this.typeError('removeEventListener', 'String', 'Function');
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* 移除事件的所有监听
|
|
501
|
+
* @param {string|string[]} types 事件类型
|
|
502
|
+
*/
|
|
503
|
+
removeAllEventListeners(types) {
|
|
504
|
+
if (Array.isArray(types)) {
|
|
505
|
+
for (const type of types) {
|
|
506
|
+
this.removeAllEventListeners(type);
|
|
507
|
+
}
|
|
508
|
+
} else if (types === undefined || typeof types === 'string') {
|
|
509
|
+
this.#events.removeAllListeners(types);
|
|
510
|
+
} else {
|
|
511
|
+
this.typeError('removeAllEventListeners', 'String');
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* 列举事件监听
|
|
517
|
+
* @param {string} type 事件类型
|
|
518
|
+
* @returns {AstListener[]}
|
|
519
|
+
*/
|
|
520
|
+
listEventListeners(type) {
|
|
521
|
+
return typeof type === 'string' ? this.#events.listeners(type) : this.typeError('listEventListeners', 'String');
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* 触发事件
|
|
526
|
+
* @param {AstEvent} e 事件对象
|
|
527
|
+
* @param {*} data 事件数据
|
|
528
|
+
*/
|
|
529
|
+
dispatchEvent(e, data) {
|
|
530
|
+
if (!(e instanceof Event)) {
|
|
531
|
+
this.typeError('dispatchEvent', 'Event');
|
|
532
|
+
} else if (!e.target) { // 初始化
|
|
533
|
+
Object.defineProperty(e, 'target', {value: this, enumerable: true});
|
|
534
|
+
|
|
535
|
+
/** 终止冒泡 */
|
|
536
|
+
e.stopPropagation = function() {
|
|
537
|
+
Object.defineProperty(this, 'bubbles', {value: false});
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
Object.defineProperties(e, { // 每次bubble更新
|
|
541
|
+
prevTarget: {value: e.currentTarget, enumerable: true, configurable: true},
|
|
542
|
+
currentTarget: {value: this, enumerable: true, configurable: true},
|
|
543
|
+
});
|
|
544
|
+
this.#events.emit(e.type, e, data);
|
|
545
|
+
if (e.bubbles && this.parentNode) {
|
|
546
|
+
this.parentNode.dispatchEvent(e, data);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/** 获取所有祖先节点 */
|
|
551
|
+
getAncestors() {
|
|
552
|
+
const /** @type {this[]} */ ancestors = [];
|
|
553
|
+
let {parentNode} = this;
|
|
554
|
+
while (parentNode) {
|
|
555
|
+
ancestors.push(parentNode);
|
|
556
|
+
({parentNode} = parentNode);
|
|
557
|
+
}
|
|
558
|
+
return ancestors;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* 比较和另一个节点的相对位置
|
|
563
|
+
* @param {this} other 待比较的节点
|
|
564
|
+
* @complexity `n`
|
|
565
|
+
* @throws `Error` 不在同一个语法树
|
|
566
|
+
*/
|
|
567
|
+
compareDocumentPosition(other) {
|
|
568
|
+
if (!(other instanceof AstNode)) {
|
|
569
|
+
this.typeError('compareDocumentPosition', 'AstNode');
|
|
570
|
+
} else if (this === other) {
|
|
571
|
+
return 0;
|
|
572
|
+
} else if (this.contains(other)) {
|
|
573
|
+
return -1;
|
|
574
|
+
} else if (other.contains(this)) {
|
|
575
|
+
return 1;
|
|
576
|
+
} else if (this.getRootNode() !== other.getRootNode()) {
|
|
577
|
+
throw new Error('不在同一个语法树!');
|
|
578
|
+
}
|
|
579
|
+
const aAncestors = [...this.getAncestors().reverse(), this],
|
|
580
|
+
bAncestors = [...other.getAncestors().reverse(), other],
|
|
581
|
+
depth = aAncestors.findIndex((ancestor, i) => bAncestors[i] !== ancestor),
|
|
582
|
+
commonAncestor = aAncestors[depth - 1],
|
|
583
|
+
{childNodes} = commonAncestor;
|
|
584
|
+
return childNodes.indexOf(aAncestors[depth]) - childNodes.indexOf(bAncestors[depth]);
|
|
585
|
+
}
|
|
586
|
+
|
|
555
587
|
/**
|
|
556
588
|
* 合并相邻的文本子节点
|
|
557
589
|
* @complexity `n`
|
|
@@ -588,11 +620,11 @@ class AstNode {
|
|
|
588
620
|
* @complexity `n`
|
|
589
621
|
*/
|
|
590
622
|
posFromIndex(index) {
|
|
591
|
-
if (
|
|
623
|
+
if (!Number.isInteger(index)) {
|
|
592
624
|
this.typeError('posFromIndex', 'Number');
|
|
593
625
|
}
|
|
594
626
|
const str = String(this);
|
|
595
|
-
if (index >= -str.length && index <= str.length
|
|
627
|
+
if (index >= -str.length && index <= str.length) {
|
|
596
628
|
const lines = str.slice(0, index).split('\n');
|
|
597
629
|
return {top: lines.length - 1, left: lines.at(-1).length};
|
|
598
630
|
}
|
|
@@ -606,12 +638,11 @@ class AstNode {
|
|
|
606
638
|
* @complexity `n`
|
|
607
639
|
*/
|
|
608
640
|
indexFromPos(top, left) {
|
|
609
|
-
if (
|
|
641
|
+
if (!Number.isInteger(top) || !Number.isInteger(left)) {
|
|
610
642
|
this.typeError('indexFromPos', 'Number');
|
|
611
643
|
}
|
|
612
644
|
const lines = String(this).split('\n');
|
|
613
|
-
return top >= 0 && left >= 0 &&
|
|
614
|
-
&& lines.length >= top + 1 && lines[top].length >= left
|
|
645
|
+
return top >= 0 && left >= 0 && lines.length >= top + 1 && lines[top].length >= left
|
|
615
646
|
? lines.slice(0, top).reduce((acc, curLine) => acc + curLine.length + 1, 0) + left
|
|
616
647
|
: undefined;
|
|
617
648
|
}
|
|
@@ -641,9 +672,6 @@ class AstNode {
|
|
|
641
672
|
* @complexity `n`
|
|
642
673
|
*/
|
|
643
674
|
getRelativeIndex(j) {
|
|
644
|
-
if (j !== undefined && typeof j !== 'number') {
|
|
645
|
-
this.typeError('getRelativeIndex', 'Number');
|
|
646
|
-
}
|
|
647
675
|
let /** @type {this[]} */ childNodes;
|
|
648
676
|
|
|
649
677
|
/**
|
|
@@ -714,6 +742,14 @@ class AstNode {
|
|
|
714
742
|
return this.#getDimension().width;
|
|
715
743
|
}
|
|
716
744
|
|
|
745
|
+
/**
|
|
746
|
+
* 位置、大小和padding
|
|
747
|
+
* @complexity `n`
|
|
748
|
+
*/
|
|
749
|
+
get style() {
|
|
750
|
+
return {...this.#getPosition(), ...this.#getDimension(), padding: this.getPadding()};
|
|
751
|
+
}
|
|
752
|
+
|
|
717
753
|
/**
|
|
718
754
|
* 相对于父容器的行号
|
|
719
755
|
* @complexity `n`
|
|
@@ -729,14 +765,6 @@ class AstNode {
|
|
|
729
765
|
get offsetLeft() {
|
|
730
766
|
return this.#getPosition().left;
|
|
731
767
|
}
|
|
732
|
-
|
|
733
|
-
/**
|
|
734
|
-
* 位置、大小和padding
|
|
735
|
-
* @complexity `n`
|
|
736
|
-
*/
|
|
737
|
-
get style() {
|
|
738
|
-
return {...this.#getPosition(), ...this.#getDimension(), padding: this.getPadding()};
|
|
739
|
-
}
|
|
740
768
|
}
|
|
741
769
|
|
|
742
770
|
Parser.classes.AstNode = __filename;
|
package/lib/ranges.js
CHANGED
|
@@ -62,7 +62,7 @@ class Range {
|
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
64
|
* 将Range转换为针对特定数组的下标集
|
|
65
|
-
* @param {number
|
|
65
|
+
* @param {number|*[]} arr 参考数组
|
|
66
66
|
* @complexity `n`
|
|
67
67
|
*/
|
|
68
68
|
applyTo(arr) {
|
|
@@ -99,7 +99,7 @@ class Ranges extends Array {
|
|
|
99
99
|
|
|
100
100
|
/**
|
|
101
101
|
* 将Ranges转换为针对特定Array的下标集
|
|
102
|
-
* @param {number
|
|
102
|
+
* @param {number|*[]} arr 参考数组
|
|
103
103
|
* @complexity `n`
|
|
104
104
|
*/
|
|
105
105
|
applyTo(arr) {
|