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/src/extLink.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const Parser = require('..'),
|
|
4
|
-
{noWrap, normalizeSpace} = require('../util/string'),
|
|
5
4
|
Token = require('.'),
|
|
6
5
|
MagicLinkToken = require('./magicLink');
|
|
7
6
|
|
|
@@ -13,78 +12,37 @@ class ExtLinkToken extends Token {
|
|
|
13
12
|
type = 'ext-link';
|
|
14
13
|
#space;
|
|
15
14
|
|
|
16
|
-
/**
|
|
17
|
-
* 协议
|
|
18
|
-
* @this {{firstChild: MagicLinkToken}}
|
|
19
|
-
*/
|
|
20
|
-
get protocol() {
|
|
21
|
-
return this.firstChild.protocol;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** @this {{firstChild: MagicLinkToken}} */
|
|
25
|
-
set protocol(value) {
|
|
26
|
-
this.firstChild.protocol = value;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* 和内链保持一致
|
|
31
|
-
* @this {{firstChild: MagicLinkToken}}
|
|
32
|
-
*/
|
|
33
|
-
get link() {
|
|
34
|
-
return this.firstChild.link;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
set link(url) {
|
|
38
|
-
this.setTarget(url);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** 链接显示文字 */
|
|
42
|
-
get innerText() {
|
|
43
|
-
return this.length > 1
|
|
44
|
-
? this.lastChild.text()
|
|
45
|
-
: `[${this.getRootNode().querySelectorAll('ext-link[childElementCount=1]').indexOf(this) + 1}]`;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
15
|
/**
|
|
49
16
|
* @param {string} url 网址
|
|
50
17
|
* @param {string} space 空白字符
|
|
51
18
|
* @param {string} text 链接文字
|
|
52
|
-
* @param {accum} accum
|
|
19
|
+
* @param {import('../typings/token').accum} accum
|
|
53
20
|
*/
|
|
54
21
|
constructor(url, space = '', text = '', config = Parser.getConfig(), accum = []) {
|
|
55
22
|
super(undefined, config, true, accum, {
|
|
56
|
-
MagicLinkToken: 0, Token: 1,
|
|
57
23
|
});
|
|
58
24
|
this.insertAt(new MagicLinkToken(url, true, config, accum));
|
|
59
25
|
this.#space = space;
|
|
60
26
|
if (text) {
|
|
61
27
|
const inner = new Token(text, config, true, accum, {
|
|
62
|
-
'Stage-7': ':', ConverterToken: ':',
|
|
63
28
|
});
|
|
64
29
|
inner.type = 'ext-link-text';
|
|
65
30
|
this.insertAt(inner.setAttribute('stage', Parser.MAX_STAGE - 1));
|
|
66
31
|
}
|
|
67
|
-
this.getAttribute('protectChildren')(0);
|
|
68
32
|
}
|
|
69
33
|
|
|
70
34
|
/**
|
|
71
35
|
* @override
|
|
72
|
-
* @param {string} selector
|
|
73
36
|
*/
|
|
74
37
|
toString(selector) {
|
|
75
|
-
if (
|
|
76
|
-
return '';
|
|
77
|
-
} else if (this.length === 1) {
|
|
38
|
+
if (this.length === 1) {
|
|
78
39
|
return `[${super.toString(selector)}${this.#space}]`;
|
|
79
40
|
}
|
|
80
|
-
this.#correct();
|
|
81
|
-
normalizeSpace(this.lastChild);
|
|
82
41
|
return `[${super.toString(selector, this.#space)}]`;
|
|
83
42
|
}
|
|
84
43
|
|
|
85
44
|
/** @override */
|
|
86
45
|
text() {
|
|
87
|
-
normalizeSpace(this.childNodes[1]);
|
|
88
46
|
return `[${super.text(' ')}]`;
|
|
89
47
|
}
|
|
90
48
|
|
|
@@ -95,86 +53,8 @@ class ExtLinkToken extends Token {
|
|
|
95
53
|
|
|
96
54
|
/** @override */
|
|
97
55
|
getGaps() {
|
|
98
|
-
this.#correct();
|
|
99
56
|
return this.#space.length;
|
|
100
57
|
}
|
|
101
|
-
|
|
102
|
-
/** @override */
|
|
103
|
-
print() {
|
|
104
|
-
return super.print(
|
|
105
|
-
this.length > 1 ? {pre: '[', sep: this.#space, post: ']'} : {pre: '[', post: `${this.#space}]`},
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/** @override */
|
|
110
|
-
cloneNode() {
|
|
111
|
-
const [url, text] = this.cloneChildNodes();
|
|
112
|
-
return Parser.run(() => {
|
|
113
|
-
const token = new ExtLinkToken(undefined, '', '', this.getAttribute('config'));
|
|
114
|
-
token.firstChild.safeReplaceWith(url);
|
|
115
|
-
if (text) {
|
|
116
|
-
token.insertAt(text);
|
|
117
|
-
}
|
|
118
|
-
return token;
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/** 修正空白字符 */
|
|
123
|
-
#correct() {
|
|
124
|
-
if (!this.#space && this.length > 1
|
|
125
|
-
// 都替换成`<`肯定不对,但无妨
|
|
126
|
-
&& /^[^[\]<>"{\0-\x1F\x7F\p{Zs}\uFFFD]/u.test(this.lastChild.text().replace(/&[lg]t;/u, '<'))
|
|
127
|
-
) {
|
|
128
|
-
this.#space = ' ';
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* 获取网址
|
|
134
|
-
* @this {{firstChild: MagicLinkToken}}
|
|
135
|
-
*/
|
|
136
|
-
getUrl() {
|
|
137
|
-
return this.firstChild.getUrl();
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* 设置链接目标
|
|
142
|
-
* @param {string|URL} url 网址
|
|
143
|
-
* @throws `SyntaxError` 非法的外链目标
|
|
144
|
-
*/
|
|
145
|
-
setTarget(url) {
|
|
146
|
-
url = String(url);
|
|
147
|
-
const root = Parser.parse(`[${url}]`, this.getAttribute('include'), 8, this.getAttribute('config')),
|
|
148
|
-
{length, firstChild: extLink} = root;
|
|
149
|
-
if (length !== 1 || extLink.type !== 'ext-link' || extLink.length !== 1) {
|
|
150
|
-
throw new SyntaxError(`非法的外链目标:${url}`);
|
|
151
|
-
}
|
|
152
|
-
const {firstChild} = extLink;
|
|
153
|
-
extLink.destroy(true);
|
|
154
|
-
this.firstChild.safeReplaceWith(firstChild);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* 设置链接显示文字
|
|
159
|
-
* @param {string} text 链接显示文字
|
|
160
|
-
* @throws `SyntaxError` 非法的链接显示文字
|
|
161
|
-
*/
|
|
162
|
-
setLinkText(text) {
|
|
163
|
-
text = String(text);
|
|
164
|
-
const root = Parser.parse(`[//url ${text}]`, this.getAttribute('include'), 8, this.getAttribute('config')),
|
|
165
|
-
{length, firstChild: extLink} = root;
|
|
166
|
-
if (length !== 1 || extLink.type !== 'ext-link' || extLink.length !== 2) {
|
|
167
|
-
throw new SyntaxError(`非法的外链文字:${noWrap(text)}`);
|
|
168
|
-
}
|
|
169
|
-
const {lastChild} = extLink;
|
|
170
|
-
if (this.length === 1) {
|
|
171
|
-
this.insertAt(lastChild);
|
|
172
|
-
} else {
|
|
173
|
-
this.lastChild.safeReplaceWith(lastChild);
|
|
174
|
-
}
|
|
175
|
-
this.#space ||= ' ';
|
|
176
|
-
}
|
|
177
58
|
}
|
|
178
59
|
|
|
179
|
-
Parser.classes.ExtLinkToken = __filename;
|
|
180
60
|
module.exports = ExtLinkToken;
|
package/src/gallery.js
CHANGED
|
@@ -13,25 +13,18 @@ class GalleryToken extends Token {
|
|
|
13
13
|
type = 'ext-inner';
|
|
14
14
|
name = 'gallery';
|
|
15
15
|
|
|
16
|
-
/** 所有图片 */
|
|
17
|
-
get images() {
|
|
18
|
-
return this.childNodes.filter(({type}) => type === 'gallery-image');
|
|
19
|
-
}
|
|
20
|
-
|
|
21
16
|
/**
|
|
22
17
|
* @param {string} inner 标签内部wikitext
|
|
23
|
-
* @param {accum} accum
|
|
18
|
+
* @param {import('../typings/token').accum} accum
|
|
24
19
|
*/
|
|
25
20
|
constructor(inner, config = Parser.getConfig(), accum = []) {
|
|
26
21
|
super(undefined, config, true, accum, {
|
|
27
|
-
AstText: ':', GalleryImageToken: ':', HiddenToken: ':',
|
|
28
22
|
});
|
|
29
23
|
for (const line of inner?.split('\n') ?? []) {
|
|
30
24
|
const matches = /^([^|]+)(?:\|(.*))?/u.exec(line);
|
|
31
25
|
if (!matches) {
|
|
32
26
|
super.insertAt(line.trim()
|
|
33
27
|
? new HiddenToken(line, undefined, config, [], {
|
|
34
|
-
AstText: ':',
|
|
35
28
|
})
|
|
36
29
|
: line);
|
|
37
30
|
continue;
|
|
@@ -42,7 +35,6 @@ class GalleryToken extends Token {
|
|
|
42
35
|
super.insertAt(new GalleryImageToken(file, alt, config, accum));
|
|
43
36
|
} else {
|
|
44
37
|
super.insertAt(new HiddenToken(line, undefined, config, [], {
|
|
45
|
-
AstText: ':',
|
|
46
38
|
}));
|
|
47
39
|
}
|
|
48
40
|
}
|
|
@@ -50,7 +42,6 @@ class GalleryToken extends Token {
|
|
|
50
42
|
|
|
51
43
|
/**
|
|
52
44
|
* @override
|
|
53
|
-
* @param {string} selector
|
|
54
45
|
*/
|
|
55
46
|
toString(selector) {
|
|
56
47
|
return super.toString(selector, '\n');
|
|
@@ -66,18 +57,13 @@ class GalleryToken extends Token {
|
|
|
66
57
|
return 1;
|
|
67
58
|
}
|
|
68
59
|
|
|
69
|
-
/** @override */
|
|
70
|
-
print() {
|
|
71
|
-
return super.print({sep: '\n'});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
60
|
/**
|
|
75
61
|
* @override
|
|
76
62
|
* @param {number} start 起始位置
|
|
77
63
|
*/
|
|
78
64
|
lint(start = this.getAbsoluteIndex()) {
|
|
79
65
|
const {top, left} = this.getRootNode().posFromIndex(start),
|
|
80
|
-
/** @type {LintError[]} */ errors = [];
|
|
66
|
+
/** @type {import('../typings/token').LintError[]} */ errors = [];
|
|
81
67
|
for (let i = 0, startIndex = start; i < this.length; i++) {
|
|
82
68
|
const child = this.childNodes[i],
|
|
83
69
|
str = String(child),
|
|
@@ -104,46 +90,6 @@ class GalleryToken extends Token {
|
|
|
104
90
|
}
|
|
105
91
|
return errors;
|
|
106
92
|
}
|
|
107
|
-
|
|
108
|
-
/** @override */
|
|
109
|
-
cloneNode() {
|
|
110
|
-
const cloned = this.cloneChildNodes();
|
|
111
|
-
return Parser.run(() => {
|
|
112
|
-
const token = new GalleryToken(undefined, this.getAttribute('config'));
|
|
113
|
-
token.append(...cloned);
|
|
114
|
-
return token;
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* 插入图片
|
|
120
|
-
* @param {string} file 图片文件名
|
|
121
|
-
* @param {number} i 插入位置
|
|
122
|
-
* @throws `SyntaxError` 非法的文件名
|
|
123
|
-
*/
|
|
124
|
-
insertImage(file, i = this.length) {
|
|
125
|
-
const title = this.normalizeTitle(file, 6, true, true);
|
|
126
|
-
if (title.valid) {
|
|
127
|
-
const token = Parser.run(() => new GalleryImageToken(file, undefined, this.getAttribute('config')));
|
|
128
|
-
return this.insertAt(token, i);
|
|
129
|
-
}
|
|
130
|
-
throw new SyntaxError(`非法的文件名:${file}`);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* @override
|
|
135
|
-
* @template {string|Token} T
|
|
136
|
-
* @param {T} token 待插入的节点
|
|
137
|
-
* @param {number} i 插入位置
|
|
138
|
-
* @throws `RangeError` 插入不可见内容
|
|
139
|
-
*/
|
|
140
|
-
insertAt(token, i = 0) {
|
|
141
|
-
if (typeof token === 'string' && token.trim() || token instanceof HiddenToken) {
|
|
142
|
-
throw new RangeError('请勿向图库中插入不可见内容!');
|
|
143
|
-
}
|
|
144
|
-
return super.insertAt(token, i);
|
|
145
|
-
}
|
|
146
93
|
}
|
|
147
94
|
|
|
148
|
-
Parser.classes.GalleryToken = __filename;
|
|
149
95
|
module.exports = GalleryToken;
|
package/src/hasNowiki/index.js
CHANGED
|
@@ -12,7 +12,7 @@ class HasNowikiToken extends Token {
|
|
|
12
12
|
/**
|
|
13
13
|
* @param {string} wikitext wikitext
|
|
14
14
|
* @param {string} type type
|
|
15
|
-
* @param {accum} accum
|
|
15
|
+
* @param {import('../../typings/token').accum} accum
|
|
16
16
|
*/
|
|
17
17
|
constructor(wikitext, type, config = Parser.getConfig(), accum = []) {
|
|
18
18
|
wikitext = wikitext.replace(
|
|
@@ -24,21 +24,9 @@ class HasNowikiToken extends Token {
|
|
|
24
24
|
},
|
|
25
25
|
);
|
|
26
26
|
super(wikitext, config, true, accum, {
|
|
27
|
-
AstText: ':', NoincludeToken: ':',
|
|
28
27
|
});
|
|
29
28
|
this.type = type;
|
|
30
29
|
}
|
|
31
|
-
|
|
32
|
-
/** @override */
|
|
33
|
-
cloneNode() {
|
|
34
|
-
const cloned = this.cloneChildNodes();
|
|
35
|
-
return Parser.run(() => {
|
|
36
|
-
const token = new HasNowikiToken(undefined, this.type, this.getAttribute('config'));
|
|
37
|
-
token.append(...cloned);
|
|
38
|
-
return token;
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
30
|
}
|
|
42
31
|
|
|
43
|
-
Parser.classes.HasNowikiToken = __filename;
|
|
44
32
|
module.exports = HasNowikiToken;
|
package/src/hasNowiki/pre.js
CHANGED
|
@@ -12,29 +12,17 @@ class PreToken extends HasNowikiToken {
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* @param {string} wikitext wikitext
|
|
15
|
-
* @param {accum} accum
|
|
15
|
+
* @param {import('../../typings/token').accum} accum
|
|
16
16
|
*/
|
|
17
17
|
constructor(wikitext, config = Parser.getConfig(), accum = []) {
|
|
18
18
|
super(wikitext, 'ext-inner', config, accum);
|
|
19
19
|
this.setAttribute('stage', Parser.MAX_STAGE - 1);
|
|
20
|
-
this.setAttribute('acceptable', {AstText: ':', NoincludeToken: ':', ConverterToken: ':'});
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
/** @override */
|
|
24
23
|
isPlain() {
|
|
25
24
|
return true;
|
|
26
25
|
}
|
|
27
|
-
|
|
28
|
-
/** @override */
|
|
29
|
-
cloneNode() {
|
|
30
|
-
const cloned = this.cloneChildNodes();
|
|
31
|
-
return Parser.run(() => {
|
|
32
|
-
const token = new PreToken(undefined, this.getAttribute('config'));
|
|
33
|
-
token.append(...cloned);
|
|
34
|
-
return token;
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
26
|
}
|
|
38
27
|
|
|
39
|
-
Parser.classes.PreToken = __filename;
|
|
40
28
|
module.exports = PreToken;
|
package/src/heading.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const {generateForSelf} = require('../util/lint'),
|
|
4
|
-
fixedToken = require('../mixin/fixedToken'),
|
|
5
|
-
sol = require('../mixin/sol'),
|
|
6
4
|
Parser = require('..'),
|
|
7
5
|
Token = require('.'),
|
|
8
6
|
SyntaxToken = require('./syntax');
|
|
@@ -11,55 +9,41 @@ const {generateForSelf} = require('../util/lint'),
|
|
|
11
9
|
* 章节标题
|
|
12
10
|
* @classdesc `{childNodes: [Token, SyntaxToken]}`
|
|
13
11
|
*/
|
|
14
|
-
class HeadingToken extends
|
|
12
|
+
class HeadingToken extends Token {
|
|
15
13
|
type = 'heading';
|
|
16
14
|
|
|
17
|
-
/** 内部wikitext */
|
|
18
|
-
get innerText() {
|
|
19
|
-
return this.firstChild.text();
|
|
20
|
-
}
|
|
21
|
-
|
|
22
15
|
/**
|
|
23
16
|
* @param {number} level 标题层级
|
|
24
17
|
* @param {string[]} input 标题文字
|
|
25
|
-
* @param {accum} accum
|
|
18
|
+
* @param {import('../typings/token').accum} accum
|
|
26
19
|
*/
|
|
27
20
|
constructor(level, input, config = Parser.getConfig(), accum = []) {
|
|
28
21
|
super(undefined, config, true, accum);
|
|
29
22
|
this.setAttribute('name', String(level));
|
|
30
23
|
const token = new Token(input[0], config, true, accum);
|
|
31
24
|
token.type = 'heading-title';
|
|
32
|
-
token.setAttribute('name', this.name);
|
|
33
25
|
token.setAttribute('stage', 2);
|
|
34
26
|
const trail = new SyntaxToken(input[1], /^[^\S\n]*$/u, 'heading-trail', config, accum, {
|
|
35
|
-
'Stage-1': ':', '!ExtToken': '',
|
|
36
27
|
});
|
|
37
28
|
this.append(token, trail);
|
|
38
29
|
}
|
|
39
30
|
|
|
40
31
|
/**
|
|
41
32
|
* @override
|
|
42
|
-
* @this {{prependNewLine(): ''|'\n'} & HeadingToken}
|
|
43
|
-
* @param {string} selector
|
|
44
33
|
* @returns {string}
|
|
45
34
|
*/
|
|
46
35
|
toString(selector) {
|
|
47
36
|
const equals = '='.repeat(Number(this.name));
|
|
48
|
-
return
|
|
49
|
-
? ''
|
|
50
|
-
: `${this.prependNewLine()}${equals}${
|
|
51
|
-
this.firstChild.toString(selector)
|
|
52
|
-
}${equals}${this.lastChild.toString(selector)}`;
|
|
37
|
+
return `${equals}${this.firstChild.toString()}${equals}${this.lastChild.toString()}`;
|
|
53
38
|
}
|
|
54
39
|
|
|
55
40
|
/**
|
|
56
41
|
* @override
|
|
57
|
-
* @this {HeadingToken & {prependNewLine(): ''|'\n'}}
|
|
58
42
|
* @returns {string}
|
|
59
43
|
*/
|
|
60
44
|
text() {
|
|
61
45
|
const equals = '='.repeat(Number(this.name));
|
|
62
|
-
return `${
|
|
46
|
+
return `${equals}${this.firstChild.text()}${equals}`;
|
|
63
47
|
}
|
|
64
48
|
|
|
65
49
|
/** @override */
|
|
@@ -72,12 +56,6 @@ class HeadingToken extends fixedToken(sol(Token)) {
|
|
|
72
56
|
return Number(this.name);
|
|
73
57
|
}
|
|
74
58
|
|
|
75
|
-
/** @override */
|
|
76
|
-
print() {
|
|
77
|
-
const equals = '='.repeat(Number(this.name));
|
|
78
|
-
return super.print({pre: equals, sep: equals});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
59
|
/**
|
|
82
60
|
* @override
|
|
83
61
|
* @param {number} start 起始位置
|
|
@@ -100,35 +78,6 @@ class HeadingToken extends fixedToken(sol(Token)) {
|
|
|
100
78
|
}
|
|
101
79
|
return errors;
|
|
102
80
|
}
|
|
103
|
-
|
|
104
|
-
/** @override */
|
|
105
|
-
cloneNode() {
|
|
106
|
-
const [title, trail] = this.cloneChildNodes();
|
|
107
|
-
return Parser.run(() => {
|
|
108
|
-
const token = new HeadingToken(Number(this.name), [], this.getAttribute('config'));
|
|
109
|
-
token.firsthild.safeReplaceWith(title);
|
|
110
|
-
token.lastChild.safeReplaceWith(trail);
|
|
111
|
-
return token;
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* 设置标题层级
|
|
117
|
-
* @param {number} n 标题层级
|
|
118
|
-
*/
|
|
119
|
-
setLevel(n) {
|
|
120
|
-
if (!Number.isInteger(n)) {
|
|
121
|
-
this.typeError('setLevel', 'Number');
|
|
122
|
-
}
|
|
123
|
-
n = Math.min(Math.max(n, 1), 6);
|
|
124
|
-
this.setAttribute('name', String(n)).firstChild.setAttribute('name', this.name);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/** 移除标题后的不可见内容 */
|
|
128
|
-
removeTrail() {
|
|
129
|
-
this.lastChild.replaceChildren();
|
|
130
|
-
}
|
|
131
81
|
}
|
|
132
82
|
|
|
133
|
-
Parser.classes.HeadingToken = __filename;
|
|
134
83
|
module.exports = HeadingToken;
|
package/src/html.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const {generateForSelf} = require('../util/lint'),
|
|
4
|
-
{noWrap} = require('../util/string'),
|
|
5
|
-
fixedToken = require('../mixin/fixedToken'),
|
|
6
|
-
attributeParent = require('../mixin/attributeParent'),
|
|
7
4
|
Parser = require('..'),
|
|
8
5
|
Token = require('.');
|
|
9
6
|
|
|
@@ -13,7 +10,7 @@ const magicWords = new Set(['if', 'ifeq', 'ifexpr', 'ifexist', 'iferror', 'switc
|
|
|
13
10
|
* HTML标签
|
|
14
11
|
* @classdesc `{childNodes: [AttributesToken]}`
|
|
15
12
|
*/
|
|
16
|
-
class HtmlToken extends
|
|
13
|
+
class HtmlToken extends Token {
|
|
17
14
|
type = 'html';
|
|
18
15
|
#closing;
|
|
19
16
|
#selfClosing;
|
|
@@ -24,47 +21,12 @@ class HtmlToken extends attributeParent(fixedToken(Token)) {
|
|
|
24
21
|
return this.#closing;
|
|
25
22
|
}
|
|
26
23
|
|
|
27
|
-
/** @throws `Error` 自闭合标签或空标签 */
|
|
28
|
-
set closing(value) {
|
|
29
|
-
if (!value) {
|
|
30
|
-
this.#closing = false;
|
|
31
|
-
return;
|
|
32
|
-
} else if (this.#selfClosing) {
|
|
33
|
-
throw new Error('这是一个自闭合标签!');
|
|
34
|
-
}
|
|
35
|
-
const {html: [,, tags]} = this.getAttribute('config');
|
|
36
|
-
if (tags.includes(this.name)) {
|
|
37
|
-
throw new Error('这是一个空标签!');
|
|
38
|
-
}
|
|
39
|
-
this.#closing = true;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** getter */
|
|
43
|
-
get selfClosing() {
|
|
44
|
-
return this.#selfClosing;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** @throws `Error` 闭合标签或无效自闭合标签 */
|
|
48
|
-
set selfClosing(value) {
|
|
49
|
-
if (!value) {
|
|
50
|
-
this.#selfClosing = false;
|
|
51
|
-
return;
|
|
52
|
-
} else if (this.#closing) {
|
|
53
|
-
throw new Error('这是一个闭合标签!');
|
|
54
|
-
}
|
|
55
|
-
const {html: [tags]} = this.getAttribute('config');
|
|
56
|
-
if (tags.includes(this.name)) {
|
|
57
|
-
throw new Error(`<${this.name}>标签自闭合无效!`);
|
|
58
|
-
}
|
|
59
|
-
this.#selfClosing = true;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
24
|
/**
|
|
63
25
|
* @param {string} name 标签名
|
|
64
26
|
* @param {AttributesToken} attr 标签属性
|
|
65
27
|
* @param {boolean} closing 是否闭合
|
|
66
28
|
* @param {boolean} selfClosing 是否自封闭
|
|
67
|
-
* @param {accum} accum
|
|
29
|
+
* @param {import('../typings/token').accum} accum
|
|
68
30
|
*/
|
|
69
31
|
constructor(name, attr, closing, selfClosing, config = Parser.getConfig(), accum = []) {
|
|
70
32
|
super(undefined, config, true, accum);
|
|
@@ -77,12 +39,9 @@ class HtmlToken extends attributeParent(fixedToken(Token)) {
|
|
|
77
39
|
|
|
78
40
|
/**
|
|
79
41
|
* @override
|
|
80
|
-
* @param {string} selector
|
|
81
42
|
*/
|
|
82
43
|
toString(selector) {
|
|
83
|
-
return
|
|
84
|
-
? ''
|
|
85
|
-
: `<${this.#closing ? '/' : ''}${this.#tag}${super.toString(selector)}${this.#selfClosing ? '/' : ''}>`;
|
|
44
|
+
return `<${this.#closing ? '/' : ''}${this.#tag}${super.toString()}${this.#selfClosing ? '/' : ''}>`;
|
|
86
45
|
}
|
|
87
46
|
|
|
88
47
|
/** @override */
|
|
@@ -97,21 +56,13 @@ class HtmlToken extends attributeParent(fixedToken(Token)) {
|
|
|
97
56
|
return this.#tag.length + (this.#closing ? 2 : 1);
|
|
98
57
|
}
|
|
99
58
|
|
|
100
|
-
/** @override */
|
|
101
|
-
print() {
|
|
102
|
-
return super.print({
|
|
103
|
-
pre: `<${this.#closing ? '/' : ''}${this.#tag}`,
|
|
104
|
-
post: `${this.#selfClosing ? '/' : ''}>`,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
59
|
/**
|
|
109
60
|
* @override
|
|
110
61
|
* @param {number} start 起始位置
|
|
111
62
|
*/
|
|
112
63
|
lint(start = this.getAbsoluteIndex()) {
|
|
113
64
|
const errors = super.lint(start);
|
|
114
|
-
let wikitext, /** @type {LintError} */ refError;
|
|
65
|
+
let wikitext, /** @type {import('../typings/token').LintError} */ refError;
|
|
115
66
|
if (this.name === 'h1' && !this.#closing) {
|
|
116
67
|
wikitext = String(this.getRootNode());
|
|
117
68
|
refError = generateForSelf(this, {start}, '<h1>');
|
|
@@ -155,7 +106,7 @@ class HtmlToken extends attributeParent(fixedToken(Token)) {
|
|
|
155
106
|
findMatchingTag() {
|
|
156
107
|
const {html} = this.getAttribute('config'),
|
|
157
108
|
{name: tagName, parentNode} = this,
|
|
158
|
-
string =
|
|
109
|
+
string = String(this);
|
|
159
110
|
if (this.#closing && (this.#selfClosing || html[2].includes(tagName))) {
|
|
160
111
|
throw new SyntaxError(`tag that is both closing and self-closing: ${string}`);
|
|
161
112
|
} else if (html[2].includes(tagName) || this.#selfClosing && html[1].includes(tagName)) { // 自封闭标签
|
|
@@ -183,72 +134,6 @@ class HtmlToken extends attributeParent(fixedToken(Token)) {
|
|
|
183
134
|
}
|
|
184
135
|
throw new SyntaxError(`${this.#closing ? 'unmatched closing' : 'unclosed'} tag: ${string}`);
|
|
185
136
|
}
|
|
186
|
-
|
|
187
|
-
/** @override */
|
|
188
|
-
cloneNode() {
|
|
189
|
-
const [attr] = this.cloneChildNodes(),
|
|
190
|
-
config = this.getAttribute('config');
|
|
191
|
-
return Parser.run(() => new HtmlToken(this.#tag, attr, this.#closing, this.#selfClosing, config));
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* @override
|
|
196
|
-
* @template {string} T
|
|
197
|
-
* @param {T} key 属性键
|
|
198
|
-
* @returns {TokenAttribute<T>}
|
|
199
|
-
*/
|
|
200
|
-
getAttribute(key) {
|
|
201
|
-
return key === 'tag' ? this.#tag : super.getAttribute(key);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* 更换标签名
|
|
206
|
-
* @param {string} tag 标签名
|
|
207
|
-
* @throws `RangeError` 非法的HTML标签
|
|
208
|
-
*/
|
|
209
|
-
replaceTag(tag) {
|
|
210
|
-
const name = tag.toLowerCase();
|
|
211
|
-
if (!this.getAttribute('config').html.flat().includes(name)) {
|
|
212
|
-
throw new RangeError(`非法的HTML标签:${tag}`);
|
|
213
|
-
}
|
|
214
|
-
this.setAttribute('name', name).#tag = tag;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/** 局部闭合 */
|
|
218
|
-
#localMatch() {
|
|
219
|
-
this.#selfClosing = false;
|
|
220
|
-
const root = Parser.parse(`</${this.name}>`, false, 3, this.getAttribute('config'));
|
|
221
|
-
this.after(root.firstChild);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* 修复无效自封闭标签
|
|
226
|
-
* @complexity `n`
|
|
227
|
-
* @throws `Error` 无法修复无效自封闭标签
|
|
228
|
-
*/
|
|
229
|
-
fix() {
|
|
230
|
-
const config = this.getAttribute('config'),
|
|
231
|
-
{parentNode, name: tagName, firstChild} = this;
|
|
232
|
-
if (!parentNode || !this.#selfClosing || !config.html[0].includes(tagName)) {
|
|
233
|
-
return;
|
|
234
|
-
} else if (firstChild.text().trim()) {
|
|
235
|
-
this.#localMatch();
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
const {childNodes} = parentNode,
|
|
239
|
-
i = childNodes.indexOf(this),
|
|
240
|
-
/** @type {HtmlToken[]} */
|
|
241
|
-
prevSiblings = childNodes.slice(0, i).filter(({type, name}) => type === 'html' && name === tagName),
|
|
242
|
-
imbalance = prevSiblings.reduce((acc, {closing}) => acc + (closing ? 1 : -1), 0);
|
|
243
|
-
if (imbalance < 0) {
|
|
244
|
-
this.#selfClosing = false;
|
|
245
|
-
this.#closing = true;
|
|
246
|
-
} else {
|
|
247
|
-
Parser.warn('无法修复无效自封闭标签', noWrap(String(this)));
|
|
248
|
-
throw new Error(`无法修复无效自封闭标签:前文共有 ${imbalance} 个未匹配的闭合标签`);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
137
|
}
|
|
252
138
|
|
|
253
|
-
Parser.classes.HtmlToken = __filename;
|
|
254
139
|
module.exports = HtmlToken;
|