wikiparser-node 0.4.0 → 0.6.1

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/config/default.json +129 -66
  2. package/config/zhwiki.json +4 -4
  3. package/index.js +97 -65
  4. package/lib/element.js +159 -302
  5. package/lib/node.js +384 -198
  6. package/lib/ranges.js +3 -4
  7. package/lib/text.js +65 -36
  8. package/lib/title.js +9 -8
  9. package/mixin/fixedToken.js +4 -4
  10. package/mixin/hidden.js +2 -0
  11. package/mixin/sol.js +16 -7
  12. package/package.json +14 -3
  13. package/parser/brackets.js +8 -2
  14. package/parser/commentAndExt.js +1 -1
  15. package/parser/converter.js +1 -1
  16. package/parser/externalLinks.js +2 -2
  17. package/parser/hrAndDoubleUnderscore.js +8 -7
  18. package/parser/links.js +8 -9
  19. package/parser/magicLinks.js +1 -1
  20. package/parser/selector.js +5 -5
  21. package/parser/table.js +18 -16
  22. package/src/arg.js +71 -42
  23. package/src/atom/index.js +7 -5
  24. package/src/attribute.js +102 -64
  25. package/src/charinsert.js +91 -0
  26. package/src/converter.js +34 -15
  27. package/src/converterFlags.js +87 -40
  28. package/src/converterRule.js +59 -53
  29. package/src/extLink.js +45 -37
  30. package/src/gallery.js +71 -16
  31. package/src/hasNowiki/index.js +42 -0
  32. package/src/hasNowiki/pre.js +40 -0
  33. package/src/heading.js +41 -18
  34. package/src/html.js +76 -48
  35. package/src/imageParameter.js +73 -51
  36. package/src/imagemap.js +205 -0
  37. package/src/imagemapLink.js +43 -0
  38. package/src/index.js +243 -138
  39. package/src/link/category.js +10 -14
  40. package/src/link/file.js +112 -56
  41. package/src/link/galleryImage.js +74 -10
  42. package/src/link/index.js +86 -61
  43. package/src/magicLink.js +48 -21
  44. package/src/nested/choose.js +24 -0
  45. package/src/nested/combobox.js +23 -0
  46. package/src/nested/index.js +88 -0
  47. package/src/nested/references.js +23 -0
  48. package/src/nowiki/comment.js +18 -4
  49. package/src/nowiki/dd.js +2 -2
  50. package/src/nowiki/doubleUnderscore.js +16 -11
  51. package/src/nowiki/index.js +12 -0
  52. package/src/nowiki/quote.js +28 -1
  53. package/src/onlyinclude.js +15 -8
  54. package/src/paramTag/index.js +83 -0
  55. package/src/paramTag/inputbox.js +42 -0
  56. package/src/parameter.js +73 -46
  57. package/src/syntax.js +9 -1
  58. package/src/table/index.js +58 -44
  59. package/src/table/td.js +63 -63
  60. package/src/table/tr.js +52 -35
  61. package/src/tagPair/ext.js +60 -43
  62. package/src/tagPair/include.js +11 -1
  63. package/src/tagPair/index.js +29 -20
  64. package/src/transclude.js +214 -166
  65. package/tool/index.js +720 -439
  66. package/util/base.js +17 -0
  67. package/util/debug.js +1 -1
  68. package/{test/util.js → util/diff.js} +15 -19
  69. package/util/lint.js +40 -0
  70. package/util/string.js +37 -20
  71. package/.eslintrc.json +0 -714
  72. package/errors/README +0 -1
  73. package/jsconfig.json +0 -7
  74. package/printed/README +0 -1
  75. package/printed/example.json +0 -120
  76. package/test/api.js +0 -83
  77. package/test/real.js +0 -133
  78. package/test/test.js +0 -28
  79. package/typings/api.d.ts +0 -13
  80. package/typings/array.d.ts +0 -28
  81. package/typings/event.d.ts +0 -24
  82. package/typings/index.d.ts +0 -94
  83. package/typings/node.d.ts +0 -29
  84. package/typings/parser.d.ts +0 -16
  85. package/typings/table.d.ts +0 -14
  86. package/typings/token.d.ts +0 -22
  87. package/typings/tool.d.ts +0 -11
