wikiparser-node 1.6.2 → 1.7.0-beta.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 (167) hide show
  1. package/bundle/bundle.min.js +38 -0
  2. package/config/default.json +5 -0
  3. package/config/enwiki.json +4 -814
  4. package/config/llwiki.json +5 -35
  5. package/config/minimum.json +3 -0
  6. package/config/moegirl.json +5 -44
  7. package/config/zhwiki.json +6 -466
  8. package/extensions/dist/base.js +64 -0
  9. package/extensions/dist/editor.js +159 -0
  10. package/extensions/dist/highlight.js +58 -0
  11. package/extensions/dist/lint.js +71 -0
  12. package/extensions/editor.css +64 -0
  13. package/extensions/ui.css +144 -0
  14. package/i18n/zh-hans.json +2 -1
  15. package/i18n/zh-hant.json +2 -1
  16. package/package.json +35 -19
  17. package/config/.schema.json +0 -172
  18. package/dist/addon/table.d.ts +0 -1
  19. package/dist/addon/table.js +0 -485
  20. package/dist/base.d.ts +0 -69
  21. package/dist/base.js +0 -38
  22. package/dist/index.d.ts +0 -31
  23. package/dist/index.js +0 -212
  24. package/dist/internal.d.ts +0 -44
  25. package/dist/lib/element.d.ts +0 -151
  26. package/dist/lib/element.js +0 -618
  27. package/dist/lib/node.d.ts +0 -146
  28. package/dist/lib/node.js +0 -426
  29. package/dist/lib/range.d.ts +0 -104
  30. package/dist/lib/range.js +0 -385
  31. package/dist/lib/ranges.d.ts +0 -28
  32. package/dist/lib/ranges.js +0 -126
  33. package/dist/lib/text.d.ts +0 -63
  34. package/dist/lib/text.js +0 -354
  35. package/dist/lib/title.d.ts +0 -40
  36. package/dist/lib/title.js +0 -179
  37. package/dist/mixin/attributesParent.d.ts +0 -50
  38. package/dist/mixin/attributesParent.js +0 -81
  39. package/dist/mixin/fixed.d.ts +0 -6
  40. package/dist/mixin/fixed.js +0 -30
  41. package/dist/mixin/flagsParent.d.ts +0 -72
  42. package/dist/mixin/flagsParent.js +0 -59
  43. package/dist/mixin/hidden.d.ts +0 -5
  44. package/dist/mixin/hidden.js +0 -24
  45. package/dist/mixin/magicLinkParent.d.ts +0 -40
  46. package/dist/mixin/magicLinkParent.js +0 -42
  47. package/dist/mixin/singleLine.d.ts +0 -6
  48. package/dist/mixin/singleLine.js +0 -26
  49. package/dist/mixin/sol.d.ts +0 -6
  50. package/dist/mixin/sol.js +0 -43
  51. package/dist/mixin/syntax.d.ts +0 -9
  52. package/dist/mixin/syntax.js +0 -50
  53. package/dist/parser/braces.js +0 -130
  54. package/dist/parser/commentAndExt.js +0 -89
  55. package/dist/parser/converter.js +0 -40
  56. package/dist/parser/externalLinks.js +0 -45
  57. package/dist/parser/hrAndDoubleUnderscore.js +0 -40
  58. package/dist/parser/html.js +0 -38
  59. package/dist/parser/links.js +0 -97
  60. package/dist/parser/list.js +0 -97
  61. package/dist/parser/magicLinks.js +0 -42
  62. package/dist/parser/quotes.js +0 -67
  63. package/dist/parser/selector.js +0 -190
  64. package/dist/parser/table.js +0 -123
  65. package/dist/src/arg.d.ts +0 -58
  66. package/dist/src/arg.js +0 -214
  67. package/dist/src/atom.d.ts +0 -12
  68. package/dist/src/atom.js +0 -27
  69. package/dist/src/attribute.d.ts +0 -71
  70. package/dist/src/attribute.js +0 -502
  71. package/dist/src/attributes.d.ts +0 -109
  72. package/dist/src/attributes.js +0 -356
  73. package/dist/src/converter.d.ts +0 -33
  74. package/dist/src/converter.js +0 -134
  75. package/dist/src/converterFlags.d.ts +0 -87
  76. package/dist/src/converterFlags.js +0 -242
  77. package/dist/src/converterRule.d.ts +0 -77
  78. package/dist/src/converterRule.js +0 -209
  79. package/dist/src/extLink.d.ts +0 -43
  80. package/dist/src/extLink.js +0 -191
  81. package/dist/src/gallery.d.ts +0 -54
  82. package/dist/src/gallery.js +0 -139
  83. package/dist/src/heading.d.ts +0 -47
  84. package/dist/src/heading.js +0 -190
  85. package/dist/src/hidden.d.ts +0 -7
  86. package/dist/src/hidden.js +0 -23
  87. package/dist/src/html.d.ts +0 -65
  88. package/dist/src/html.js +0 -358
  89. package/dist/src/imageParameter.d.ts +0 -65
  90. package/dist/src/imageParameter.js +0 -257
  91. package/dist/src/imagemap.d.ts +0 -54
  92. package/dist/src/imagemap.js +0 -144
  93. package/dist/src/imagemapLink.d.ts +0 -31
  94. package/dist/src/imagemapLink.js +0 -93
  95. package/dist/src/index.d.ts +0 -143
  96. package/dist/src/index.js +0 -851
  97. package/dist/src/link/base.d.ts +0 -52
  98. package/dist/src/link/base.js +0 -228
  99. package/dist/src/link/category.d.ts +0 -13
  100. package/dist/src/link/category.js +0 -28
  101. package/dist/src/link/file.d.ts +0 -98
  102. package/dist/src/link/file.js +0 -272
  103. package/dist/src/link/galleryImage.d.ts +0 -32
  104. package/dist/src/link/galleryImage.js +0 -158
  105. package/dist/src/link/index.d.ts +0 -56
  106. package/dist/src/link/index.js +0 -133
  107. package/dist/src/magicLink.d.ts +0 -59
  108. package/dist/src/magicLink.js +0 -223
  109. package/dist/src/nested.d.ts +0 -43
  110. package/dist/src/nested.js +0 -105
  111. package/dist/src/nowiki/base.d.ts +0 -31
  112. package/dist/src/nowiki/base.js +0 -93
  113. package/dist/src/nowiki/comment.d.ts +0 -25
  114. package/dist/src/nowiki/comment.js +0 -76
  115. package/dist/src/nowiki/dd.d.ts +0 -8
  116. package/dist/src/nowiki/dd.js +0 -24
  117. package/dist/src/nowiki/doubleUnderscore.d.ts +0 -18
  118. package/dist/src/nowiki/doubleUnderscore.js +0 -101
  119. package/dist/src/nowiki/hr.d.ts +0 -5
  120. package/dist/src/nowiki/hr.js +0 -63
  121. package/dist/src/nowiki/index.d.ts +0 -16
  122. package/dist/src/nowiki/index.js +0 -27
  123. package/dist/src/nowiki/list.d.ts +0 -16
  124. package/dist/src/nowiki/list.js +0 -109
  125. package/dist/src/nowiki/listBase.d.ts +0 -5
  126. package/dist/src/nowiki/listBase.js +0 -61
  127. package/dist/src/nowiki/noinclude.d.ts +0 -10
  128. package/dist/src/nowiki/noinclude.js +0 -23
  129. package/dist/src/nowiki/quote.d.ts +0 -14
  130. package/dist/src/nowiki/quote.js +0 -131
  131. package/dist/src/onlyinclude.d.ts +0 -16
  132. package/dist/src/onlyinclude.js +0 -57
  133. package/dist/src/paramTag/index.d.ts +0 -37
  134. package/dist/src/paramTag/index.js +0 -77
  135. package/dist/src/paramTag/inputbox.d.ts +0 -8
  136. package/dist/src/paramTag/inputbox.js +0 -22
  137. package/dist/src/parameter.d.ts +0 -70
  138. package/dist/src/parameter.js +0 -264
  139. package/dist/src/pre.d.ts +0 -31
  140. package/dist/src/pre.js +0 -59
  141. package/dist/src/syntax.d.ts +0 -20
  142. package/dist/src/syntax.js +0 -86
  143. package/dist/src/table/base.d.ts +0 -27
  144. package/dist/src/table/base.js +0 -81
  145. package/dist/src/table/index.d.ts +0 -242
  146. package/dist/src/table/index.js +0 -497
  147. package/dist/src/table/td.d.ts +0 -86
  148. package/dist/src/table/td.js +0 -355
  149. package/dist/src/table/tr.d.ts +0 -32
  150. package/dist/src/table/tr.js +0 -58
  151. package/dist/src/table/trBase.d.ts +0 -53
  152. package/dist/src/table/trBase.js +0 -156
  153. package/dist/src/tagPair/ext.d.ts +0 -32
  154. package/dist/src/tagPair/ext.js +0 -203
  155. package/dist/src/tagPair/include.d.ts +0 -35
  156. package/dist/src/tagPair/include.js +0 -74
  157. package/dist/src/tagPair/index.d.ts +0 -27
  158. package/dist/src/tagPair/index.js +0 -128
  159. package/dist/src/transclude.d.ts +0 -167
  160. package/dist/src/transclude.js +0 -717
  161. package/dist/util/constants.js +0 -27
  162. package/dist/util/debug.js +0 -81
  163. package/dist/util/diff.js +0 -83
  164. package/dist/util/lint.js +0 -31
  165. package/dist/util/string.js +0 -60
  166. package/errors/README +0 -1
  167. package/printed/README +0 -1
