wikiparser-node 1.18.2 → 1.18.3

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 (74) hide show
  1. package/README.md +6 -1
  2. package/bundle/bundle-es7.min.js +29 -29
  3. package/bundle/bundle-lsp.min.js +30 -30
  4. package/bundle/bundle.min.js +26 -26
  5. package/config/minimum.json +7 -0
  6. package/dist/addon/token.js +10 -9
  7. package/dist/addon/transclude.js +1 -3
  8. package/dist/base.d.mts +4 -0
  9. package/dist/base.d.ts +4 -0
  10. package/dist/base.js +1 -0
  11. package/dist/base.mjs +2 -1
  12. package/dist/bin/config.js +3 -2
  13. package/dist/index.d.ts +5 -1
  14. package/dist/index.js +65 -72
  15. package/dist/lib/element.d.ts +6 -0
  16. package/dist/lib/element.js +543 -466
  17. package/dist/lib/lsp.d.ts +1 -0
  18. package/dist/lib/lsp.js +16 -10
  19. package/dist/lib/redirectMap.d.ts +7 -0
  20. package/dist/lib/redirectMap.js +31 -0
  21. package/dist/lib/text.d.ts +2 -2
  22. package/dist/lib/text.js +383 -325
  23. package/dist/lib/title.d.ts +23 -4
  24. package/dist/lib/title.js +17 -5
  25. package/dist/mixin/noEscape.d.ts +4 -0
  26. package/dist/mixin/noEscape.js +22 -0
  27. package/dist/mixin/readOnly.d.ts +4 -0
  28. package/dist/mixin/readOnly.js +26 -0
  29. package/dist/parser/braces.js +29 -15
  30. package/dist/parser/commentAndExt.js +5 -16
  31. package/dist/parser/links.js +1 -1
  32. package/dist/parser/quotes.js +1 -1
  33. package/dist/parser/redirect.js +1 -3
  34. package/dist/src/arg.js +253 -202
  35. package/dist/src/attribute.d.ts +0 -5
  36. package/dist/src/attribute.js +3 -7
  37. package/dist/src/converter.js +213 -162
  38. package/dist/src/gallery.js +1 -2
  39. package/dist/src/heading.js +5 -6
  40. package/dist/src/imageParameter.js +16 -16
  41. package/dist/src/imagemap.js +3 -2
  42. package/dist/src/index.d.ts +1 -1
  43. package/dist/src/index.js +722 -694
  44. package/dist/src/link/base.js +292 -241
  45. package/dist/src/link/file.js +13 -17
  46. package/dist/src/link/galleryImage.js +1 -1
  47. package/dist/src/link/redirectTarget.js +1 -2
  48. package/dist/src/magicLink.d.ts +0 -6
  49. package/dist/src/magicLink.js +5 -15
  50. package/dist/src/nested.js +7 -7
  51. package/dist/src/nowiki/base.js +2 -1
  52. package/dist/src/nowiki/index.js +4 -3
  53. package/dist/src/onlyinclude.js +95 -44
  54. package/dist/src/parameter.d.ts +0 -6
  55. package/dist/src/parameter.js +1 -13
  56. package/dist/src/redirect.js +6 -6
  57. package/dist/src/syntax.d.ts +4 -1
  58. package/dist/src/syntax.js +4 -1
  59. package/dist/src/table/base.d.ts +0 -5
  60. package/dist/src/table/base.js +2 -9
  61. package/dist/src/table/index.js +6 -3
  62. package/dist/src/table/td.d.ts +1 -0
  63. package/dist/src/table/td.js +2 -3
  64. package/dist/src/table/trBase.js +3 -1
  65. package/dist/src/tagPair/index.js +2 -1
  66. package/dist/src/transclude.js +705 -657
  67. package/dist/util/debug.js +10 -3
  68. package/dist/util/string.js +4 -5
  69. package/extensions/dist/base.js +8 -6
  70. package/extensions/dist/lint.js +1 -1
  71. package/extensions/es7/base.js +8 -6
  72. package/extensions/es7/lint.js +1 -1
  73. package/extensions/ui.css +1 -1
  74. package/package.json +3 -3
@@ -4,13 +4,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.FileToken = void 0;
7
- const string_1 = require("../../util/string");
8
7
  const lint_1 = require("../../util/lint");
9
8
  const rect_1 = require("../../lib/rect");
10
9
  const index_1 = __importDefault(require("../../index"));
11
10
  const base_1 = require("./base");
12
11
  const imageParameter_1 = require("../imageParameter");
