wikiparser-node 1.3.6 → 1.3.7-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 (154) hide show
  1. package/bundle/bundle.min.js +36 -0
  2. package/config/llwiki.json +1 -35
  3. package/config/moegirl.json +1 -44
  4. package/config/zhwiki.json +1 -466
  5. package/extensions/dist/base.js +68 -0
  6. package/extensions/dist/editor.js +159 -0
  7. package/extensions/dist/highlight.js +30 -0
  8. package/extensions/dist/lint.js +48 -0
  9. package/extensions/editor.css +63 -0
  10. package/extensions/ui.css +114 -0
  11. package/package.json +32 -12
  12. package/config/.schema.json +0 -172
  13. package/dist/addon/table.d.ts +0 -6
  14. package/dist/addon/table.js +0 -558
  15. package/dist/base.d.ts +0 -45
  16. package/dist/bin/toc.js +0 -18
  17. package/dist/index.d.ts +0 -32
  18. package/dist/index.js +0 -209
  19. package/dist/internal.d.ts +0 -44
  20. package/dist/lib/element.d.ts +0 -154
  21. package/dist/lib/element.js +0 -625
  22. package/dist/lib/node.d.ts +0 -146
  23. package/dist/lib/node.js +0 -423
  24. package/dist/lib/range.d.ts +0 -104
  25. package/dist/lib/range.js +0 -385
  26. package/dist/lib/ranges.d.ts +0 -26
  27. package/dist/lib/ranges.js +0 -118
  28. package/dist/lib/text.d.ts +0 -62
  29. package/dist/lib/text.js +0 -247
  30. package/dist/lib/title.d.ts +0 -38
  31. package/dist/lib/title.js +0 -162
  32. package/dist/mixin/attributesParent.js +0 -89
  33. package/dist/mixin/fixed.js +0 -25
  34. package/dist/mixin/flagsParent.js +0 -70
  35. package/dist/mixin/hidden.js +0 -26
  36. package/dist/mixin/magicLinkParent.js +0 -41
  37. package/dist/mixin/singleLine.js +0 -25
  38. package/dist/mixin/sol.js +0 -43
  39. package/dist/mixin/syntax.js +0 -54
  40. package/dist/parser/braces.js +0 -128
  41. package/dist/parser/commentAndExt.js +0 -77
  42. package/dist/parser/converter.js +0 -40
  43. package/dist/parser/externalLinks.js +0 -28
  44. package/dist/parser/hrAndDoubleUnderscore.js +0 -38
  45. package/dist/parser/html.js +0 -36
  46. package/dist/parser/links.js +0 -94
  47. package/dist/parser/list.js +0 -66
  48. package/dist/parser/magicLinks.js +0 -40
  49. package/dist/parser/quotes.js +0 -67
  50. package/dist/parser/selector.js +0 -161
  51. package/dist/parser/table.js +0 -120
  52. package/dist/src/arg.d.ts +0 -56
  53. package/dist/src/arg.js +0 -187
  54. package/dist/src/atom.d.ts +0 -12
  55. package/dist/src/atom.js +0 -27
  56. package/dist/src/attribute.d.ts +0 -88
  57. package/dist/src/attribute.js +0 -392
  58. package/dist/src/attributes.d.ts +0 -109
  59. package/dist/src/attributes.js +0 -344
  60. package/dist/src/converter.d.ts +0 -53
  61. package/dist/src/converter.js +0 -79
  62. package/dist/src/converterFlags.d.ts +0 -87
  63. package/dist/src/converterFlags.js +0 -224
  64. package/dist/src/converterRule.d.ts +0 -77
  65. package/dist/src/converterRule.js +0 -208
  66. package/dist/src/extLink.d.ts +0 -55
  67. package/dist/src/extLink.js +0 -122
  68. package/dist/src/gallery.d.ts +0 -54
  69. package/dist/src/gallery.js +0 -121
  70. package/dist/src/heading.d.ts +0 -76
  71. package/dist/src/heading.js +0 -127
  72. package/dist/src/hidden.d.ts +0 -23
  73. package/dist/src/hidden.js +0 -23
  74. package/dist/src/html.d.ts +0 -104
  75. package/dist/src/html.js +0 -226
  76. package/dist/src/imageParameter.d.ts +0 -65
  77. package/dist/src/imageParameter.js +0 -245
  78. package/dist/src/imagemap.d.ts +0 -56
  79. package/dist/src/imagemap.js +0 -147
  80. package/dist/src/imagemapLink.d.ts +0 -61
  81. package/dist/src/imagemapLink.js +0 -40
  82. package/dist/src/index.d.ts +0 -139
  83. package/dist/src/index.js +0 -777
  84. package/dist/src/link/base.d.ts +0 -52
  85. package/dist/src/link/base.js +0 -209
  86. package/dist/src/link/category.d.ts +0 -13
  87. package/dist/src/link/category.js +0 -29
  88. package/dist/src/link/file.d.ts +0 -96
  89. package/dist/src/link/file.js +0 -256
  90. package/dist/src/link/galleryImage.d.ts +0 -45
  91. package/dist/src/link/galleryImage.js +0 -106
  92. package/dist/src/link/index.d.ts +0 -53
  93. package/dist/src/link/index.js +0 -123
  94. package/dist/src/magicLink.d.ts +0 -69
  95. package/dist/src/magicLink.js +0 -146
  96. package/dist/src/nested.d.ts +0 -43
  97. package/dist/src/nested.js +0 -86
  98. package/dist/src/nowiki/base.d.ts +0 -48
  99. package/dist/src/nowiki/base.js +0 -42
  100. package/dist/src/nowiki/comment.d.ts +0 -41
  101. package/dist/src/nowiki/comment.js +0 -67
  102. package/dist/src/nowiki/dd.d.ts +0 -8
  103. package/dist/src/nowiki/dd.js +0 -25
  104. package/dist/src/nowiki/doubleUnderscore.d.ts +0 -47
  105. package/dist/src/nowiki/doubleUnderscore.js +0 -50
  106. package/dist/src/nowiki/hr.d.ts +0 -33
  107. package/dist/src/nowiki/hr.js +0 -14
  108. package/dist/src/nowiki/index.d.ts +0 -16
  109. package/dist/src/nowiki/index.js +0 -21
  110. package/dist/src/nowiki/list.d.ts +0 -31
  111. package/dist/src/nowiki/list.js +0 -48
  112. package/dist/src/nowiki/listBase.d.ts +0 -20
  113. package/dist/src/nowiki/listBase.js +0 -12
  114. package/dist/src/nowiki/noinclude.d.ts +0 -26
  115. package/dist/src/nowiki/noinclude.js +0 -24
  116. package/dist/src/nowiki/quote.d.ts +0 -24
  117. package/dist/src/nowiki/quote.js +0 -45
  118. package/dist/src/onlyinclude.d.ts +0 -16
  119. package/dist/src/onlyinclude.js +0 -57
  120. package/dist/src/paramTag/index.d.ts +0 -37
  121. package/dist/src/paramTag/index.js +0 -68
  122. package/dist/src/paramTag/inputbox.d.ts +0 -8
  123. package/dist/src/paramTag/inputbox.js +0 -23
  124. package/dist/src/parameter.d.ts +0 -86
  125. package/dist/src/parameter.js +0 -205
  126. package/dist/src/pre.d.ts +0 -28
  127. package/dist/src/pre.js +0 -51
  128. package/dist/src/syntax.d.ts +0 -30
  129. package/dist/src/syntax.js +0 -34
  130. package/dist/src/table/base.d.ts +0 -55
  131. package/dist/src/table/base.js +0 -78
  132. package/dist/src/table/index.d.ts +0 -228
  133. package/dist/src/table/index.js +0 -378
  134. package/dist/src/table/td.d.ts +0 -107
  135. package/dist/src/table/td.js +0 -260
  136. package/dist/src/table/tr.d.ts +0 -32
  137. package/dist/src/table/tr.js +0 -56
  138. package/dist/src/table/trBase.d.ts +0 -53
  139. package/dist/src/table/trBase.js +0 -151
  140. package/dist/src/tagPair/ext.d.ts +0 -58
  141. package/dist/src/tagPair/ext.js +0 -142
  142. package/dist/src/tagPair/include.d.ts +0 -54
  143. package/dist/src/tagPair/include.js +0 -63
  144. package/dist/src/tagPair/index.d.ts +0 -49
  145. package/dist/src/tagPair/index.js +0 -93
  146. package/dist/src/transclude.d.ts +0 -167
  147. package/dist/src/transclude.js +0 -696
  148. package/dist/util/constants.js +0 -108
  149. package/dist/util/debug.js +0 -83
  150. package/dist/util/diff.js +0 -72
  151. package/dist/util/lint.js +0 -30
  152. package/dist/util/string.js +0 -51
  153. package/errors/README +0 -1
  154. package/printed/README +0 -1
