wikiparser-node 0.7.0 → 0.7.1-b

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.
Files changed (87) hide show
  1. package/bundle/bundle.min.js +40 -0
  2. package/extensions/editor.css +60 -0
  3. package/extensions/editor.js +324 -0
  4. package/extensions/ui.css +119 -0
  5. package/package.json +12 -11
  6. package/README.md +0 -39
  7. package/config/default.json +0 -832
  8. package/config/llwiki.json +0 -630
  9. package/config/moegirl.json +0 -728
  10. package/config/zhwiki.json +0 -1269
  11. package/index.js +0 -321
  12. package/lib/element.js +0 -611
  13. package/lib/node.js +0 -772
  14. package/lib/ranges.js +0 -130
  15. package/lib/text.js +0 -215
  16. package/lib/title.js +0 -80
  17. package/mixin/attributeParent.js +0 -117
  18. package/mixin/fixedToken.js +0 -40
  19. package/mixin/hidden.js +0 -21
  20. package/mixin/singleLine.js +0 -31
  21. package/mixin/sol.js +0 -65
  22. package/parser/brackets.js +0 -120
  23. package/parser/commentAndExt.js +0 -62
  24. package/parser/converter.js +0 -46
  25. package/parser/externalLinks.js +0 -33
  26. package/parser/hrAndDoubleUnderscore.js +0 -38
  27. package/parser/html.js +0 -42
  28. package/parser/links.js +0 -94
  29. package/parser/list.js +0 -59
  30. package/parser/magicLinks.js +0 -41
  31. package/parser/quotes.js +0 -64
  32. package/parser/selector.js +0 -177
  33. package/parser/table.js +0 -114
  34. package/src/arg.js +0 -203
  35. package/src/atom/hidden.js +0 -13
  36. package/src/atom/index.js +0 -43
  37. package/src/attribute.js +0 -420
  38. package/src/attributes.js +0 -452
  39. package/src/charinsert.js +0 -97
  40. package/src/converter.js +0 -176
  41. package/src/converterFlags.js +0 -284
  42. package/src/converterRule.js +0 -258
  43. package/src/extLink.js +0 -179
  44. package/src/gallery.js +0 -151
  45. package/src/hasNowiki/index.js +0 -44
  46. package/src/hasNowiki/pre.js +0 -40
  47. package/src/heading.js +0 -134
  48. package/src/html.js +0 -248
  49. package/src/imageParameter.js +0 -277
  50. package/src/imagemap.js +0 -199
  51. package/src/imagemapLink.js +0 -41
  52. package/src/index.js +0 -913
  53. package/src/link/category.js +0 -49
  54. package/src/link/file.js +0 -282
  55. package/src/link/galleryImage.js +0 -120
  56. package/src/link/index.js +0 -383
  57. package/src/magicLink.js +0 -149
  58. package/src/nested/choose.js +0 -24
  59. package/src/nested/combobox.js +0 -23
  60. package/src/nested/index.js +0 -96
  61. package/src/nested/references.js +0 -23
  62. package/src/nowiki/comment.js +0 -71
  63. package/src/nowiki/dd.js +0 -59
  64. package/src/nowiki/doubleUnderscore.js +0 -56
  65. package/src/nowiki/hr.js +0 -41
  66. package/src/nowiki/index.js +0 -56
  67. package/src/nowiki/list.js +0 -16
  68. package/src/nowiki/noinclude.js +0 -28
  69. package/src/nowiki/quote.js +0 -69
  70. package/src/onlyinclude.js +0 -64
  71. package/src/paramTag/index.js +0 -89
  72. package/src/paramTag/inputbox.js +0 -44
  73. package/src/parameter.js +0 -239
  74. package/src/syntax.js +0 -91
  75. package/src/table/index.js +0 -984
  76. package/src/table/td.js +0 -339
  77. package/src/table/tr.js +0 -319
  78. package/src/tagPair/ext.js +0 -138
  79. package/src/tagPair/include.js +0 -60
  80. package/src/tagPair/index.js +0 -126
  81. package/src/transclude.js +0 -824
  82. package/tool/index.js +0 -1202
  83. package/util/base.js +0 -17
  84. package/util/debug.js +0 -73
  85. package/util/diff.js +0 -76
  86. package/util/lint.js +0 -54
  87. package/util/string.js +0 -107