13
12
  /* NOT FOR BROWSER */
13
+ const string_1 = require("../../util/string");
14
14
  const debug_1 = require("../../util/debug");
15
15
  const constants_1 = require("../../util/constants");
16
16
  const title_1 = require("../../lib/title");
@@ -20,24 +20,21 @@ const frame = new Map([
20
20
  ['frameless', 'Frameless'],
21
21
  ['framed', 'Frame'],
22
22
  ['thumbnail', 'Thumb'],
23
- ]), horizAlign = new Set(['left', 'right', 'center', 'none']), vertAlign = new Set(['baseline', 'sub', 'super', 'top', 'text-top', 'middle', 'bottom', 'text-bottom']);
23
+ ]), horizAlign = new Set(['left', 'right', 'center', 'none']), vertAlign = new Set(['baseline', 'sub', 'super', 'top', 'text-top', 'middle', 'bottom', 'text-bottom']), extensions = new Set(['tiff', 'tif', 'png', 'gif', 'jpg', 'jpeg', 'webp', 'xcf', 'pdf', 'svg', 'djvu']);
24
24
  /**
25
25
  * a more sophisticated string-explode function
26
- * @param start start syntax of a nested AST node
27
- * @param end end syntax of a nested AST node
28
- * @param separator syntax for explosion
29
26
  * @param str string to be exploded
30
27
  */
