wikiparser-node 0.10.0 → 0.11.0-m
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/README.md +44 -32
- package/config/.schema.json +1 -8
- package/config/default.json +1 -2
- package/config/llwiki.json +1 -36
- package/config/moegirl.json +1 -45
- package/config/zhwiki.json +1 -467
- package/dist/index.d.ts +110 -0
- package/dist/lib/element.d.ts +48 -0
- package/dist/lib/node.d.ts +108 -0
- package/dist/lib/text.d.ts +30 -0
- package/dist/lib/title.d.ts +15 -0
- package/dist/mixin/hidden.d.ts +8 -0
- package/dist/parser/brackets.d.ts +12 -0
- package/dist/parser/commentAndExt.d.ts +8 -0
- package/dist/parser/converter.d.ts +7 -0
- package/dist/parser/externalLinks.d.ts +7 -0
- package/dist/parser/hrAndDoubleUnderscore.d.ts +11 -0
- package/dist/parser/html.d.ts +7 -0
- package/dist/parser/links.d.ts +7 -0
- package/dist/parser/list.d.ts +7 -0
- package/dist/parser/magicLinks.d.ts +7 -0
- package/dist/parser/quotes.d.ts +7 -0
- package/dist/parser/table.d.ts +11 -0
- package/dist/src/arg.d.ts +25 -0
- package/dist/src/atom/hidden.d.ts +5 -0
- package/dist/src/atom/index.d.ts +14 -0
- package/dist/src/attribute.d.ts +42 -0
- package/dist/src/attributes.d.ts +33 -0
- package/dist/src/converter.d.ts +29 -0
- package/dist/src/converterFlags.d.ts +27 -0
- package/dist/src/converterRule.d.ts +29 -0
- package/dist/src/extLink.d.ts +22 -0
- package/dist/src/gallery.d.ts +19 -0
- package/dist/src/hasNowiki/index.d.ts +14 -0
- package/dist/src/hasNowiki/pre.d.ts +13 -0
- package/dist/src/heading.d.ts +24 -0
- package/dist/src/html.d.ts +33 -0
- package/dist/src/imageParameter.d.ts +23 -0
- package/dist/src/imagemap.d.ts +26 -0
- package/dist/src/imagemapLink.d.ts +16 -0
- package/dist/src/index.d.ts +53 -0
- package/dist/src/link/category.d.ts +8 -0
- package/dist/src/link/file.d.ts +27 -0
- package/dist/src/link/galleryImage.d.ts +15 -0
- package/dist/src/link/index.d.ts +29 -0
- package/dist/src/magicLink.d.ts +14 -0
- package/dist/src/nested/choose.d.ts +13 -0
- package/dist/src/nested/combobox.d.ts +13 -0
- package/dist/src/nested/index.d.ts +20 -0
- package/dist/src/nested/references.d.ts +13 -0
- package/dist/src/nowiki/comment.d.ts +19 -0
- package/dist/src/nowiki/dd.d.ts +8 -0
- package/dist/src/nowiki/doubleUnderscore.d.ts +12 -0
- package/dist/src/nowiki/hr.d.ts +13 -0
- package/dist/src/nowiki/index.d.ts +18 -0
- package/dist/src/nowiki/list.d.ts +8 -0
- package/dist/src/nowiki/noinclude.d.ts +8 -0
- package/dist/src/nowiki/quote.d.ts +20 -0
- package/dist/src/onlyinclude.d.ts +17 -0
- package/dist/src/paramTag/index.d.ts +24 -0
- package/dist/src/paramTag/inputbox.d.ts +8 -0
- package/dist/src/parameter.d.ts +28 -0
- package/dist/src/syntax.d.ts +15 -0
- package/dist/src/table/index.d.ts +16 -0
- package/dist/src/table/td.d.ts +39 -0
- package/dist/src/table/tr.d.ts +17 -0
- package/dist/src/tagPair/ext.d.ts +17 -0
- package/dist/src/tagPair/include.d.ts +16 -0
- package/dist/src/tagPair/index.d.ts +28 -0
- package/dist/src/transclude.d.ts +75 -0
- package/dist/util/lint.d.ts +28 -0
- package/dist/util/string.d.ts +31 -0
- package/i18n/zh-hans.json +1 -1
- package/i18n/zh-hant.json +1 -1
- package/index.js +5 -257
- package/lib/element.js +7 -482
- package/lib/node.js +11 -540
- package/lib/text.js +3 -96
- package/lib/title.js +1 -28
- package/mixin/hidden.js +0 -3
- package/package.json +11 -5
- package/parser/brackets.js +3 -2
- package/parser/commentAndExt.js +8 -6
- package/parser/converter.js +1 -2
- package/parser/externalLinks.js +1 -2
- package/parser/hrAndDoubleUnderscore.js +1 -2
- package/parser/html.js +1 -2
- package/parser/links.js +5 -6
- package/parser/list.js +1 -2
- package/parser/magicLinks.js +1 -2
- package/parser/quotes.js +1 -2
- package/parser/table.js +1 -2
- package/src/arg.js +4 -118
- package/src/atom/hidden.js +0 -2
- package/src/atom/index.js +1 -18
- package/src/attribute.js +6 -190
- package/src/attributes.js +5 -308
- package/src/converter.js +3 -109
- package/src/converterFlags.js +1 -188
- package/src/converterRule.js +2 -184
- package/src/extLink.js +2 -122
- package/src/gallery.js +2 -56
- package/src/hasNowiki/index.js +1 -13
- package/src/hasNowiki/pre.js +1 -13
- package/src/heading.js +4 -55
- package/src/html.js +5 -120
- package/src/imageParameter.js +3 -165
- package/src/imagemap.js +3 -62
- package/src/imagemapLink.js +2 -14
- package/src/index.js +9 -530
- package/src/link/category.js +1 -32
- package/src/link/file.js +3 -158
- package/src/link/galleryImage.js +3 -61
- package/src/link/index.js +4 -273
- package/src/magicLink.js +6 -87
- package/src/nested/choose.js +1 -2
- package/src/nested/combobox.js +1 -2
- package/src/nested/index.js +8 -32
- package/src/nested/references.js +1 -2
- package/src/nowiki/comment.js +2 -26
- package/src/nowiki/dd.js +1 -47
- package/src/nowiki/doubleUnderscore.js +1 -31
- package/src/nowiki/hr.js +2 -21
- package/src/nowiki/index.js +2 -24
- package/src/nowiki/list.js +2 -5
- package/src/nowiki/noinclude.js +0 -14
- package/src/nowiki/quote.js +2 -16
- package/src/onlyinclude.js +2 -27
- package/src/paramTag/index.js +2 -25
- package/src/paramTag/inputbox.js +2 -5
- package/src/parameter.js +6 -148
- package/src/syntax.js +1 -69
- package/src/table/index.js +2 -939
- package/src/table/td.js +6 -226
- package/src/table/tr.js +3 -248
- package/src/tagPair/ext.js +4 -23
- package/src/tagPair/include.js +1 -25
- package/src/tagPair/index.js +3 -52
- package/src/transclude.js +6 -513
- package/typings/api.d.ts +9 -0
- package/typings/index.d.ts +51 -0
- package/typings/node.d.ts +16 -0
- package/typings/parser.d.ts +5 -0
- package/typings/token.d.ts +28 -0
- package/util/lint.js +2 -0
- package/util/string.js +0 -51
- package/lib/ranges.js +0 -130
- package/mixin/attributeParent.js +0 -117
- package/mixin/fixedToken.js +0 -40
- package/mixin/singleLine.js +0 -31
- package/mixin/sol.js +0 -54
- package/parser/selector.js +0 -177
- package/src/charinsert.js +0 -97
- package/tool/index.js +0 -1202
- package/util/debug.js +0 -73
package/lib/node.js
CHANGED
|
@@ -1,34 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
/**
|
|
4
|
+
* @template T
|
|
5
|
+
* @typedef {import('../typings/node').TokenAttribute<T>} TokenAttribute
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const {text} = require('../util/string');
|
|
8
9
|
|
|
9
10
|
/** 类似Node */
|
|
10
11
|
class AstNode {
|
|
11
12
|
/** @type {string} */ type;
|
|
12
13
|
/** @type {this[]} */ childNodes = [];
|
|
13
14
|
/** @type {this} */ #parentNode;
|
|
14
|
-
/** @type {Set<string>} */ #optional = new Set();
|
|
15
|
-
#events = new EventEmitter();
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* 检查在某个位置增删子节点是否合法
|
|
19
|
-
* @param {number} i 增删位置
|
|
20
|
-
* @param {number} addition 将会插入的子节点个数
|
|
21
|
-
* @throws `RangeError` 指定位置不存在子节点
|
|
22
|
-
*/
|
|
23
|
-
#verifyChild = (i, addition = 0) => {
|
|
24
|
-
if (!Number.isInteger(i)) {
|
|
25
|
-
this.typeError('verifyChild', 'Number');
|
|
26
|
-
}
|
|
27
|
-
const {childNodes: {length}} = this;
|
|
28
|
-
if (i < -length || i >= length + addition) {
|
|
29
|
-
throw new RangeError(`不存在第 ${i} 个子节点!`);
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
15
|
|
|
33
16
|
/** 首位子节点 */
|
|
34
17
|
get firstChild() {
|
|
@@ -63,158 +46,6 @@ class AstNode {
|
|
|
63
46
|
return childNodes && childNodes[childNodes.indexOf(this) - 1];
|
|
64
47
|
}
|
|
65
48
|
|
|
66
|
-
/**
|
|
67
|
-
* 后一个非文本兄弟节点
|
|
68
|
-
* @complexity `n`
|
|
69
|
-
* @returns {this}
|
|
70
|
-
*/
|
|
71
|
-
get nextElementSibling() {
|
|
72
|
-
const childNodes = this.#parentNode?.childNodes,
|
|
73
|
-
i = childNodes?.indexOf(this);
|
|
74
|
-
return childNodes?.slice(i + 1)?.find(({type}) => type !== 'text');
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* 前一个非文本兄弟节点
|
|
79
|
-
* @complexity `n`
|
|
80
|
-
* @returns {this}
|
|
81
|
-
*/
|
|
82
|
-
get previousElementSibling() {
|
|
83
|
-
const childNodes = this.#parentNode?.childNodes,
|
|
84
|
-
i = childNodes?.indexOf(this);
|
|
85
|
-
return childNodes?.slice(0, i)?.findLast(({type}) => type !== 'text');
|
|
86
|
-
}
|
|
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
|
-
/**
|
|
100
|
-
* 后方是否还有其他节点(不含后代)
|
|
101
|
-
* @returns {boolean}
|
|
102
|
-
* @complexity `n`
|
|
103
|
-
*/
|
|
104
|
-
get eof() {
|
|
105
|
-
if (this.type === 'root') {
|
|
106
|
-
return true;
|
|
107
|
-
}
|
|
108
|
-
let {nextSibling} = this;
|
|
109
|
-
while (nextSibling?.type === 'text' && String(nextSibling).trim() === '') {
|
|
110
|
-
({nextSibling} = nextSibling);
|
|
111
|
-
}
|
|
112
|
-
return nextSibling === undefined && this.parentNode?.eof;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
constructor() {
|
|
116
|
-
Object.defineProperty(this, 'childNodes', {writable: false});
|
|
117
|
-
Object.freeze(this.childNodes);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* 标记仅用于代码调试的方法
|
|
122
|
-
* @param {string} method
|
|
123
|
-
* @throws `Error`
|
|
124
|
-
*/
|
|
125
|
-
debugOnly(method = 'debugOnly') {
|
|
126
|
-
throw new Error(`${this.constructor.name}.${method} 方法仅用于代码调试!`);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* 抛出`TypeError`
|
|
131
|
-
* @param {string} method
|
|
132
|
-
* @param {...string} types 可接受的参数类型
|
|
133
|
-
*/
|
|
134
|
-
typeError(method, ...types) {
|
|
135
|
-
return typeError(this.constructor, method, ...types);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* 冻结部分属性
|
|
140
|
-
* @param {string|string[]} keys 属性键
|
|
141
|
-
* @param {boolean} permanent 是否永久
|
|
142
|
-
*/
|
|
143
|
-
seal(keys, permanent) {
|
|
144
|
-
if (!Parser.running && !Parser.debugging) {
|
|
145
|
-
this.debugOnly('seal');
|
|
146
|
-
}
|
|
147
|
-
keys = Array.isArray(keys) ? keys : [keys];
|
|
148
|
-
if (!permanent) {
|
|
149
|
-
for (const key of keys) {
|
|
150
|
-
this.#optional.add(key);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
for (const key of keys) {
|
|
154
|
-
Object.defineProperty(this, key, {
|
|
155
|
-
writable: false, enumerable: !permanent && Boolean(this[key]), configurable: !permanent,
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* 是否是全同节点
|
|
162
|
-
* @param {this} node 待比较的节点
|
|
163
|
-
* @throws `assert.AssertionError`
|
|
164
|
-
*/
|
|
165
|
-
isEqualNode(node) {
|
|
166
|
-
try {
|
|
167
|
-
assert.deepStrictEqual(this, node);
|
|
168
|
-
} catch (e) {
|
|
169
|
-
if (e instanceof assert.AssertionError) {
|
|
170
|
-
return false;
|
|
171
|
-
}
|
|
172
|
-
throw e;
|
|
173
|
-
}
|
|
174
|
-
return true;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/** 获取所有属性键 */
|
|
178
|
-
getAttributeNames() {
|
|
179
|
-
const names = Object.getOwnPropertyNames(this);
|
|
180
|
-
return names.filter(name => typeof this[name] !== 'function');
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/** 是否具有任意属性 */
|
|
184
|
-
hasAttributes() {
|
|
185
|
-
return this.getAttributeNames().length > 0;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* 移除某属性
|
|
190
|
-
* @param {PropertyKey} key 属性键
|
|
191
|
-
* @throws `RangeError` 不可删除的属性
|
|
192
|
-
*/
|
|
193
|
-
removeAttribute(key) {
|
|
194
|
-
if (this.hasAttribute(key)) {
|
|
195
|
-
const descriptor = Object.getOwnPropertyDescriptor(this, key);
|
|
196
|
-
if (!descriptor || !descriptor.writable) {
|
|
197
|
-
throw new RangeError(`属性 ${key} 不可删除!`);
|
|
198
|
-
}
|
|
199
|
-
delete this[key];
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* 开关某属性
|
|
205
|
-
* @param {PropertyKey} key 属性键
|
|
206
|
-
* @param {boolean|undefined} force 强制开启或关闭
|
|
207
|
-
* @throws `RangeError` 不为Boolean类型的属性值
|
|
208
|
-
*/
|
|
209
|
-
toggleAttribute(key, force) {
|
|
210
|
-
if (force !== undefined && typeof force !== 'boolean') {
|
|
211
|
-
this.typeError('toggleAttribute', 'Boolean');
|
|
212
|
-
} else if (this.hasAttribute(key) && typeof this[key] !== 'boolean') {
|
|
213
|
-
throw new RangeError(`${key} 属性的值不为 Boolean!`);
|
|
214
|
-
}
|
|
215
|
-
this.setAttribute(key, force === true || force === undefined && !this[key]);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
49
|
/**
|
|
219
50
|
* 是否具有某属性
|
|
220
51
|
* @param {PropertyKey} key 属性键
|
|
@@ -223,7 +54,7 @@ class AstNode {
|
|
|
223
54
|
const type = typeof key;
|
|
224
55
|
return type === 'string' || type === 'number' || type === 'symbol'
|
|
225
56
|
? key in this
|
|
226
|
-
:
|
|
57
|
+
: false;
|
|
227
58
|
}
|
|
228
59
|
|
|
229
60
|
/**
|
|
@@ -233,11 +64,6 @@ class AstNode {
|
|
|
233
64
|
* @returns {TokenAttribute<T>}
|
|
234
65
|
*/
|
|
235
66
|
getAttribute(key) {
|
|
236
|
-
if (key === 'optional') {
|
|
237
|
-
return new Set(this.#optional);
|
|
238
|
-
} else if (key === 'verifyChild') {
|
|
239
|
-
return this.#verifyChild;
|
|
240
|
-
}
|
|
241
67
|
return this.hasAttribute(key) ? String(this[key]) : undefined;
|
|
242
68
|
}
|
|
243
69
|
|
|
@@ -250,17 +76,6 @@ class AstNode {
|
|
|
250
76
|
setAttribute(key, value) {
|
|
251
77
|
if (key === 'parentNode') {
|
|
252
78
|
this.#parentNode = value;
|
|
253
|
-
} else if (Object.hasOwn(this, key)) {
|
|
254
|
-
const descriptor = Object.getOwnPropertyDescriptor(this, key);
|
|
255
|
-
if (this.#optional.has(key)) {
|
|
256
|
-
descriptor.enumerable = Boolean(value);
|
|
257
|
-
}
|
|
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);
|
|
263
|
-
}
|
|
264
79
|
} else {
|
|
265
80
|
this[key] = value;
|
|
266
81
|
}
|
|
@@ -282,13 +97,8 @@ class AstNode {
|
|
|
282
97
|
* @param {number} i 移除位置
|
|
283
98
|
*/
|
|
284
99
|
removeAt(i) {
|
|
285
|
-
this
|
|
286
|
-
const childNodes = [...this.childNodes],
|
|
287
|
-
e = new Event('remove', {bubbles: true}),
|
|
100
|
+
const {childNodes} = this,
|
|
288
101
|
[node] = childNodes.splice(i, 1);
|
|
289
|
-
node.setAttribute('parentNode');
|
|
290
|
-
this.setAttribute('childNodes', childNodes);
|
|
291
|
-
this.dispatchEvent(e, {position: i, removed: node});
|
|
292
102
|
return node;
|
|
293
103
|
}
|
|
294
104
|
|
|
@@ -298,298 +108,24 @@ class AstNode {
|
|
|
298
108
|
* @param {T} node 待插入的子节点
|
|
299
109
|
* @param {number} i 插入位置
|
|
300
110
|
* @complexity `n`
|
|
301
|
-
* @throws `RangeError` 不能插入祖先节点
|
|
302
111
|
*/
|
|
303
112
|
insertAt(node, i = this.childNodes.length) {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
} else if (node.contains(this)) {
|
|
307
|
-
Parser.error('不能插入祖先节点!', node);
|
|
308
|
-
throw new RangeError('不能插入祖先节点!');
|
|
309
|
-
}
|
|
310
|
-
this.getAttribute('verifyChild')(i, 1);
|
|
311
|
-
const childNodes = [...this.childNodes],
|
|
312
|
-
e = new Event('insert', {bubbles: true}),
|
|
313
|
-
j = Parser.running ? -1 : childNodes.indexOf(node);
|
|
113
|
+
const {childNodes} = this,
|
|
114
|
+
j = -1;
|
|
314
115
|
if (j === -1) {
|
|
315
|
-
node.parentNode?.removeChild(node);
|
|
316
116
|
node.setAttribute('parentNode', this);
|
|
317
|
-
} else {
|
|
318
|
-
childNodes.splice(j, 1);
|
|
319
117
|
}
|
|
320
118
|
childNodes.splice(i, 0, node);
|
|
321
|
-
this.setAttribute('childNodes', childNodes);
|
|
322
|
-
this.dispatchEvent(e, {position: i < 0 ? i + this.childNodes.length - 1 : i, inserted: node});
|
|
323
119
|
return node;
|
|
324
120
|
}
|
|
325
121
|
|
|
326
|
-
/**
|
|
327
|
-
* 获取子节点的位置
|
|
328
|
-
* @param {this} node 子节点
|
|
329
|
-
* @complexity `n`
|
|
330
|
-
* @throws `RangeError` 找不到子节点
|
|
331
|
-
*/
|
|
332
|
-
#getChildIndex(node) {
|
|
333
|
-
const i = this.childNodes.indexOf(node);
|
|
334
|
-
if (i === -1) {
|
|
335
|
-
Parser.error('找不到子节点!', node);
|
|
336
|
-
throw new RangeError('找不到子节点!');
|
|
337
|
-
}
|
|
338
|
-
return i;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* 移除子节点
|
|
343
|
-
* @template {this} T
|
|
344
|
-
* @param {T} node 子节点
|
|
345
|
-
* @complexity `n`
|
|
346
|
-
*/
|
|
347
|
-
removeChild(node) {
|
|
348
|
-
this.removeAt(this.#getChildIndex(node));
|
|
349
|
-
return node;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* 在末尾插入子节点
|
|
354
|
-
* @template {this} T
|
|
355
|
-
* @param {T} node 插入节点
|
|
356
|
-
* @complexity `n`
|
|
357
|
-
*/
|
|
358
|
-
appendChild(node) {
|
|
359
|
-
return this.insertAt(node);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* 在指定位置前插入子节点
|
|
364
|
-
* @template {this} T
|
|
365
|
-
* @param {T} child 插入节点
|
|
366
|
-
* @param {this} reference 指定位置处的子节点
|
|
367
|
-
* @complexity `n`
|
|
368
|
-
*/
|
|
369
|
-
insertBefore(child, reference) {
|
|
370
|
-
return reference === undefined ? this.insertAt(child) : this.insertAt(child, this.#getChildIndex(reference));
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* 替换子节点
|
|
375
|
-
* @template {this} T
|
|
376
|
-
* @param {this} newChild 新子节点
|
|
377
|
-
* @param {T} oldChild 原子节点
|
|
378
|
-
* @complexity `n`
|
|
379
|
-
*/
|
|
380
|
-
replaceChild(newChild, oldChild) {
|
|
381
|
-
const i = this.#getChildIndex(oldChild);
|
|
382
|
-
this.removeAt(i);
|
|
383
|
-
this.insertAt(newChild, i);
|
|
384
|
-
return oldChild;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
/**
|
|
388
|
-
* 在当前节点前后插入兄弟节点
|
|
389
|
-
* @param {this[]} nodes 插入节点
|
|
390
|
-
* @param {number} offset 插入的相对位置
|
|
391
|
-
* @complexity `n`
|
|
392
|
-
* @throws `Error` 不存在父节点
|
|
393
|
-
*/
|
|
394
|
-
#insertAdjacent(nodes, offset) {
|
|
395
|
-
const {parentNode} = this;
|
|
396
|
-
if (!parentNode) {
|
|
397
|
-
throw new Error('不存在父节点!');
|
|
398
|
-
}
|
|
399
|
-
const i = parentNode.childNodes.indexOf(this) + offset;
|
|
400
|
-
for (let j = 0; j < nodes.length; j++) {
|
|
401
|
-
parentNode.insertAt(nodes[j], i + j);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* 在后方批量插入兄弟节点
|
|
407
|
-
* @param {...this} nodes 插入节点
|
|
408
|
-
* @complexity `n`
|
|
409
|
-
*/
|
|
410
|
-
after(...nodes) {
|
|
411
|
-
this.#insertAdjacent(nodes, 1);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
/**
|
|
415
|
-
* 在前方批量插入兄弟节点
|
|
416
|
-
* @param {...this} nodes 插入节点
|
|
417
|
-
* @complexity `n`
|
|
418
|
-
*/
|
|
419
|
-
before(...nodes) {
|
|
420
|
-
this.#insertAdjacent(nodes, 0);
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
/**
|
|
424
|
-
* 移除当前节点
|
|
425
|
-
* @complexity `n`
|
|
426
|
-
* @throws `Error` 不存在父节点
|
|
427
|
-
*/
|
|
428
|
-
remove() {
|
|
429
|
-
const {parentNode} = this;
|
|
430
|
-
if (!parentNode) {
|
|
431
|
-
throw new Error('不存在父节点!');
|
|
432
|
-
}
|
|
433
|
-
parentNode.removeChild(this);
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
/**
|
|
437
|
-
* 将当前节点批量替换为新的节点
|
|
438
|
-
* @param {...this} nodes 插入节点
|
|
439
|
-
* @complexity `n`
|
|
440
|
-
*/
|
|
441
|
-
replaceWith(...nodes) {
|
|
442
|
-
this.after(...nodes);
|
|
443
|
-
this.remove();
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
/** 是否具有子节点 */
|
|
447
|
-
hasChildNodes() {
|
|
448
|
-
return this.childNodes.length > 0;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/**
|
|
452
|
-
* 是自身或后代节点
|
|
453
|
-
* @param {this} node 待检测节点
|
|
454
|
-
* @returns {boolean}
|
|
455
|
-
* @complexity `n`
|
|
456
|
-
*/
|
|
457
|
-
contains(node) {
|
|
458
|
-
return node instanceof AstNode
|
|
459
|
-
? node === this || this.childNodes.some(child => child.contains(node))
|
|
460
|
-
: this.typeError('contains', 'AstNode');
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
/**
|
|
464
|
-
* 添加事件监听
|
|
465
|
-
* @param {string|string[]} types 事件类型
|
|
466
|
-
* @param {AstListener} listener 监听函数
|
|
467
|
-
* @param {{once: boolean}} options 选项
|
|
468
|
-
*/
|
|
469
|
-
addEventListener(types, listener, options) {
|
|
470
|
-
if (Array.isArray(types)) {
|
|
471
|
-
for (const type of types) {
|
|
472
|
-
this.addEventListener(type, listener, options);
|
|
473
|
-
}
|
|
474
|
-
} else if (typeof types === 'string' && typeof listener === 'function') {
|
|
475
|
-
this.#events[options?.once ? 'once' : 'on'](types, listener);
|
|
476
|
-
} else {
|
|
477
|
-
this.typeError('addEventListener', 'String', 'Function');
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
/**
|
|
482
|
-
* 移除事件监听
|
|
483
|
-
* @param {string|string[]} types 事件类型
|
|
484
|
-
* @param {AstListener} listener 监听函数
|
|
485
|
-
*/
|
|
486
|
-
removeEventListener(types, listener) {
|
|
487
|
-
if (Array.isArray(types)) {
|
|
488
|
-
for (const type of types) {
|
|
489
|
-
this.removeEventListener(type, listener);
|
|
490
|
-
}
|
|
491
|
-
} else if (typeof types === 'string' && typeof listener === 'function') {
|
|
492
|
-
this.#events.off(types, listener);
|
|
493
|
-
} else {
|
|
494
|
-
this.typeError('removeEventListener', 'String', 'Function');
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
/**
|
|
499
|
-
* 移除事件的所有监听
|
|
500
|
-
* @param {string|string[]} types 事件类型
|
|
501
|
-
*/
|
|
502
|
-
removeAllEventListeners(types) {
|
|
503
|
-
if (Array.isArray(types)) {
|
|
504
|
-
for (const type of types) {
|
|
505
|
-
this.removeAllEventListeners(type);
|
|
506
|
-
}
|
|
507
|
-
} else if (types === undefined || typeof types === 'string') {
|
|
508
|
-
this.#events.removeAllListeners(types);
|
|
509
|
-
} else {
|
|
510
|
-
this.typeError('removeAllEventListeners', 'String');
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
/**
|
|
515
|
-
* 列举事件监听
|
|
516
|
-
* @param {string} type 事件类型
|
|
517
|
-
* @returns {AstListener[]}
|
|
518
|
-
*/
|
|
519
|
-
listEventListeners(type) {
|
|
520
|
-
return typeof type === 'string' ? this.#events.listeners(type) : this.typeError('listEventListeners', 'String');
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
/**
|
|
524
|
-
* 触发事件
|
|
525
|
-
* @param {AstEvent} e 事件对象
|
|
526
|
-
* @param {*} data 事件数据
|
|
527
|
-
*/
|
|
528
|
-
dispatchEvent(e, data) {
|
|
529
|
-
if (!(e instanceof Event)) {
|
|
530
|
-
this.typeError('dispatchEvent', 'Event');
|
|
531
|
-
} else if (!e.target) { // 初始化
|
|
532
|
-
Object.defineProperty(e, 'target', {value: this, enumerable: true});
|
|
533
|
-
|
|
534
|
-
/** 终止冒泡 */
|
|
535
|
-
e.stopPropagation = function() {
|
|
536
|
-
Object.defineProperty(this, 'bubbles', {value: false});
|
|
537
|
-
};
|
|
538
|
-
}
|
|
539
|
-
Object.defineProperties(e, { // 每次bubble更新
|
|
540
|
-
prevTarget: {value: e.currentTarget, enumerable: true, configurable: true},
|
|
541
|
-
currentTarget: {value: this, enumerable: true, configurable: true},
|
|
542
|
-
});
|
|
543
|
-
this.#events.emit(e.type, e, data);
|
|
544
|
-
if (e.bubbles && this.parentNode) {
|
|
545
|
-
this.parentNode.dispatchEvent(e, data);
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
/** 获取所有祖先节点 */
|
|
550
|
-
getAncestors() {
|
|
551
|
-
const /** @type {this[]} */ ancestors = [];
|
|
552
|
-
let {parentNode} = this;
|
|
553
|
-
while (parentNode) {
|
|
554
|
-
ancestors.push(parentNode);
|
|
555
|
-
({parentNode} = parentNode);
|
|
556
|
-
}
|
|
557
|
-
return ancestors;
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
/**
|
|
561
|
-
* 比较和另一个节点的相对位置
|
|
562
|
-
* @param {this} other 待比较的节点
|
|
563
|
-
* @complexity `n`
|
|
564
|
-
* @throws `Error` 不在同一个语法树
|
|
565
|
-
*/
|
|
566
|
-
compareDocumentPosition(other) {
|
|
567
|
-
if (!(other instanceof AstNode)) {
|
|
568
|
-
this.typeError('compareDocumentPosition', 'AstNode');
|
|
569
|
-
} else if (this === other) {
|
|
570
|
-
return 0;
|
|
571
|
-
} else if (this.contains(other)) {
|
|
572
|
-
return -1;
|
|
573
|
-
} else if (other.contains(this)) {
|
|
574
|
-
return 1;
|
|
575
|
-
} else if (this.getRootNode() !== other.getRootNode()) {
|
|
576
|
-
throw new Error('不在同一个语法树!');
|
|
577
|
-
}
|
|
578
|
-
const aAncestors = [...this.getAncestors().reverse(), this],
|
|
579
|
-
bAncestors = [...other.getAncestors().reverse(), other],
|
|
580
|
-
depth = aAncestors.findIndex((ancestor, i) => bAncestors[i] !== ancestor),
|
|
581
|
-
commonAncestor = aAncestors[depth - 1],
|
|
582
|
-
{childNodes} = commonAncestor;
|
|
583
|
-
return childNodes.indexOf(aAncestors[depth]) - childNodes.indexOf(bAncestors[depth]);
|
|
584
|
-
}
|
|
585
|
-
|
|
586
122
|
/**
|
|
587
123
|
* 合并相邻的文本子节点
|
|
588
124
|
* @complexity `n`
|
|
589
125
|
*/
|
|
590
126
|
normalize() {
|
|
591
127
|
const AstText = require('./text');
|
|
592
|
-
const /** @type {AstText[]} */ childNodes =
|
|
128
|
+
const /** @type {{childNodes: AstText[]}} */ {childNodes} = this;
|
|
593
129
|
for (let i = childNodes.length - 1; i >= 0; i--) {
|
|
594
130
|
const {type, data} = childNodes[i];
|
|
595
131
|
if (this.getGaps(i - 1)) {
|
|
@@ -601,7 +137,6 @@ class AstNode {
|
|
|
601
137
|
childNodes.splice(i, 1);
|
|
602
138
|
}
|
|
603
139
|
}
|
|
604
|
-
this.setAttribute('childNodes', childNodes);
|
|
605
140
|
}
|
|
606
141
|
|
|
607
142
|
/** 获取根节点 */
|
|
@@ -619,9 +154,6 @@ class AstNode {
|
|
|
619
154
|
* @complexity `n`
|
|
620
155
|
*/
|
|
621
156
|
posFromIndex(index) {
|
|
622
|
-
if (!Number.isInteger(index)) {
|
|
623
|
-
this.typeError('posFromIndex', 'Number');
|
|
624
|
-
}
|
|
625
157
|
const str = String(this);
|
|
626
158
|
if (index >= -str.length && index <= str.length) {
|
|
627
159
|
const lines = str.slice(0, index).split('\n');
|
|
@@ -630,22 +162,6 @@ class AstNode {
|
|
|
630
162
|
return undefined;
|
|
631
163
|
}
|
|
632
164
|
|
|
633
|
-
/**
|
|
634
|
-
* 将行列号转换为字符位置
|
|
635
|
-
* @param {number} top 行号
|
|
636
|
-
* @param {number} left 列号
|
|
637
|
-
* @complexity `n`
|
|
638
|
-
*/
|
|
639
|
-
indexFromPos(top, left) {
|
|
640
|
-
if (!Number.isInteger(top) || !Number.isInteger(left)) {
|
|
641
|
-
this.typeError('indexFromPos', 'Number');
|
|
642
|
-
}
|
|
643
|
-
const lines = String(this).split('\n');
|
|
644
|
-
return top >= 0 && left >= 0 && lines.length >= top + 1 && lines[top].length >= left
|
|
645
|
-
? lines.slice(0, top).reduce((acc, curLine) => acc + curLine.length + 1, 0) + left
|
|
646
|
-
: undefined;
|
|
647
|
-
}
|
|
648
|
-
|
|
649
165
|
/**
|
|
650
166
|
* 获取行数和最后一行的列数
|
|
651
167
|
* @complexity `n`
|
|
@@ -691,7 +207,6 @@ class AstNode {
|
|
|
691
207
|
}
|
|
692
208
|
return 0;
|
|
693
209
|
}
|
|
694
|
-
this.getAttribute('verifyChild')(j, 1);
|
|
695
210
|
({childNodes} = this);
|
|
696
211
|
return getIndex(j, this);
|
|
697
212
|
}
|
|
@@ -706,25 +221,6 @@ class AstNode {
|
|
|
706
221
|
return parentNode ? parentNode.getAbsoluteIndex() + this.getRelativeIndex() : 0;
|
|
707
222
|
}
|
|
708
223
|
|
|
709
|
-
/**
|
|
710
|
-
* 获取当前节点的相对位置,或其第`j`个子节点的相对位置
|
|
711
|
-
* @param {number|undefined} j 子节点序号
|
|
712
|
-
* @complexity `n`
|
|
713
|
-
*/
|
|
714
|
-
#getPosition(j) {
|
|
715
|
-
return j === undefined
|
|
716
|
-
? this.parentNode?.posFromIndex(this.getRelativeIndex()) ?? {top: 0, left: 0}
|
|
717
|
-
: this.posFromIndex(this.getRelativeIndex(j));
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
/**
|
|
721
|
-
* 获取当前节点的行列位置和大小
|
|
722
|
-
* @complexity `n`
|
|
723
|
-
*/
|
|
724
|
-
getBoundingClientRect() {
|
|
725
|
-
return {...this.#getDimension(), ...this.getRootNode().posFromIndex(this.getAbsoluteIndex())};
|
|
726
|
-
}
|
|
727
|
-
|
|
728
224
|
/**
|
|
729
225
|
* 行数
|
|
730
226
|
* @complexity `n`
|
|
@@ -740,31 +236,6 @@ class AstNode {
|
|
|
740
236
|
get offsetWidth() {
|
|
741
237
|
return this.#getDimension().width;
|
|
742
238
|
}
|
|
743
|
-
|
|
744
|
-
/**
|
|
745
|
-
* 相对于父容器的行号
|
|
746
|
-
* @complexity `n`
|
|
747
|
-
*/
|
|
748
|
-
get offsetTop() {
|
|
749
|
-
return this.#getPosition().top;
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
/**
|
|
753
|
-
* 相对于父容器的列号
|
|
754
|
-
* @complexity `n`
|
|
755
|
-
*/
|
|
756
|
-
get offsetLeft() {
|
|
757
|
-
return this.#getPosition().left;
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
/**
|
|
761
|
-
* 位置、大小和padding
|
|
762
|
-
* @complexity `n`
|
|
763
|
-
*/
|
|
764
|
-
get style() {
|
|
765
|
-
return {...this.#getPosition(), ...this.#getDimension(), padding: this.getPadding()};
|
|
766
|
-
}
|
|
767
239
|
}
|
|
768
240
|
|
|
769
|
-
Parser.classes.AstNode = __filename;
|
|
770
241
|
module.exports = AstNode;
|