package/src/link/index.js DELETED
@@ -1,383 +0,0 @@
1
- 'use strict';
2
-
3
- const {generateForChild} = require('../../util/lint'),
4
- {noWrap} = require('../../util/string'),
5
- {undo} = require('../../util/debug'),
6
- Parser = require('../..'),
7
- Title = require('../../lib/title'),
8
- AstText = require('../../lib/text'),
9
- Token = require('..'),
10
- AtomToken = require('../atom');
11
-
12
- /**
13
- * 内链
14
- * @classdesc `{childNodes: [AtomToken, ?Token]}`
15
- */
16
- class LinkToken extends Token {
17
- type = 'link';
18
- #bracket = true;
19
- #delimiter;
20
- #fragment = '';
21
- #encoded = false;
22
-
23
- /** 完整链接,和FileToken保持一致 */
24
- get link() {
25
- return String(this.#getTitle());
26
- }
27
-
28
- set link(link) {
29
- this.setTarget(link);
30
- }
31
-
32
- /** 是否链接到自身 */
33
- get selfLink() {
34
- return !this.#getTitle().title;
35
- }
36
-
37
- set selfLink(selfLink) {
38
- if (selfLink === true) {
39
- this.asSelfLink();
40
- }
41
- }
42
-
43
- /** fragment */
44
- get fragment() {
45
- return this.#getTitle().fragment;
46
- }
47
-
48
- set fragment(fragment) {
49
- this.setFragment(fragment);
50
- }
51
-
52
- /** interwiki */
53
- get interwiki() {
54
- return this.#getTitle().interwiki;
55
- }
56
-
57
- set interwiki(interwiki) {
58
- if (typeof interwiki !== 'string') {
59
- this.typeError('set interwiki', 'String');
60
- }
61
- const {prefix, main, fragment} = this.#getTitle(),
62
- link = `${interwiki}:${prefix}${main}${fragment && '#'}${fragment}`;
63
- if (interwiki && !this.isInterwiki(link)) {
64
- throw new RangeError(`${interwiki} 不是合法的跨维基前缀!`);
65
- }
66
- this.setTarget(link);
67
- }
68
-
69
- /** 链接显示文字 */
70
- get innerText() {
71
- if (this.type === 'link') {
72
- return this.length > 1
73
- ? this.lastChild.text()
74
- : this.firstChild.text().replace(/^\s*:/u, '');
75
- }
76
- return undefined;
77
- }
78
-
79
- /**
80
- * @param {string} link 链接标题
81
- * @param {string|undefined} linkText 链接显示文字
82
- * @param {Title} title 链接标题对象
83
- * @param {accum} accum
84
- * @param {string} delimiter `|`
85
- */
86
- constructor(link, linkText, title, config = Parser.getConfig(), accum = [], delimiter = '|') {
87
- super(undefined, config, true, accum, {
88
- AtomToken: 0, Token: 1,
89
- });
90
- this.insertAt(new AtomToken(link, 'link-target', config, accum, {
91
- 'Stage-2': ':', '!ExtToken': '', '!HeadingToken': '',
92
- }));
93
- if (linkText !== undefined) {
94
- const inner = new Token(linkText, config, true, accum, {
95
- 'Stage-5': ':', ConverterToken: ':',
96
- });
97
- inner.type = 'link-text';
98
- this.insertAt(inner.setAttribute('stage', Parser.MAX_STAGE - 1));
99
- }
100
- this.#delimiter = delimiter;
101
- this.getAttribute('protectChildren')(0);
102
- }
103
-
104
- /**
105
- * @override
106
- * @throws `Error` 非法的内链目标
107
- * @throws `Error` 不可更改命名空间
108
- */
109
- afterBuild() {
110
- const titleObj = this.normalizeTitle(this.firstChild.text(), 0, false, true, true);
111
- this.setAttribute('name', titleObj.title);
112
- this.#fragment = titleObj.fragment;
113
- this.#encoded = titleObj.encoded;
114
- if (this.#delimiter?.includes('\0')) {
115
- this.#delimiter = this.getAttribute('buildFromStr')(this.#delimiter, 'string');
116
- }
117
- const /** @type {AstListener} */ linkListener = (e, data) => {
118
- const {prevTarget} = e;
119
- if (prevTarget?.type === 'link-target') {
120
- const name = prevTarget.text(),
121
- {title, interwiki, ns, valid, fragment, encoded} = this.normalizeTitle(name, 0, false, true, true);
122
- if (!valid) {
123
- undo(e, data);
124
- throw new Error(`非法的内链目标:${name}`);
125
- } else if (this.type === 'category' && (interwiki || ns !== 14)
126
- || this.type === 'file' && (interwiki || ns !== 6)
127
- ) {
128
- undo(e, data);
129
- throw new Error(`${this.type === 'file' ? '文件' : '分类'}链接不可更改命名空间:${name}`);
130
- } else if (this.type === 'link' && !interwiki && (ns === 6 || ns === 14) && name.trim()[0] !== ':') {
131
- const /** @type {{firstChild: AstText}} */ {firstChild} = prevTarget;
132
- if (firstChild.type === 'text') {
133
- firstChild.insertData(0, ':');
134
- } else {
135
- prevTarget.prepend(':');
136
- }
137
- }
138
- this.setAttribute('name', title);
139
- this.#fragment = fragment;
140
- this.#encoded = encoded;
141
- }
142
- };
143
- this.addEventListener(['remove', 'insert', 'replace', 'text'], linkListener);
144
- }
145
-
146
- /**
147
- * @override
148
- * @template {string} T
149
- * @param {T} key 属性键
150
- * @param {TokenAttribute<T>} value 属性值
151
- */
152
- setAttribute(key, value) {
153
- if (key === 'bracket') {
154
- this.#bracket = Boolean(value);
155
- return this;
156
- }
157
- return super.setAttribute(key, value);
158
- }
159
-
160
- /**
161
- * @override
162
- * @param {string} selector
163
- */
164
- toString(selector) {
165
- const str = super.toString(selector, this.#delimiter);
166
- return this.#bracket && !(selector && this.matches(selector)) ? `[[${str}]]` : str;
167
- }
168
-
169
- /** @override */
170
- text() {
171
- const str = super.text('|');
172
- return this.#bracket ? `[[${str}]]` : str;
173
- }
174
-
175
- /** @override */
176
- getPadding() {
177
- return 2;
178
- }
179
-
180
- /** @override */
181
- getGaps() {
182
- return this.#delimiter.length;
183
- }
184
-
185
- /** @override */
186
- print() {
187
- return super.print(this.#bracket ? {pre: '[[', post: ']]', sep: this.#delimiter} : {sep: this.#delimiter});
188
- }
189
-
190
- /**
191
- * @override
192
- * @param {number} start 起始位置
193
- */
194
- lint(start = 0) {
195
- const errors = super.lint(start),
196
- {childNodes: [target, linkText], type: linkType} = this;
197
- let rect;
198
- if (this.#encoded) {
199
- rect = {start, ...this.getRootNode().posFromIndex(start)};
200
- errors.push(generateForChild(target, rect, '内链中不必要的URL编码'));
201
- }
202
- if (linkType === 'link' && linkText?.childNodes?.some(
203
- /** @param {AstText} */ ({type, data}) => type === 'text' && data.includes('|'),
204
- )) {
205
- rect ||= {start, ...this.getRootNode().posFromIndex(start)};
206
- errors.push(generateForChild(linkText, rect, '链接文本中多余的"|"', 'warning'));
207
- } else if (linkType !== 'link' && this.#fragment) {
208
- rect ||= {start, ...this.getRootNode().posFromIndex(start)};
209
- errors.push(generateForChild(target, rect, '多余的fragment'));
210
- }
211
- return errors;
212
- }
213
-
214
- /** 生成Title对象 */
215
- #getTitle() {
216
- return this.normalizeTitle(this.firstChild.text(), 0, false, true, true);
217
- }
218
-
219
- /**
220
- * @override
221
- * @this {LinkToken & {constructor: typeof LinkToken}}
222
- */
223
- cloneNode() {
224
- const [link, ...linkText] = this.cloneChildNodes();
225
- return Parser.run(() => {
226
- const token = new this.constructor('', undefined, this.#getTitle(), this.getAttribute('config'));
227
- token.firstChild.safeReplaceWith(link);
228
- token.append(...linkText);
229
- token.afterBuild();
230
- return token;
231
- });
232
- }
233
-
234
- /**
235
- * 设置链接目标
236
- * @param {string} link 链接目标
237
- * @throws `SyntaxError` 非法的链接目标
238
- */
239
- setTarget(link) {
240
- link = String(link);
241
- if (this.type === 'link' && !/^\s*[:#]/u.test(link)) {
242
- link = `:${link}`;
243
- }
244
- const root = Parser.parse(`[[${link}]]`, this.getAttribute('include'), 6, this.getAttribute('config')),
245
- {length, firstChild: wikiLink} = root,
246
- {type, firstChild, length: linkLength} = wikiLink;
247
- if (length !== 1 || type !== this.type || linkLength !== 1) {
248
- const msgs = {link: '内链', file: '文件链接', category: '分类'};
249
- throw new SyntaxError(`非法的${msgs[this.type]}目标:${link}`);
250
- }
251
- wikiLink.destroy(true);
252
- this.firstChild.safeReplaceWith(firstChild);
253
- }
254
-
255
- /**
256
- * 设置跨语言链接
257
- * @param {string} lang 语言前缀
258
- * @param {string} link 页面标题
259
- * @throws `SyntaxError` 非法的跨语言链接
260
- */
261
- setLangLink(lang, link) {
262
- if (typeof lang !== 'string') {
263
- this.typeError('setLangLink', 'String');
264
- }
265
- link = String(link).trim();
266
- const [char] = link;
267
- if (char === '#') {
268
- throw new SyntaxError('跨语言链接不能仅为fragment!');
269
- } else if (char === ':') {
270
- link = link.slice(1);
271
- }
272
- const root = Parser.parse(`[[${lang}:${link}]]`, this.getAttribute('include'), 6, this.getAttribute('config')),
273
- /** @type {Token & {firstChild: LinkToken}} */ {length, firstChild: wikiLink} = root,
274
- {type, length: linkLength, interwiki, firstChild} = wikiLink;
275
- if (length !== 1 || type !== 'link' || linkLength !== 1 || interwiki !== lang.toLowerCase()) {
276
- throw new SyntaxError(`非法的跨语言链接目标:${lang}:${link}`);
277
- }
278
- wikiLink.destroy(true);
279
- this.firstChild.safeReplaceWith(firstChild);
280
- }
281
-
282
- /**
283
- * 设置fragment
284
- * @param {string} fragment fragment
285
- * @param {boolean} page 是否是其他页面
286
- * @throws `SyntaxError` 非法的fragment
287
- */
288
- #setFragment(fragment, page = true) {
289
- fragment = String(fragment).replace(/[<>[\]#|=]/gu, p => encodeURIComponent(p));
290
- const include = this.getAttribute('include'),
291
- config = this.getAttribute('config'),
292
- root = Parser.parse(`[[${page ? `:${this.name}` : ''}#${fragment}]]`, include, 6, config),
293
- {length, firstChild: wikiLink} = root,
294
- {type, length: linkLength, firstChild} = wikiLink;
295
- if (length !== 1 || type !== 'link' || linkLength !== 1) {
296
- throw new SyntaxError(`非法的 fragment:${fragment}`);
297
- } else if (page) {
298
- Parser.warn(`${this.constructor.name}.setFragment 方法会同时规范化页面名!`);
299
- }
300
- wikiLink.destroy(true);
301
- this.firstChild.safeReplaceWith(firstChild);
302
- }
303
-
304
- /**
305
- * 设置fragment
306
- * @param {string} fragment fragment
307
- */
308
- setFragment(fragment) {
309
- this.#setFragment(fragment);
310
- }
311
-
312
- /**
313
- * 修改为到自身的链接
314
- * @param {string} fragment fragment
315
- * @throws `RangeError` 空fragment
316
- */
317
- asSelfLink(fragment = this.fragment) {
318
- fragment = String(fragment);
319
- if (!fragment.trim()) {
320
- throw new RangeError(`${this.constructor.name}.asSelfLink 方法必须指定非空的 fragment!`);
321
- }
322
- this.#setFragment(fragment, false);
323
- }
324
-
325
- /**
326
- * 设置链接显示文字
327
- * @param {string} linkText 链接显示文字
328
- * @throws `SyntaxError` 非法的链接显示文字
329
- */
330
- setLinkText(linkText = '') {
331
- linkText = String(linkText);
332
- let lastChild;
333
- const config = this.getAttribute('config');
334
- if (linkText) {
335
- const root = Parser.parse(`[[${
336
- this.type === 'category' ? 'Category:' : ''
337
- }L|${linkText}]]`, this.getAttribute('include'), 6, config),
338
- {length, firstChild: wikiLink} = root;
339
- if (length !== 1 || wikiLink.type !== this.type || wikiLink.length !== 2) {
340
- throw new SyntaxError(`非法的${this.type === 'link' ? '内链文字' : '分类关键字'}:${noWrap(linkText)}`);
341
- }
342
- ({lastChild} = wikiLink);
343
- } else {
344
- lastChild = Parser.run(() => new Token('', config));
345
- lastChild.setAttribute('stage', 7).type = 'link-text';
346
- }
347
- if (this.length === 1) {
348
- this.insertAt(lastChild);
349
- } else {
350
- this.lastChild.safeReplaceWith(lastChild);
351
- }
352
- }
353
-
354
- /**
355
- * 自动生成管道符后的链接文字
356
- * @throws `Error` 带有"#"或"%"时不可用
357
- */
358
- pipeTrick() {
359
- const linkText = this.firstChild.text();
360
- if (linkText.includes('#') || linkText.includes('%')) {
361
- throw new Error('Pipe trick 不能用于带有"#"或"%"的场合!');
362
- }
363
- const m1 = /^:?(?:[ \w\x80-\xFF-]+:)?([^(]+)\(.+\)$/u.exec(linkText);
364
- if (m1) {
365
- this.setLinkText(m1[1].trim());
366
- return;
367
- }
368
- const m2 = /^:?(?:[ \w\x80-\xFF-]+:)?([^(]+)(.+)$/u.exec(linkText);
369
- if (m2) {
370
- this.setLinkText(m2[1].trim());
371
- return;
372
- }
373
- const m3 = /^:?(?:[ \w\x80-\xFF-]+:)?(.+?)(?:(?<!\()\(.+\))?(?:, |,|، )./u.exec(linkText);
374
- if (m3) {
375
- this.setLinkText(m3[1].trim());
376
- return;
377
- }
378
- this.setLinkText(linkText);
379
- }
380
- }
381
-
382
- Parser.classes.LinkToken = __filename;
383
- module.exports = LinkToken;
package/src/magicLink.js DELETED
@@ -1,149 +0,0 @@
1
- 'use strict';
2
-
3
- const {generateForChild} = require('../util/lint'),
4
- Parser = require('..'),
5
- Token = require('.');
6
-
7
- /**
8
- * 自由外链
9
- * @classdesc `{childNodes: [...AstText|CommentToken|IncludeToken|NoincludeToken]}`
10
- */
11
- class MagicLinkToken extends Token {
12
- type = 'free-ext-link';
13
- #protocolRegex;
14
-
15
- /** 协议 */
16
- get protocol() {
17
- return this.#protocolRegex.exec(this.text())?.[0];
18
- }
19
-
20
- set protocol(value) {
21
- if (typeof value !== 'string') {
22
- this.typeError('protocol', 'String');
23
- } else if (!new RegExp(`${this.#protocolRegex.source}$`, 'iu').test(value)) {
24
- throw new RangeError(`非法的外链协议:${value}`);
25
- }
26
- const {link} = this;
27
- if (!this.#protocolRegex.test(link)) {
28
- throw new Error(`特殊外链无法更改协议!${link}`);
29
- }
30
- this.replaceChildren(link.replace(this.#protocolRegex, value));
31
- }
32
-
33
- /** 和内链保持一致 */
34
- get link() {
35
- return this.text();
36
- }
37
-
38
- set link(url) {
39
- this.setTarget(url);
40
- }
41
-
42
- /**
43
- * @override
44
- * @param {number} start 起始位置
45
- */
46
- lint(start = 0) {
47
- const errors = super.lint(start),
48
- source = `[,;。:!?()]+${this.type === 'ext-link-url' ? '|\\|+' : ''}`;
49
- let /** @type {{top: number, left: number}} */ rect;
50
- for (const child of this.childNodes) {
51
- const str = String(child);
52
- if (child.type !== 'text' || !new RegExp(source, 'u').test(str)) {
53
- continue;
54
- }
55
- rect ||= {start, ...this.getRootNode().posFromIndex(start)};
56
- const refError = generateForChild(child, rect, '', 'warning');
57
- errors.push(...[...str.matchAll(new RegExp(source, 'gu'))].map(({index, 0: {0: char, length}}) => {
58
- const lines = str.slice(0, index).split('\n'),
59
- {length: top} = lines,
60
- {length: left} = lines.at(-1),
61
- startIndex = start + index,
62
- startLine = refError.startLine + top - 1,
63
- startCol = (top > 1 ? 0 : refError.startCol) + left;
64
- return {
65
- ...refError,
66
- message: `URL中的${char === '|' ? '"|"' : '全角标点'}`,
67
- startIndex,
68
- endIndex: startIndex + length,
69
- startLine,
70
- endLine: startLine,
71
- startCol,
72
- endCol: startCol + length,
73
- excerpt: str.slice(Math.max(0, index - 25), index + 25),
74
- };
75
- }));
76
- }
77
- return errors;
78
- }
79
-
80
- /**
81
- * @param {string} url 网址
82
- * @param {boolean} doubleSlash 是否接受"//"作为协议
83
- * @param {accum} accum
84
- */
85
- constructor(url, doubleSlash, config = Parser.getConfig(), accum = []) {
86
- super(url, config, true, accum, {
87
- 'Stage-1': ':', '!ExtToken': '',
88
- });
89
- if (doubleSlash) {
90
- this.type = 'ext-link-url';
91
- }
92
- this.#protocolRegex = new RegExp(`^(?:${config.protocol}${doubleSlash ? '|//' : ''})`, 'iu');
93
- }
94
-
95
- /** @override */
96
- cloneNode() {
97
- const cloned = this.cloneChildNodes();
98
- return Parser.run(() => {
99
- const token = new MagicLinkToken(undefined, this.type === 'ext-link-url', this.getAttribute('config'));
100
- token.append(...cloned);
101
- token.afterBuild();
102
- return token;
103
- });
104
- }
105
-
106
- /**
107
- * 获取网址
108
- * @throws `Error` 非标准协议
109
- */
110
- getUrl() {
111
- let url = this.text();
112
- if (url.startsWith('//')) {
113
- url = `https:${url}`;
114
- }
115
- try {
116
- return new URL(url);
117
- } catch (e) {
118
- if (e instanceof TypeError && e.message === 'Invalid URL') {
119
- throw new Error(`非标准协议的外部链接:${url}`);
120
- }
121
- throw e;
122
- }
123
- }
124
-
125
- /**
126
- * 设置外链目标
127
- * @param {string|URL} url 含协议的网址
128
- * @throws `SyntaxError` 非法的自由外链目标
129
- */
130
- setTarget(url) {
131
- url = String(url);
132
- const root = Parser.parse(url, this.getAttribute('include'), 9, this.getAttribute('config')),
133
- {length, firstChild: freeExtLink} = root;
134
- if (length !== 1 || freeExtLink.type !== 'free-ext-link') {
135
- throw new SyntaxError(`非法的自由外链目标:${url}`);
136
- }
137
- this.replaceChildren(...freeExtLink.childNodes);
138
- }
139
-
140
- /** 是否是模板或魔术字参数 */
141
- isParamValue() {
142
- const ParameterToken = require('./parameter');
143
- const /** @type {ParameterToken} */ parameter = this.closest('parameter');
144
- return parameter?.getValue() === this.text();
145
- }
146
- }
147
-
148
- Parser.classes.MagicLinkToken = __filename;
149
- module.exports = MagicLinkToken;
@@ -1,24 +0,0 @@
1
- 'use strict';
2
-
3
- const Parser = require('../..'),
4
- NestedToken = require('.');
5
-
6
- /**
7
- * `<choose>`
8
- * @classdesc `{childNodes: [...ExtToken|NoincludeToken]}`
9
- */
10
- class ChooseToken extends NestedToken {
11
- name = 'choose';
12
-
13
- /**
14
- * @param {string|undefined} wikitext wikitext
15
- * @param {accum} accum
16
- */
17
- constructor(wikitext, config = Parser.getConfig(), accum = []) {
18
- const regex = /<(option|choicetemplate)(\s[^>]*)?>(.*?)<\/(\1)>/gsu;
19
- super(wikitext, regex, ['option', 'choicetemplate'], config, accum);
20
- }
21
- }
22
-
23
- Parser.classes.ChooseToken = __filename;
24
- module.exports = ChooseToken;
@@ -1,23 +0,0 @@
1
- 'use strict';
2
-
3
- const Parser = require('../..'),
4
- NestedToken = require('.');
5
-
6
- /**
7
- * `<combobox>`
8
- * @classdesc `{childNodes: [...ExtToken|NoincludeToken]}`
9
- */
10
- class ComboboxToken extends NestedToken {
11
- name = 'combobox';
12
-
13
- /**
14
- * @param {string|undefined} wikitext wikitext
15
- * @param {accum} accum
16
- */
17
- constructor(wikitext, config = Parser.getConfig(), accum = []) {
18
- super(wikitext, /<(combooption)(\s[^>]*)?>(.*?)<\/(combooption\s*)>/gisu, ['combooption'], config, accum);
19
- }
20
- }
21
-
22
- Parser.classes.ComboboxToken = __filename;
23
- module.exports = ComboboxToken;
@@ -1,96 +0,0 @@
1
- 'use strict';
2
-
3
- const {generateForChild} = require('../../util/lint'),
4
- Parser = require('../..'),
5
- Token = require('..'),
6
- ExtToken = require('../tagPair/ext'),
7
- NoincludeToken = require('../nowiki/noinclude'),
8
- CommentToken = require('../nowiki/comment');
9
-
10
- /**
11
- * 嵌套式的扩展标签
12
- * @classdesc `{childNodes: [...ExtToken|NoincludeToken|CommentToken]}`
13
- */
14
- class NestedToken extends Token {
15
- type = 'ext-inner';
16
- #tags;
17
-
18
- /**
19
- * @param {string|undefined} wikitext wikitext
20
- * @param {RegExp} regex 内层正则
21
- * @param {string[]} tags 内层标签名
22
- * @param {accum} accum
23
- */
24
- constructor(wikitext, regex, tags, config = Parser.getConfig(), accum = []) {
25
- const text = wikitext?.replace(
26
- regex,
27
- /** @type {function(...string): string} */ (comment, name, attr, inner, closing) => {
28
- const str = `\0${accum.length + 1}${name ? 'e' : 'c'}\x7F`;
29
- if (name) {
30
- new ExtToken(name, attr, inner, closing, config, accum);
31
- } else {
32
- const closed = comment.endsWith('-->');
33
- new CommentToken(comment.slice(4, closed ? -3 : undefined), closed, config, accum);
34
- }
35
- return str;
36
- },
37
- )?.replace(/(?<=^|\0\d+[ce]\x7F).*?(?=$|\0\d+[ce]\x7F)/gsu, substr => {
38
- if (substr === '') {
39
- return '';
40
- }
41
- new NoincludeToken(substr, config, accum);
42
- return `\0${accum.length}c\x7F`;
43
- });
44
- super(text, config, true, accum, {
45
- NoincludeToken: ':', ExtToken: ':',
46
- });
47
- this.#tags = tags;
48
- }
49
-
50
- /**
51
- * @override
52
- * @param {number} start 起始位置
53
- */
54
- lint(start = 0) {
55
- let rect;
56
- return [
57
- ...super.lint(start),
58
- ...this.childNodes.filter(child => {
59
- if (child.type === 'ext' || child.type === 'comment') {
60
- return false;
61
- }
62
- const str = String(child).trim();
63
- return str && !/^<!--.*-->$/u.test(str);
64
- }).map(child => {
65
- rect ||= {start, ...this.getRootNode().posFromIndex(start)};
66
- return generateForChild(child, rect, `<${this.name}>内的无效内容`);
67
- }),
68
- ];
69
- }
70
-
71
- /**
72
- * @override
73
- * @template {string|Token} T
74
- * @param {T} token 待插入的子节点
75
- * @param {number} i 插入位置
76
- */
77
- insertAt(token, i = this.length) {
78
- return token.type === 'ext' && !this.#tags.includes(token.name)
79
- ? this.typeError(`${this.constructor.name}只能以${this.#tags.join('或')}标签作为子节点!`)
80
- : super.insertAt(token, i);
81
- }
82
-
83
- /** @override */
84
- cloneNode() {
85
- const cloned = this.cloneChildNodes(),
86
- config = this.getAttribute('config');
87
- return Parser.run(() => {
88
- const token = new this.constructor(undefined, config);
89
- token.append(...cloned);
90
- return token;
91
- });
92
- }
93
- }
94
-
95
- Parser.classes.NestedToken = __filename;
96
- module.exports = NestedToken;
@@ -1,23 +0,0 @@
1
- 'use strict';
2
-
3
- const Parser = require('../..'),
4
- NestedToken = require('.');
5
-
6
- /**
7
- * `<references>`
8
- * @classdesc `{childNodes: [...ExtToken|NoincludeToken|CommentToken]}`
9
- */
10
- class ReferencesToken extends NestedToken {
11
- name = 'references';
12
-
13
- /**
14
- * @param {string|undefined} wikitext wikitext
15
- * @param {accum} accum
16
- */
17
- constructor(wikitext, config = Parser.getConfig(), accum = []) {
18
- super(wikitext, /<!--.*?(?:-->|$)|<(ref)(\s[^>]*)?>(.*?)<\/(ref\s*)>/gisu, ['ref'], config, accum);
19
- }
20
- }
21
-
22
- Parser.classes.ReferencesToken = __filename;
23
- module.exports = ReferencesToken;