31
- const explode = (start, end, separator, str) => {
28
+ const explode = (str) => {
32
29
  if (str === undefined) {
33
30
  return [];
34
31
  }
35
- const regex = new RegExp(`${[start, end, separator].map(string_1.escapeRegExp).join('|')}`, 'gu'), exploded = [];
32
+ const regex = /-\{|\}-|\|/gu, exploded = [];
36
33
  let mt = regex.exec(str), depth = 0, lastIndex = 0;
37
34
  while (mt) {
38
35
  const { 0: match, index } = mt;
39
- if (match !== separator) {
40
- depth += match === start ? 1 : -1;
36
+ if (match !== '|') {
37
+ depth += match === '-{' ? 1 : -1;
41
38
  }
42
39
  else if (depth === 0) {
43
40
  exploded.push(str.slice(lastIndex, index));
@@ -59,12 +56,10 @@ class FileToken extends base_1.LinkBaseToken {
59
56
  get type() {
60
57
  return 'file';
61
58
  }
62
- /* PRINT ONLY */
63
59
  /** file extension / 扩展名 */
64
60
  get extension() {
65
61
  return this.getAttribute('title').extension;
66
62
  }
67
- /* PRINT ONLY END */
68
63
  /* NOT FOR BROWSER */
69
64
  /** image link / 图片链接 */
70
65
  get link() {
@@ -124,7 +119,7 @@ class FileToken extends base_1.LinkBaseToken {
124
119
  /* NOT FOR BROWSER END */
125
120
  const { extension } = this.getTitle(true, true);
126
121
  /-\{|\}-|\|/gu; // eslint-disable-line @typescript-eslint/no-unused-expressions
127
- this.append(...explode('-{', '}-', '|', text).map(
122
+ this.append(...explode(text).map(
128
123
  // @ts-expect-error abstract class
129
124
  (part) => new imageParameter_1.ImageParameterToken(part, extension, config, accum)));
130
125
  }
@@ -155,12 +150,14 @@ class FileToken extends base_1.LinkBaseToken {
155
150
  * 图片参数到语法错误的映射
156
151
  * @param msg 消息键
157
152
  * @param p1 替换$1
153
+ * @param severity 错误等级
158
154
  */
159
- const generate = (msg, p1) => (arg) => {
160
- const e = (0, lint_1.generateForChild)(arg, rect, 'no-duplicate', index_1.default.msg(`${msg} image $1 parameter`, p1));
155
+ const generate = (msg, p1, severity) => (arg) => {
156
+ const e = (0, lint_1.generateForChild)(arg, rect, 'no-duplicate', index_1.default.msg(`${msg} image $1 parameter`, p1), severity);
161
157
  e.suggestions = [{ desc: 'remove', range: [e.startIndex - 1, e.endIndex], text: '' }];
162
158
  return e;
163
159
  };
160
+ const { extension } = this;
164
161
  for (const key of keys) {
165
162
  if (key === 'invalid' || key === 'width' && unscaled) {
166
163
  continue;
@@ -173,7 +170,7 @@ class FileToken extends base_1.LinkBaseToken {
173
170
  ];
174
171
  }
175
172
  if (relevantArgs.length > 1) {
176
- errors.push(...relevantArgs.map(generate('duplicated', key)));
173
+ errors.push(...relevantArgs.map(generate('duplicated', key, key === 'caption' && extension && !extensions.has(extension) ? 'warning' : 'error')));
177
174
  }
178
175
  }
179
176
  if (frameKeys.length > 1) {
@@ -368,7 +365,6 @@ class FileToken extends base_1.LinkBaseToken {
368
365
  .parse(value, this.getAttribute('include'), undefined, config);
369
366
  parameter.replaceChildren(...childNodes);
370
367
  }
371
- parameter.afterBuild();
372
368
  this.insertAt(parameter);
373
369
  }
374
370
  /* istanbul ignore next */
@@ -407,7 +403,7 @@ class FileToken extends base_1.LinkBaseToken {
407
403
  catch { }
408
404
  }
409
405
  const a = link
410
- ? `<a${href && ` href="${href}"`}${hasLink ? '' : ` class="mw-file-description"`}${titleAttr}${typeof link === 'string' ? ` rel="nofollow"` : ''}>${img}</a>`
406
+ ? `<a${href && ` href="${href}"`}${hasLink ? '' : ' class="mw-file-description"'}${titleAttr}${typeof link === 'string' ? ' rel="nofollow"' : ''}>${img}</a>`
411
407
  : `<span${titleAttr}>${img}</span>`;
412
408
  if (type !== 'gallery-image') {
413
409
  return horiz || vert || visibleCaption
@@ -106,7 +106,7 @@ let GalleryImageToken = (() => {
106
106
  /** @private */
107
107
  getTitle(temporary) {
108
108
  const imagemap = this.type === 'imagemap-image';
109
- return this.normalizeTitle(this.firstChild.toString(), imagemap ? 0 : 6, temporary, true, !imagemap);
109
+ return this.normalizeTitle(this.firstChild.toString(), imagemap ? 0 : 6, { halfParsed: true, temporary, decode: !imagemap });
110
110
  }
111
111
  /** @private */
112
112
  getAttribute(key) {
@@ -41,8 +41,7 @@ class RedirectTargetToken extends base_1.LinkBaseToken {
41
41
  }
42
42
  /** @private */
43
43
  getTitle() {
44
- return this
45
- .normalizeTitle(this.firstChild.toString(), 0, false, true, true);
44
+ return this.normalizeTitle(this.firstChild.toString(), 0, { halfParsed: true, decode: true });
46
45
  }
47
46
  /** @private */
48
47
  lint(start = this.getAbsoluteIndex()) {
@@ -63,11 +63,5 @@ export declare abstract class MagicLinkToken extends Token {
63
63
  * 是否是模板或魔术字参数
64
64
  */
65
65
  isParamValue(): boolean;
66
- /**
67
- * Escape `=`
68
- *
69
- * 转义 `=`
70
- */
71
- escape(): void;
72
66
  }
73
67
  export {};
@@ -38,6 +38,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
38
38
  };
39
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
40
  exports.MagicLinkToken = void 0;
41
+ const common_1 = require("@bhsd/common");
41
42
  const lint_1 = require("../util/lint");
42
43
  const string_1 = require("../util/string");
43
44
  const rect_1 = require("../lib/rect");
@@ -59,6 +60,8 @@ const isbnPattern = new RegExp(String.raw `^(ISBN)${space}+(?:97[89]${spdash}?)?
59
60
  // eslint-disable-next-line @typescript-eslint/no-unused-expressions, es-x/no-regexp-unicode-property-escapes
60
61
  /^(RFC|PMID)[\p{Zs}\t]+\d+$/u;
61
62
  const rfcPattern = new RegExp(String.raw `^(RFC|PMID)${space}+\d+$`, 'u');
63
+ /^(ftp:\/\/|\/\/)/iu; // eslint-disable-line @typescript-eslint/no-unused-expressions
64
+ const getUrlRegex = (0, common_1.getRegex)(protocol => new RegExp(`^(${protocol})`, 'iu'));
62
65
  /* NOT FOR BROWSER END */
63
66
  /**
64
67
  * free external link
@@ -141,8 +144,7 @@ let MagicLinkToken = (() => {
141
144
  pattern = url?.startsWith('ISBN') ? isbnPattern : rfcPattern;
142
145
  }
143
146
  else {
144
- /^(ftp:\/\/|\/\/)/iu; // eslint-disable-line @typescript-eslint/no-unused-expressions
145
- pattern = new RegExp(`^(${config.protocol}${type === 'ext-link-url' ? '|//' : ''})`, 'iu');
147
+ pattern = getUrlRegex(config.protocol + (type === 'ext-link-url' ? '|//' : ''));
146
148
  }
147
149
  this.setAttribute('pattern', pattern);
148
150
  }
@@ -188,7 +190,7 @@ let MagicLinkToken = (() => {
188
190
  if (type === 'magic-link') {
189
191
  if (link.startsWith('ISBN')) {
190
192
  return this
191
- .normalizeTitle(`BookSources/${link.slice(5)}`, -1, true)
193
+ .normalizeTitle(`BookSources/${link.slice(5)}`, -1, { temporary: true })
192
194
  .getUrl(articlePath);
193
195
  }
194
196
  link = link.startsWith('RFC')
@@ -243,18 +245,6 @@ let MagicLinkToken = (() => {
243
245
  isParamValue() {
244
246
  return this.closest('parameter')?.getValue() === this.text();
245
247
  }
246
- /**
247
- * Escape `=`
248
- *
249
- * 转义 `=`
250
- */
251
- escape() {
252
- for (const child of this.childNodes) {
253
- if (child.type === 'text') {
254
- child.escape();
255
- }
256
- }
257
- }
258
248
  /** @private */
259
249
  toHtmlInternal() {
260
250
  const { type, innerText, protocol } = this;
@@ -15,7 +15,12 @@ const noinclude_1 = require("./nowiki/noinclude");
15
15
  /* NOT FOR BROWSER */
16
16
  const debug_1 = require("../util/debug");
17
17
  const constants_1 = require("../util/constants");
18
- const childTypes = new Set(['comment', 'include', 'arg', 'template', 'magic-word']);
18
+ const childTypes = new Set(['comment', 'include', 'arg', 'template', 'magic-word']), lintRegex = [false, true].map(article => {
19
+ const noinclude = article ? 'includeonly' : 'noinclude';
20
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
21
+ /^(?:<noinclude(?:\s[^>]*)?\/?>|<\/noinclude\s*>)$/iu;
22
+ return new RegExp(String.raw `^(?:<${noinclude}(?:\s[^>]*)?/?>|</${noinclude}\s*>)$`, 'iu');
23
+ });
19
24
  /**
20
25
  * extension tag that has a nested structure
21
26
  *
@@ -60,12 +65,7 @@ class NestedToken extends index_2.Token {
60
65
  }
61
66
  /** @private */
62
67
  lint(start = this.getAbsoluteIndex(), re) {
63
- const rect = new rect_1.BoundingRect(this, start), noinclude = this.#regex ? 'includeonly' : 'noinclude';
64
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
65
- /^(?:<noinclude(?:\s[^>]*)?\/?>|<\/noinclude\s*>)$/iu;
66
- const regex = typeof this.#regex === 'boolean'
67
- ? new RegExp(String.raw `^(?:<${noinclude}(?:\s[^>]*)?/?>|</${noinclude}\s*>)$`, 'iu')
68
- : /^<!--[\s\S]*-->$/u;
68
+ const rect = new rect_1.BoundingRect(this, start), regex = typeof this.#regex === 'boolean' ? lintRegex[this.#regex ? 1 : 0] : /^<!--[\s\S]*-->$/u;
69
69
  return [
70
70
  ...super.lint(start, re),
71
71
  ...this.childNodes.filter(child => {
@@ -40,6 +40,7 @@ const index_1 = require("../index");
40
40
  const debug_1 = require("../../util/debug");
41
41
  const constants_1 = require("../../util/constants");
42
42
  const fixed_1 = require("../../mixin/fixed");
43
+ const noEscape_1 = require("../../mixin/noEscape");
43
44
  /**
44
45
  * text-only token that will not be parsed
45
46
  *
@@ -47,7 +48,7 @@ const fixed_1 = require("../../mixin/fixed");
47
48
  * @classdesc `{childNodes: [AstText]}`
48
49
  */
49
50
  let NowikiBaseToken = (() => {
50
- let _classDecorators = [fixed_1.fixedToken];
51
+ let _classDecorators = [fixed_1.fixedToken, noEscape_1.noEscape];
51
52
  let _classDescriptor;
52
53
  let _classExtraInitializers = [];
53
54
  let _classThis;
@@ -4,12 +4,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.NowikiToken = void 0;
7
+ const common_1 = require("@bhsd/common");
7
8
  const lint_1 = require("../../util/lint");
8
9
  const index_1 = __importDefault(require("../../index"));
9
10
  const base_1 = require("./base");
10
11
  /* NOT FOR BROWSER */
11
12
  const constants_1 = require("../../util/constants");
12
13
  /* NOT FOR BROWSER END */
14
+ /<\s*(?:\/\s*)?(nowiki)\b/giu; // eslint-disable-line @typescript-eslint/no-unused-expressions
15
+ const getLintRegex = (0, common_1.getRegex)(name => new RegExp(String.raw `<\s*(?:/\s*)${name === 'nowiki' ? '' : '?'}(${name})\b`, 'giu'));
13
16
  /**
14
17
  * text-only token inside an extension tag
15
18
  *
@@ -28,9 +31,7 @@ class NowikiToken extends base_1.NowikiBaseToken {
28
31
  e.fix = { range: [start, e.endIndex], text: '', desc: 'empty' };
29
32
  return [e];
30
33
  }
31
- /<\s*(?:\/\s*)?(nowiki)\b/giu; // eslint-disable-line @typescript-eslint/no-unused-expressions
32
- const re = new RegExp(String.raw `<\s*(?:/\s*)${name === 'nowiki' ? '' : '?'}(${name})\b`, 'giu');
33
- return super.lint(start, re);
34
+ return super.lint(start, getLintRegex(name));
34
35
  }
35
36
  }
36
37
  exports.NowikiToken = NowikiToken;
@@ -1,4 +1,38 @@
1
1
  "use strict";
2
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
3
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
4
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
5
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
6
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
7
+ var _, done = false;
8
+ for (var i = decorators.length - 1; i >= 0; i--) {
9
+ var context = {};
10
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
11
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
12
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
13
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
14
+ if (kind === "accessor") {
15
+ if (result === void 0) continue;
16
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
17
+ if (_ = accept(result.get)) descriptor.get = _;
18
+ if (_ = accept(result.set)) descriptor.set = _;
19
+ if (_ = accept(result.init)) initializers.unshift(_);
20
+ }
21
+ else if (_ = accept(result)) {
22
+ if (kind === "field") initializers.unshift(_);
23
+ else descriptor[key] = _;
24
+ }
25
+ }
26
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
27
+ done = true;
28
+ };
29
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
30
+ var useValue = arguments.length > 2;
31
+ for (var i = 0; i < initializers.length; i++) {
32
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
33
+ }
34
+ return useValue ? value : void 0;
35
+ };
2
36
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
37
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
38
  };
@@ -8,6 +42,7 @@ const index_1 = require("./index");
8
42
  /* NOT FOR BROWSER */
9
43
  const debug_1 = require("../util/debug");
10
44
  const constants_1 = require("../util/constants");
45
+ const noEscape_1 = require("../mixin/noEscape");
11
46
  const index_2 = __importDefault(require("../index"));
12
47
  /* NOT FOR BROWSER END */
13
48
  /**
@@ -16,51 +51,67 @@ const index_2 = __importDefault(require("../index"));
16
51
  * 嵌入时的`<onlyinclude>`
17
52
  * @classdesc `{childNodes: (AstText|Token)[]}`
18
53
  */
19
- class OnlyincludeToken extends index_1.Token {
20
- get type() {
21
- return 'onlyinclude';
22
- }
23
- /* NOT FOR BROWSER */
24
- /** inner wikitext / 内部wikitext */
25
- get innerText() {
26
- return this.text();
27
- }
28
- /** @throws `RangeError` 不允许包含`</onlyinclude>` */
29
- set innerText(text) {
30
- /* istanbul ignore if */
31
- if (text.includes('</onlyinclude>')) {
32
- throw new RangeError('"</onlyinclude>" is not allowed in the text!');
54
+ let OnlyincludeToken = (() => {
55
+ let _classDecorators = [noEscape_1.noEscape];
56
+ let _classDescriptor;
57
+ let _classExtraInitializers = [];
58
+ let _classThis;
59
+ let _classSuper = index_1.Token;
60
+ var OnlyincludeToken = class extends _classSuper {
61
+ static { _classThis = this; }
62
+ static {
63
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
64
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
65
+ OnlyincludeToken = _classThis = _classDescriptor.value;
66
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
67
+ __runInitializers(_classThis, _classExtraInitializers);
33
68
  }
34
- this.replaceChildren(...index_2.default.parse(text, true, undefined, this.getAttribute('config')).childNodes);
35
- }
36
- /* NOT FOR BROWSER END */
37
- /** @private */
38
- toString(skip) {
39
- return `<onlyinclude>${super.toString(skip)}</onlyinclude>`;
40
- }
41
- /** @private */
42
- getAttribute(key) {
43
- if (key === 'padding') {
44
- return 13;
69
+ get type() {
70
+ return 'onlyinclude';
45
71
  }
46
- return (key === 'plain') || super.getAttribute(key);
47
- }
48
- /** @private */
49
- print() {
50
- return super.print({
51
- pre: '<span class="wpb-ext">&lt;onlyinclude&gt;</span>',
52
- post: '<span class="wpb-ext">&lt;/onlyinclude&gt;</span>',
53
- });
54
- }
55
- /* NOT FOR BROWSER */
56
- cloneNode() {
57
- const cloned = this.cloneChildNodes();
58
- return debug_1.Shadow.run(() => {
59
- const token = new OnlyincludeToken(undefined, this.getAttribute('config'));
60
- token.append(...cloned);
61
- return token;
62
- });
63
- }
64
- }
72
+ /* NOT FOR BROWSER */
73
+ /** inner wikitext / 内部wikitext */
74
+ get innerText() {
75
+ return this.text();
76
+ }
77
+ /** @throws `RangeError` 不允许包含`</onlyinclude>` */
78
+ set innerText(text) {
79
+ /* istanbul ignore if */
80
+ if (text.includes('</onlyinclude>')) {
81
+ throw new RangeError('"</onlyinclude>" is not allowed in the text!');
82
+ }
83
+ this.replaceChildren(...index_2.default.parse(text, true, undefined, this.getAttribute('config')).childNodes);
84
+ }
85
+ /* NOT FOR BROWSER END */
86
+ /** @private */
87
+ toString(skip) {
88
+ return `<onlyinclude>${super.toString(skip)}</onlyinclude>`;
89
+ }
90
+ /** @private */
91
+ getAttribute(key) {
92
+ if (key === 'padding') {
93
+ return 13;
94
+ }
95
+ return (key === 'plain') || super.getAttribute(key);
96
+ }
97
+ /** @private */
98
+ print() {
99
+ return super.print({
100
+ pre: '<span class="wpb-ext">&lt;onlyinclude&gt;</span>',
101
+ post: '<span class="wpb-ext">&lt;/onlyinclude&gt;</span>',
102
+ });
103
+ }
104
+ /* NOT FOR BROWSER */
105
+ cloneNode() {
106
+ const cloned = this.cloneChildNodes();
107
+ return debug_1.Shadow.run(() => {
108
+ const token = new OnlyincludeToken(undefined, this.getAttribute('config'));
109
+ token.append(...cloned);
110
+ return token;
111
+ });
112
+ }
113
+ };
114
+ return OnlyincludeToken = _classThis;
115
+ })();
65
116
  exports.OnlyincludeToken = OnlyincludeToken;
66
117
  constants_1.classes['OnlyincludeToken'] = __filename;
@@ -63,10 +63,4 @@ export declare abstract class ParameterToken extends Token {
63
63
  * @throws `RangeError` 更名造成重复参数
64
64
  */
65
65
  rename(key: string, force?: boolean): void;
66
- /**
67
- * Ecape `=`
68
- *
69
- * 转义 `=`
70
- */
71
- escape(): void;
72
66
  }
@@ -195,7 +195,7 @@ let ParameterToken = (() => {
195
195
  /** @private */
196
196
  json(_, start = this.getAbsoluteIndex()) {
197
197
  const json = super.json(undefined, start);
198
- Object.assign(json, { anon: this.anon, duplicated: this.duplicated });
198
+ Object.assign(json, { anon: this.anon }, this.duplicated && { duplicated: true });
199
199
  return json;
200
200
  }
201
201
  /* NOT FOR BROWSER */
@@ -269,18 +269,6 @@ let ParameterToken = (() => {
269
269
  }
270
270
  this.firstChild.replaceChildren(...root.childNodes);
271
271
  }
272
- /**
273
- * Ecape `=`
274
- *
275
- * 转义 `=`
276
- */
277
- escape() {
278
- for (const child of this.lastChild.childNodes) {
279
- if (child.type === 'text') {
280
- child.escape();
281
- }
282
- }
283
- }
284
272
  };
285
273
  return ParameterToken = _classThis;
286
274
  })();
@@ -40,9 +40,13 @@ const index_1 = require("./index");
40
40
  const syntax_1 = require("./syntax");
41
41
  const redirectTarget_1 = require("./link/redirectTarget");
42
42
  /* NOT FOR BROWSER */
43
+ const common_1 = require("@bhsd/common");
43
44
  const constants_1 = require("../util/constants");
44
45
  const debug_1 = require("../util/debug");
45
46
  const fixed_1 = require("../mixin/fixed");
47
+ const noEscape_1 = require("../mixin/noEscape");
48
+ /^(?:#redirect|#重定向)\s*(?::\s*)?$/iu; // eslint-disable-line @typescript-eslint/no-unused-expressions
49
+ const getPattern = (0, common_1.getObjRegex)(redirection => new RegExp(String.raw `^(?:${redirection.join('|')})\s*(?::\s*)?$`, 'iu'));
46
50
  /* NOT FOR BROWSER END */
47
51
  /**
48
52
  * redirect
@@ -51,7 +55,7 @@ const fixed_1 = require("../mixin/fixed");
51
55
  * @classdesc `{childNodes: [SyntaxToken, LinkToken]}`
52
56
  */
53
57
  let RedirectToken = (() => {
54
- let _classDecorators = [fixed_1.fixedToken, (0, hidden_1.hiddenToken)(false, false)];
58
+ let _classDecorators = [fixed_1.fixedToken, noEscape_1.noEscape, (0, hidden_1.hiddenToken)(false, false)];
55
59
  let _classDescriptor;
56
60
  let _classExtraInitializers = [];
57
61
  let _classThis;
@@ -82,11 +86,7 @@ let RedirectToken = (() => {
82
86
  super(undefined, config, accum);
83
87
  this.#pre = pre;
84
88
  this.#post = post;
85
- /^(?:#redirect|#重定向)\s*(?::\s*)?$/iu; // eslint-disable-line @typescript-eslint/no-unused-expressions
86
- const pattern = new RegExp(String.raw `^(?:${config.redirection.join('|')})\s*(?::\s*)?$`, 'iu');
87
- this.append(new syntax_1.SyntaxToken(syntax, pattern, 'redirect-syntax', config, accum, {
88
- AstText: ':',
89
- }),
89
+ this.append(new syntax_1.SyntaxToken(syntax, getPattern(config.redirection), 'redirect-syntax', config, accum, { AstText: ':' }),
90
90
  // @ts-expect-error abstract class
91
91
  new redirectTarget_1.RedirectTargetToken(link, text?.slice(1), config, accum));
92
92
  }
@@ -12,7 +12,10 @@ declare type SyntaxTypes = 'heading-trail' | 'magic-word-name' | 'table-syntax'
12
12
  export declare class SyntaxToken extends Token {
13
13
  #private;
14
14
  get type(): SyntaxTypes;
15
- /** @param pattern 语法正则 */
15
+ /**
16
+ * @class
17
+ * @param pattern 语法正则
18
+ */
16
19
  constructor(wikitext: string | undefined, pattern: RegExp, type: SyntaxTypes, config?: Config, accum?: Token[], acceptable?: Acceptable);
17
20
  cloneNode(): this;
18
21
  }
@@ -64,7 +64,10 @@ let SyntaxToken = (() => {
64
64
  get type() {
65
65
  return this.#type;
66
66
  }
67
- /** @param pattern 语法正则 */
67
+ /**
68
+ * @class
69
+ * @param pattern 语法正则
70
+ */
68
71
  constructor(wikitext, pattern, type, config, accum, acceptable) {
69
72
  super(wikitext, config, accum, acceptable);
70
73
  this.#type = type;
@@ -22,11 +22,6 @@ export declare abstract class TableBaseToken extends Token {
22
22
  */
23
23
  constructor(pattern: RegExp, syntax: string, type: TableTypes, attr?: string, config?: Parser.Config, accum?: Token[], acceptable?: Acceptable);
24
24
  cloneNode(): this;
25
- /**
26
- * Escape the table syntax
27
- *
28
- * 转义表格语法
29
- */
30
25
  escape(): void;
31
26
  }
32
27
  export {};
@@ -39,9 +39,7 @@ class TableBaseToken extends (0, attributesParent_1.attributesParent)(1)(index_2
39
39
  */
40
40
  constructor(pattern, syntax, type, attr, config = index_1.default.getConfig(), accum = [], acceptable) {
41
41
  super(undefined, config, accum, acceptable);
42
- this.append(new syntax_1.SyntaxToken(syntax, pattern, 'table-syntax', config, accum, {
43
- 'Stage-1': ':', '!ExtToken': '', TranscludeToken: ':',
44
- }),
42
+ this.append(new syntax_1.SyntaxToken(syntax, pattern, 'table-syntax', config, accum, { 'Stage-1': ':', '!ExtToken': '', TranscludeToken: ':' }),
45
43
  // @ts-expect-error abstract class
46
44
  new attributes_1.AttributesToken(attr, 'table-attrs', type, config, accum));
47
45
  /* NOT FOR BROWSER */
@@ -63,17 +61,12 @@ class TableBaseToken extends (0, attributesParent_1.attributesParent)(1)(index_2
63
61
  return token;
64
62
  });
65
63
  }
66
- /**
67
- * Escape the table syntax
68
- *
69
- * 转义表格语法
70
- */
71
64
  escape() {
72
65
  for (const child of this.childNodes) {
73
66
  if (child instanceof syntax_1.SyntaxToken) {
74
67
  escapeTable(child);
75
68
  }
76
- else if (child instanceof TableBaseToken) {
69
+ else {
77
70
  child.escape();
78
71
  }
79
72
  }
@@ -130,9 +130,12 @@ class TableToken extends trBase_1.TrBaseToken {
130
130
  * @param halfParsed
131
131
  */
132
132
  close(syntax = '\n|}', halfParsed) {
133
- const config = this.getAttribute('config'), accum = this.getAttribute('accum'), inner = halfParsed
134
- ? [syntax]
135
- : index_1.default.parse(syntax, this.getAttribute('include'), 2, config).childNodes;
133
+ const config = this.getAttribute('config'), accum = this.getAttribute('accum'),
134
+ /* eslint-disable unicorn/no-negated-condition, @stylistic/operator-linebreak */
135
+ inner = !halfParsed ?
136
+ index_1.default.parse(syntax, this.getAttribute('include'), 2, config).childNodes :
137
+ [syntax];
138
+ /* eslint-enable unicorn/no-negated-condition, @stylistic/operator-linebreak */
136
139
  if (this.lastChild.type !== 'table-syntax') {
137
140
  debug_1.Shadow.run(() => {
138
141
  const token = new syntax_1.SyntaxToken(undefined, closingPattern, 'table-syntax', config, accum, { 'Stage-1': ':', '!ExtToken': '', TranscludeToken: ':' });
@@ -67,6 +67,7 @@ export declare abstract class TdToken extends TableBaseToken {
67
67
  */
68
68
  setAttr<T extends string>(key: T, value: TdAttrSetter<T>): void;
69
69
  setAttr(prop: Record<string, string | number | boolean>): void;
70
+ escape(): void;
70
71
  }
71
72
  /**
72
73
  * 创建新的单元格
@@ -260,8 +260,8 @@ let TdToken = (() => {
260
260
  }
261
261
  /** @private */
262
262
  json(_, start = this.getAbsoluteIndex()) {
263
- const json = super.json(undefined, start);
264
- Object.assign(json, { subtype: this.subtype, rowspan: this.rowspan, colspan: this.colspan });
263
+ const json = super.json(undefined, start), { rowspan, colspan } = this;
264
+ Object.assign(json, { subtype: this.subtype }, rowspan !== 1 && { rowspan }, colspan !== 1 && { colspan });
265
265
  return json;
266
266
  }
267
267
  /* NOT FOR BROWSER */
@@ -335,7 +335,6 @@ let TdToken = (() => {
335
335
  this.#innerSyntax = '';
336
336
  }
337
337
  }
338
- /** @private */
339
338
  escape() {
340
339
  super.escape();
341
340
  if (this.childNodes[1].toString()) {
@@ -9,6 +9,7 @@ const debug_1 = require("../../util/debug");
9
9
  const constants_1 = require("../../util/constants");
10
10
  const html_1 = require("../../util/html");
11
11
  const index_1 = require("../index");
12
+ const tableTags = new Set(['tr', 'td', 'th', 'caption']);
12
13
  /**
13
14
  * table row or table
14
15
  *
@@ -24,7 +25,8 @@ class TrBaseToken extends base_1.TableBaseToken {
24
25
  const first = inter.childNodes.find(child => child.text().trim()), tdPattern = /^\s*(?:!|\{\{\s*![!-]?\s*\}\})/u;
25
26
  if (!first
26
27
  || tdPattern.test(first.toString())
27
- || first.is('arg') && tdPattern.test(first.default || '')) {
28
+ || first.is('arg') && tdPattern.test(first.default || '')
29
+ || first.is('html') && tableTags.has(first.name)) {
28
30
  return errors;
29
31
  }
30
32
  else if (first.is('magic-word')) {