wikiparser-node 0.3.0 → 0.4.0
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/.eslintrc.json +472 -34
- package/README.md +1 -1
- package/config/default.json +58 -30
- package/config/llwiki.json +22 -90
- package/config/moegirl.json +51 -13
- package/config/zhwiki.json +1269 -0
- package/index.js +114 -104
- package/lib/element.js +448 -440
- package/lib/node.js +335 -115
- package/lib/ranges.js +27 -18
- package/lib/text.js +146 -0
- package/lib/title.js +13 -5
- package/mixin/attributeParent.js +70 -24
- package/mixin/fixedToken.js +14 -6
- package/mixin/hidden.js +6 -4
- package/mixin/sol.js +27 -10
- package/package.json +9 -3
- package/parser/brackets.js +22 -17
- package/parser/commentAndExt.js +18 -16
- package/parser/converter.js +14 -13
- package/parser/externalLinks.js +12 -11
- package/parser/hrAndDoubleUnderscore.js +23 -14
- package/parser/html.js +10 -9
- package/parser/links.js +15 -14
- package/parser/list.js +12 -11
- package/parser/magicLinks.js +12 -11
- package/parser/quotes.js +6 -5
- package/parser/selector.js +175 -0
- package/parser/table.js +25 -18
- package/printed/example.json +120 -0
- package/src/arg.js +56 -32
- package/src/atom/hidden.js +5 -2
- package/src/atom/index.js +17 -9
- package/src/attribute.js +182 -100
- package/src/converter.js +68 -41
- package/src/converterFlags.js +67 -45
- package/src/converterRule.js +117 -65
- package/src/extLink.js +66 -18
- package/src/gallery.js +42 -15
- package/src/heading.js +34 -15
- package/src/html.js +97 -35
- package/src/imageParameter.js +83 -54
- package/src/index.js +299 -178
- package/src/link/category.js +20 -52
- package/src/link/file.js +59 -28
- package/src/link/galleryImage.js +21 -7
- package/src/link/index.js +146 -60
- package/src/magicLink.js +34 -12
- package/src/nowiki/comment.js +22 -10
- package/src/nowiki/dd.js +37 -22
- package/src/nowiki/doubleUnderscore.js +16 -7
- package/src/nowiki/hr.js +11 -7
- package/src/nowiki/index.js +16 -9
- package/src/nowiki/list.js +2 -2
- package/src/nowiki/noinclude.js +8 -4
- package/src/nowiki/quote.js +11 -7
- package/src/onlyinclude.js +19 -7
- package/src/parameter.js +65 -38
- package/src/syntax.js +26 -20
- package/src/table/index.js +260 -165
- package/src/table/td.js +98 -52
- package/src/table/tr.js +102 -58
- package/src/tagPair/ext.js +27 -19
- package/src/tagPair/include.js +16 -11
- package/src/tagPair/index.js +64 -29
- package/src/transclude.js +170 -93
- package/test/api.js +83 -0
- package/test/real.js +133 -0
- package/test/test.js +28 -0
- package/test/util.js +80 -0
- package/tool/index.js +41 -31
- package/typings/api.d.ts +13 -0
- package/typings/array.d.ts +28 -0
- package/typings/event.d.ts +24 -0
- package/typings/index.d.ts +46 -4
- package/typings/node.d.ts +15 -9
- package/typings/parser.d.ts +7 -0
- package/typings/tool.d.ts +3 -2
- package/util/debug.js +21 -18
- package/util/string.js +40 -27
- package/typings/element.d.ts +0 -28
package/src/nowiki/index.js
CHANGED
|
@@ -1,33 +1,40 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const fixedToken = require('../../mixin/fixedToken'),
|
|
4
|
-
|
|
5
|
-
Token = require('..')
|
|
4
|
+
Parser = require('../..'),
|
|
5
|
+
Token = require('..'),
|
|
6
|
+
AstText = require('../../lib/text');
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* 纯文字Token,不会被解析
|
|
9
|
-
* @classdesc `{childNodes: [
|
|
10
|
+
* @classdesc `{childNodes: [AstText]}`
|
|
10
11
|
*/
|
|
11
12
|
class NowikiToken extends fixedToken(Token) {
|
|
12
13
|
type = 'ext-inner';
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
|
-
* @param {string} wikitext
|
|
16
|
+
* @param {string} wikitext wikitext
|
|
16
17
|
* @param {accum} accum
|
|
17
18
|
*/
|
|
18
19
|
constructor(wikitext, config = Parser.getConfig(), accum = []) {
|
|
19
20
|
super(wikitext, config, true, accum);
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* @override
|
|
25
|
+
* @this {NowikiToken & {firstChild: AstText, constructor: typeof NowikiToken}}
|
|
26
|
+
*/
|
|
23
27
|
cloneNode() {
|
|
24
|
-
const
|
|
25
|
-
token = Parser.run(() => new
|
|
26
|
-
token.type =
|
|
28
|
+
const {constructor, firstChild: {data}, type} = this,
|
|
29
|
+
token = Parser.run(() => new constructor(data, this.getAttribute('config')));
|
|
30
|
+
token.type = type;
|
|
27
31
|
return token;
|
|
28
32
|
}
|
|
29
33
|
|
|
30
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* @override
|
|
36
|
+
* @param {string} str 新文本
|
|
37
|
+
*/
|
|
31
38
|
setText(str) {
|
|
32
39
|
return super.setText(str, 0);
|
|
33
40
|
}
|
package/src/nowiki/list.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const sol = require('../../mixin/sol'),
|
|
4
|
-
|
|
4
|
+
Parser = require('../..'),
|
|
5
5
|
DdToken = require('./dd');
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* ;:*#
|
|
9
|
-
* @classdesc `{childNodes: [
|
|
9
|
+
* @classdesc `{childNodes: [AstText]}`
|
|
10
10
|
*/
|
|
11
11
|
class ListToken extends sol(DdToken) {
|
|
12
12
|
type = 'list';
|
package/src/nowiki/noinclude.js
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const hidden = require('../../mixin/hidden'),
|
|
4
|
-
|
|
4
|
+
Parser = require('../..'),
|
|
5
5
|
NowikiToken = require('.');
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* `<noinclude>`和`</noinclude>`,不可进行任何更改
|
|
9
|
-
* @classdesc `{childNodes: [
|
|
9
|
+
* @classdesc `{childNodes: [AstText]}`
|
|
10
10
|
*/
|
|
11
11
|
class NoincludeToken extends hidden(NowikiToken) {
|
|
12
12
|
type = 'noinclude';
|
|
13
13
|
|
|
14
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* @override
|
|
16
|
+
* @param {string} str 新文本
|
|
17
|
+
* @throws `Error` 不可更改
|
|
18
|
+
*/
|
|
15
19
|
setText(str) {
|
|
16
|
-
if (/^<\/?(?:(?:no|only)include|includeonly)(?:\s.*)?\/?>$/
|
|
20
|
+
if (/^<\/?(?:(?:no|only)include|includeonly)(?:\s.*)?\/?>$/isu.test(String(this))) {
|
|
17
21
|
throw new Error(`${this.constructor.name} 不可更改文字内容!`);
|
|
18
22
|
}
|
|
19
23
|
return super.setText(str);
|
package/src/nowiki/quote.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const Parser = require('../..'),
|
|
4
4
|
NowikiToken = require('.');
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* `<hr>`
|
|
8
|
-
* @classdesc `{childNodes: [
|
|
8
|
+
* @classdesc `{childNodes: [AstText]}`
|
|
9
9
|
*/
|
|
10
10
|
class QuoteToken extends NowikiToken {
|
|
11
11
|
type = 'quote';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* @param {number} n
|
|
14
|
+
* @param {number} n 字符串长度
|
|
15
15
|
* @param {accum} accum
|
|
16
16
|
*/
|
|
17
17
|
constructor(n, config = Parser.getConfig(), accum = []) {
|
|
@@ -19,12 +19,16 @@ class QuoteToken extends NowikiToken {
|
|
|
19
19
|
this.setAttribute('name', String(n));
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* @override
|
|
24
|
+
* @param {string} str 新文本
|
|
25
|
+
* @throws `RangeError` 错误的单引号语法
|
|
26
|
+
*/
|
|
23
27
|
setText(str) {
|
|
24
|
-
if (
|
|
25
|
-
|
|
28
|
+
if (str === "''" || str === "'''" || str === "'''''") {
|
|
29
|
+
return super.setText(str);
|
|
26
30
|
}
|
|
27
|
-
|
|
31
|
+
throw new RangeError(`${this.constructor.name} 的内部文本只能为连续 2/3/5 个"'"!`);
|
|
28
32
|
}
|
|
29
33
|
}
|
|
30
34
|
|
package/src/onlyinclude.js
CHANGED
|
@@ -1,40 +1,52 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const Parser = require('..'),
|
|
4
4
|
Token = require('.');
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* 嵌入时的`<onlyinclude>`
|
|
8
|
-
* @classdesc `{childNodes: ...
|
|
8
|
+
* @classdesc `{childNodes: ...AstText|Token}`
|
|
9
9
|
*/
|
|
10
10
|
class OnlyincludeToken extends Token {
|
|
11
11
|
type = 'onlyinclude';
|
|
12
12
|
|
|
13
|
+
/** 内部wikitext */
|
|
14
|
+
get innerText() {
|
|
15
|
+
return this.text();
|
|
16
|
+
}
|
|
17
|
+
|
|
13
18
|
/**
|
|
14
|
-
* @param {string} inner
|
|
19
|
+
* @param {string} inner 标签内部wikitext
|
|
15
20
|
* @param {accum} accum
|
|
16
21
|
*/
|
|
17
22
|
constructor(inner, config = Parser.getConfig(), accum = []) {
|
|
18
23
|
super(inner, config, true, accum);
|
|
19
24
|
}
|
|
20
25
|
|
|
26
|
+
/** @override */
|
|
21
27
|
cloneNode() {
|
|
22
|
-
const cloned = this.
|
|
28
|
+
const cloned = this.cloneChildNodes(),
|
|
23
29
|
token = Parser.run(() => new OnlyincludeToken(undefined, this.getAttribute('config')));
|
|
24
30
|
token.append(...cloned);
|
|
25
31
|
return token;
|
|
26
32
|
}
|
|
27
33
|
|
|
28
|
-
|
|
29
|
-
|
|
34
|
+
/**
|
|
35
|
+
* @override
|
|
36
|
+
* @param {string} selector
|
|
37
|
+
*/
|
|
38
|
+
toString(selector) {
|
|
39
|
+
return selector && this.matches(selector) ? '' : `<onlyinclude>${super.toString(selector)}</onlyinclude>`;
|
|
30
40
|
}
|
|
31
41
|
|
|
42
|
+
/** @override */
|
|
32
43
|
getPadding() {
|
|
33
44
|
return 13;
|
|
34
45
|
}
|
|
35
46
|
|
|
47
|
+
/** @override */
|
|
36
48
|
isPlain() {
|
|
37
|
-
return
|
|
49
|
+
return true;
|
|
38
50
|
}
|
|
39
51
|
}
|
|
40
52
|
|
package/src/parameter.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const {noWrap} = require('../util/string'),
|
|
4
4
|
fixedToken = require('../mixin/fixedToken'),
|
|
5
|
-
|
|
5
|
+
Parser = require('..'),
|
|
6
6
|
Token = require('.');
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -11,18 +11,30 @@ const {noWrap} = require('../util/string'),
|
|
|
11
11
|
*/
|
|
12
12
|
class ParameterToken extends fixedToken(Token) {
|
|
13
13
|
type = 'parameter';
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
/** 是否是匿名参数 */
|
|
16
|
+
get anon() {
|
|
17
|
+
return this.firstElementChild.childNodes.length === 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** getValue()的getter */
|
|
21
|
+
get value() {
|
|
22
|
+
return this.getValue();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
set value(value) {
|
|
26
|
+
this.setValue(value);
|
|
27
|
+
}
|
|
15
28
|
|
|
16
29
|
/**
|
|
17
|
-
* @param {string|number} key
|
|
18
|
-
* @param {string} value
|
|
30
|
+
* @param {string|number} key 参数名
|
|
31
|
+
* @param {string} value 参数值
|
|
19
32
|
* @param {accum} accum
|
|
20
33
|
*/
|
|
21
34
|
constructor(key, value, config = Parser.getConfig(), accum = []) {
|
|
22
35
|
super(undefined, config, true, accum);
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
keyToken = new AtomToken(this.anon ? undefined : key, 'parameter-key', config, accum, {
|
|
36
|
+
const AtomToken = require('./atom');
|
|
37
|
+
const keyToken = new AtomToken(typeof key === 'number' ? undefined : key, 'parameter-key', config, accum, {
|
|
26
38
|
'Stage-2': ':', '!HeadingToken': '',
|
|
27
39
|
}),
|
|
28
40
|
token = new Token(value, config, true, accum);
|
|
@@ -30,8 +42,9 @@ class ParameterToken extends fixedToken(Token) {
|
|
|
30
42
|
this.append(keyToken, token.setAttribute('stage', 2));
|
|
31
43
|
}
|
|
32
44
|
|
|
45
|
+
/** @override */
|
|
33
46
|
cloneNode() {
|
|
34
|
-
const [key, value] = this.
|
|
47
|
+
const [key, value] = this.cloneChildNodes(),
|
|
35
48
|
config = this.getAttribute('config');
|
|
36
49
|
return Parser.run(() => {
|
|
37
50
|
const token = new ParameterToken(this.anon ? Number(this.name) : undefined, undefined, config);
|
|
@@ -41,6 +54,7 @@ class ParameterToken extends fixedToken(Token) {
|
|
|
41
54
|
});
|
|
42
55
|
}
|
|
43
56
|
|
|
57
|
+
/** @override */
|
|
44
58
|
afterBuild() {
|
|
45
59
|
if (!this.anon) {
|
|
46
60
|
const name = this.firstElementChild.text().trim(),
|
|
@@ -51,19 +65,14 @@ class ParameterToken extends fixedToken(Token) {
|
|
|
51
65
|
parentNode.getArgs(name, false, false).add(this);
|
|
52
66
|
}
|
|
53
67
|
}
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
* @type {AstListener}
|
|
58
|
-
*/
|
|
59
|
-
const parameterListener = ({prevTarget}, data) => {
|
|
60
|
-
if (!that.anon) { // 匿名参数不管怎么变动还是匿名
|
|
61
|
-
const {firstElementChild} = that;
|
|
68
|
+
const /** @type {AstListener} */ parameterListener = ({prevTarget}, data) => {
|
|
69
|
+
if (!this.anon) { // 匿名参数不管怎么变动还是匿名
|
|
70
|
+
const {firstElementChild, name} = this;
|
|
62
71
|
if (prevTarget === firstElementChild) {
|
|
63
72
|
const newKey = firstElementChild.text().trim();
|
|
64
|
-
data.oldKey =
|
|
73
|
+
data.oldKey = name;
|
|
65
74
|
data.newKey = newKey;
|
|
66
|
-
|
|
75
|
+
this.setAttribute('name', newKey);
|
|
67
76
|
}
|
|
68
77
|
}
|
|
69
78
|
};
|
|
@@ -71,22 +80,33 @@ class ParameterToken extends fixedToken(Token) {
|
|
|
71
80
|
return this;
|
|
72
81
|
}
|
|
73
82
|
|
|
74
|
-
/**
|
|
75
|
-
|
|
76
|
-
|
|
83
|
+
/**
|
|
84
|
+
* @override
|
|
85
|
+
* @param {string} selector
|
|
86
|
+
* @returns {string}
|
|
87
|
+
*/
|
|
88
|
+
toString(selector) {
|
|
89
|
+
return this.anon && !(selector && this.matches(selector))
|
|
90
|
+
? this.lastElementChild.toString(selector)
|
|
91
|
+
: super.toString(selector, '=');
|
|
77
92
|
}
|
|
78
93
|
|
|
94
|
+
/** @override */
|
|
79
95
|
getGaps() {
|
|
80
96
|
return this.anon ? 0 : 1;
|
|
81
97
|
}
|
|
82
98
|
|
|
83
|
-
/**
|
|
99
|
+
/**
|
|
100
|
+
* @override
|
|
101
|
+
* @returns {string}
|
|
102
|
+
*/
|
|
84
103
|
text() {
|
|
85
104
|
return this.anon ? this.lastElementChild.text() : super.text('=');
|
|
86
105
|
}
|
|
87
106
|
|
|
88
107
|
/**
|
|
89
|
-
* @
|
|
108
|
+
* @override
|
|
109
|
+
* @param {ParameterToken} token 待替换的节点
|
|
90
110
|
* @complexity `n`
|
|
91
111
|
*/
|
|
92
112
|
safeReplaceWith(token) {
|
|
@@ -94,15 +114,20 @@ class ParameterToken extends fixedToken(Token) {
|
|
|
94
114
|
return this.replaceWith(token);
|
|
95
115
|
}
|
|
96
116
|
|
|
117
|
+
/** 获取参数值 */
|
|
97
118
|
getValue() {
|
|
98
119
|
const value = this.lastElementChild.text();
|
|
99
120
|
return this.anon && this.parentNode?.matches('template, magic-word#invoke') ? value : value.trim();
|
|
100
121
|
}
|
|
101
122
|
|
|
102
|
-
/**
|
|
123
|
+
/**
|
|
124
|
+
* 设置参数值
|
|
125
|
+
* @param {string} value 参数值
|
|
126
|
+
* @throws `SyntaxError` 非法的模板参数
|
|
127
|
+
*/
|
|
103
128
|
setValue(value) {
|
|
104
129
|
value = String(value);
|
|
105
|
-
const templateLike = this.
|
|
130
|
+
const templateLike = this.parentNode?.matches('template, magic-word#invoke'),
|
|
106
131
|
wikitext = `{{${templateLike ? ':T|' : 'lc:'}${this.anon ? '' : '1='}${value}}}`,
|
|
107
132
|
root = Parser.parse(wikitext, this.getAttribute('include'), 2, this.getAttribute('config')),
|
|
108
133
|
{childNodes: {length}, firstElementChild} = root,
|
|
@@ -113,15 +138,20 @@ class ParameterToken extends fixedToken(Token) {
|
|
|
113
138
|
) {
|
|
114
139
|
throw new SyntaxError(`非法的模板参数:${noWrap(value)}`);
|
|
115
140
|
}
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
lastElementChild.destroy();
|
|
120
|
-
this.lastElementChild.safeReplaceWith(newValue);
|
|
141
|
+
const {lastChild} = lastElementChild;
|
|
142
|
+
lastElementChild.destroy(true);
|
|
143
|
+
this.lastElementChild.safeReplaceWith(lastChild);
|
|
121
144
|
}
|
|
122
145
|
|
|
123
|
-
/**
|
|
124
|
-
|
|
146
|
+
/**
|
|
147
|
+
* 修改参数名
|
|
148
|
+
* @param {string} key 新参数名
|
|
149
|
+
* @param {boolean} force 是否无视冲突命名
|
|
150
|
+
* @throws `Error` 仅用于模板参数
|
|
151
|
+
* @throws `SyntaxError` 非法的模板参数名
|
|
152
|
+
* @throws `RangeError` 更名造成重复参数
|
|
153
|
+
*/
|
|
154
|
+
rename(key, force) {
|
|
125
155
|
if (typeof key !== 'string') {
|
|
126
156
|
this.typeError('rename', 'String');
|
|
127
157
|
}
|
|
@@ -138,8 +168,7 @@ class ParameterToken extends fixedToken(Token) {
|
|
|
138
168
|
throw new SyntaxError(`非法的模板参数名:${key}`);
|
|
139
169
|
}
|
|
140
170
|
const {lastElementChild} = firstElementChild,
|
|
141
|
-
{name} = lastElementChild
|
|
142
|
-
keyToken = lastElementChild.firstChild;
|
|
171
|
+
{name, firstChild} = lastElementChild;
|
|
143
172
|
if (this.name === name) {
|
|
144
173
|
Parser.warn('未改变实际参数名', name);
|
|
145
174
|
} else if (parentNode.hasArg(name)) {
|
|
@@ -149,10 +178,8 @@ class ParameterToken extends fixedToken(Token) {
|
|
|
149
178
|
throw new RangeError(`参数更名造成重复参数:${name}`);
|
|
150
179
|
}
|
|
151
180
|
}
|
|
152
|
-
|
|
153
|
-
firstElementChild.
|
|
154
|
-
lastElementChild.destroy();
|
|
155
|
-
this.firstElementChild.safeReplaceWith(keyToken);
|
|
181
|
+
lastElementChild.destroy(true);
|
|
182
|
+
this.firstElementChild.safeReplaceWith(firstChild);
|
|
156
183
|
}
|
|
157
184
|
}
|
|
158
185
|
|
package/src/syntax.js
CHANGED
|
@@ -2,30 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
const {undo} = require('../util/debug'),
|
|
4
4
|
{text} = require('../util/string'),
|
|
5
|
-
|
|
5
|
+
Parser = require('..'),
|
|
6
6
|
Token = require('.');
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* 满足特定语法格式的plain Token
|
|
10
|
-
* @classdesc `{childNodes: (
|
|
10
|
+
* @classdesc `{childNodes: (AstText|Token)[]}`
|
|
11
11
|
*/
|
|
12
12
|
class SyntaxToken extends Token {
|
|
13
13
|
#pattern;
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* @param {
|
|
17
|
-
* @param {RegExp} pattern
|
|
16
|
+
* @param {string} wikitext 语法wikitext
|
|
17
|
+
* @param {RegExp} pattern 语法正则
|
|
18
|
+
* @param {string} type Token.type
|
|
18
19
|
* @param {accum} accum
|
|
19
|
-
* @param {acceptable} acceptable
|
|
20
|
+
* @param {acceptable} acceptable 可接受的子节点设置
|
|
21
|
+
* @throws `RangeError` 含有g修饰符的语法正则
|
|
20
22
|
*/
|
|
21
23
|
constructor(wikitext, pattern, type = 'plain', config = Parser.getConfig(), accum = [], acceptable = null) {
|
|
24
|
+
if (pattern.global) {
|
|
25
|
+
throw new RangeError(`SyntaxToken 的语法正则不能含有 g 修饰符:${pattern}`);
|
|
26
|
+
}
|
|
22
27
|
super(wikitext, config, true, accum, acceptable);
|
|
23
28
|
this.type = type;
|
|
24
29
|
this.#pattern = pattern;
|
|
25
30
|
}
|
|
26
31
|
|
|
32
|
+
/** @override */
|
|
27
33
|
cloneNode() {
|
|
28
|
-
const cloned = this.
|
|
34
|
+
const cloned = this.cloneChildNodes(),
|
|
29
35
|
config = this.getAttribute('config'),
|
|
30
36
|
acceptable = this.getAttribute('acceptable');
|
|
31
37
|
return Parser.run(() => {
|
|
@@ -35,33 +41,33 @@ class SyntaxToken extends Token {
|
|
|
35
41
|
});
|
|
36
42
|
}
|
|
37
43
|
|
|
44
|
+
/** @override */
|
|
38
45
|
afterBuild() {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
const /** @type {AstListener} */ syntaxListener = (e, data) => {
|
|
47
|
+
const pattern = this.#pattern;
|
|
48
|
+
if (!Parser.running && !pattern.test(this.text())) {
|
|
49
|
+
undo(e, data);
|
|
50
|
+
Parser.error(`不可修改 ${this.constructor.name} 的语法!`, pattern);
|
|
51
|
+
throw new Error(`不可修改 ${this.constructor.name} 的语法!`);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
47
54
|
this.addEventListener(['remove', 'insert', 'replace', 'text'], syntaxListener);
|
|
48
55
|
return this;
|
|
49
56
|
}
|
|
50
57
|
|
|
51
58
|
/**
|
|
59
|
+
* @override
|
|
52
60
|
* @template {string} T
|
|
53
|
-
* @param {T} key
|
|
61
|
+
* @param {T} key 属性键
|
|
54
62
|
* @returns {TokenAttribute<T>}
|
|
55
63
|
*/
|
|
56
64
|
getAttribute(key) {
|
|
57
|
-
|
|
58
|
-
return this.#pattern;
|
|
59
|
-
}
|
|
60
|
-
return super.getAttribute(key);
|
|
65
|
+
return key === 'pattern' ? this.#pattern : super.getAttribute(key);
|
|
61
66
|
}
|
|
62
67
|
|
|
63
68
|
/**
|
|
64
|
-
* @
|
|
69
|
+
* @override
|
|
70
|
+
* @param {...Token} elements 待替换的子节点
|
|
65
71
|
* @complexity `n`
|
|
66
72
|
*/
|
|
67
73
|
replaceChildren(...elements) {
|