@@ -1,696 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TranscludeToken = void 0;
4
- const string_1 = require("../util/string");
5
- const lint_1 = require("../util/lint");
6
- const debug_1 = require("../util/debug");
7
- const constants_1 = require("../util/constants");
8
- const Parser = require("../index");
9
- const index_1 = require("./index");
10
- const parameter_1 = require("./parameter");
11
- const atom_1 = require("./atom");
12
- const syntax_1 = require("./syntax");
13
- const insensitiveVars = new Set([
14
- 'pageid',
15
- 'articlepath',
16
- 'server',
17
- 'servername',
18
- 'scriptpath',
19
- 'stylepath',
20
- ]);
21
- /**
22
- * 模板或魔术字
23
- * @classdesc `{childNodes: [AtomToken|SyntaxToken, ...AtomToken, ...ParameterToken]}`
24
- */
25
- class TranscludeToken extends index_1.Token {
26
- type = 'template';
27
- modifier = '';
28
- #raw = false;
29
- #args = new Map();
30
- /* NOT FOR BROWSER */
31
- #keys = new Set();
32
- /* NOT FOR BROWSER */
33
- /** 是否存在重复参数 */
34
- get duplication() {
35
- return this.isTemplate() && Boolean(this.hasDuplicatedArgs());
36
- }
37
- set duplication(duplication) {
38
- if (this.duplication && !duplication) {
39
- this.fixDuplication();
40
- }
41
- }
42
- /* NOT FOR BROWSER END */
43
- /**
44
- * @param title 模板标题或魔术字
45
- * @param parts 参数各部分
46
- * @throws `SyntaxError` 非法的模板名称
47
- */
48
- constructor(title, parts, config = Parser.getConfig(), accum = []) {
49
- super(undefined, config, accum, {
50
- AtomToken: 0, SyntaxToken: 0, ParameterToken: '1:',
51
- });
52
- this.seal('modifier');
53
- const { parserFunction: [insensitive, sensitive] } = config, argSubst = /^(?:\s|\0\d+c\x7F)*\0\d+s\x7F/u.exec(title)?.[0];
54
- if (argSubst) {
55
- this.setAttribute('modifier', argSubst);
56
- title = title.slice(argSubst.length);
57
- }
58
- else if (title.includes(':')) {
59
- const [modifier, ...arg] = title.split(':'), [mt] = /^(?:\s|\0\d+c\x7F)*/u.exec(arg[0] ?? '');
60
- if (this.setModifier(`${modifier}:${mt}`)) {
61
- title = arg.join(':').slice(mt.length);
62
- }
63
- }
64
- const isFunction = title.includes(':');
65
- if (isFunction || parts.length === 0 && !this.#raw) {
66
- const [magicWord, ...arg] = title.split(':'), cleaned = (0, string_1.removeComment)(magicWord), name = cleaned[arg.length > 0 ? 'trimStart' : 'trim'](), lcName = name.toLowerCase(), canonicalName = insensitive[lcName], isSensitive = sensitive.includes(name), isVar = isSensitive || insensitiveVars.has(canonicalName);
67
- if (isVar || isFunction && canonicalName) {
68
- this.setAttribute('name', canonicalName ?? lcName);
69
- this.type = 'magic-word';
70
- const pattern = new RegExp(`^\\s*${name}\\s*$`, isSensitive ? 'u' : 'iu'), token = new syntax_1.SyntaxToken(magicWord, pattern, 'magic-word-name', config, accum, {
71
- 'Stage-1': ':', '!ExtToken': '',
72
- });
73
- super.insertAt(token);
74
- if (arg.length > 0) {
75
- parts.unshift([arg.join(':')]);
76
- }
77
- if (this.name === 'invoke') {
78
- this.setAttribute('acceptable', { SyntaxToken: 0, AtomToken: '1:3', ParameterToken: '3:' });
79
- for (let i = 0; i < 2; i++) {
80
- const part = parts.shift();
81
- if (!part) {
82
- break;
83
- }
84
- const invoke = new atom_1.AtomToken(part.join('='), `invoke-${i ? 'function' : 'module'}`, config, accum, { 'Stage-1': ':', '!ExtToken': '' });
85
- super.insertAt(invoke);
86
- }
87
- this.protectChildren('1:3');
88
- }
89
- }
90
- }
91
- if (this.type === 'template') {
92
- const name = (0, string_1.removeComment)((0, string_1.decodeHtml)(title)).split('#')[0].trim();
93
- if (!name || /\0\d+[eh!+-]\x7F|[<>[\]{}\n]|%[\da-f]{2}/u.test(name)) {
94
- accum.pop();
95
- throw new SyntaxError(`非法的模板名称:${(0, string_1.noWrap)(name)}`);
96
- }
97
- const token = new atom_1.AtomToken(title, 'template-name', config, accum, {
98
- 'Stage-2': ':', '!HeadingToken': '',
99
- });
100
- super.insertAt(token);
101
- }
102
- const templateLike = this.isTemplate();
103
- let i = 1;
104
- for (let j = 0; j < parts.length; j++) {
105
- const part = parts[j];
106
- if (!templateLike && !(this.name === 'switch' && j > 0)) {
107
- part[0] = part.join('=');
108
- part.length = 1;
109
- }
110
- if (part.length === 1) {
111
- part.unshift(i);
112
- i++;
113
- }
114
- this.insertAt(new parameter_1.ParameterToken(...part, config, accum));
115
- }
116
- this.protectChildren(0);
117
- }
118
- /**
119
- * 设置引用修饰符
120
- * @param modifier 引用修饰符
121
- */
122
- setModifier(modifier) {
123
- const { parserFunction: [, , raw, subst] } = this.getAttribute('config'), lcModifier = (0, string_1.removeComment)(modifier).trim();
124
- if (modifier && !lcModifier.endsWith(':')) {
125
- return false;
126
- }
127
- const magicWord = lcModifier.slice(0, -1).toLowerCase(), isRaw = raw.includes(magicWord), isSubst = subst.includes(magicWord);
128
- if (this.#raw && isRaw
129
- || !this.#raw && (isSubst || modifier === '')
130
- || (debug_1.Shadow.running || this.length > 1) && (isRaw || isSubst || modifier === '')) {
131
- this.setAttribute('modifier', modifier);
132
- this.#raw = isRaw;
133
- return Boolean(modifier);
134
- }
135
- return false;
136
- }
137
- /** 是否是模板或模块 */
138
- isTemplate() {
139
- return this.type === 'template' || this.name === 'invoke';
140
- }
141
- /** 获取模板或模块名 */
142
- #getTitle() {
143
- const isTemplate = this.type === 'template', child = this.childNodes[isTemplate ? 0 : 1];
144
- return child && this.normalizeTitle(child.text(), isTemplate ? 10 : 828);
145
- }
146
- /** @private */
147
- afterBuild() {
148
- if (this.modifier.includes('\0')) {
149
- this.setAttribute('modifier', this.buildFromStr(this.modifier, 'string'));
150
- }
151
- if (this.isTemplate()) {
152
- const isTemplate = this.type === 'template';
153
- if (isTemplate || this.length > 1) {
154
- this.setAttribute(isTemplate ? 'name' : 'module', this.#getTitle().title);
155
- }
156
- /**
157
- * 当事件bubble到`parameter`时,将`oldKey`和`newKey`保存进AstEventData。
158
- * 当继续bubble到`template`时,处理并删除`oldKey`和`newKey`。
159
- * @implements
160
- */
161
- const transcludeListener = (e, data) => {
162
- const { prevTarget } = e, { oldKey, newKey } = data;
163
- if (typeof oldKey === 'string') {
164
- delete data.oldKey;
165
- delete data.newKey;
166
- }
167
- if (prevTarget === this.firstChild && isTemplate
168
- || prevTarget === this.childNodes[1] && !isTemplate && this.name === 'invoke') {
169
- this.setAttribute(isTemplate ? 'name' : 'module', this.#getTitle().title);
170
- }
171
- else if (oldKey !== newKey && prevTarget instanceof parameter_1.ParameterToken) {
172
- const oldArgs = this.getArgs(oldKey, false, false);
173
- oldArgs.delete(prevTarget);
174
- this.getArgs(newKey, false, false).add(prevTarget);
175
- this.#keys.add(newKey);
176
- if (oldArgs.size === 0) {
177
- this.#keys.delete(oldKey);
178
- }
179
- }
180
- };
181
- this.addEventListener(['remove', 'insert', 'replace', 'text'], transcludeListener);
182
- }
183
- }
184
- /** @private */
185
- toString(omit) {
186
- if (omit && this.matchesTypes(omit)) {
187
- return '';
188
- }
189
- return `{{${this.modifier}${this.type === 'magic-word'
190
- ? `${this.firstChild.toString(omit)}${this.length === 1 ? '' : ':'}${this.childNodes.slice(1).map(child => child.toString(omit)).join('|')}`
191
- : super.toString(omit, '|')}}}`;
192
- }
193
- /** @override */
194
- text() {
195
- const { childNodes, length, firstChild, modifier, type, name } = this;
196
- return type === 'magic-word' && name === 'vardefine'
197
- ? ''
198
- : `{{${modifier}${type === 'magic-word'
199
- ? `${firstChild.text()}${length === 1 ? '' : ':'}${(0, string_1.text)(childNodes.slice(1), '|')}`
200
- : super.text('|')}}}`;
201
- }
202
- /** @private */
203
- getAttribute(key) {
204
- switch (key) {
205
- case 'padding':
206
- return this.modifier.length + 2;
207
- case 'args':
208
- return new Map(this.#args);
209
- case 'keys':
210
- return this.#keys;
211
- default:
212
- return super.getAttribute(key);
213
- }
214
- }
215
- /** @private */
216
- getGaps() {
217
- return 1;
218
- }
219
- /** @override */
220
- lint(start = this.getAbsoluteIndex()) {
221
- const errors = super.lint(start), { type, childNodes, length } = this;
222
- let rect;
223
- if (!this.isTemplate()) {
224
- return errors;
225
- }
226
- const title = this.#getTitle();
227
- if (!title) {
228
- rect = { start, ...this.getRootNode().posFromIndex(start) };
229
- errors.push((0, lint_1.generateForSelf)(this, rect, 'missing module name'));
230
- return errors;
231
- }
232
- else if (title.fragment !== undefined) {
233
- rect = { start, ...this.getRootNode().posFromIndex(start) };
234
- errors.push((0, lint_1.generateForChild)(childNodes[type === 'template' ? 0 : 1], rect, 'useless fragment'));
235
- }
236
- if (!title.valid) {
237
- rect ??= { start, ...this.getRootNode().posFromIndex(start) };
238
- errors.push((0, lint_1.generateForChild)(childNodes[1], rect, 'illegal module name'));
239
- }
240
- if (type === 'magic-word' && length === 2) {
241
- rect ??= { start, ...this.getRootNode().posFromIndex(start) };
242
- errors.push((0, lint_1.generateForSelf)(this, rect, 'missing module function'));
243
- return errors;
244
- }
245
- const duplicatedArgs = this.getDuplicatedArgs();
246
- if (duplicatedArgs.length > 0) {
247
- rect ??= { start, ...this.getRootNode().posFromIndex(start) };
248
- errors.push(...duplicatedArgs.flatMap(([, args]) => args).map(arg => (0, lint_1.generateForChild)(arg, rect, 'duplicated parameter')));
249
- }
250
- return errors;
251
- }
252
- /**
253
- * 处理匿名参数更改
254
- * @param addedToken 新增的参数
255
- */
256
- #handleAnonArgChange(addedToken) {
257
- const args = this.getAnonArgs(), added = typeof addedToken !== 'number';
258
- const maxAnon = String(args.length + (added ? 0 : 1));
259
- if (added) {
260
- this.#keys.add(maxAnon);
261
- }
262
- else if (!this.hasArg(maxAnon, true)) {
263
- this.#keys.delete(maxAnon);
264
- }
265
- for (let i = added ? args.indexOf(addedToken) : addedToken - 1; i < args.length; i++) {
266
- const token = args[i], { name } = token, newName = String(i + 1);
267
- if (name !== newName) {
268
- token.setAttribute('name', newName);
269
- this.getArgs(newName, false, false).add(token);
270
- if (name) {
271
- this.getArgs(name, false, false).delete(token);
272
- }
273
- }
274
- }
275
- }
276
- /**
277
- * @override
278
- * @param token 待插入的子节点
279
- * @param i 插入位置
280
- */
281
- insertAt(token, i = this.length) {
282
- super.insertAt(token, i);
283
- if (token.anon) {
284
- this.#handleAnonArgChange(token);
285
- }
286
- else if (token.name) {
287
- this.getArgs(token.name, false, false).add(token);
288
- this.#keys.add(token.name);
289
- }
290
- return token;
291
- }
292
- /** 获取所有参数 */
293
- getAllArgs() {
294
- return this.childNodes.filter((0, debug_1.isToken)('parameter'));
295
- }
296
- /** 获取所有匿名参数 */
297
- getAnonArgs() {
298
- return this.getAllArgs().filter(({ anon }) => anon);
299
- }
300
- /**
301
- * 获取指定参数
302
- * @param key 参数名
303
- * @param exact 是否匹配匿名性
304
- * @param copy 是否返回一个备份
305
- */
306
- getArgs(key, exact = false, copy = true) {
307
- const keyStr = String(key).replace(/^[ \t\n\0\v]+|(?<=[^ \t\n\0\v])[ \t\n\0\v]+$/gu, '');
308
- let args;
309
- if (this.#args.has(keyStr)) {
310
- args = this.#args.get(keyStr);
311
- }
312
- else {
313
- args = new Set(this.getAllArgs().filter(({ name }) => keyStr === name));
314
- this.#args.set(keyStr, args);
315
- }
316
- if (exact && !Number.isNaN(Number(keyStr))) {
317
- args = new Set([...args].filter(({ anon }) => typeof key === 'number' === anon));
318
- }
319
- else if (copy) {
320
- args = new Set(args);
321
- }
322
- return args;
323
- }
324
- /**
325
- * 获取重名参数
326
- * @throws `Error` 仅用于模板
327
- */
328
- getDuplicatedArgs() {
329
- if (this.isTemplate()) {
330
- return [...this.#args].filter(([, { size }]) => size > 1).map(([key, args]) => [key, [...args]]);
331
- }
332
- throw new Error('getDuplicatedArgs 方法仅供模板使用!');
333
- }
334
- /**
335
- * 对特定魔术字获取可能的取值
336
- * @throws `Error` 不是可接受的魔术字
337
- */
338
- getPossibleValues() {
339
- const { type, name, childNodes, constructor: { name: cName } } = this;
340
- if (type === 'template') {
341
- throw new Error(`${cName}.getPossibleValues 方法仅供特定魔术字使用!`);
342
- }
343
- let start;
344
- switch (name) {
345
- case 'if':
346
- case 'ifexist':
347
- case 'ifexpr':
348
- case 'iferror':
349
- start = 2;
350
- break;
351
- case 'ifeq':
352
- start = 3;
353
- break;
354
- default:
355
- throw new Error(`${cName}.getPossibleValues 方法仅供特定魔术字使用!`);
356
- }
357
- const queue = childNodes.slice(start, start + 2).map(({ childNodes: [, value] }) => value);
358
- for (let i = 0; i < queue.length;) {
359
- const { length, 0: first } = queue[i].childNodes.filter(child => child.text().trim());
360
- if (length === 0) {
361
- queue.splice(i, 1);
362
- }
363
- else if (length > 1 || first.type !== 'magic-word') {
364
- i++;
365
- }
366
- else {
367
- try {
368
- const possibleValues = first.getPossibleValues();
369
- queue.splice(i, 1, ...possibleValues);
370
- i += possibleValues.length;
371
- }
372
- catch {
373
- i++;
374
- }
375
- }
376
- }
377
- return queue;
378
- }
379
- /** @override */
380
- print() {
381
- const { childNodes, length, firstChild, modifier, type } = this;
382
- return `<span class="wpb-${type}">{{${modifier}${type === 'magic-word'
383
- ? `${firstChild.print()}${length === 1 ? '' : ':'}${(0, string_1.print)(childNodes.slice(1), { sep: '|' })}`
384
- : (0, string_1.print)(childNodes, { sep: '|' })}}}</span>`;
385
- }
386
- /* NOT FOR BROWSER */
387
- /** @override */
388
- cloneNode() {
389
- const [first, ...cloned] = this.cloneChildNodes(), config = this.getAttribute('config');
390
- return debug_1.Shadow.run(() => {
391
- const token = new TranscludeToken(this.type === 'template' ? 'T' : first.text(), [], config);
392
- if (this.#raw) {
393
- token.setModifier(this.modifier);
394
- }
395
- else {
396
- token.setAttribute('modifier', this.modifier);
397
- }
398
- token.firstChild.safeReplaceWith(first);
399
- token.afterBuild();
400
- token.append(...cloned);
401
- return token;
402
- });
403
- }
404
- /** 替换引用 */
405
- subst() {
406
- this.setModifier('subst:');
407
- }
408
- /** 安全的替换引用 */
409
- safesubst() {
410
- this.setModifier('safesubst:');
411
- }
412
- /**
413
- * @override
414
- * @param i 移除位置
415
- */
416
- removeAt(i) {
417
- const token = super.removeAt(i);
418
- if (token.anon) {
419
- this.#handleAnonArgChange(Number(token.name));
420
- }
421
- else {
422
- const args = this.getArgs(token.name, false, false);
423
- args.delete(token);
424
- if (args.size === 0) {
425
- this.#keys.delete(token.name);
426
- }
427
- }
428
- return token;
429
- }
430
- /**
431
- * 是否具有某参数
432
- * @param key 参数名
433
- * @param exact 是否匹配匿名性
434
- */
435
- hasArg(key, exact = false) {
436
- return this.getArgs(key, exact, false).size > 0;
437
- }
438
- /**
439
- * 获取生效的指定参数
440
- * @param key 参数名
441
- * @param exact 是否匹配匿名性
442
- */
443
- getArg(key, exact = false) {
444
- return [...this.getArgs(key, exact, false)].sort((a, b) => a.compareDocumentPosition(b)).at(-1);
445
- }
446
- /**
447
- * 移除指定参数
448
- * @param key 参数名
449
- * @param exact 是否匹配匿名性
450
- */
451
- removeArg(key, exact = false) {
452
- debug_1.Shadow.run(() => {
453
- for (const token of this.getArgs(key, exact, false)) {
454
- this.removeChild(token);
455
- }
456
- });
457
- }
458
- /** 获取所有参数名 */
459
- getKeys() {
460
- const args = this.getAllArgs();
461
- if (this.#keys.size === 0 && args.length > 0) {
462
- for (const { name } of args) {
463
- this.#keys.add(name);
464
- }
465
- }
466
- return [...this.#keys];
467
- }
468
- /**
469
- * 获取参数值
470
- * @param key 参数名
471
- */
472
- getValues(key) {
473
- return [...this.getArgs(key, false, false)].map(token => token.getValue());
474
- }
475
- /**
476
- * 获取生效的参数值
477
- * @param key 参数名
478
- */
479
- getValue(key) {
480
- return key === undefined
481
- ? Object.fromEntries(this.getKeys().map(k => [k, this.getValue(k)]))
482
- : this.getArg(key)?.getValue();
483
- }
484
- /**
485
- * 插入匿名参数
486
- * @param val 参数值
487
- */
488
- newAnonArg(val) {
489
- const config = this.getAttribute('config'), { childNodes } = Parser.parse(val, this.getAttribute('include'), undefined, config), token = debug_1.Shadow.run(() => new parameter_1.ParameterToken(undefined, undefined, config));
490
- token.lastChild.append(...childNodes);
491
- token.afterBuild();
492
- return this.insertAt(token);
493
- }
494
- /**
495
- * 设置参数值
496
- * @param key 参数名
497
- * @param value 参数值
498
- * @throws `Error` 仅用于模板
499
- */
500
- setValue(key, value) {
501
- if (!this.isTemplate()) {
502
- throw new Error('setValue 方法仅供模板使用!');
503
- }
504
- const arg = this.getArg(key);
505
- if (arg) {
506
- arg.setValue(value);
507
- return;
508
- }
509
- const include = this.getAttribute('include'), config = this.getAttribute('config'), k = Parser.parse(key, include, undefined, config), v = Parser.parse(value, include, undefined, config), token = debug_1.Shadow.run(() => new parameter_1.ParameterToken(undefined, undefined, config));
510
- token.firstChild.append(...k.childNodes);
511
- token.lastChild.append(...v.childNodes);
512
- token.afterBuild();
513
- this.insertAt(token);
514
- }
515
- /**
516
- * 将匿名参数改写为命名参数
517
- * @throws `Error` 仅用于模板
518
- */
519
- anonToNamed() {
520
- if (!this.isTemplate()) {
521
- throw new Error('anonToNamed 方法仅供模板使用!');
522
- }
523
- for (const token of this.getAnonArgs()) {
524
- token.firstChild.replaceChildren(token.name);
525
- }
526
- }
527
- /**
528
- * 替换模板名
529
- * @param title 模板名
530
- * @throws `Error` 仅用于模板
531
- */
532
- replaceTemplate(title) {
533
- if (this.type === 'magic-word') {
534
- throw new Error('replaceTemplate 方法仅用于更换模板!');
535
- }
536
- const { childNodes } = Parser.parse(title, this.getAttribute('include'), 2, this.getAttribute('config'));
537
- this.firstChild.replaceChildren(...childNodes);
538
- }
539
- /**
540
- * 替换模块名
541
- * @param title 模块名
542
- * @throws `Error` 仅用于模块
543
- */
544
- replaceModule(title) {
545
- if (this.type !== 'magic-word' || this.name !== 'invoke') {
546
- throw new Error('replaceModule 方法仅用于更换模块!');
547
- }
548
- const config = this.getAttribute('config');
549
- if (this.length === 1) {
550
- super.insertAt(new atom_1.AtomToken(undefined, 'invoke-module', config, [], {
551
- 'Stage-1': ':', '!ExtToken': '',
552
- }));
553
- return;
554
- }
555
- const { childNodes } = Parser.parse(title, this.getAttribute('include'), 2, config);
556
- this.childNodes[1].replaceChildren(...childNodes);
557
- }
558
- /**
559
- * 替换模块函数
560
- * @param func 模块函数名
561
- * @throws `Error` 仅用于模块
562
- * @throws `Error` 尚未指定模块名称
563
- */
564
- replaceFunction(func) {
565
- if (this.type !== 'magic-word' || this.name !== 'invoke') {
566
- throw new Error('replaceModule 方法仅用于更换模块!');
567
- }
568
- else if (this.length < 2) {
569
- throw new Error('尚未指定模块名称!');
570
- }
571
- const config = this.getAttribute('config');
572
- if (this.length === 2) {
573
- super.insertAt(new atom_1.AtomToken(undefined, 'invoke-function', config, [], {
574
- 'Stage-1': ':', '!ExtToken': '',
575
- }));
576
- return;
577
- }
578
- const { childNodes } = Parser.parse(func, this.getAttribute('include'), 2, config);
579
- this.childNodes[2].replaceChildren(...childNodes);
580
- }
581
- /**
582
- * 重复参数计数
583
- * @throws `Error` 仅用于模板
584
- */
585
- hasDuplicatedArgs() {
586
- if (this.isTemplate()) {
587
- return this.getAllArgs().length - this.getKeys().length;
588
- }
589
- throw new Error('hasDuplicatedArgs 方法仅供模板使用!');
590
- }
591
- /**
592
- * 修复重名参数:
593
- * `aggressive = false`时只移除空参数和全同参数,优先保留匿名参数,否则将所有匿名参数更改为命名。
594
- * `aggressive = true`时还会尝试处理连续的以数字编号的参数。
595
- * @param aggressive 是否使用有更大风险的修复手段
596
- */
597
- fixDuplication(aggressive = false) {
598
- if (!this.hasDuplicatedArgs()) {
599
- return [];
600
- }
601
- const duplicatedKeys = [];
602
- let { length: anonCount } = this.getAnonArgs();
603
- for (const [key, args] of this.getDuplicatedArgs()) {
604
- if (args.length <= 1) {
605
- continue;
606
- }
607
- const values = new Map();
608
- for (const arg of args) {
609
- const val = arg.getValue().trim();
610
- if (values.has(val)) {
611
- values.get(val).push(arg);
612
- }
613
- else {
614
- values.set(val, [arg]);
615
- }
616
- }
617
- let noMoreAnon = anonCount === 0 || Number.isNaN(Number(key));
618
- const emptyArgs = values.get('') ?? [], duplicatedArgs = [...values].filter(([val, { length }]) => val && length > 1).flatMap(([, curArgs]) => {
619
- const anonIndex = noMoreAnon ? -1 : curArgs.findIndex(({ anon }) => anon);
620
- if (anonIndex !== -1) {
621
- noMoreAnon = true;
622
- }
623
- curArgs.splice(anonIndex, 1);
624
- return curArgs;
625
- }), badArgs = [...emptyArgs, ...duplicatedArgs], index = noMoreAnon ? -1 : emptyArgs.findIndex(({ anon }) => anon);
626
- if (badArgs.length === args.length) {
627
- badArgs.splice(index, 1);
628
- }
629
- else if (index !== -1) {
630
- this.anonToNamed();
631
- anonCount = 0;
632
- }
633
- for (const arg of badArgs) {
634
- arg.remove();
635
- }
636
- let remaining = args.length - badArgs.length;
637
- if (remaining === 1) {
638
- continue;
639
- }
640
- else if (aggressive && (anonCount ? /\D\d+$/u : /(?:^|\D)\d+$/u).test(key)) {
641
- let last;
642
- const str = key.slice(0, -/(?<!\d)\d+$/u.exec(key)[0].length), regex = new RegExp(`^${(0, string_1.escapeRegExp)(str)}\\d+$`, 'u'), series = this.getAllArgs().filter(({ name }) => regex.test(name)), ordered = series.every(({ name }, i) => {
643
- const j = Number(name.slice(str.length)), cmp = j <= i + 1 && (i === 0 || j >= last || name === key);
644
- last = j;
645
- return cmp;
646
- });
647
- if (ordered) {
648
- for (let i = 0; i < series.length; i++) {
649
- const name = `${str}${i + 1}`, arg = series[i];
650
- if (arg.name !== name) {
651
- if (arg.name === key) {
652
- remaining--;
653
- }
654
- arg.rename(name, true);
655
- }
656
- }
657
- }
658
- }
659
- if (remaining > 1) {
660
- Parser.error(`${this.type === 'template'
661
- ? this.name
662
- : this.normalizeTitle(this.childNodes[1].text(), 828)
663
- .title} 还留有 ${remaining} 个重复的 ${key} 参数:${[...this.getArgs(key)].map(arg => {
664
- const { top, left } = arg.getBoundingClientRect();
665
- return `第 ${String(top)} 行第 ${String(left)} 列`;
666
- }).join('、')}`);
667
- duplicatedKeys.push(key);
668
- continue;
669
- }
670
- }
671
- return duplicatedKeys;
672
- }
673
- /**
674
- * 转义模板内的表格
675
- * @throws `Error` 转义失败
676
- */
677
- escapeTables() {
678
- if (!/\n[^\S\n]*(?::+[^\S\n]*)?\{\|/u.test(this.text())) {
679
- return this;
680
- }
681
- const stripped = String(this).slice(2, -2), include = this.getAttribute('include'), config = this.getAttribute('config'), parsed = Parser.parse(stripped, include, 4, config), isTable = (0, debug_1.isToken)('table');
682
- for (const table of parsed.childNodes) {
683
- if (isTable(table)) {
684
- table.escape();
685
- }
686
- }
687
- const { firstChild, length } = Parser.parse(`{{${String(parsed)}}}`, include, undefined, config);
688
- if (length !== 1 || !(firstChild instanceof TranscludeToken)) {
689
- throw new Error('转义表格失败!');
690
- }
691
- this.safeReplaceWith(firstChild);
692
- return firstChild;
693
- }
694
- }
695
- exports.TranscludeToken = TranscludeToken;
696
- constants_1.classes['TranscludeToken'] = __filename;