wikiparser-node 1.30.0 → 1.32.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.
Files changed (101) hide show
  1. package/README.md +9 -4
  2. package/bundle/bundle-es8.min.js +28 -29
  3. package/bundle/bundle-lsp.min.js +34 -34
  4. package/bundle/bundle.min.js +23 -23
  5. package/dist/addon/attribute.js +166 -0
  6. package/dist/addon/link.js +92 -0
  7. package/dist/addon/table.js +12 -3
  8. package/dist/addon/token.js +5 -316
  9. package/dist/addon/transclude.js +11 -8
  10. package/dist/base.d.mts +13 -4
  11. package/dist/base.d.ts +13 -4
  12. package/dist/base.js +2 -0
  13. package/dist/base.mjs +2 -0
  14. package/dist/bin/config.js +1 -1
  15. package/dist/index.d.ts +34 -5
  16. package/dist/index.js +100 -88
  17. package/dist/internal.d.ts +6 -1
  18. package/dist/lib/document.d.ts +9 -7
  19. package/dist/lib/document.js +91 -66
  20. package/dist/lib/element.d.ts +8 -8
  21. package/dist/lib/element.js +52 -50
  22. package/dist/lib/lintConfig.js +6 -2
  23. package/dist/lib/lsp.js +120 -56
  24. package/dist/lib/node.js +21 -15
  25. package/dist/lib/redirectMap.js +1 -1
  26. package/dist/lib/text.js +17 -14
  27. package/dist/lib/title.d.ts +11 -0
  28. package/dist/lib/title.js +37 -13
  29. package/dist/mixin/elementLike.js +2 -3
  30. package/dist/mixin/syntax.js +13 -7
  31. package/dist/parser/commentAndExt.js +4 -4
  32. package/dist/parser/hrAndDoubleUnderscore.js +11 -9
  33. package/dist/parser/selector.js +16 -41
  34. package/dist/render/expand.js +216 -0
  35. package/dist/render/extension.js +141 -0
  36. package/dist/render/html.js +91 -0
  37. package/dist/render/magicWords.js +768 -0
  38. package/dist/render/syntaxhighlight.js +415 -0
  39. package/dist/src/arg.js +8 -1
  40. package/dist/src/atom.js +2 -0
  41. package/dist/src/attribute.d.ts +5 -0
  42. package/dist/src/attribute.js +59 -104
  43. package/dist/src/attributes.d.ts +5 -0
  44. package/dist/src/attributes.js +17 -51
  45. package/dist/src/converter.js +4 -2
  46. package/dist/src/converterFlags.js +8 -6
  47. package/dist/src/converterRule.js +19 -15
  48. package/dist/src/extLink.js +2 -2
  49. package/dist/src/heading.d.ts +1 -1
  50. package/dist/src/heading.js +5 -3
  51. package/dist/src/imageParameter.d.ts +0 -1
  52. package/dist/src/imageParameter.js +34 -24
  53. package/dist/src/index.d.ts +5 -5
  54. package/dist/src/index.js +37 -27
  55. package/dist/src/link/base.js +26 -36
  56. package/dist/src/link/category.d.ts +8 -1
  57. package/dist/src/link/category.js +104 -38
  58. package/dist/src/link/file.js +21 -8
  59. package/dist/src/link/galleryImage.js +2 -3
  60. package/dist/src/link/index.d.ts +1 -1
  61. package/dist/src/link/index.js +12 -33
  62. package/dist/src/multiLine/index.js +1 -1
  63. package/dist/src/nowiki/comment.js +1 -1
  64. package/dist/src/nowiki/doubleUnderscore.js +4 -2
  65. package/dist/src/nowiki/index.js +34 -31
  66. package/dist/src/nowiki/list.js +3 -1
  67. package/dist/src/nowiki/listBase.d.ts +2 -1
  68. package/dist/src/nowiki/listBase.js +22 -8
  69. package/dist/src/nowiki/quote.d.ts +1 -1
  70. package/dist/src/nowiki/quote.js +3 -3
  71. package/dist/src/onlyinclude.js +1 -1
  72. package/dist/src/paramLine.js +2 -0
  73. package/dist/src/parameter.js +1 -1
  74. package/dist/src/redirect.js +1 -1
  75. package/dist/src/table/base.js +5 -4
  76. package/dist/src/table/index.d.ts +1 -6
  77. package/dist/src/table/index.js +7 -16
  78. package/dist/src/table/td.js +12 -9
  79. package/dist/src/tag/html.js +2 -3
  80. package/dist/src/tag/index.js +8 -6
  81. package/dist/src/tagPair/ext.js +18 -41
  82. package/dist/src/tagPair/index.js +6 -4
  83. package/dist/src/tagPair/translate.d.ts +1 -0
  84. package/dist/src/tagPair/translate.js +10 -3
  85. package/dist/src/transclude.js +18 -21
  86. package/dist/util/constants.js +9 -3
  87. package/dist/util/debug.js +72 -5
  88. package/dist/util/diff.js +17 -15
  89. package/dist/util/html.js +14 -5
  90. package/dist/util/selector.js +37 -0
  91. package/dist/util/sharable.d.mts +4 -1
  92. package/dist/util/sharable.js +7 -7
  93. package/dist/util/sharable.mjs +7 -7
  94. package/dist/util/string.js +51 -20
  95. package/extensions/dist/base.js +2 -2
  96. package/extensions/editor.css +1 -1
  97. package/i18n/en.json +1 -0
  98. package/i18n/zh-hans.json +30 -29
  99. package/i18n/zh-hant.json +31 -30
  100. package/package.json +23 -16
  101. package/dist/addon/magicWords.js +0 -132
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ /* eslint @stylistic/operator-linebreak: [2, "before", {overrides: {"=": "after"}}] */
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const constants_1 = require("../util/constants");
8
+ const debug_1 = require("../util/debug");
9
+ const string_1 = require("../util/string");
10
+ const index_1 = __importDefault(require("../index"));
11
+ const document_1 = require("../lib/document");
12
+ const attribute_1 = require("../src/attribute");
13
+ const attributes_1 = require("../src/attributes");
14
+ const atom_1 = require("../src/atom");
15
+ attribute_1.AttributeToken.prototype.setValue =
16
+ /** @implements */
17
+ function (value) {
18
+ if (value === false) {
19
+ this.remove();
20
+ return;
21
+ }
22
+ else if (value === true) {
23
+ this.setAttribute('equal', '');
24
+ return;
25
+ }
26
+ const { type, lastChild } = this;
27
+ if (type === 'ext-attr' && value.includes('>')) {
28
+ throw new RangeError('Attributes of an extension tag cannot contain ">"!');
29
+ }
30
+ else if (value.includes('"') && value.includes(`'`)) {
31
+ throw new RangeError('Attribute values cannot contain single and double quotes simultaneously!');
32
+ }
33
+ const { childNodes } = index_1.default.parseWithRef(value, this, attribute_1.stages[type] + 1);
34
+ lastChild.safeReplaceChildren(childNodes);
35
+ if (value.includes('"')) {
36
+ this.setAttribute('quotes', [`'`, `'`]);
37
+ }
38
+ else if (value.includes(`'`) || !this.getAttribute('quotes')[0]) {
39
+ this.setAttribute('quotes', ['"', '"']);
40
+ }
41
+ else {
42
+ this.close();
43
+ }
44
+ };
45
+ attribute_1.AttributeToken.prototype.rename =
46
+ /** @implements */
47
+ function (key) {
48
+ const { type, name, tag, firstChild } = this;
49
+ if (name === 'title' || name === 'alt' && tag === 'img') {
50
+ throw new Error(`${name} attribute cannot be renamed!`);
51
+ }
52
+ const { childNodes } = index_1.default.parseWithRef(key, this, attribute_1.stages[type] + 1);
53
+ firstChild.safeReplaceChildren(childNodes);
54
+ };
55
+ attribute_1.AttributeToken.prototype.css =
56
+ /** @implements */
57
+ function (key, value) {
58
+ const { name, lastChild } = this;
59
+ if (name !== 'style') {
60
+ throw new Error('Not a style attribute!');
61
+ }
62
+ else if (lastChild.length !== 1 || lastChild.firstChild.type !== 'text') {
63
+ throw new Error('Complex style attribute!');
64
+ }
65
+ const cssLSP = (0, document_1.loadCssLSP)();
66
+ if (!cssLSP) {
67
+ throw new Error('CSS language service is not available!');
68
+ }
69
+ const doc = new document_1.EmbeddedCSSDocument(this.getRootNode(), lastChild), styleSheet = doc.styleSheet, { children: [{ declarations }] } = styleSheet, declaration = declarations.children?.filter(({ property }) => property.getText() === key) ?? [];
70
+ if (value === undefined) {
71
+ return declaration.at(-1)?.value.getText();
72
+ }
73
+ else if (typeof value === 'number') {
74
+ value = String(value);
75
+ }
76
+ const style = styleSheet.getText().slice(0, -1);
77
+ if (!value) {
78
+ if (declaration.length === declarations.children?.length) {
79
+ this.setValue('');
80
+ }
81
+ else if (declaration.length > 0) {
82
+ let output = '', start = doc.pre.length;
83
+ for (const { offset, length } of declaration) {
84
+ output += style.slice(start, offset);
85
+ start = offset + length;
86
+ }
87
+ output += style.slice(start);
88
+ this.setValue(output.replace(/^\s*;\s*|;\s*(?=;)/gu, ''));
89
+ }
90
+ return undefined;
91
+ }
92
+ const hasQuote = value.includes('"'), [quot] = this.getAttribute('quotes');
93
+ if (quot && value.includes(quot) || hasQuote && value.includes(`'`)) {
94
+ const quote = quot || '"';
95
+ throw new RangeError(`Please consider replacing \`${quote}\` with \`${quote === '"' ? `'` : '"'}\`!`);
96
+ }
97
+ else if (declaration.length > 0) {
98
+ const { offset, length } = declaration.at(-1).value;
99
+ this.setValue(style.slice(doc.pre.length, offset) + value + style.slice(offset + length));
100
+ }
101
+ else {
102
+ this.setValue(`${style.slice(doc.pre.length)}${/;\s*$/u.test(style) ? '' : '; '}${key}: ${value}`);
103
+ }
104
+ return undefined;
105
+ };
106
+ attributes_1.AttributesToken.prototype.sanitize =
107
+ /** @implements */
108
+ function () {
109
+ let dirty = false;
110
+ for (let i = this.length - 1; i >= 0; i--) {
111
+ const child = this.childNodes[i];
112
+ if (child instanceof atom_1.AtomToken && child.text().trim()) {
113
+ dirty = true;
114
+ this.removeAt(i);
115
+ }
116
+ }
117
+ if (!debug_1.Shadow.running && dirty) {
118
+ index_1.default.warn('AttributesToken.sanitize will remove invalid attributes!');
119
+ }
120
+ };
121
+ attributes_1.AttributesToken.prototype.setAttr =
122
+ /** @implements */
123
+ function (keyOrProp, value) {
124
+ if (typeof keyOrProp === 'object') {
125
+ for (const [key, val] of Object.entries(keyOrProp)) {
126
+ this.setAttr(key, val);
127
+ }
128
+ return;
129
+ }
130
+ const { type, name } = this;
131
+ if (type === 'ext-attrs' && typeof value === 'string' && value.includes('>')) {
132
+ throw new RangeError('Attributes of an extension tag cannot contain ">"!');
133
+ }
134
+ const key = (0, string_1.trimLc)(keyOrProp), attr = this.getAttrToken(key);
135
+ if (attr) {
136
+ attr.setValue(value);
137
+ return;
138
+ }
139
+ else if (value === false) {
140
+ return;
141
+ }
142
+ // @ts-expect-error abstract class
143
+ const token = debug_1.Shadow.run(() => new attribute_1.AttributeToken((0, attributes_1.toAttributeType)(type), name, key, value === true ? '' : '=', value === true ? '' : value, ['"', '"'], this.getAttribute('config')));
144
+ this.insertAt(token);
145
+ };
146
+ attributes_1.AttributesToken.prototype.toggleAttr =
147
+ /** @implements */
148
+ function (key, force) {
149
+ key = (0, string_1.trimLc)(key);
150
+ const attr = this.getAttrToken(key);
151
+ if (attr && attr.getValue() !== true) {
152
+ throw new RangeError(`${key} attribute is not Boolean!`);
153
+ }
154
+ else if (attr) {
155
+ attr.setValue(force === true);
156
+ }
157
+ else if (force !== false) {
158
+ this.setAttr(key, true);
159
+ }
160
+ };
161
+ attributes_1.AttributesToken.prototype.css =
162
+ /** @implements */
163
+ function (key, value) {
164
+ return this.getAttrToken('style')?.css(key, value);
165
+ };
166
+ constants_1.classes['ExtendedAttributeToken'] = __filename;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ /* eslint @stylistic/operator-linebreak: [2, "before", {overrides: {"=": "after"}}] */
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const constants_1 = require("../util/constants");
8
+ const debug_1 = require("../util/debug");
9
+ const string_1 = require("../util/string");
10
+ const index_1 = __importDefault(require("../index"));
11
+ const base_1 = require("../src/link/base");
12
+ const index_2 = require("../src/link/index");
13
+ const atom_1 = require("../src/atom");
14
+ base_1.LinkBaseToken.prototype.setTarget =
15
+ /** @implements */
16
+ function (link) {
17
+ const { childNodes } = index_1.default.parseWithRef(link, this, 2), token = debug_1.Shadow.run(() => new atom_1.AtomToken(undefined, 'link-target', this.getAttribute('config'), [], { 'Stage-2': ':', '!ExtToken': '', '!HeadingToken': '' }));
18
+ token.concat(childNodes); // eslint-disable-line unicorn/prefer-spread
19
+ this.firstChild.safeReplaceWith(token);
20
+ };
21
+ base_1.LinkBaseToken.prototype.setFragment =
22
+ /** @implements */
23
+ function (fragment) {
24
+ const { type, name } = this;
25
+ if (fragment === undefined || (0, debug_1.isLink)(type)) {
26
+ fragment &&= (0, string_1.encode)(fragment);
27
+ this.setTarget(name + (fragment === undefined ? '' : `#${fragment}`));
28
+ }
29
+ };
30
+ base_1.LinkBaseToken.prototype.setLinkText =
31
+ /** @implements */
32
+ function (linkStr) {
33
+ const { childNodes, lastChild, length } = this;
34
+ if (linkStr === undefined) {
35
+ childNodes[1]?.remove();
36
+ return;
37
+ }
38
+ const root = index_1.default.parseWithRef(linkStr, this);
39
+ if (length === 1) {
40
+ root.type = 'link-text';
41
+ root.setAttribute('acceptable', {
42
+ 'Stage-5': ':', QuoteToken: ':', ConverterToken: ':',
43
+ });
44
+ this.insertAt(root);
45
+ }
46
+ else {
47
+ lastChild.safeReplaceChildren(root.childNodes);
48
+ }
49
+ };
50
+ index_2.LinkToken.prototype.setLangLink =
51
+ /** @implements */
52
+ function (lang, link) {
53
+ link = link.trim();
54
+ /* istanbul ignore if */
55
+ if (link.startsWith('#')) {
56
+ throw new SyntaxError('An interlanguage link cannot be fragment only!');
57
+ }
58
+ this.setTarget(lang + (link.startsWith(':') ? '' : ':') + link);
59
+ };
60
+ index_2.LinkToken.prototype.asSelfLink =
61
+ /** @implements */
62
+ function (fragment) {
63
+ fragment ??= this.fragment;
64
+ /* istanbul ignore if */
65
+ if (!fragment?.trim()) {
66
+ throw new RangeError('LinkToken.asSelfLink method must specify a non-empty fragment!');
67
+ }
68
+ this.setTarget(`#${(0, string_1.encode)(fragment)}`);
69
+ };
70
+ index_2.LinkToken.prototype.pipeTrick =
71
+ /** @implements */
72
+ function () {
73
+ const linkText = this.firstChild.text();
74
+ /* istanbul ignore if */
75
+ if (linkText.includes('#') || linkText.includes('%')) {
76
+ throw new Error('Pipe trick cannot be used with "#" or "%"!');
77
+ }
78
+ const m1 = /^:?(?:[ \w\x80-\xFF-]+:)?([^(]+?) ?\(.+\)$/u.exec(linkText);
79
+ if (m1) {
80
+ this.setLinkText(m1[1]);
81
+ return;
82
+ }
83
+ const m2 = /^:?(?:[ \w\x80-\xFF-]+:)?([^(]+?) ?(.+)$/u.exec(linkText);
84
+ if (m2) {
85
+ this.setLinkText(m2[1]);
86
+ return;
87
+ }
88
+ const m3 = /^:?(?:[ \w\x80-\xFF-]+:)?(.*?)(?: ?(?<!\()\(.+\))?(?:(?:, |,|، ).|$)/u
89
+ .exec(linkText);
90
+ this.setLinkText(m3[1]);
91
+ };
92
+ constants_1.classes['ExtendedLinkToken'] = __filename;
@@ -106,6 +106,15 @@ const getMaxCol = (layout) => {
106
106
  }
107
107
  return maxCol;
108
108
  };
109
+ index_2.TableToken.prototype.getNthCell =
110
+ /** @implements */
111
+ function (coords) {
112
+ let rawCoords = coords;
113
+ if (coords.row === undefined) {
114
+ rawCoords = this.toRawCoords(coords);
115
+ }
116
+ return rawCoords && this.getNthRow(rawCoords.row, false, false)?.getNthCol(rawCoords.column);
117
+ };
109
118
  index_2.TableToken.prototype.printLayout =
110
119
  /** @implements */
111
120
  function () {
@@ -144,7 +153,7 @@ index_2.TableToken.prototype.getFullCol =
144
153
  /** @implements */
145
154
  function (x) {
146
155
  const layout = this.getLayout(), rows = this.getAllRows();
147
- return new Map(layout.map(row => row[x]).filter(Boolean).map(coords => [rows[coords.row].getNthCol(coords.column), layout[coords.row][x - 1] !== coords]));
156
+ return new Map(layout.map(row => row[x]).filter(coords => coords !== undefined).map(coords => [rows[coords.row].getNthCol(coords.column), layout[coords.row][x - 1] !== coords]));
148
157
  };
149
158
  index_2.TableToken.prototype.formatTableRow =
150
159
  /** @implements */
@@ -470,7 +479,7 @@ index_2.TableToken.prototype.moveTableRowAfter =
470
479
  }
471
480
  }
472
481
  if (afterToken === this) {
473
- const index = this.childNodes.slice(2).findIndex(index_2.isRowEnd);
482
+ const index = this.childNodes.slice(2).findIndex(debug_1.isRowEnd);
474
483
  this.insertAt(rowToken, index + 2);
475
484
  }
476
485
  else {
@@ -509,7 +518,7 @@ index_2.TableToken.prototype.moveCol =
509
518
  if (start) {
510
519
  const col = rowLayout.slice(reference + Number(after)).find(({ row }) => row === i)?.column;
511
520
  rowToken.insertBefore(token, col === undefined
512
- ? rowToken.childNodes.slice(2).find(index_2.isRowEnd)
521
+ ? rowToken.childNodes.slice(2).find(debug_1.isRowEnd)
513
522
  : rowToken.getNthCol(col));
514
523
  }
515
524
  }
@@ -1,329 +1,18 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const fs_1 = __importDefault(require("fs"));
7
- const path_1 = __importDefault(require("path"));
8
3
  const constants_1 = require("../util/constants");
9
4
  const debug_1 = require("../util/debug");
10
- const string_1 = require("../util/string");
11
- const index_1 = __importDefault(require("../index"));
12
- const index_2 = require("../src/index");
5
+ const index_1 = require("../src/index");
13
6
  const comment_1 = require("../src/nowiki/comment");
14
7
  const include_1 = require("../src/tagPair/include");
15
8
  const ext_1 = require("../src/tagPair/ext");
16
9
  const html_1 = require("../src/tag/html");
17
10
  const attributes_1 = require("../src/attributes");
18
- const magicWords_1 = require("./magicWords");
19
- const blockElems = 'table|h1|h2|h3|h4|h5|h6|pre|p|ul|ol|dl', antiBlockElems = 'td|th', solvedMagicWords = new Set([
20
- 'if',
21
- 'ifeq',
22
- 'ifexist',
23
- 'switch',
24
- ]);
25
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
26
- /<(?:table|\/(?:td|th)|\/?(?:tr|caption|dt|dd|li))\b/iu;
27
- const openRegex = new RegExp(String.raw `<(?:${blockElems}|\/(?:${antiBlockElems})|\/?(?:tr|caption|dt|dd|li))\b`, 'iu');
28
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
29
- /<(?:\/(?:h1|h2)|td|th|\/?(?:center|blockquote|div|hr|figure))\b/iu;
30
- const closeRegex = new RegExp(String.raw `<(?:\/(?:${blockElems})|${antiBlockElems}|\/?(?:center|blockquote|div|hr|figure))\b`, 'iu');
31
- /**
32
- * 隐式换行
33
- * @param str 字符串
34
- * @param prev 前一个字符
35
- */
36
- const implicitNewLine = (str, prev) => prev + (prev !== '\n' && /^(?:\{\||[:;#*])/u.test(str) ? `\n${str}` : str);
37
- /**
38
- * 比较两个字符串是否相等
39
- * @param a
40
- * @param b
41
- */
42
- const cmp = (a, b) => a === b || Boolean(a && b) && Number(a) === Number(b);
43
- /**
44
- * 解析 if/ifexist/ifeq 解析器函数
45
- * @param accum
46
- * @param prev 解析器函数前的字符串
47
- * @param effective 生效的参数
48
- */
49
- const parseIf = (accum, prev, effective) => {
50
- if (effective) {
51
- // @ts-expect-error sparse array
52
- accum[accum.indexOf(effective.lastChild)] = undefined;
53
- return implicitNewLine(effective.value, prev);
54
- }
55
- return prev;
56
- };
57
- /**
58
- * 展开模板
59
- * @param wikitext
60
- * @param page 页面名称
61
- * @param config
62
- * @param include
63
- * @param context 模板调用环境
64
- * @param now 当前时间
65
- * @param accum
66
- * @param stack 模板调用栈
67
- */
68
- const expand = (wikitext, page, config, include, context, now = index_1.default.now ?? new Date(), accum = [], stack = []) => {
69
- const n = accum.length, token = new index_2.Token(wikitext, { ...config, inExt: true }, accum);
70
- token.type = 'root';
71
- token.pageName = page;
72
- token.parseOnce(0, include);
73
- if (context !== false) {
74
- token.setText((0, string_1.removeCommentLine)(token.firstChild.toString(), true));
75
- }
76
- token.parseOnce();
77
- for (const plain of [...accum.slice(n), token]) {
78
- if (plain.length !== 1 || plain.firstChild.type !== 'text') {
79
- continue;
80
- }
81
- const { data } = plain.firstChild;
82
- if (!/\0\d+t\x7F/u.test(data)) {
83
- continue;
84
- }
85
- const expanded = data.replace(/([^\x7F]?)\0(\d+)t\x7F/gu, (m, prev, i) => {
86
- const target = accum[i], { type, name, length, firstChild: f, childNodes } = target, isTemplate = type === 'template', args = childNodes.slice(1);
87
- if (type === 'arg') {
88
- const arg = (0, string_1.removeCommentLine)(f.toString()).trim();
89
- if (/\0\d+t\x7F/u.test(arg)) {
90
- return m;
91
- }
92
- else if (!context || !context.hasArg(arg)) {
93
- const effective = target.childNodes[1] ?? target;
94
- // @ts-expect-error sparse array
95
- accum[accum.indexOf(length === 1 ? f : effective)] = undefined;
96
- return prev + effective.toString();
97
- }
98
- // @ts-expect-error sparse array
99
- accum[accum.indexOf(context.getArg(arg).lastChild)] = undefined;
100
- return prev + context.getValue(arg);
101
- }
102
- else if (isTemplate || name === 'int') {
103
- if (context === false) {
104
- return m;
105
- }
106
- const nameToken = isTemplate ? f : args[0], key = (0, string_1.removeComment)(nameToken.toString()), fallback = isTemplate ? m : `${prev}⧼${key}⧽`, { title, valid } = index_1.default.normalizeTitle((isTemplate ? '' : 'MediaWiki:') + key, 10, include, config, { halfParsed: true, temporary: true, page });
107
- if (!valid) {
108
- // @ts-expect-error sparse array
109
- accum[accum.indexOf(target)] = undefined;
110
- // @ts-expect-error sparse array
111
- accum[accum.indexOf(f)] = undefined;
112
- return isTemplate ? prev + target.toString() : fallback;
113
- }
114
- else if (!index_1.default.templates.has(title)) {
115
- if (index_1.default.templateDir === undefined) {
116
- return fallback;
117
- }
118
- else if (!path_1.default.isAbsolute(index_1.default.templateDir)) {
119
- index_1.default.templateDir = path_1.default.join(__dirname, '..', '..', index_1.default.templateDir);
120
- }
121
- const file = fs_1.default.readdirSync(index_1.default.templateDir, { withFileTypes: true, recursive: true })
122
- .filter(dirent => dirent.isFile())
123
- .find(({ name: fl, parentPath }) => {
124
- const t = path_1.default.relative(index_1.default.templateDir, path_1.default.join(parentPath, fl.replace(/\.(?:wiki|txt)$/iu, ''))).replaceAll('꞉', ':');
125
- try {
126
- return decodeURIComponent(t) === title;
127
- }
128
- catch {
129
- return t === title;
130
- }
131
- });
132
- if (!file) {
133
- return fallback;
134
- }
135
- index_1.default.templates.set(title, fs_1.default.readFileSync(path_1.default.join(file.parentPath, file.name), 'utf8'));
136
- }
137
- else if (stack.includes(title)) {
138
- return `${prev}<span class="error">Template loop detected: [[${title}]]</span>`;
139
- }
140
- let template = index_1.default.templates.get(title);
141
- if (!isTemplate) {
142
- for (let j = 1; j < args.length; j++) {
143
- template = template.replaceAll(`$${j}`, (0, string_1.removeComment)(args[j].toString()));
144
- }
145
- }
146
- return implicitNewLine(expand(template, title, config, true, target, now, accum, [...stack, title]).toString(), prev);
147
- }
148
- else if (index_1.default.functionHooks.has(name)) {
149
- return context === false ? m : prev + index_1.default.functionHooks.get(name)(target, context || undefined);
150
- }
151
- else if (magicWords_1.expandedMagicWords.has(name)) {
152
- return context === false ? m : `${prev}${(0, magicWords_1.expandMagicWord)(name, now, config, args)}`;
153
- }
154
- else if (!solvedMagicWords.has(name)) {
155
- return m;
156
- }
157
- else if (length < 3 || name === 'ifeq' && length === 3) {
158
- return prev;
159
- }
160
- const var1 = (0, string_1.decodeHtml)(args[0].value), var2 = (0, string_1.decodeHtml)(args[1].value), known = !/\0\d+t\x7F/u.test(var1);
161
- if (known && (name === 'if' || name === 'ifexist')) {
162
- let bool = Boolean(var1);
163
- if (name === 'ifexist') {
164
- const { valid, interwiki } = index_1.default.normalizeTitle(var1, 0, include, config, { halfParsed: true, temporary: true, page: '' });
165
- bool = valid && !interwiki;
166
- }
167
- return parseIf(accum, prev, args[bool ? 1 : 2]);
168
- }
169
- else if (known && name === 'ifeq' && !/\0\d+t\x7F/u.test(var2)) {
170
- return parseIf(accum, prev, args[cmp(var1, var2) ? 2 : 3]);
171
- }
172
- else if (known && name === 'switch') {
173
- let defaultVal = '', j = 2,
174
- /**
175
- * - `1` 表示默认值
176
- * - `2` 表示匹配值
177
- */
178
- found = 0, transclusion = false, // eslint-disable-line no-useless-assignment
179
- defaultParam;
180
- for (; j < length; j++) {
181
- const { anon, value, lastChild, name: option } = args[j - 1];
182
- transclusion = /\0\d+t\x7F/u.test(anon ? value : option);
183
- if (anon) {
184
- if (j === length - 1) { // 位于最后的匿名参数是默认值
185
- defaultParam = lastChild;
186
- defaultVal = value;
187
- }
188
- else if (transclusion) { // 不支持复杂参数
189
- break;
190
- }
191
- else if (cmp(var1, (0, string_1.decodeHtml)(value))) { // 下一个命名参数视为匹配值
192
- found = 2;
193
- }
194
- else if (value === '#default' && found !== 2) { // 下一个命名参数视为默认值
195
- found = 1;
196
- }
197
- }
198
- else if (transclusion) { // 不支持复杂参数
199
- break;
200
- }
201
- else if (found === 2 || cmp(var1, (0, string_1.decodeHtml)(option))) { // 第一个匹配值
202
- // @ts-expect-error sparse array
203
- accum[accum.indexOf(lastChild)] = undefined;
204
- return implicitNewLine(value, prev);
205
- }
206
- else if (found === 1 || option.toLowerCase() === '#default') { // 更新默认值
207
- defaultParam = lastChild;
208
- defaultVal = value;
209
- found = 0;
210
- }
211
- }
212
- if (j === length) { // 不含复杂参数
213
- if (defaultParam) {
214
- // @ts-expect-error sparse array
215
- accum[accum.indexOf(defaultParam)] = undefined;
216
- }
217
- return implicitNewLine(defaultVal, prev);
218
- }
219
- }
220
- return m;
221
- });
222
- plain.setText(expanded);
223
- if (plain.type === 'parameter-key') {
224
- plain.parentNode.trimName((0, string_1.removeCommentLine)(expanded));
225
- }
226
- }
227
- return token;
228
- };
229
- /**
230
- * 展开指定节点的模板
231
- * @param token 目标节点
232
- * @param context 模板调用环境
233
- */
234
- const expandToken = (token, context) => expand(token.toString(), token.pageName, token.getAttribute('config'), token.getAttribute('include'), context);
235
- index_2.Token.prototype.expand = /** @implements */ function () {
236
- return debug_1.Shadow.run(() => expandToken(this).parse());
237
- };
238
- index_2.Token.prototype.solveConst = /** @implements */ function () {
239
- return debug_1.Shadow.run(() => expandToken(this, false).parse());
240
- };
241
- index_2.Token.prototype.toHtml = /** @implements */ function () {
242
- const { viewOnly } = index_1.default;
243
- let html;
244
- if (this.type === 'root') {
245
- index_1.default.viewOnly = true;
246
- const expanded = debug_1.Shadow.run(() => expandToken(this).parse(undefined, false, true));
247
- index_1.default.viewOnly = false;
248
- constants_1.states.set(expanded, { headings: new Set() });
249
- const lines = expanded.toHtmlInternal().split('\n');
250
- let output = '', inBlockElem = false, pendingPTag = false, inBlockquote = false, lastParagraph = '';
251
- const /** @ignore */ closeParagraph = () => {
252
- if (lastParagraph) {
253
- const result = `</${lastParagraph}>\n`;
254
- lastParagraph = '';
255
- return result;
256
- }
257
- return '';
258
- };
259
- for (let line of lines) {
260
- const openMatch = openRegex.test(line), closeMatch = closeRegex.test(line);
261
- if (openMatch || closeMatch) {
262
- const blockquote = /<(\/?)blockquote[\s>](?!.*<\/?blockquote[\s>])/iu.exec(line)?.[1];
263
- inBlockquote = blockquote === undefined ? inBlockquote : !blockquote;
264
- pendingPTag = false;
265
- output += closeParagraph();
266
- inBlockElem = !closeMatch;
267
- }
268
- else if (!inBlockElem) {
269
- if (line.startsWith(' ') && (lastParagraph === 'pre' || line.trim()) && !inBlockquote) {
270
- if (lastParagraph !== 'pre') {
271
- pendingPTag = false;
272
- output += `${closeParagraph()}<pre>`;
273
- lastParagraph = 'pre';
274
- }
275
- line = line.slice(1);
276
- }
277
- else if (/^(?:<link\b[^>]*>\s*)+$/iu.test(line)) {
278
- if (pendingPTag) {
279
- output += closeParagraph();
280
- pendingPTag = false;
281
- }
282
- }
283
- else if (!line.trim()) {
284
- if (pendingPTag) {
285
- output += `${pendingPTag}<br>`;
286
- pendingPTag = false;
287
- lastParagraph = 'p';
288
- }
289
- else if (lastParagraph === 'p') {
290
- pendingPTag = '</p><p>';
291
- }
292
- else {
293
- output += closeParagraph();
294
- pendingPTag = '<p>';
295
- }
296
- }
297
- else if (pendingPTag) {
298
- output += pendingPTag;
299
- pendingPTag = false;
300
- lastParagraph = 'p';
301
- }
302
- else if (lastParagraph !== 'p') {
303
- output += `${closeParagraph()}<p>`;
304
- lastParagraph = 'p';
305
- }
306
- }
307
- if (!pendingPTag) {
308
- output += `${line}\n`;
309
- }
310
- }
311
- output += closeParagraph();
312
- constants_1.states.delete(expanded);
313
- html = output.trimEnd();
314
- }
315
- else {
316
- index_1.default.viewOnly = false;
317
- html = this.cloneNode().toHtmlInternal();
318
- }
319
- index_1.default.viewOnly = viewOnly;
320
- return html;
321
- };
322
- index_2.Token.prototype.createComment = /** @implements */ function (data = '') {
11
+ index_1.Token.prototype.createComment = /** @implements */ function (data = '') {
323
12
  // @ts-expect-error abstract class
324
13
  return debug_1.Shadow.run(() => new comment_1.CommentToken(data.replaceAll('-->', '--&gt;'), true, this.getAttribute('config')));
325
14
  };
326
- index_2.Token.prototype.createElement = /** @implements */ function (tagName, { selfClosing, closing } = {}) {
15
+ index_1.Token.prototype.createElement = /** @implements */ function (tagName, { selfClosing, closing } = {}) {
327
16
  const config = this.getAttribute('config'), include = this.getAttribute('include');
328
17
  if (tagName === (include ? 'noinclude' : 'includeonly')) {
329
18
  return debug_1.Shadow.run(
@@ -347,7 +36,7 @@ index_2.Token.prototype.createElement = /** @implements */ function (tagName, {
347
36
  /* istanbul ignore next */
348
37
  throw new RangeError(`Invalid tag name: ${tagName}`);
349
38
  };
350
- index_2.Token.prototype.sections = /** @implements */ function () {
39
+ index_1.Token.prototype.sections = /** @implements */ function () {
351
40
  if (this.type !== 'root') {
352
41
  return undefined;
353
42
  }
@@ -379,7 +68,7 @@ index_2.Token.prototype.sections = /** @implements */ function () {
379
68
  sections.unshift(range);
380
69
  return sections;
381
70
  };
382
- index_2.Token.prototype.findEnclosingHtml = /** @implements */ function (tag) {
71
+ index_1.Token.prototype.findEnclosingHtml = /** @implements */ function (tag) {
383
72
  tag &&= tag.toLowerCase();
384
73
  const { html } = this.getAttribute('config'), normalTags = new Set(html[0]), voidTags = new Set(html[2]);
385
74
  /* istanbul ignore next */