package/src/magicLink.js CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const Parser = require('..'),
3
+ const {generateForChild} = require('../util/lint'),
4
+ Parser = require('..'),
4
5
  Token = require('.');
5
6
 
6
7
  /**
@@ -19,11 +20,14 @@ class MagicLinkToken extends Token {
19
20
  set protocol(value) {
20
21
  if (typeof value !== 'string') {
21
22
  this.typeError('protocol', 'String');
22
- }
23
- if (!new RegExp(`${this.#protocolRegex.source}$`, 'iu').test(value)) {
23
+ } else if (!new RegExp(`${this.#protocolRegex.source}$`, 'iu').test(value)) {
24
24
  throw new RangeError(`非法的外链协议:${value}`);
25
25
  }
26
- this.replaceChildren(this.text().replace(this.#protocolRegex, value));
26
+ const {link} = this;
27
+ if (!this.#protocolRegex.test(link)) {
28
+ throw new Error(`特殊外链无法更改协议!${link}`);
29
+ }
30
+ this.replaceChildren(link.replace(this.#protocolRegex, value));
27
31
  }
28
32
 
29
33
  /** 和内链保持一致 */
@@ -48,25 +52,41 @@ class MagicLinkToken extends Token {
48
52
  this.#protocolRegex = new RegExp(`^(?:${config.protocol}${doubleSlash ? '|//' : ''})`, 'iu');
49
53
  }
50
54
 
