wikiparser-node 1.9.2 → 1.9.3
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/dist/base.d.ts +9 -3
- package/dist/index.js +0 -1
- package/dist/lib/element.d.ts +1 -0
- package/dist/lib/element.js +23 -249
- package/dist/lib/node.d.ts +3 -1
- package/dist/lib/range.js +12 -12
- package/dist/lib/text.d.ts +2 -1
- package/dist/lib/text.js +8 -2
- package/dist/mixin/hidden.js +5 -0
- package/dist/mixin/syntax.js +2 -1
- package/dist/parser/selector.js +223 -20
- package/dist/parser/table.js +3 -3
- package/dist/src/arg.d.ts +1 -2
- package/dist/src/arg.js +3 -2
- package/dist/src/atom.d.ts +5 -3
- package/dist/src/atom.js +28 -2
- package/dist/src/attribute.d.ts +1 -2
- package/dist/src/attribute.js +5 -2
- package/dist/src/attributes.d.ts +1 -2
- package/dist/src/attributes.js +7 -2
- package/dist/src/converter.d.ts +1 -2
- package/dist/src/converter.js +5 -2
- package/dist/src/converterFlags.d.ts +1 -2
- package/dist/src/converterFlags.js +5 -2
- package/dist/src/converterRule.d.ts +1 -3
- package/dist/src/converterRule.js +5 -3
- package/dist/src/extLink.d.ts +1 -2
- package/dist/src/extLink.js +5 -2
- package/dist/src/gallery.d.ts +1 -2
- package/dist/src/gallery.js +7 -4
- package/dist/src/heading.d.ts +1 -2
- package/dist/src/heading.js +3 -2
- package/dist/src/hidden.d.ts +1 -2
- package/dist/src/hidden.js +3 -2
- package/dist/src/html.d.ts +1 -2
- package/dist/src/html.js +3 -2
- package/dist/src/imageParameter.d.ts +1 -2
- package/dist/src/imageParameter.js +3 -2
- package/dist/src/imagemap.d.ts +1 -2
- package/dist/src/imagemap.js +3 -2
- package/dist/src/imagemapLink.d.ts +1 -1
- package/dist/src/imagemapLink.js +5 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.js +26 -1
- package/dist/src/link/base.d.ts +1 -2
- package/dist/src/link/base.js +5 -3
- package/dist/src/link/category.d.ts +1 -1
- package/dist/src/link/category.js +5 -1
- package/dist/src/link/file.d.ts +1 -1
- package/dist/src/link/file.js +3 -1
- package/dist/src/link/galleryImage.d.ts +1 -2
- package/dist/src/link/galleryImage.js +7 -33
- package/dist/src/link/index.d.ts +1 -2
- package/dist/src/link/index.js +5 -2
- package/dist/src/link/redirectTarget.d.ts +1 -2
- package/dist/src/link/redirectTarget.js +5 -2
- package/dist/src/magicLink.d.ts +2 -2
- package/dist/src/magicLink.js +8 -5
- package/dist/src/nested.d.ts +1 -2
- package/dist/src/nested.js +3 -2
- package/dist/src/nowiki/base.d.ts +1 -2
- package/dist/src/nowiki/base.js +1 -3
- package/dist/src/nowiki/comment.d.ts +1 -2
- package/dist/src/nowiki/comment.js +3 -2
- package/dist/src/nowiki/dd.d.ts +1 -1
- package/dist/src/nowiki/dd.js +3 -1
- package/dist/src/nowiki/doubleUnderscore.d.ts +1 -2
- package/dist/src/nowiki/doubleUnderscore.js +3 -2
- package/dist/src/nowiki/hr.d.ts +1 -1
- package/dist/src/nowiki/hr.js +3 -1
- package/dist/src/nowiki/index.d.ts +1 -1
- package/dist/src/nowiki/index.js +3 -1
- package/dist/src/nowiki/list.d.ts +1 -1
- package/dist/src/nowiki/list.js +3 -1
- package/dist/src/nowiki/listBase.d.ts +1 -1
- package/dist/src/nowiki/noinclude.d.ts +1 -5
- package/dist/src/nowiki/noinclude.js +3 -5
- package/dist/src/nowiki/quote.d.ts +1 -4
- package/dist/src/nowiki/quote.js +3 -4
- package/dist/src/onlyinclude.d.ts +1 -2
- package/dist/src/onlyinclude.js +3 -2
- package/dist/src/paramTag/index.d.ts +1 -2
- package/dist/src/paramTag/index.js +3 -2
- package/dist/src/parameter.d.ts +1 -7
- package/dist/src/parameter.js +3 -7
- package/dist/src/pre.d.ts +1 -2
- package/dist/src/pre.js +3 -2
- package/dist/src/redirect.d.ts +1 -2
- package/dist/src/redirect.js +3 -2
- package/dist/src/syntax.d.ts +4 -4
- package/dist/src/syntax.js +6 -3
- package/dist/src/table/base.d.ts +1 -2
- package/dist/src/table/base.js +0 -1
- package/dist/src/table/index.d.ts +1 -10
- package/dist/src/table/index.js +3 -10
- package/dist/src/table/td.d.ts +1 -7
- package/dist/src/table/td.js +3 -7
- package/dist/src/table/tr.d.ts +1 -1
- package/dist/src/table/tr.js +3 -1
- package/dist/src/table/trBase.d.ts +1 -1
- package/dist/src/tagPair/ext.d.ts +1 -2
- package/dist/src/tagPair/ext.js +7 -4
- package/dist/src/tagPair/include.d.ts +1 -3
- package/dist/src/tagPair/include.js +5 -3
- package/dist/src/tagPair/index.d.ts +1 -1
- package/dist/src/transclude.d.ts +1 -2
- package/dist/src/transclude.js +8 -5
- package/dist/util/constants.js +2 -2
- package/dist/util/debug.js +0 -2
- package/package.json +1 -1
package/dist/base.d.ts
CHANGED
|
@@ -53,8 +53,14 @@ export interface AstNode {
|
|
|
53
53
|
/** 以HTML格式打印 */
|
|
54
54
|
print(): string;
|
|
55
55
|
}
|
|
56
|
-
/**
|
|
57
|
-
interface
|
|
56
|
+
/** 所有节点的基类 */
|
|
57
|
+
interface Token extends AstNode {
|
|
58
|
+
readonly name?: string;
|
|
59
|
+
/**
|
|
60
|
+
* 符合选择器的所有后代节点
|
|
61
|
+
* @param selector 选择器
|
|
62
|
+
*/
|
|
63
|
+
querySelectorAll<T = Token>(selector: string): T[];
|
|
58
64
|
/** 保存为JSON */
|
|
59
65
|
json(): AST;
|
|
60
66
|
}
|
|
@@ -68,6 +74,6 @@ export interface Parser {
|
|
|
68
74
|
* @param include 是否嵌入
|
|
69
75
|
* @param maxStage 最大解析层级
|
|
70
76
|
*/
|
|
71
|
-
parse(wikitext: string, include?: boolean, maxStage?: number, config?: Config):
|
|
77
|
+
parse(wikitext: string, include?: boolean, maxStage?: number, config?: Config): Token;
|
|
72
78
|
}
|
|
73
79
|
export {};
|
package/dist/index.js
CHANGED
package/dist/lib/element.d.ts
CHANGED
package/dist/lib/element.js
CHANGED
|
@@ -6,34 +6,21 @@ const path = require("path");
|
|
|
6
6
|
const string_1 = require("../util/string");
|
|
7
7
|
const debug_1 = require("../util/debug");
|
|
8
8
|
const constants_1 = require("../util/constants");
|
|
9
|
-
const ranges_1 = require("./ranges");
|
|
10
|
-
const title_1 = require("./title");
|
|
11
9
|
const node_1 = require("./node");
|
|
12
|
-
/* NOT FOR BROWSER */
|
|
13
10
|
/**
|
|
14
|
-
*
|
|
15
|
-
* @param
|
|
16
|
-
* @param i 是否对大小写不敏感
|
|
11
|
+
* 将选择器转化为类型谓词
|
|
12
|
+
* @param selector 选择器
|
|
17
13
|
*/
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
* @param node 节点
|
|
28
|
-
* @param node.attributes 节点属性
|
|
29
|
-
* @param regex 语言正则
|
|
30
|
-
*/
|
|
31
|
-
const matchesLang = ({ attributes }, regex) => {
|
|
32
|
-
const lang = attributes?.['lang'];
|
|
33
|
-
return lang === undefined ? undefined : typeof lang === 'string' && regex.test(lang);
|
|
14
|
+
const getCondition = (selector) => {
|
|
15
|
+
/* NOT FOR BROWSER */
|
|
16
|
+
if (/[^a-z\-,\s]/u.test(selector)) {
|
|
17
|
+
const { checkToken } = require('../parser/selector');
|
|
18
|
+
return checkToken(selector);
|
|
19
|
+
}
|
|
20
|
+
/* NOT FOR BROWSER END */
|
|
21
|
+
const types = new Set(selector.split(',').map(str => str.trim()));
|
|
22
|
+
return (({ type }) => types.has(type));
|
|
34
23
|
};
|
|
35
|
-
const primitives = new Set(['string', 'number', 'boolean', 'undefined']);
|
|
36
|
-
/* NOT FOR BROWSER END */
|
|
37
24
|
/** 类似HTMLElement */
|
|
38
25
|
class AstElement extends node_1.AstNode {
|
|
39
26
|
/** 子节点总数 */
|
|
@@ -41,6 +28,13 @@ class AstElement extends node_1.AstNode {
|
|
|
41
28
|
return this.childNodes.length;
|
|
42
29
|
}
|
|
43
30
|
/* NOT FOR BROWSER */
|
|
31
|
+
set length(n) {
|
|
32
|
+
if (n >= 0 && n < this.length) {
|
|
33
|
+
for (let i = this.length - 1; i >= n; i--) {
|
|
34
|
+
this.removeAt(i);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
44
38
|
/** 全部非文本子节点 */
|
|
45
39
|
get children() {
|
|
46
40
|
return this.childNodes.filter((child) => child.type !== 'text');
|
|
@@ -153,27 +147,12 @@ class AstElement extends node_1.AstNode {
|
|
|
153
147
|
(0, debug_1.setChildNodes)(this, i, 0, [node]);
|
|
154
148
|
return node;
|
|
155
149
|
}
|
|
156
|
-
/**
|
|
157
|
-
* 将选择器转化为类型谓词
|
|
158
|
-
* @param selector 选择器
|
|
159
|
-
*/
|
|
160
|
-
#getCondition(selector) {
|
|
161
|
-
/* NOT FOR BROWSER */
|
|
162
|
-
if (/[^a-z\-,\s]/u.test(selector)) {
|
|
163
|
-
const { parseSelector } = require('../parser/selector');
|
|
164
|
-
const stack = parseSelector(selector);
|
|
165
|
-
return (token => stack.some(copy => token.#matchesArray(copy)));
|
|
166
|
-
}
|
|
167
|
-
/* NOT FOR BROWSER END */
|
|
168
|
-
const types = new Set(selector.split(',').map(str => str.trim()));
|
|
169
|
-
return (({ type }) => types.has(type));
|
|
170
|
-
}
|
|
171
150
|
/**
|
|
172
151
|
* 最近的祖先节点
|
|
173
152
|
* @param selector 选择器
|
|
174
153
|
*/
|
|
175
154
|
closest(selector) {
|
|
176
|
-
const condition =
|
|
155
|
+
const condition = getCondition(selector);
|
|
177
156
|
let { parentNode } = this;
|
|
178
157
|
while (parentNode) {
|
|
179
158
|
if (condition(parentNode)) {
|
|
@@ -207,7 +186,7 @@ class AstElement extends node_1.AstNode {
|
|
|
207
186
|
* @param selector 选择器
|
|
208
187
|
*/
|
|
209
188
|
querySelector(selector) {
|
|
210
|
-
const condition =
|
|
189
|
+
const condition = getCondition(selector);
|
|
211
190
|
return this.#getElementBy(condition);
|
|
212
191
|
}
|
|
213
192
|
/**
|
|
@@ -232,7 +211,7 @@ class AstElement extends node_1.AstNode {
|
|
|
232
211
|
* @param selector 选择器
|
|
233
212
|
*/
|
|
234
213
|
querySelectorAll(selector) {
|
|
235
|
-
const condition =
|
|
214
|
+
const condition = getCondition(selector);
|
|
236
215
|
return this.#getElementsBy(condition);
|
|
237
216
|
}
|
|
238
217
|
/**
|
|
@@ -302,6 +281,7 @@ class AstElement extends node_1.AstNode {
|
|
|
302
281
|
json(file, start = this.getAbsoluteIndex()) {
|
|
303
282
|
const json = {
|
|
304
283
|
...this,
|
|
284
|
+
type: this.type,
|
|
305
285
|
range: [start, start + this.toString().length],
|
|
306
286
|
childNodes: [],
|
|
307
287
|
};
|
|
@@ -320,218 +300,12 @@ class AstElement extends node_1.AstNode {
|
|
|
320
300
|
return json;
|
|
321
301
|
}
|
|
322
302
|
/* NOT FOR BROWSER */
|
|
323
|
-
/** 是否受保护。保护条件来自Token,这里仅提前用于:required和:optional伪选择器。 */
|
|
324
|
-
#isProtected() {
|
|
325
|
-
const { parentNode } = this;
|
|
326
|
-
if (!parentNode) {
|
|
327
|
-
return undefined;
|
|
328
|
-
}
|
|
329
|
-
const { childNodes, fixed } = parentNode;
|
|
330
|
-
return fixed
|
|
331
|
-
|| parentNode.getAttribute('protectedChildren').applyTo(childNodes)
|
|
332
|
-
.includes(childNodes.indexOf(this));
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* 获取属性
|
|
336
|
-
* @param key 属性键
|
|
337
|
-
*/
|
|
338
|
-
#getAttr(key) {
|
|
339
|
-
if (typeof this.getAttr === 'function') {
|
|
340
|
-
const attr = this.getAttr(key);
|
|
341
|
-
if (attr !== undefined) {
|
|
342
|
-
return attr;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
const val = this.getAttribute(key);
|
|
346
|
-
return val instanceof RegExp ? val.source : val;
|
|
347
|
-
}
|
|
348
|
-
/**
|
|
349
|
-
* 检查是否符合属性选择器
|
|
350
|
-
* @param key 属性键
|
|
351
|
-
* @param equal 比较符
|
|
352
|
-
* @param val 属性值
|
|
353
|
-
* @param i 是否对大小写不敏感
|
|
354
|
-
* @throws `RangeError` 复杂属性不能用于选择器
|
|
355
|
-
*/
|
|
356
|
-
#matchesAttr(key, equal, val = '', i) {
|
|
357
|
-
const isAttr = typeof this.hasAttr === 'function' && typeof this.getAttr === 'function';
|
|
358
|
-
if (!(key in this) && (!isAttr || !this.hasAttr(key))) {
|
|
359
|
-
return equal === '!=';
|
|
360
|
-
}
|
|
361
|
-
const v = toCase(val, i), thisVal = this.#getAttr(key);
|
|
362
|
-
if (!equal) {
|
|
363
|
-
return thisVal !== undefined && thisVal !== false;
|
|
364
|
-
}
|
|
365
|
-
if (equal === '~=') {
|
|
366
|
-
const thisVals = typeof thisVal === 'string' ? thisVal.split(/\s/u) : thisVal;
|
|
367
|
-
return Boolean(thisVals?.[Symbol.iterator])
|
|
368
|
-
&& [...thisVals].some(w => typeof w === 'string' && toCase(w, i) === v);
|
|
369
|
-
}
|
|
370
|
-
else if (!primitives.has(typeof thisVal) && !(thisVal instanceof title_1.Title)) {
|
|
371
|
-
throw new RangeError(`The complex attribute ${key} cannot be used in a selector!`);
|
|
372
|
-
}
|
|
373
|
-
const stringVal = toCase(String(thisVal), i);
|
|
374
|
-
switch (equal) {
|
|
375
|
-
case '|=':
|
|
376
|
-
return stringVal === v || stringVal.startsWith(`${v}-`);
|
|
377
|
-
case '^=':
|
|
378
|
-
return stringVal.startsWith(v);
|
|
379
|
-
case '$=':
|
|
380
|
-
return stringVal.endsWith(v);
|
|
381
|
-
case '*=':
|
|
382
|
-
return stringVal.includes(v);
|
|
383
|
-
case '!=':
|
|
384
|
-
return stringVal !== v;
|
|
385
|
-
default: // `=`
|
|
386
|
-
return stringVal === v;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
/**
|
|
390
|
-
* 检查是否符合解析后的选择器,不含节点关系
|
|
391
|
-
* @param step 解析后的选择器
|
|
392
|
-
* @throws `SyntaxError` 错误的正则伪选择器
|
|
393
|
-
* @throws `SyntaxError` 未定义的伪选择器
|
|
394
|
-
*/
|
|
395
|
-
#matches(step) {
|
|
396
|
-
const { parentNode, type, name, childNodes, link } = this, children = parentNode?.children, childrenOfType = children?.filter(({ type: t }) => t === type), siblingsCount = children?.length ?? 1, siblingsCountOfType = childrenOfType?.length ?? 1, index = (children?.indexOf(this) ?? 0) + 1, indexOfType = (childrenOfType?.indexOf(this) ?? 0) + 1, lastIndex = siblingsCount - index + 1, lastIndexOfType = siblingsCountOfType - indexOfType + 1;
|
|
397
|
-
return step.every(selector => {
|
|
398
|
-
if (typeof selector === 'string') {
|
|
399
|
-
switch (selector) { // 情形1:简单伪选择器、type和name
|
|
400
|
-
case '*':
|
|
401
|
-
return true;
|
|
402
|
-
case ':root':
|
|
403
|
-
return !parentNode;
|
|
404
|
-
case ':first-child':
|
|
405
|
-
return index === 1;
|
|
406
|
-
case ':first-of-type':
|
|
407
|
-
return indexOfType === 1;
|
|
408
|
-
case ':last-child':
|
|
409
|
-
return lastIndex === 1;
|
|
410
|
-
case ':last-of-type':
|
|
411
|
-
return lastIndexOfType === 1;
|
|
412
|
-
case ':only-child':
|
|
413
|
-
return siblingsCount === 1;
|
|
414
|
-
case ':only-of-type':
|
|
415
|
-
return siblingsCountOfType === 1;
|
|
416
|
-
case ':empty':
|
|
417
|
-
return !childNodes.some(({ type: t, data }) => t !== 'text' || data);
|
|
418
|
-
case ':parent':
|
|
419
|
-
return childNodes.some(({ type: t, data }) => t !== 'text' || data);
|
|
420
|
-
case ':header':
|
|
421
|
-
return type === 'heading';
|
|
422
|
-
case ':hidden':
|
|
423
|
-
return this.text() === '';
|
|
424
|
-
case ':visible':
|
|
425
|
-
return this.text() !== '';
|
|
426
|
-
case ':only-whitespace':
|
|
427
|
-
return this.text().trim() === '';
|
|
428
|
-
case ':any-link':
|
|
429
|
-
return type === 'link'
|
|
430
|
-
|| type === 'free-ext-link'
|
|
431
|
-
|| type === 'magic-link'
|
|
432
|
-
|| type === 'ext-link'
|
|
433
|
-
|| (type === 'file' || type === 'gallery-image') && link;
|
|
434
|
-
case ':local-link':
|
|
435
|
-
return (type === 'link' || type === 'file' || type === 'gallery-image')
|
|
436
|
-
&& link instanceof title_1.Title
|
|
437
|
-
&& link.title === '';
|
|
438
|
-
case ':invalid':
|
|
439
|
-
return type === 'table-inter' || type === 'image-parameter' && name === 'invalid';
|
|
440
|
-
case ':required':
|
|
441
|
-
return this.#isProtected() === true;
|
|
442
|
-
case ':optional':
|
|
443
|
-
return this.#isProtected() === false;
|
|
444
|
-
default: {
|
|
445
|
-
const [t, n] = selector.split('#');
|
|
446
|
-
return (!t || t === type) && (!n || n === name);
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
else if (selector.length === 4) { // 情形2:属性选择器
|
|
451
|
-
return this.#matchesAttr(...selector);
|
|
452
|
-
}
|
|
453
|
-
const [s, pseudo] = selector; // 情形3:复杂伪选择器
|
|
454
|
-
switch (pseudo) {
|
|
455
|
-
case 'is':
|
|
456
|
-
return this.matches(s);
|
|
457
|
-
case 'not':
|
|
458
|
-
return !this.matches(s);
|
|
459
|
-
case 'nth-child':
|
|
460
|
-
return nth(s, index);
|
|
461
|
-
case 'nth-of-type':
|
|
462
|
-
return nth(s, indexOfType);
|
|
463
|
-
case 'nth-last-child':
|
|
464
|
-
return nth(s, lastIndex);
|
|
465
|
-
case 'nth-last-of-type':
|
|
466
|
-
return nth(s, lastIndexOfType);
|
|
467
|
-
case 'contains':
|
|
468
|
-
return this.text().includes(s);
|
|
469
|
-
case 'has':
|
|
470
|
-
return Boolean(this.querySelector(s));
|
|
471
|
-
case 'lang': {
|
|
472
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
473
|
-
/^zh(?:-|$)/iu;
|
|
474
|
-
const regex = new RegExp(`^${s}(?:-|$)`, 'iu');
|
|
475
|
-
for (let node = this; node; node = node.parentNode) {
|
|
476
|
-
const result = matchesLang(node, regex);
|
|
477
|
-
if (result !== undefined) {
|
|
478
|
-
return result;
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
return false;
|
|
482
|
-
}
|
|
483
|
-
case 'regex': {
|
|
484
|
-
const mt = /^([^,]+),\s*\/(.+)\/([a-z]*)$/u.exec(s);
|
|
485
|
-
if (!mt) {
|
|
486
|
-
throw new SyntaxError(`Wrong usage of the regex pseudo-selector. Use ":regex('attr, /re/i')" format.`);
|
|
487
|
-
}
|
|
488
|
-
try {
|
|
489
|
-
return new RegExp(mt[2], mt[3]).test(String(this.#getAttr(mt[1].trim())));
|
|
490
|
-
}
|
|
491
|
-
catch {
|
|
492
|
-
throw new SyntaxError(`Invalid regular expression: /${mt[2]}/${mt[3]}`);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
default:
|
|
496
|
-
throw new SyntaxError(`Undefined pseudo-selector: ${pseudo}`);
|
|
497
|
-
}
|
|
498
|
-
});
|
|
499
|
-
}
|
|
500
|
-
/**
|
|
501
|
-
* 检查是否符合解析后的选择器
|
|
502
|
-
* @param copy 解析后的选择器
|
|
503
|
-
*/
|
|
504
|
-
#matchesArray(copy) {
|
|
505
|
-
const condition = [...copy], step = condition.pop();
|
|
506
|
-
if (this.#matches(step)) {
|
|
507
|
-
const { parentNode, previousElementSibling } = this;
|
|
508
|
-
switch (condition[condition.length - 1]?.relation) {
|
|
509
|
-
case undefined:
|
|
510
|
-
return true;
|
|
511
|
-
case '>':
|
|
512
|
-
return Boolean(parentNode && parentNode.#matchesArray(condition));
|
|
513
|
-
case '+':
|
|
514
|
-
return Boolean(previousElementSibling && previousElementSibling.#matchesArray(condition));
|
|
515
|
-
case '~': {
|
|
516
|
-
if (!parentNode) {
|
|
517
|
-
return false;
|
|
518
|
-
}
|
|
519
|
-
const { children } = parentNode;
|
|
520
|
-
return children.slice(0, children.indexOf(this))
|
|
521
|
-
.some(child => child.#matchesArray(condition));
|
|
522
|
-
}
|
|
523
|
-
default: // ' '
|
|
524
|
-
return this.getAncestors().some(ancestor => ancestor.#matchesArray(condition));
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
return false;
|
|
528
|
-
}
|
|
529
303
|
/**
|
|
530
304
|
* 检查是否符合选择器
|
|
531
305
|
* @param selector 选择器
|
|
532
306
|
*/
|
|
533
307
|
matches(selector) {
|
|
534
|
-
return selector === undefined ||
|
|
308
|
+
return selector === undefined || getCondition(selector)(this);
|
|
535
309
|
}
|
|
536
310
|
/**
|
|
537
311
|
* 类型选择器
|
package/dist/lib/node.d.ts
CHANGED
|
@@ -16,9 +16,11 @@ export interface CaretPosition {
|
|
|
16
16
|
/** 类似Node */
|
|
17
17
|
export declare abstract class AstNode implements AstNodeBase {
|
|
18
18
|
#private;
|
|
19
|
-
type: TokenTypes | 'text';
|
|
20
19
|
data?: string | undefined;
|
|
21
20
|
readonly childNodes: readonly AstNodes[];
|
|
21
|
+
/** 节点类型 */
|
|
22
|
+
abstract get type(): TokenTypes | 'text';
|
|
23
|
+
abstract set type(value: TokenTypes | 'text');
|
|
22
24
|
text(): string;
|
|
23
25
|
lint(): LintError[];
|
|
24
26
|
print(): string;
|
package/dist/lib/range.js
CHANGED
|
@@ -20,6 +20,14 @@ const getParent = (node) => {
|
|
|
20
20
|
}
|
|
21
21
|
throw new RangeError('The reference node has no parent node!');
|
|
22
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* 未初始化时抛出错误
|
|
25
|
+
* @param start 是否未初始化起点
|
|
26
|
+
* @throws `Error` 未初始化
|
|
27
|
+
*/
|
|
28
|
+
const notInit = (start) => {
|
|
29
|
+
throw new Error(`Please set the ${start ? 'start' : 'end'} position first!`);
|
|
30
|
+
};
|
|
23
31
|
/** 模拟Range对象 */
|
|
24
32
|
class AstRange {
|
|
25
33
|
#startContainer;
|
|
@@ -28,11 +36,11 @@ class AstRange {
|
|
|
28
36
|
#endOffset;
|
|
29
37
|
/** 起点容器 */
|
|
30
38
|
get startContainer() {
|
|
31
|
-
return this.#startContainer ??
|
|
39
|
+
return this.#startContainer ?? notInit(true);
|
|
32
40
|
}
|
|
33
41
|
/** 起点位置 */
|
|
34
42
|
get startOffset() {
|
|
35
|
-
return this.#startOffset ??
|
|
43
|
+
return this.#startOffset ?? notInit(true);
|
|
36
44
|
}
|
|
37
45
|
/** 起点绝对位置 */
|
|
38
46
|
get startIndex() {
|
|
@@ -44,11 +52,11 @@ class AstRange {
|
|
|
44
52
|
}
|
|
45
53
|
/** 终点容器 */
|
|
46
54
|
get endContainer() {
|
|
47
|
-
return this.#endContainer ??
|
|
55
|
+
return this.#endContainer ?? notInit(false);
|
|
48
56
|
}
|
|
49
57
|
/** 终点位置 */
|
|
50
58
|
get endOffset() {
|
|
51
|
-
return this.#endOffset ??
|
|
59
|
+
return this.#endOffset ?? notInit(false);
|
|
52
60
|
}
|
|
53
61
|
/** 终点绝对位置 */
|
|
54
62
|
get endIndex() {
|
|
@@ -67,14 +75,6 @@ class AstRange {
|
|
|
67
75
|
const { startContainer, endContainer } = this;
|
|
68
76
|
return startContainer.contains(endContainer) ? startContainer : startContainer.parentNode;
|
|
69
77
|
}
|
|
70
|
-
/**
|
|
71
|
-
* 未初始化时抛出错误
|
|
72
|
-
* @param start 是否未初始化起点
|
|
73
|
-
* @throws `Error` 未初始化
|
|
74
|
-
*/
|
|
75
|
-
#notInit(start) {
|
|
76
|
-
throw new Error(`Please set the ${start ? 'start' : 'end'} position first!`);
|
|
77
|
-
}
|
|
78
78
|
/**
|
|
79
79
|
* 检查起点和终点的设置是否有效
|
|
80
80
|
* @throws `RangeError` 起点和终点不是兄弟节点
|
package/dist/lib/text.d.ts
CHANGED
|
@@ -3,11 +3,12 @@ import type { LintError } from '../base';
|
|
|
3
3
|
/** 文本节点 */
|
|
4
4
|
export declare class AstText extends AstNode {
|
|
5
5
|
#private;
|
|
6
|
-
readonly type = "text";
|
|
7
6
|
readonly name: undefined;
|
|
8
7
|
readonly data: string;
|
|
8
|
+
get type(): 'text';
|
|
9
9
|
/** 文本长度 */
|
|
10
10
|
get length(): number;
|
|
11
|
+
set length(n: number);
|
|
11
12
|
/** @param text 包含文本 */
|
|
12
13
|
constructor(text: string);
|
|
13
14
|
/** 可见部分 */
|
package/dist/lib/text.js
CHANGED
|
@@ -76,20 +76,26 @@ const source = String.raw `<\s*(?:/\s*)?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*?\])
|
|
|
76
76
|
];
|
|
77
77
|
/** 文本节点 */
|
|
78
78
|
class AstText extends node_1.AstNode {
|
|
79
|
-
type = 'text';
|
|
80
79
|
data = '';
|
|
80
|
+
get type() {
|
|
81
|
+
return 'text';
|
|
82
|
+
}
|
|
81
83
|
/* NOT FOR BROWSER */
|
|
82
84
|
/** 文本长度 */
|
|
83
85
|
get length() {
|
|
84
86
|
return this.data.length;
|
|
85
87
|
}
|
|
88
|
+
set length(n) {
|
|
89
|
+
if (n >= 0 && n < this.length) {
|
|
90
|
+
this.replaceData(this.data.slice(0, n));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
86
93
|
/* NOT FOR BROWSER END */
|
|
87
94
|
/** @param text 包含文本 */
|
|
88
95
|
constructor(text) {
|
|
89
96
|
super();
|
|
90
97
|
Object.defineProperties(this, {
|
|
91
98
|
childNodes: { enumerable: false, configurable: false },
|
|
92
|
-
type: { enumerable: false, writable: false },
|
|
93
99
|
data: {
|
|
94
100
|
value: text,
|
|
95
101
|
/* NOT FOR BROWSER */
|
package/dist/mixin/hidden.js
CHANGED
|
@@ -21,6 +21,11 @@ const hiddenToken = (linter) => (constructor, _) => {
|
|
|
21
21
|
// @ts-expect-error private argument
|
|
22
22
|
return linter ? [] : super.lint(start);
|
|
23
23
|
}
|
|
24
|
+
/* NOT FOR BROWSER */
|
|
25
|
+
/** @private */
|
|
26
|
+
dispatchEvent() {
|
|
27
|
+
//
|
|
28
|
+
}
|
|
24
29
|
}
|
|
25
30
|
(0, debug_1.mixin)(AnyHiddenToken, constructor);
|
|
26
31
|
return AnyHiddenToken;
|
package/dist/mixin/syntax.js
CHANGED
|
@@ -23,8 +23,9 @@ const syntax = (pattern) => (constructor, _) => {
|
|
|
23
23
|
}
|
|
24
24
|
/** @private */
|
|
25
25
|
afterBuild() {
|
|
26
|
+
super.afterBuild();
|
|
26
27
|
const /** @implements */ syntaxListener = (e, data) => {
|
|
27
|
-
if (!debug_1.Shadow.running && !this.pattern.test(
|
|
28
|
+
if (!debug_1.Shadow.running && !this.pattern.test((0, string_1.text)(this.childNodes))) {
|
|
28
29
|
(0, debug_1.undo)(e, data);
|
|
29
30
|
this.constructorError('cannot modify the syntax pattern');
|
|
30
31
|
}
|