package/dist/src/index.js DELETED
@@ -1,851 +0,0 @@
1
- "use strict";
2
- // PHP解析器的步骤:
3
- // -1. 替换签名和`{{subst:}}`,参见Parser::preSaveTransform;这在revision中不可能保留,可以跳过
4
- // 0. 移除特定字符`\0`和`\x7F`,参见Parser::parse
5
- // 1. 注释/扩展标签('<'相关),参见Preprocessor_Hash::buildDomTreeArrayFromText和Sanitizer::decodeTagAttributes
6
- // 2. 模板/模板变量/标题,注意rightmost法则,以及`-{`和`[[`可以破坏`{{`或`{{{`语法,
7
- // 参见Preprocessor_Hash::buildDomTreeArrayFromText
8
- // 3. HTML标签(允许不匹配),参见Sanitizer::internalRemoveHtmlTags
9
- // 4. 表格,参见Parser::handleTables
10
- // 5. 水平线、状态开关和余下的标题,参见Parser::internalParse
11
- // 6. 内链,含文件和分类,参见Parser::handleInternalLinks2
12
- // 7. `'`,参见Parser::doQuotes
13
- // 8. 外链,参见Parser::handleExternalLinks
14
- // 9. ISBN、RFC(未来将废弃,不予支持)和自由外链,参见Parser::handleMagicLinks
15
- // 10. 段落和列表,参见BlockLevelPass::execute
16
- // 11. 转换,参见LanguageConverter::recursiveConvertTopLevel
17
- // \0\d+.\x7F标记Token:
18
- // !: `{{!}}`专用
19
- // {: `{{(!}}`专用
20
- // }: `{{!)}}`专用
21
- // -: `{{!-}}`专用
22
- // +: `{{!!}}`专用
23
- // ~: `{{=}}`专用
24
- // a: AttributeToken
25
- // b: TableToken
26
- // c: CommentToken、NoIncludeToken和IncludeToken
27
- // d: ListToken
28
- // e: ExtToken
29
- // f: MagicLinkToken inside ImageParameterToken
30
- // h: HeadingToken
31
- // l: LinkToken
32
- // m: `{{fullurl:}}`、`{{canonicalurl:}}`或`{{filepath:}}`
33
- // q: QuoteToken
34
- // r: HrToken
35
- // s: `{{{|subst:}}}`
36
- // t: ArgToken或TranscludeToken
37
- // u: DoubleUnderscoreToken
38
- // v: ConverterToken
39
- // w: ExtLinkToken
40
- // x: HtmlToken
41
- Object.defineProperty(exports, "__esModule", { value: true });
42
- exports.Token = void 0;
43
- const assert = require("assert/strict");
44
- const string_1 = require("../util/string");
45
- const constants_1 = require("../util/constants");
46
- const debug_1 = require("../util/debug");
47
- const lint_1 = require("../util/lint");
48
- const ranges_1 = require("../lib/ranges");
49
- const range_1 = require("../lib/range");
50
- const index_1 = require("../index");
51
- const element_1 = require("../lib/element");
52
- const text_1 = require("../lib/text");
53
- /* NOT FOR BROWSER END */
54
- /**
55
- * 所有节点的基类
56
- * @classdesc `{childNodes: ...(AstText|Token)}`
57
- */
58
- class Token extends element_1.AstElement {
59
- type = 'root';
60
- /** 解析阶段,参见顶部注释。只对plain Token有意义。 */
61
- #stage = 0;
62
- #config;
63
- /** 这个数组起两个作用:1. 数组中的Token会在build时替换`/\0\d+.\x7F/`标记;2. 数组中的Token会依次执行parseOnce和build方法。 */
64
- #accum;
65
- #include;
66
- /* NOT FOR BROWSER */
67
- #acceptable;
68
- #protectedChildren = new ranges_1.Ranges();
69
- /** 所有图片,包括图库 */
70
- get images() {
71
- return this.querySelectorAll('file, gallery-image, imagemap-image');
72
- }
73
- /** 所有内链、外链和自由外链 */
74
- get links() {
75
- return this.querySelectorAll('link, ext-link, free-ext-link, image-parameter#link');
76
- }
77
- /** 所有模板和模块 */
78
- get embeds() {
79
- return this.querySelectorAll('template, magic-word#invoke');
80
- }
81
- /* NOT FOR BROWSER END */
82
- /** @class */
83
- constructor(wikitext, config = index_1.default.getConfig(), accum = [], acceptable) {
84
- super();
85
- if (typeof wikitext === 'string') {
86
- this.insertAt(wikitext);
87
- }
88
- this.#config = config;
89
- this.#accum = accum;
90
- accum.push(this);
91
- /* NOT FOR BROWSER */
92
- this.setAttribute('acceptable', acceptable);
93
- }
94
- /** @private */
95
- parseOnce(n = this.#stage, include = false) {
96
- if (n < this.#stage || !this.getAttribute('plain') || this.length === 0) {
97
- return this;
98
- }
99
- else if (this.#stage >= constants_1.MAX_STAGE) {
100
- /* NOt FOR BROWSER */
101
- if (this.type === 'root') {
102
- index_1.default.error('已完全解析!');
103
- }
104
- /* NOT FOR BROWSER END */
105
- return this;
106
- }
107
- switch (n) {
108
- case 0:
109
- if (this.type === 'root') {
110
- this.#accum.shift();
111
- }
112
- this.#include = include;
113
- this.#parseCommentAndExt(include);
114
- break;
115
- case 1:
116
- this.#parseBraces();
117
- break;
118
- case 2:
119
- this.#parseHtml();
120
- break;
121
- case 3:
122
- this.#parseTable();
123
- break;
124
- case 4:
125
- this.#parseHrAndDoubleUnderscore();
126
- break;
127
- case 5:
128
- this.#parseLinks();
129
- break;
130
- case 6:
131
- this.#parseQuotes();
132
- break;
133
- case 7:
134
- this.#parseExternalLinks();
135
- break;
136
- case 8:
137
- this.#parseMagicLinks();
138
- break;
139
- case 9:
140
- this.#parseList();
141
- break;
142
- case 10:
143
- this.#parseConverter();
144
- // no default
145
- }
146
- if (this.type === 'root') {
147
- for (const token of this.#accum) {
148
- token.parseOnce(n, include);
149
- }
150
- }
151
- this.#stage++;
152
- return this;
153
- }
154
- /** @private */
155
- buildFromStr(str, type) {
156
- const nodes = str.split(/[\0\x7F]/u).map((s, i) => {
157
- if (i % 2 === 0) {
158
- return new text_1.AstText(s);
159
- }
160
- else if (isNaN(s.slice(-1))) {
161
- return this.#accum[Number(s.slice(0, -1))];
162
- }
163
- throw new Error(`解析错误!未正确标记的 Token:${s}`);
164
- });
165
- if (type === constants_1.BuildMethod.String) {
166
- return nodes.map(String).join('');
167
- }
168
- else if (type === constants_1.BuildMethod.Text) {
169
- return (0, string_1.text)(nodes);
170
- }
171
- return nodes;
172
- }
173
- /** 将占位符替换为子Token */
174
- #build() {
175
- this.#stage = constants_1.MAX_STAGE;
176
- const { length, firstChild } = this, str = String(firstChild);
177
- if (length === 1 && firstChild.type === 'text' && str.includes('\0')) {
178
- this.replaceChildren(...this.buildFromStr(str));
179
- this.normalize();
180
- if (this.type === 'root') {
181
- for (const token of this.#accum) {
182
- token.#build();
183
- }
184
- }
185
- }
186
- }
187
- /** @private */
188
- afterBuild() {
189
- if (this.type === 'root') {
190
- for (const token of this.#accum) {
191
- token.afterBuild();
192
- }
193
- }
194
- }
195
- /** @private */
196
- parse(n = constants_1.MAX_STAGE, include) {
197
- n = Math.min(n, constants_1.MAX_STAGE);
198
- while (this.#stage < n) {
199
- this.parseOnce(this.#stage, include);
200
- }
201
- if (n) {
202
- this.#build();
203
- this.afterBuild();
204
- }
205
- return this;
206
- }
207
- /**
208
- * 解析HTML注释和扩展标签
209
- * @param includeOnly 是否嵌入
210
- */
211
- #parseCommentAndExt(includeOnly) {
212
- const { parseCommentAndExt } = require('../parser/commentAndExt');
213
- this.setText(parseCommentAndExt(String(this.firstChild), this.#config, this.#accum, includeOnly));
214
- }
215
- /** 解析花括号 */
216
- #parseBraces() {
217
- const { parseBraces } = require('../parser/braces');
218
- const str = this.type === 'root' ? String(this.firstChild) : `\0${String(this.firstChild)}`, parsed = parseBraces(str, this.#config, this.#accum);
219
- this.setText(this.type === 'root' ? parsed : parsed.slice(1));
220
- }
221
- /** 解析HTML标签 */
222
- #parseHtml() {
223
- if (this.#config.excludes?.includes('html')) {
224
- return;
225
- }
226
- const { parseHtml } = require('../parser/html');
227
- this.setText(parseHtml(String(this.firstChild), this.#config, this.#accum));
228
- }
229
- /** 解析表格 */
230
- #parseTable() {
231
- if (this.#config.excludes?.includes('table')) {
232
- return;
233
- }
234
- const { parseTable } = require('../parser/table');
235
- this.setText(parseTable(this, this.#config, this.#accum));
236
- }
237
- /** 解析`<hr>`和状态开关 */
238
- #parseHrAndDoubleUnderscore() {
239
- if (this.#config.excludes?.includes('hr')) {
240
- return;
241
- }
242
- const { parseHrAndDoubleUnderscore } = require('../parser/hrAndDoubleUnderscore');
243
- this.setText(parseHrAndDoubleUnderscore(this, this.#config, this.#accum));
244
- }
245
- /** 解析内部链接 */
246
- #parseLinks() {
247
- const { parseLinks } = require('../parser/links');
248
- this.setText(parseLinks(String(this.firstChild), this.#config, this.#accum));
249
- }
250
- /** 解析单引号 */
251
- #parseQuotes() {
252
- if (this.#config.excludes?.includes('quote')) {
253
- return;
254
- }
255
- const { parseQuotes } = require('../parser/quotes');
256
- const lines = String(this.firstChild).split('\n');
257
- for (let i = 0; i < lines.length; i++) {
258
- lines[i] = parseQuotes(lines[i], this.#config, this.#accum);
259
- }
260
- this.setText(lines.join('\n'));
261
- }
262
- /** 解析外部链接 */
263
- #parseExternalLinks() {
264
- if (this.#config.excludes?.includes('extLink')) {
265
- return;
266
- }
267
- const { parseExternalLinks } = require('../parser/externalLinks');
268
- this.setText(parseExternalLinks(String(this.firstChild), this.#config, this.#accum));
269
- }
270
- /** 解析自由外链 */
271
- #parseMagicLinks() {
272
- if (this.#config.excludes?.includes('magicLink')) {
273
- return;
274
- }
275
- const { parseMagicLinks } = require('../parser/magicLinks');
276
- this.setText(parseMagicLinks(String(this.firstChild), this.#config, this.#accum));
277
- }
278
- /** 解析列表 */
279
- #parseList() {
280
- if (this.#config.excludes?.includes('list')) {
281
- return;
282
- }
283
- const { parseList } = require('../parser/list');
284
- const lines = String(this.firstChild).split('\n');
285
- let i = this.type === 'root' || this.type === 'ext-inner' && this.name === 'poem' ? 0 : 1;
286
- for (; i < lines.length; i++) {
287
- lines[i] = parseList(lines[i], this.#config, this.#accum);
288
- }
289
- this.setText(lines.join('\n'));
290
- }
291
- /** 解析语言变体转换 */
292
- #parseConverter() {
293
- if (this.#config.variants.length > 0) {
294
- const { parseConverter } = require('../parser/converter');
295
- this.setText(parseConverter(String(this.firstChild), this.#config, this.#accum));
296
- }
297
- }
298
- /** @private */
299
- getAttribute(key) {
300
- switch (key) {
301
- case 'plain':
302
- return (this.constructor === Token);
303
- case 'config':
304
- return structuredClone(this.#config);
305
- case 'include': {
306
- if (this.#include !== undefined) {
307
- return this.#include;
308
- }
309
- const root = this.getRootNode();
310
- return (root !== this && root.getAttribute('include'));
311
- }
312
- case 'accum':
313
- return this.#accum;
314
- /* NOT FOR BROWSER */
315
- case 'stage':
316
- return this.#stage;
317
- case 'acceptable':
318
- return (this.#acceptable ? { ...this.#acceptable } : undefined);
319
- case 'protectedChildren':
320
- return new ranges_1.Ranges(this.#protectedChildren);
321
- /* NOT FOR BROWSER END */
322
- default:
323
- return super.getAttribute(key);
324
- }
325
- }
326
- /** @private */
327
- setAttribute(key, value) {
328
- switch (key) {
329
- case 'stage':
330
- if (this.#stage === 0 && this.type === 'root') {
331
- this.#accum.shift();
332
- }
333
- this.#stage = value;
334
- break;
335
- /* NOT FOR BROWSER */
336
- case 'acceptable': {
337
- const acceptable = {};
338
- if (value) {
339
- for (const [k, v] of Object.entries(value)) {
340
- if (k.startsWith('Stage-')) {
341
- for (let i = 0; i <= Number(k.slice(6)); i++) {
342
- for (const type of constants_1.aliases[i]) {
343
- acceptable[type] = new ranges_1.Ranges(v);
344
- }
345
- }
346
- }
347
- else if (k.startsWith('!')) { // `!`项必须放在最后
348
- delete acceptable[k.slice(1)];
349
- }
350
- else {
351
- acceptable[k] = new ranges_1.Ranges(v);
352
- }
353
- }
354
- }
355
- this.#acceptable = value && acceptable;
356
- break;
357
- }
358
- /* NOT FOR BROWSER END */
359
- default:
360
- super.setAttribute(key, value);
361
- }
362
- }
363
- insertAt(child, i = this.length) {
364
- const token = typeof child === 'string' ? new text_1.AstText(child) : child;
365
- /* NOT FOR BROWSER */
366
- if (!debug_1.Shadow.running && this.#acceptable) {
367
- const acceptableIndices = Object.fromEntries(Object.entries(this.#acceptable).map(([str, ranges]) => [str, ranges.applyTo(this.length + 1)])), nodesAfter = this.childNodes.slice(i), insertedName = token.constructor.name;
368
- i += i < 0 ? this.length : 0;
369
- if (!acceptableIndices[insertedName]?.includes(i)) {
370
- this.constructorError(`的第 ${i} 个子节点不能为 ${insertedName}`);
371
- }
372
- else if (nodesAfter.some(({ constructor: { name } }, j) => !acceptableIndices[name]?.includes(i + j + 1))) {
373
- this.constructorError(`插入新的第 ${i} 个子节点会破坏规定的顺序`);
374
- }
375
- }
376
- /* NOT FOR BROWSER END */
377
- super.insertAt(token, i);
378
- /* NOT FOR BROWSER */
379
- const e = new Event('insert', { bubbles: true });
380
- this.dispatchEvent(e, { type: 'insert', position: i < 0 ? i + this.length - 1 : i });
381
- if (token.constructor === Token && this.getAttribute('plain')) {
382
- index_1.default.warn('您正将一个普通节点作为另一个普通节点的子节点,请考虑要不要执行 flatten 方法。');
383
- }
384
- /* NOT FOR BROWSER END */
385
- if (token.type === 'root') {
386
- token.type = 'plain';
387
- }
388
- return token;
389
- }
390
- /**
391
- * 规范化页面标题
392
- * @param title 标题(含或不含命名空间前缀)
393
- * @param defaultNs 命名空间
394
- * @param halfParsed 仅供内部使用
395
- * @param decode 是否需要解码
396
- * @param selfLink 是否允许selfLink
397
- */
398
- normalizeTitle(title, defaultNs = 0, halfParsed, decode, selfLink) {
399
- return index_1.default.normalizeTitle(title, defaultNs, this.#include, this.#config, halfParsed, decode, selfLink);
400
- }
401
- /** @override */
402
- lint(start = this.getAbsoluteIndex(), re) {
403
- const errors = super.lint(start, re);
404
- if (this.type === 'root') {
405
- const record = {};
406
- for (const cat of this.querySelectorAll('category')) {
407
- const thisCat = record[cat.name];
408
- if (thisCat) {
409
- thisCat.add(cat);
410
- }
411
- else {
412
- record[cat.name] = new Set([cat]);
413
- }
414
- }
415
- for (const value of Object.values(record)) {
416
- if (value.size > 1) {
417
- errors.push(...[...value].map(cat => {
418
- const e = (0, lint_1.generateForSelf)(cat, { start: cat.getAbsoluteIndex() }, 'no-duplicate', 'duplicated category');
419
- e.suggestions = [
420
- {
421
- desc: 'remove',
422
- range: [e.startIndex, e.endIndex],
423
- text: '',
424
- },
425
- ];
426
- return e;
427
- }));
428
- }
429
- }
430
- const regex = /<!--\s*lint-(disable(?:(?:-next)?-line)?|enable)(\s[\sa-z,-]*)?-->/gu, wikitext = String(this), ignores = [];
431
- let mt = regex.exec(wikitext), last = 0, curLine = 0;
432
- while (mt) {
433
- const { 1: type, index } = mt, detail = mt[2]?.trim();
434
- curLine += wikitext.slice(last, index).split('\n').length - 1;
435
- last = index;
436
- ignores.push({
437
- line: curLine + (type === 'disable-line' ? 0 : 1),
438
- from: type === 'disable' ? regex.lastIndex : undefined,
439
- to: type === 'enable' ? regex.lastIndex : undefined,
440
- rules: detail ? new Set(detail.split(',').map(r => r.trim())) : undefined,
441
- });
442
- mt = regex.exec(wikitext);
443
- }
444
- return errors.filter(({ rule, startLine, startIndex }) => {
445
- const nearest = { pos: 0 };
446
- for (const { line, from, to, rules } of ignores) {
447
- if (line > startLine + 1) {
448
- break;
449
- }
450
- else if (rules && !rules.has(rule)) {
451
- continue;
452
- }
453
- else if (line === startLine && from === undefined && to === undefined) {
454
- return false;
455
- }
456
- else if (from <= startIndex && from > nearest.pos) {
457
- nearest.pos = from;
458
- nearest.type = 'from';
459
- }
460
- else if (to <= startIndex && to > nearest.pos) {
461
- nearest.pos = to;
462
- nearest.type = 'to';
463
- }
464
- }
465
- return nearest.type !== 'from';
466
- });
467
- }
468
- return errors;
469
- }
470
- /* NOT FOR BROWSER */
471
- /** @private */
472
- protectChildren(...args) {
473
- this.#protectedChildren.push(...new ranges_1.Ranges(args));
474
- }
475
- /**
476
- * @override
477
- * @param i 移除位置
478
- */
479
- removeAt(i) {
480
- i += i < 0 ? this.length : 0;
481
- if (!debug_1.Shadow.running) {
482
- const protectedIndices = this.#protectedChildren.applyTo(this.childNodes);
483
- if (protectedIndices.includes(i)) {
484
- this.constructorError(`的第 ${i} 个子节点不可移除`);
485
- }
486
- else if (this.#acceptable) {
487
- const acceptableIndices = Object.fromEntries(Object.entries(this.#acceptable).map(([str, ranges]) => [str, ranges.applyTo(this.length - 1)])), nodesAfter = this.childNodes.slice(i + 1);
488
- if (nodesAfter.some(({ constructor: { name } }, j) => !acceptableIndices[name]?.includes(i + j))) {
489
- this.constructorError(`移除第 ${i} 个子节点会破坏规定的顺序`);
490
- }
491
- }
492
- }
493
- const node = super.removeAt(i);
494
- const e = new Event('remove', { bubbles: true });
495
- this.dispatchEvent(e, { type: 'remove', position: i, removed: node });
496
- return node;
497
- }
498
- /**
499
- * 替换为同类节点
500
- * @param token 待替换的节点
501
- * @throws `Error` 不存在父节点
502
- */
503
- safeReplaceWith(token) {
504
- const { parentNode } = this;
505
- if (!parentNode) {
506
- throw new Error('不存在父节点!');
507
- }
508
- else if (token.constructor !== this.constructor) {
509
- this.typeError('safeReplaceWith', this.constructor.name);
510
- }
511
- try {
512
- assert.deepEqual(token.getAttribute('acceptable'), this.#acceptable);
513
- }
514
- catch (e) {
515
- if (e instanceof assert.AssertionError) {
516
- this.constructorError('带有不同的 #acceptable 属性');
517
- }
518
- throw e;
519
- }
520
- const i = parentNode.childNodes.indexOf(this);
521
- super.removeAt.call(parentNode, i);
522
- super.insertAt.call(parentNode, token, i);
523
- if (token.type === 'root') {
524
- token.type = 'plain';
525
- }
526
- const e = new Event('replace', { bubbles: true });
527
- token.dispatchEvent(e, { type: 'replace', position: i, oldToken: this });
528
- }
529
- /**
530
- * 创建HTML注释
531
- * @param data 注释内容
532
- */
533
- createComment(data = '') {
534
- const { CommentToken } = require('./nowiki/comment');
535
- const config = this.getAttribute('config');
536
- // @ts-expect-error abstract class
537
- return debug_1.Shadow.run(() => new CommentToken(data.replace(/-->/gu, '--&gt;'), true, config));
538
- }
539
- /**
540
- * 创建标签
541
- * @param tagName 标签名
542
- * @param options 选项
543
- * @param options.selfClosing 是否自封闭
544
- * @param options.closing 是否是闭合标签
545
- * @throws `RangeError` 非法的标签名
546
- */
547
- createElement(tagName, { selfClosing, closing } = {}) {
548
- const config = this.getAttribute('config'), include = this.getAttribute('include');
549
- if (tagName === (include ? 'noinclude' : 'includeonly')) {
550
- const { IncludeToken } = require('./tagPair/include');
551
- return debug_1.Shadow.run(
552
- // @ts-expect-error abstract class
553
- () => new IncludeToken(tagName, '', undefined, selfClosing ? undefined : tagName, config));
554
- }
555
- else if (config.ext.includes(tagName)) {
556
- const { ExtToken } = require('./tagPair/ext');
557
- // @ts-expect-error abstract class
558
- return debug_1.Shadow.run(() => new ExtToken(tagName, '', undefined, selfClosing ? undefined : '', config));
559
- }
560
- else if (config.html.flat().includes(tagName)) {
561
- const { HtmlToken } = require('./html'), { AttributesToken } = require('./attributes');
562
- return debug_1.Shadow.run(() => {
563
- // @ts-expect-error abstract class
564
- const attr = new AttributesToken(undefined, 'html-attrs', tagName, config);
565
- // @ts-expect-error abstract class
566
- return new HtmlToken(tagName, attr, Boolean(closing), Boolean(selfClosing), config);
567
- });
568
- }
569
- throw new RangeError(`非法的标签名:${tagName}`);
570
- }
571
- /**
572
- * 创建纯文本节点
573
- * @param data 文本内容
574
- */
575
- createTextNode(data = '') {
576
- return new text_1.AstText(data);
577
- }
578
- /** 创建AstRange对象 */
579
- createRange() {
580
- return new range_1.AstRange();
581
- }
582
- /**
583
- * 找到给定位置
584
- * @param index 位置
585
- */
586
- caretPositionFromIndex(index) {
587
- if (index === undefined) {
588
- return undefined;
589
- }
590
- const { length } = String(this);
591
- if (index >= length || index < -length) {
592
- return undefined;
593
- }
594
- index += index < 0 ? length : 0;
595
- let self = this, acc = 0, start = 0;
596
- while (self.type !== 'text') {
597
- const { childNodes } = self;
598
- acc += self.getAttribute('padding');
599
- for (let i = 0; acc <= index && i < childNodes.length; i++) {
600
- const cur = childNodes[i], l = String(cur).length;
601
- acc += l;
602
- if (acc > index) {
603
- self = cur;
604
- acc -= l;
605
- start = acc;
606
- break;
607
- }
608
- acc += self.getGaps(i);
609
- }
610
- if (self.childNodes === childNodes) {
611
- return { offsetNode: self, offset: index - start };
612
- }
613
- }
614
- return { offsetNode: self, offset: index - start };
615
- }
616
- /**
617
- * 找到给定位置
618
- * @param x 列数
619
- * @param y 行数
620
- */
621
- caretPositionFromPoint(x, y) {
622
- return this.caretPositionFromIndex(this.indexFromPos(y, x));
623
- }
624
- /**
625
- * 找到给定位置所在的最外层节点
626
- * @param index 位置
627
- */
628
- elementFromIndex(index) {
629
- return this.caretPositionFromIndex(index)?.offsetNode;
630
- }
631
- /**
632
- * 找到给定位置所在的最外层节点
633
- * @param x 列数
634
- * @param y 行数
635
- */
636
- elementFromPoint(x, y) {
637
- return this.elementFromIndex(this.indexFromPos(y, x));
638
- }
639
- /**
640
- * 找到给定位置所在的所有节点
641
- * @param index 位置
642
- */
643
- elementsFromIndex(index) {
644
- const offsetNode = this.caretPositionFromIndex(index)?.offsetNode;
645
- return offsetNode ? [...offsetNode.getAncestors().reverse(), offsetNode] : [];
646
- }
647
- /**
648
- * 找到给定位置所在的所有节点
649
- * @param x 列数
650
- * @param y 行数
651
- */
652
- elementsFromPoint(x, y) {
653
- return this.elementsFromIndex(this.indexFromPos(y, x));
654
- }
655
- /**
656
- * 判断标题是否是跨维基链接
657
- * @param title 标题
658
- */
659
- isInterwiki(title) {
660
- return index_1.default.isInterwiki(title, this.#config);
661
- }
662
- /** @private */
663
- cloneChildNodes() {
664
- return this.childNodes.map(child => child.cloneNode());
665
- }
666
- /** 深拷贝节点 */
667
- cloneNode() {
668
- if (this.constructor !== Token) {
669
- this.constructorError('未定义复制方法');
670
- }
671
- const cloned = this.cloneChildNodes();
672
- return debug_1.Shadow.run(() => {
673
- const token = new Token(undefined, this.#config, [], this.#acceptable);
674
- token.type = this.type;
675
- token.setAttribute('name', this.name);
676
- token.append(...cloned);
677
- token.protectChildren(...this.#protectedChildren);
678
- return token;
679
- });
680
- }
681
- /** 获取全部章节 */
682
- sections() {
683
- if (this.type !== 'root') {
684
- return undefined;
685
- }
686
- const { childNodes } = this, headings = [...childNodes.entries()]
687
- .filter((entry) => entry[1].type === 'heading')
688
- .map(([i, { level }]) => [i, level]), lastHeading = [-1, -1, -1, -1, -1, -1], sections = new Array(headings.length);
689
- for (let i = 0; i < headings.length; i++) {
690
- const [index, level] = headings[i];
691
- for (let j = level; j < 6; j++) {
692
- const last = lastHeading[j];
693
- if (last >= 0) {
694
- sections[last] = childNodes.slice(headings[last][0], index);
695
- }
696
- lastHeading[j] = j === level ? i : -1;
697
- }
698
- }
699
- for (const last of lastHeading) {
700
- if (last >= 0) {
701
- sections[last] = childNodes.slice(headings[last][0]);
702
- }
703
- }
704
- sections.unshift(childNodes.slice(0, headings[0]?.[0]));
705
- return sections;
706
- }
707
- /**
708
- * 获取指定章节
709
- * @param n 章节序号
710
- */
711
- section(n) {
712
- return this.sections()?.[n];
713
- }
714
- /**
715
- * 获取指定的外层HTML标签
716
- * @param tag HTML标签名
717
- * @throws `RangeError` 非法的标签或空标签
718
- */
719
- findEnclosingHtml(tag) {
720
- tag = tag?.toLowerCase();
721
- if (tag !== undefined && !this.#config.html.slice(0, 2).flat().includes(tag)) {
722
- throw new RangeError(`非法的标签或空标签:${tag}`);
723
- }
724
- const { parentNode } = this;
725
- if (!parentNode) {
726
- return undefined;
727
- }
728
- const isHtml = (0, debug_1.isToken)('html'), { childNodes, length } = parentNode, index = childNodes.indexOf(this);
729
- let i;
730
- for (i = index - 1; i >= 0; i--) {
731
- const child = childNodes[i];
732
- if (isHtml(child) && (!tag || child.name === tag) && !child.selfClosing && !child.closing) {
733
- break;
734
- }
735
- }
736
- if (i === -1) {
737
- return parentNode.findEnclosingHtml(tag);
738
- }
739
- const opening = childNodes[i];
740
- for (i = index + 1; i < length; i++) {
741
- const child = childNodes[i];
742
- if (isHtml(child) && child.name === opening.name && !child.selfClosing && child.closing) {
743
- break;
744
- }
745
- }
746
- if (i === length) {
747
- return parentNode.findEnclosingHtml(tag);
748
- }
749
- const range = this.createRange();
750
- range.setStartBefore(opening);
751
- range.setEnd(parentNode, i + 1);
752
- return range;
753
- }
754
- /** 获取全部分类 */
755
- getCategories() {
756
- const categories = this.querySelectorAll('category');
757
- return categories.map(({ name, sortkey }) => [name, sortkey]);
758
- }
759
- /** 重新解析单引号 */
760
- redoQuotes() {
761
- const acceptable = this.getAttribute('acceptable');
762
- if (acceptable && !('QuoteToken' in acceptable)) {
763
- return;
764
- }
765
- const accum = [];
766
- for (const child of this.childNodes) {
767
- if (child.type !== 'quote' && child.type !== 'text') {
768
- child.replaceWith(`\0${accum.length}e\x7F`);
769
- accum.push(child);
770
- }
771
- }
772
- const token = debug_1.Shadow.run(() => {
773
- const node = new Token(String(this), this.getAttribute('config'), accum);
774
- node.type = 'plain';
775
- node.setAttribute('stage', 6);
776
- return node.parse(7);
777
- });
778
- this.setAttribute('childNodes', [...token.childNodes]);
779
- }
780
- /** 解析部分魔术字 */
781
- solveConst() {
782
- const targets = this.querySelectorAll('magic-word, arg'), magicWords = new Set(['if', 'ifeq', 'switch']);
783
- for (let i = targets.length - 1; i >= 0; i--) {
784
- const target = targets[i], { type, name, childNodes, length } = target, [, var1, var2] = childNodes;
785
- if (type === 'arg' || type === 'magic-word' && magicWords.has(name)) {
786
- let replace = '';
787
- if (type === 'arg') {
788
- replace = target.default === false ? String(target) : target.default;
789
- }
790
- else if (name === 'if' && !var1?.getElementByTypes('magic-word, template')) {
791
- replace = String(childNodes[String(var1 ?? '').trim() ? 2 : 3] ?? '').trim();
792
- }
793
- else if (name === 'ifeq'
794
- && !childNodes.slice(1, 3).some(child => child.getElementByTypes('magic-word, template'))) {
795
- replace = String(childNodes[String(var1 ?? '').trim() === String(var2 ?? '').trim() ? 3 : 4] ?? '').trim();
796
- }
797
- else if (name === 'switch' && !var1?.getElementByTypes('magic-word, template')) {
798
- const key = String(var1 ?? '').trim();
799
- let defaultVal = '', found = false, transclusion = false;
800
- for (let j = 2; j < length; j++) {
801
- const { anon, name: option, value, firstChild } = childNodes[j];
802
- transclusion = Boolean(firstChild.getElementByTypes('magic-word, template'));
803
- if (anon) {
804
- if (j === length - 1) {
805
- defaultVal = value;
806
- }
807
- else if (transclusion) {
808
- break;
809
- }
810
- else {
811
- found ||= key === value;
812
- }
813
- }
814
- else if (transclusion) {
815
- break;
816
- }
817
- else if (found || option === key) {
818
- replace = value;
819
- break;
820
- }
821
- else if (option.toLowerCase() === '#default') {
822
- defaultVal = value;
823
- }
824
- if (j === length - 1) {
825
- replace = defaultVal;
826
- }
827
- }
828
- if (transclusion) {
829
- continue;
830
- }
831
- }
832
- else {
833
- continue;
834
- }
835
- target.replaceWith(replace);
836
- }
837
- }
838
- }
839
- /** 合并普通节点的普通子节点 */
840
- flatten() {
841
- if (this.getAttribute('plain')) {
842
- for (const child of this.childNodes) {
843
- if (child.type !== 'text' && child.getAttribute('plain')) {
844
- child.replaceWith(...child.childNodes);
845
- }
846
- }
847
- }
848
- }
849
- }
850
- exports.Token = Token;
851
- constants_1.classes['Token'] = __filename;