51
- /** @override */
52
- afterBuild() {
53
- const ParameterToken = require('./parameter');
54
- const /** @type {ParameterToken} */ parameter = this.closest('parameter');
55
- if (parameter?.getValue() === this.text()) {
56
- this.replaceWith(...this.childNodes);
55
+ /**
56
+ * @override
57
+ * @param {number} start 起始位置
58
+ */
59
+ lint(start = 0) {
60
+ const errors = super.lint(start);
61
+ let /** @type {{top: number, left: number}} */ rect;
62
+ for (const child of this.childNodes) {
63
+ const str = String(child);
64
+ if (child.type !== 'text' || !/[,;。:!?()【】]/u.test(str)) {
65
+ continue;
66
+ }
67
+ rect ||= this.getRootNode().posFromIndex(start);
68
+ const refError = generateForChild(child, rect, 'URL中的全角标点', 'warning');
69
+ errors.push(...[...str.matchAll(/[,;。:!?()【】]/gu)].map(({index}) => {
70
+ const lines = str.slice(0, index).split('\n'),
71
+ {length: top} = lines,
72
+ {length: left} = lines.at(-1),
73
+ startLine = refError.startLine + top - 1,
74
+ startCol = top > 1 ? left : refError.startCol + left;
75
+ return {...refError, startLine, endLine: startLine, startCol, endCol: startCol + 1};
76
+ }));
57
77
  }
58
- return this;
78
+ return errors;
59
79
  }
60
80
 
61
81
  /** @override */
62
82
  cloneNode() {
63
- const cloned = this.cloneChildNodes(),
64
- token = Parser.run(() => new MagicLinkToken(
65
- undefined, this.type === 'ext-link-url', this.getAttribute('config'),
66
- ));
67
- token.append(...cloned);
68
- token.afterBuild();
69
- return token;
83
+ const cloned = this.cloneChildNodes();
84
+ return Parser.run(() => {
85
+ const token = new MagicLinkToken(undefined, this.type === 'ext-link-url', this.getAttribute('config'));
86
+ token.append(...cloned);
87
+ token.afterBuild();
88
+ return token;
89
+ });
70
90
  }
71
91
 
72
92
  /**
@@ -96,11 +116,18 @@ class MagicLinkToken extends Token {
96
116
  setTarget(url) {
97
117
  url = String(url);
98
118
  const root = Parser.parse(url, this.getAttribute('include'), 9, this.getAttribute('config')),
99
- {childNodes: {length}, firstElementChild} = root;
100
- if (length !== 1 || firstElementChild?.type !== 'free-ext-link') {
119
+ {length, firstChild: freeExtLink} = root;
120
+ if (length !== 1 || freeExtLink.type !== 'free-ext-link') {
101
121
  throw new SyntaxError(`非法的自由外链目标:${url}`);
102
122
  }
103
- this.replaceChildren(...firstElementChild.childNodes);
123
+ this.replaceChildren(...freeExtLink.childNodes);
124
+ }
125
+
126
+ /** 是否是模板或魔术字参数 */
127
+ isParamValue() {
128
+ const ParameterToken = require('./parameter');
129
+ const /** @type {ParameterToken} */ parameter = this.closest('parameter');
130
+ return parameter?.getValue() === this.text();
104
131
  }
105
132
  }
106
133
 
@@ -0,0 +1,24 @@
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;
@@ -0,0 +1,23 @@
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;
@@ -0,0 +1,88 @@
1
+ 'use strict';
2
+
3
+ const {generateForChild} = require('../../util/lint'),
4
+ Parser = require('../..'),
5
+ Token = require('..');
6
+
7
+ /**
8
+ * 嵌套式的扩展标签
9
+ * @classdesc `{childNodes: [...ExtToken|NoincludeToken]}`
10
+ */
11
+ class NestedToken extends Token {
12
+ type = 'ext-inner';
13
+ #tags;
14
+
15
+ /**
16
+ * @param {string|undefined} wikitext wikitext
17
+ * @param {RegExp} regex 内层正则
18
+ * @param {string[]} tags 内层标签名
19
+ * @param {accum} accum
20
+ */
21
+ constructor(wikitext, regex, tags, config = Parser.getConfig(), accum = []) {
22
+ const ExtToken = require('../tagPair/ext'),
23
+ NoincludeToken = require('../nowiki/noinclude');
24
+ const text = wikitext?.replaceAll(
25
+ regex,
26
+ /** @type {function(...string): string} */ (_, name, attr, inner, closing) => {
27
+ const str = `\0${accum.length + 1}e\x7F`;
28
+ new ExtToken(name, attr, inner, closing, config, accum);
29
+ return str;
30
+ },
31
+ )?.replaceAll(/(?<=^|\0\d+e\x7F).*?(?=$|\0\d+e\x7F)/gsu, substr => {
32
+ if (substr === '') {
33
+ return '';
34
+ }
35
+ new NoincludeToken(substr, config, accum);
36
+ return `\0${accum.length}c\x7F`;
37
+ });
38
+ super(text, config, true, accum, {NoincludeToken: ':', ExtToken: ':'});
39
+ this.#tags = tags;
40
+ }
41
+
42
+ /**
43
+ * @override
44
+ * @param {number} start 起始位置
45
+ */
46
+ lint(start = 0) {
47
+ let rect;
48
+ return [
49
+ ...super.lint(start),
50
+ ...this.childNodes.filter(child => {
51
+ if (child.type === 'ext') {
52
+ return false;
53
+ }
54
+ const str = String(child).trim();
55
+ return str && !/^<!--.*-->$/u.test(str);
56
+ }).map(child => {
57
+ rect ||= this.getRootNode().posFromIndex(start);
58
+ return generateForChild(child, rect, `<${this.name}>内的无效内容`);
59
+ }),
60
+ ];
61
+ }
62
+
63
+ /**
64
+ * @override
65
+ * @template {string|Token} T
66
+ * @param {T} token 待插入的子节点
67
+ * @param {number} i 插入位置
68
+ */
69
+ insertAt(token, i = this.childNodes.length) {
70
+ return token.type === 'ext' && !this.#tags.includes(token.name)
71
+ ? this.typeError(`${this.constructor.name}只能以${this.#tags.join('或')}标签作为子节点!`)
72
+ : super.insertAt(token, i);
73
+ }
74
+
75
+ /** @override */
76
+ cloneNode() {
77
+ const cloned = this.cloneChildNodes(),
78
+ config = this.getAttribute('config');
79
+ return Parser.run(() => {
80
+ const token = new this.constructor(undefined, config);
81
+ token.append(...cloned);
82
+ return token;
83
+ });
84
+ }
85
+ }
86
+
87
+ Parser.classes.NestedToken = __filename;
88
+ module.exports = NestedToken;
@@ -0,0 +1,23 @@
1
+ 'use strict';
2
+
3
+ const Parser = require('../..'),
4
+ NestedToken = require('.');
5
+
6
+ /**
7
+ * `<references>`
8
+ * @classdesc `{childNodes: [...ExtToken|NoincludeToken]}`
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;
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const hidden = require('../../mixin/hidden'),
4
+ {generateForSelf} = require('../../util/lint'),
4
5
  Parser = require('../..'),
5
6
  NowikiToken = require('.');
6
7
 
@@ -29,8 +30,21 @@ class CommentToken extends hidden(NowikiToken) {
29
30
  }
30
31
 
31
32
  /** @override */
32
- cloneNode() {
33
- return Parser.run(() => new CommentToken(String(this.firstChild), this.closed, this.getAttribute('config')));
33
+ getPadding() {
34
+ return 4;
35
+ }
36
+
37
+ /** @override */
38
+ print() {
39
+ return super.print({pre: '&lt;!--', post: this.closed ? '--&gt;' : ''});
40
+ }
41
+
42
+ /**
43
+ * @override
44
+ * @param {number} start 起始位置
45
+ */
46
+ lint(start = 0) {
47
+ return this.closed ? [] : [generateForSelf(this, this.getRootNode().posFromIndex(start), '未闭合的HTML注释')];
34
48
  }
35
49
 
36
50
  /**
@@ -48,8 +62,8 @@ class CommentToken extends hidden(NowikiToken) {
48
62
  }
49
63
 
50
64
  /** @override */
51
- getPadding() {
52
- return 4;
65
+ cloneNode() {
66
+ return Parser.run(() => new CommentToken(String(this.firstChild), this.closed, this.getAttribute('config')));
53
67
  }
54
68
  }
55
69
 
package/src/nowiki/dd.js CHANGED
@@ -32,9 +32,9 @@ class DdToken extends NowikiToken {
32
32
 
33
33
  set indent(indent) {
34
34
  if (this.type === 'dd') {
35
- if (typeof indent !== 'number') {
35
+ if (!Number.isInteger(indent)) {
36
36
  this.typeError('set indent', 'Number');
37
- } else if (!Number.isInteger(indent) || indent < 0) {
37
+ } else if (indent < 0) {
38
38
  throw new RangeError(`indent 应为自然数!${indent}`);
39
39
  }
40
40
  this.setText(':'.repeat(indent));
@@ -11,18 +11,14 @@ const hidden = require('../../mixin/hidden'),
11
11
  class DoubleUnderscoreToken extends hidden(NowikiToken) {
12
12
  type = 'double-underscore';
13
13
 
14
- /**
15
- * @param {string} word 状态开关名
16
- * @param {accum} accum
17
- */
18
- constructor(word, config = Parser.getConfig(), accum = []) {
19
- super(word, config, accum);
20
- this.setAttribute('name', word.toLowerCase());
14
+ /** @override */
15
+ getPadding() {
16
+ return 2;
21
17
  }
22
18
 
23
19
  /** @override */
24
- cloneNode() {
25
- return Parser.run(() => new DoubleUnderscoreToken(String(this.firstChild), this.getAttribute('config')));
20
+ print() {
21
+ return super.print({pre: '__', post: '__'});
26
22
  }
27
23
 
28
24
  /**
@@ -33,9 +29,18 @@ class DoubleUnderscoreToken extends hidden(NowikiToken) {
33
29
  return selector && this.matches(selector) ? '' : `__${String(this.firstChild)}__`;
34
30
  }
35
31
 
32
+ /**
33
+ * @param {string} word 状态开关名
34
+ * @param {accum} accum
35
+ */
36
+ constructor(word, config = Parser.getConfig(), accum = []) {
37
+ super(word, config, accum);
38
+ this.setAttribute('name', word.toLowerCase());
39
+ }
40
+
36
41
  /** @override */
37
- getPadding() {
38
- return 2;
42
+ cloneNode() {
43
+ return Parser.run(() => new DoubleUnderscoreToken(String(this.firstChild), this.getAttribute('config')));
39
44
  }
40
45
 
41
46
  /**
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const fixedToken = require('../../mixin/fixedToken'),
4
+ {generateForSelf} = require('../../util/lint'),
4
5
  Parser = require('../..'),
5
6
  Token = require('..'),
6
7
  AstText = require('../../lib/text');
@@ -20,6 +21,17 @@ class NowikiToken extends fixedToken(Token) {
20
21
  super(wikitext, config, true, accum);
21
22
  }
22
23
 
24
+ /**
25
+ * @override
26
+ * @param {number} start 起始位置
27
+ */
28
+ lint(start = 0) {
29
+ const {type, name} = this;
30
+ return type === 'ext-inner' && (name === 'templatestyles' || name === 'section') && String(this)
31
+ ? [generateForSelf(this, this.getRootNode().posFromIndex(start), `<${name}>标签内不应有任何内容`)]
32
+ : super.lint(start);
33
+ }
34
+
23
35
  /**
24
36
  * @override
25
37
  * @this {NowikiToken & {firstChild: AstText, constructor: typeof NowikiToken}}
@@ -1,6 +1,8 @@
1
1
  'use strict';
2
2
 
3
- const Parser = require('../..'),
3
+ const {generateForSelf} = require('../../util/lint'),
4
+ Parser = require('../..'),
5
+ AstText = require('../../lib/text'),
4
6
  NowikiToken = require('.');
5
7
 
6
8
  /**
@@ -19,6 +21,31 @@ class QuoteToken extends NowikiToken {
19
21
  this.setAttribute('name', String(n));
20
22
  }
21
23
 
24
+ /**
25
+ * @override
26
+ * @this {AstText}
27
+ * @param {number} start 起始位置
28
+ */
29
+ lint(start = 0) {
30
+ const {previousSibling, nextSibling} = this,
31
+ message = `孤立的"'"`,
32
+ /** @type {LintError[]} */ errors = [];
33
+ let /** @type {LintError} */ refError;
34
+ if (previousSibling?.type === 'text' && previousSibling.data.at(-1) === "'") {
35
+ refError = generateForSelf(this, this.getRootNode().posFromIndex(start), '');
36
+ const {startLine, startCol} = refError,
37
+ [{length}] = previousSibling.data.match(/(?<!')'+$/u);
38
+ errors.push({message, startLine, startCol: startCol - length, endLine: startLine, endCol: startCol});
39
+ }
40
+ if (nextSibling?.type === 'text' && nextSibling.data[0] === "'") {
41
+ refError ||= generateForSelf(this, this.getRootNode().posFromIndex(start), '');
42
+ const {endLine, endCol} = refError,
43
+ [{length}] = nextSibling.data.match(/^'+/u);
44
+ errors.push({message, startLine: endLine, startCol: endCol, endLine, endCol: endCol + length});
45
+ }
46
+ return errors;
47
+ }
48
+
22
49
  /**
23
50
  * @override
24
51
  * @param {string} str 新文本
@@ -23,14 +23,6 @@ class OnlyincludeToken extends Token {
23
23
  super(inner, config, true, accum);
24
24
  }
25
25
 
26
- /** @override */
27
- cloneNode() {
28
- const cloned = this.cloneChildNodes(),
29
- token = Parser.run(() => new OnlyincludeToken(undefined, this.getAttribute('config')));
30
- token.append(...cloned);
31
- return token;
32
- }
33
-
34
26
  /**
35
27
  * @override
36
28
  * @param {string} selector
@@ -44,10 +36,25 @@ class OnlyincludeToken extends Token {
44
36
  return 13;
45
37
  }
46
38
 
39
+ /** @override */
40
+ print() {
41
+ return super.print({pre: '&lt;onlyinclude&gt;', post: '&lt;/onlyinclude&gt;'});
42
+ }
43
+
47
44
  /** @override */
48
45
  isPlain() {
49
46
  return true;
50
47
  }
48
+
49
+ /** @override */
50
+ cloneNode() {
51
+ const cloned = this.cloneChildNodes();
52
+ return Parser.run(() => {
53
+ const token = new OnlyincludeToken(undefined, this.getAttribute('config'));
54
+ token.append(...cloned);
55
+ return token;
56
+ });
57
+ }
51
58
  }
52
59
 
53
60
  Parser.classes.OnlyincludeToken = __filename;
@@ -0,0 +1,83 @@
1
+ 'use strict';
2
+
3
+ const {generateForChild} = require('../../util/lint'),
4
+ Parser = require('../..'),
5
+ Token = require('..'),
6
+ AtomToken = require('../atom');
7
+
8
+ /**
9
+ * `<inputbox>`
10
+ * @classdesc `{childNodes: ...AtomToken}`
11
+ */
12
+ class ParamTagToken extends Token {
13
+ type = 'ext-inner';
14
+
15
+ /**
16
+ * @param {string} wikitext wikitext
17
+ * @param {accum} accum
18
+ */
19
+ constructor(wikitext, config = Parser.getConfig(), accum = []) {
20
+ super(undefined, config, true, accum, {AtomToken: ':'});
21
+ if (wikitext) {
22
+ this.append(
23
+ ...wikitext.split('\n').map(line => new AtomToken(line, 'param-line', config, accum, {AstText: ':'})),
24
+ );
25
+ }
26
+ }
27
+
28
+ /**
29
+ * @override
30
+ * @param {string} selector
31
+ */
32
+ toString(selector) {
33
+ return super.toString(selector, '\n');
34
+ }
35
+
36
+ /** @override */
37
+ getGaps() {
38
+ return 1;
39
+ }
40
+
41
+ /** @override */
42
+ print() {
43
+ return super.print({sep: '\n'});
44
+ }
45
+
46
+ /**
47
+ * @override
48
+ * @param {number} start 起始位置
49
+ */
50
+ lint(start = 0) {
51
+ let /** @type {{top: number, left: number}} */ rect;
52
+ return this.childNodes.filter(child => {
53
+ const {childNodes} = child,
54
+ i = childNodes.findIndex(({type}) => type !== 'text'),
55
+ str = (i >= 0 ? childNodes.slice(0, i).map(String).join('') : String(child)).trim();
56
+ return str && !(i >= 0 ? /^[a-z]+\s*(?:=|$)/iu : /^[a-z]+\s*=/iu).test(str);
57
+ }).map(child => {
58
+ rect ||= this.getRootNode().posFromIndex(start);
59
+ return generateForChild(child, rect, `${this.name}的无效参数`);
60
+ });
61
+ }
62
+
63
+ /** @override */
64
+ text() {
65
+ return super.text('\n');
66
+ }
67
+
68
+ /**
69
+ * @override
70
+ * @this {ParamTagToken & {constructor: typeof ParamTagToken}}
71
+ */
72
+ cloneNode() {
73
+ const cloned = this.cloneChildNodes();
74
+ return Parser.run(() => {
75
+ const token = new this.constructor(undefined, this.getAttribute('config'));
76
+ token.append(...cloned);
77
+ return token;
78
+ });
79
+ }
80
+ }
81
+
82
+ Parser.classes.ParamTagToken = __filename;
83
+ module.exports = ParamTagToken;
@@ -0,0 +1,42 @@
1
+ 'use strict';
2
+
3
+ const parseBrackets = require('../../parser/brackets'),
4
+ Parser = require('../..'),
5
+ ParamTagToken = require('.'),
6
+ AtomToken = require('../atom');
7
+
8
+ /**
9
+ * `<inputbox>`
10
+ * @classdesc `{childNodes: ...AtomToken}`
11
+ */
12
+ class InputboxToken extends ParamTagToken {
13
+ name = 'inputbox';
14
+
15
+ /**
16
+ * @param {string} wikitext wikitext
17
+ * @param {accum} accum
18
+ */
19
+ constructor(wikitext, config = Parser.getConfig(), accum = []) {
20
+ super(undefined, config, accum);
21
+ wikitext = parseBrackets(wikitext, config, accum);
22
+ accum.splice(accum.indexOf(this), 1);
23
+ accum.push(this);
24
+ if (wikitext) {
25
+ this.append(...wikitext.split('\n').map(line => new AtomToken(
26
+ line, 'param-line', config, accum, {AstText: ':', ArgToken: ':', TranscludeToken: ':'},
27
+ )));
28
+ }
29
+ }
30
+
31
+ /** @override */
32
+ afterBuild() {
33
+ for (const heading of this.querySelectorAll('heading')) {
34
+ const {firstChild, lastChild, name} = heading,
35
+ syntax = '='.repeat(name);
36
+ heading.replaceWith(syntax, ...firstChild.cloneChildNodes(), `${syntax}${String(lastChild)}`);
37
+ }
38
+ }
39
+ }
40
+
41
+ Parser.classes.InputboxToken = __filename;
42
+ module.exports = InputboxToken;