wikilint 2.11.1 → 2.12.4

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 (48) hide show
  1. package/config/.schema.json +24 -7
  2. package/config/default.json +34 -30
  3. package/config/enwiki.json +19 -15
  4. package/config/llwiki.json +21 -20
  5. package/config/minimum.json +4 -1
  6. package/config/moegirl.json +21 -20
  7. package/config/zhwiki.json +32 -28
  8. package/dist/base.d.ts +1 -1
  9. package/dist/index.js +16 -1
  10. package/dist/lib/element.js +4 -4
  11. package/dist/lib/text.js +1 -0
  12. package/dist/lib/title.d.ts +6 -2
  13. package/dist/lib/title.js +30 -13
  14. package/dist/parser/braces.js +4 -4
  15. package/dist/parser/commentAndExt.js +6 -3
  16. package/dist/parser/converter.js +1 -1
  17. package/dist/parser/hrAndDoubleUnderscore.js +6 -6
  18. package/dist/parser/list.js +1 -1
  19. package/dist/parser/magicLinks.js +2 -1
  20. package/dist/parser/redirect.js +1 -1
  21. package/dist/parser/table.js +1 -1
  22. package/dist/src/arg.js +4 -4
  23. package/dist/src/attribute.js +2 -2
  24. package/dist/src/attributes.d.ts +2 -1
  25. package/dist/src/attributes.js +4 -5
  26. package/dist/src/converterFlags.js +3 -3
  27. package/dist/src/extLink.js +1 -1
  28. package/dist/src/gallery.js +2 -2
  29. package/dist/src/heading.d.ts +2 -0
  30. package/dist/src/heading.js +3 -3
  31. package/dist/src/html.js +1 -1
  32. package/dist/src/imagemap.js +1 -1
  33. package/dist/src/imagemapLink.d.ts +3 -1
  34. package/dist/src/index.js +30 -17
  35. package/dist/src/magicLink.js +7 -5
  36. package/dist/src/nested.js +2 -2
  37. package/dist/src/nowiki/doubleUnderscore.d.ts +2 -2
  38. package/dist/src/nowiki/doubleUnderscore.js +2 -1
  39. package/dist/src/parameter.js +2 -1
  40. package/dist/src/pre.js +1 -1
  41. package/dist/src/table/index.js +2 -3
  42. package/dist/src/table/td.js +1 -1
  43. package/dist/src/tagPair/ext.js +19 -25
  44. package/dist/src/transclude.js +4 -5
  45. package/dist/util/string.js +7 -7
  46. package/i18n/zh-hans.json +1 -0
  47. package/i18n/zh-hant.json +1 -0
  48. package/package.json +2 -2
@@ -15,19 +15,19 @@ const parseHrAndDoubleUnderscore = ({ firstChild: { data }, type, name }, config
15
15
  if (type !== 'root' && (type !== 'ext-inner' || name !== 'poem')) {
16
16
  data = `\0${data}`;
17
17
  }
18
- data = data.replace(/^((?:\0\d+c\x7F)*)(-{4,})/gmu, (_, lead, m) => {
18
+ data = data.replace(/^((?:\0\d+[cno]\x7F)*)(-{4,})/gmu, (_, lead, m) => {
19
19
  // @ts-expect-error abstract class
20
20
  new hr_1.HrToken(m, config, accum);
21
21
  return `${lead}\0${accum.length - 1}r\x7F`;
22
- }).replace(new RegExp(`__(${[...doubleUnderscore[0], ...doubleUnderscore[1]].join('|')})__`, 'giu'), (m, p1) => {
23
- const caseSensitive = sensitive.has(p1);
24
- if (caseSensitive || insensitive.has(p1.toLowerCase())) {
22
+ }).replace(new RegExp(`__(${[...insensitive, ...sensitive].join('|')})__`, 'giu'), (m, p1) => {
23
+ const caseSensitive = sensitive.has(p1), lc = p1.toLowerCase(), caseInsensitive = insensitive.has(lc);
24
+ if (caseSensitive || caseInsensitive) {
25
25
  // @ts-expect-error abstract class
26
26
  new doubleUnderscore_1.DoubleUnderscoreToken(p1, caseSensitive, config, accum);
27
- return `\0${accum.length - 1}u\x7F`;
27
+ return `\0${accum.length - 1}${caseInsensitive && (doubleUnderscore[2]?.[lc] ?? lc) === 'toc' ? 'u' : 'n'}\x7F`;
28
28
  }
29
29
  return m;
30
- }).replace(/^((?:\0\d+c\x7F)*)(={1,6})(.+)\2((?:[^\S\n]|\0\d+c\x7F)*)$/gmu, (_, lead, equals, heading, trail) => {
30
+ }).replace(/^((?:\0\d+[cn]\x7F)*)(={1,6})(.+)\2((?:\s|\0\d+[cn]\x7F)*)$/gmu, (_, lead, equals, heading, trail) => {
31
31
  const text = `${lead}\0${accum.length}h\x7F`;
32
32
  // @ts-expect-error abstract class
33
33
  new heading_1.HeadingToken(equals.length, [heading, trail], config, accum);
@@ -13,7 +13,7 @@ const dd_1 = require("../src/nowiki/dd");
13
13
  * @param accum
14
14
  */
15
15
  const parseList = (wikitext, state, config, accum) => {
16
- const mt = /^((?:\0\d+c\x7F)*)([;:*#]+\s*)/u.exec(wikitext);
16
+ const mt = /^((?:\0\d+[cno]\x7F)*)([;:*#]+\s*)/u.exec(wikitext);
17
17
  if (!mt) {
18
18
  state.lastPrefix = '';
19
19
  return wikitext;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseMagicLinks = void 0;
4
4
  const string_1 = require("../util/string");
5
5
  const magicLink_1 = require("../src/magicLink");
6
+ const space = String.raw `[\p{Zs}\t]| |&#0*160;|&#x0*a0;`, sp = `(?:${space})+`, spdash = `(?:${space}|-)`, magicLinkPattern = String.raw `(?:RFC|PMID)${sp}\d+\b|ISBN${sp}(?:97[89]${spdash}?)?(?:\d${spdash}?){9}[\dx]\b`;
6
7
  /**
7
8
  * 解析自由外链
8
9
  * @param wikitext
@@ -10,7 +11,7 @@ const magicLink_1 = require("../src/magicLink");
10
11
  * @param accum
11
12
  */
12
13
  const parseMagicLinks = (wikitext, config, accum) => {
13
- const space = String.raw `[\p{Zs}\t]| |&#0*160;|&#x0*a0;`, spdash = `(?:${space}|-)`, regex = new RegExp(String.raw `(^|[^\p{L}\d_])(?:(?:${config.protocol})(${string_1.extUrlCharFirst}${string_1.extUrlChar})|(?:RFC|PMID)(?:${space})+\d+\b|ISBN(?:${space})+(?:97[89]${spdash}?)?(?:\d${spdash}?){9}[\dx]\b)`, 'giu');
14
+ const regex = new RegExp(String.raw `(^|[^\p{L}\d_])(?:(?:${config.protocol})(${string_1.extUrlCharFirst}${string_1.extUrlChar})|${magicLinkPattern})`, 'giu');
14
15
  return wikitext.replace(regex, (m, lead, p1) => {
15
16
  let url = lead ? m.slice(lead.length) : m;
16
17
  if (p1) {
@@ -12,7 +12,7 @@ const redirect_1 = require("../src/redirect");
12
12
  const parseRedirect = (text, config, accum) => {
13
13
  const re = new RegExp(String.raw `^(\s*)((?:${config.redirection.join('|')})\s*(?::\s*)?)\[\[([^\n|\]]+)(\|.*?)?\]\](\s*)`, 'iu'), mt = re.exec(text);
14
14
  if (mt && index_1.default.normalizeTitle(mt[3], 0, false, config, true, true).valid) {
15
- text = `\0${accum.length}c\x7F${text.slice(mt[0].length)}`;
15
+ text = `\0${accum.length}o\x7F${text.slice(mt[0].length)}`;
16
16
  // @ts-expect-error abstract class
17
17
  new redirect_1.RedirectToken(...mt.slice(1), config, accum);
18
18
  return text;
@@ -47,7 +47,7 @@ const parseTable = ({ firstChild: { data }, type, name }, config, accum) => {
47
47
  pop = () => top.type === 'td' ? stack.pop() : top;
48
48
  for (const outLine of lines) {
49
49
  top = stack.pop();
50
- const [spaces] = /^(?:\s|\0\d+c\x7F)*/u.exec(outLine), line = outLine.slice(spaces.length), matchesStart = /^(:*)((?:\s|\0\d+c\x7F)*)(\{\||\{(?:\0\d+c\x7F)*\0\d+!\x7F|\0\d+\{\x7F)(.*)$/u
50
+ const [spaces] = /^(?:\s|\0\d+[cno]\x7F)*/u.exec(outLine), line = outLine.slice(spaces.length), matchesStart = /^(:*)((?:\s|\0\d+[cn]\x7F)*)(\{\||\{(?:\0\d+[cn]\x7F)*\0\d+!\x7F|\0\d+\{\x7F)(.*)$/u
51
51
  .exec(line);
52
52
  if (matchesStart) {
53
53
  while (top && top.type !== 'td') {
package/dist/src/arg.js CHANGED
@@ -23,17 +23,17 @@ class ArgToken extends index_2.Token {
23
23
  /** @param parts 以'|'分隔的各部分 */
24
24
  constructor(parts, config = index_1.default.getConfig(), accum = []) {
25
25
  super(undefined, config, accum, {});
26
- for (let i = 0; i < parts.length; i++) {
26
+ for (const [i, part] of parts.entries()) {
27
27
  if (i === 0) {
28
- const token = new atom_1.AtomToken(parts[i], 'arg-name', config, accum, {});
28
+ const token = new atom_1.AtomToken(part, 'arg-name', config, accum, {});
29
29
  super.insertAt(token);
30
30
  }
31
31
  else if (i > 1) {
32
- const token = new hidden_1.HiddenToken(parts[i], config, accum);
32
+ const token = new hidden_1.HiddenToken(part, config, accum);
33
33
  super.insertAt(token);
34
34
  }
35
35
  else {
36
- const token = new index_2.Token(parts[i], config, accum);
36
+ const token = new index_2.Token(part, config, accum);
37
37
  token.type = 'arg-default';
38
38
  token.setAttribute('stage', 2);
39
39
  super.insertAt(token);
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AttributeToken = void 0;
4
4
  const lint_1 = require("../util/lint");
5
- const rect_1 = require("../lib/rect");
6
5
  const string_1 = require("../util/string");
7
6
  const constants_1 = require("../util/constants");
7
+ const rect_1 = require("../lib/rect");
8
8
  const index_1 = require("../index");
9
9
  const index_2 = require("./index");
10
10
  const atom_1 = require("./atom");
@@ -270,7 +270,7 @@ class AttributeToken extends index_2.Token {
270
270
  if (attrs && !attrs.has(name)
271
271
  || (type === 'ext-attr' ? tag in htmlAttrs : !/\{\{[^{]+\}\}/u.test(name))
272
272
  && !htmlAttrs[tag]?.has(name)
273
- && !/^(?:xmlns:[\w:.-]+|data-[^:]*)$/u.test(name)
273
+ && !/^(?:xmlns:[\w:.-]+|data-(?!ooui|mw|parsoid)[^:]*)$/u.test(name)
274
274
  && (tag === 'meta' || tag === 'link' || !commonHtmlAttrs.has(name))) {
275
275
  errors.push((0, lint_1.generateForChild)(firstChild, rect, 'illegal-attr', 'illegal attribute name'));
276
276
  }
@@ -3,7 +3,7 @@ import { Token } from './index';
3
3
  import { AtomToken } from './atom';
4
4
  import { AttributeToken } from './attribute';
5
5
  import type { LintError } from '../base';
6
- import type { ExtToken, HtmlToken, TdToken, TrToken, TableToken } from '../internal';
6
+ import type { ExtToken, HtmlToken, TdToken, TrToken, TableToken, SyntaxToken } from '../internal';
7
7
  import type { AttributeTypes } from './attribute';
8
8
  declare type AttributesTypes = `${AttributeTypes}s`;
9
9
  /**
@@ -17,6 +17,7 @@ export declare abstract class AttributesToken extends Token {
17
17
  abstract get firstChild(): AtomToken | AttributeToken | undefined;
18
18
  abstract get lastChild(): AtomToken | AttributeToken | undefined;
19
19
  abstract get parentNode(): ExtToken | HtmlToken | TableToken | TrToken | TdToken | undefined;
20
+ abstract get previousSibling(): SyntaxToken | undefined;
20
21
  get type(): AttributesTypes;
21
22
  /**
22
23
  * @param attr 标签属性
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AttributesToken = void 0;
4
4
  const lint_1 = require("../util/lint");
5
- const rect_1 = require("../lib/rect");
6
5
  const string_1 = require("../util/string");
6
+ const rect_1 = require("../lib/rect");
7
7
  const index_1 = require("../index");
8
8
  const index_2 = require("./index");
9
9
  const atom_1 = require("./atom");
@@ -37,7 +37,7 @@ class AttributesToken extends index_2.Token {
37
37
  this.#type = type;
38
38
  this.setAttribute('name', name);
39
39
  if (attr) {
40
- const regex = /([^\s/](?:(?!\0\d+~\x7F)[^\s/=])*)(?:((?:\s(?:\s|\0\d+c\x7F)*)?(?:=|\0\d+~\x7F)(?:\s|\0\d+c\x7F)*)(?:(["'])(.*?)(\3|$)|(\S*)))?/gsu;
40
+ const regex = /([^\s/](?:(?!\0\d+~\x7F)[^\s/=])*)(?:((?:\s(?:\s|\0\d+[cn]\x7F)*)?(?:=|\0\d+~\x7F)(?:\s|\0\d+[cn]\x7F)*)(?:(["'])(.*?)(\3|$)|(\S*)))?/gsu;
41
41
  let out = '', mt = regex.exec(attr), lastIndex = 0;
42
42
  const insertDirty = /** 插入无效属性 */ () => {
43
43
  if (out) {
@@ -97,14 +97,13 @@ class AttributesToken extends index_2.Token {
97
97
  }
98
98
  /** @private */
99
99
  lint(start = this.getAbsoluteIndex(), re) {
100
- const errors = super.lint(start, re), { parentNode, length, childNodes } = this, attrs = new Map(), duplicated = new Set(), rect = new rect_1.BoundingRect(this, start);
100
+ const errors = super.lint(start, re), { parentNode, childNodes } = this, attrs = new Map(), duplicated = new Set(), rect = new rect_1.BoundingRect(this, start);
101
101
  if (parentNode?.type === 'html' && parentNode.closing && this.text().trim()) {
102
102
  const e = (0, lint_1.generateForSelf)(this, rect, 'no-ignored', 'attributes of a closing tag');
103
103
  e.fix = { range: [start, e.endIndex], text: '' };
104
104
  errors.push(e);
105
105
  }
106
- for (let i = 0; i < length; i++) {
107
- const attr = childNodes[i];
106
+ for (const attr of childNodes) {
108
107
  if (attr instanceof atom_1.AtomToken && attr.text().trim()) {
109
108
  const e = (0, lint_1.generateForChild)(attr, rect, 'no-ignored', 'containing invalid attribute');
110
109
  e.suggestions = [
@@ -53,9 +53,9 @@ class ConverterFlagsToken extends index_2.Token {
53
53
  if (variantFlags.size === knownFlagCount || validFlags.size === knownFlagCount) {
54
54
  return errors;
55
55
  }
56
- const rect = new rect_1.BoundingRect(this, start), { childNodes, length } = this;
57
- for (let i = 0; i < length; i++) {
58
- const child = childNodes[i], flag = child.text().trim();
56
+ const rect = new rect_1.BoundingRect(this, start);
57
+ for (const [i, child] of this.childNodes.entries()) {
58
+ const flag = child.text().trim();
59
59
  if (flag
60
60
  && !variantFlags.has(flag)
61
61
  && !unknownFlags.has(flag)
@@ -22,7 +22,7 @@ class ExtLinkToken extends index_2.Token {
22
22
  */
23
23
  constructor(url, space = '', text = '', config = index_1.default.getConfig(), accum = []) {
24
24
  super(undefined, config, accum, {});
25
- const link = url && /\0\d+f\x7F/u.test(url)
25
+ const link = url && /^\0\d+f\x7F$/u.test(url)
26
26
  ? accum[Number(url.slice(1, -2))]
27
27
  // @ts-expect-error abstract class
28
28
  : new magicLink_1.MagicLinkToken(url, 'ext-link-url', config, accum);
@@ -56,8 +56,8 @@ class GalleryToken extends index_2.Token {
56
56
  /** @private */
57
57
  lint(start = this.getAbsoluteIndex(), re) {
58
58
  const { top, left } = this.getRootNode().posFromIndex(start), errors = [];
59
- for (let i = 0; i < this.length; i++) {
60
- const child = this.childNodes[i], str = child.toString(), { length } = str, trimmed = str.trim(), startLine = top + i, startCol = i ? 0 : left;
59
+ for (const [i, child] of this.childNodes.entries()) {
60
+ const str = child.toString(), { length } = str, trimmed = str.trim(), startLine = top + i, startCol = i ? 0 : left;
61
61
  if (child.type === 'noinclude' && trimmed && !/^<!--.*-->$/u.test(trimmed)) {
62
62
  const endIndex = start + length;
63
63
  errors.push({
@@ -2,6 +2,7 @@ import Parser from '../index';
2
2
  import { Token } from './index';
3
3
  import { SyntaxToken } from './syntax';
4
4
  import type { LintError } from '../base';
5
+ import type { AstText } from '../internal';
5
6
  /**
6
7
  * 章节标题
7
8
  * @classdesc `{childNodes: [Token, SyntaxToken]}`
@@ -11,6 +12,7 @@ export declare abstract class HeadingToken extends Token {
11
12
  readonly childNodes: readonly [Token, SyntaxToken];
12
13
  abstract get firstChild(): Token;
13
14
  abstract get lastChild(): SyntaxToken;
15
+ abstract get nextSibling(): AstText | undefined;
14
16
  get type(): 'heading';
15
17
  /** 标题层级 */
16
18
  get level(): number;
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.HeadingToken = void 0;
4
4
  const lint_1 = require("../util/lint");
5
- const rect_1 = require("../lib/rect");
6
5
  const debug_1 = require("../util/debug");
6
+ const rect_1 = require("../lib/rect");
7
7
  const index_1 = require("../index");
8
8
  const index_2 = require("./index");
9
9
  const syntax_1 = require("./syntax");
@@ -34,7 +34,7 @@ class HeadingToken extends index_2.Token {
34
34
  const token = new index_2.Token(input[0], config, accum);
35
35
  token.type = 'heading-title';
36
36
  token.setAttribute('stage', 2);
37
- const trail = new syntax_1.SyntaxToken(input[1], /^[^\S\n]*$/u, 'heading-trail', config, accum, {});
37
+ const trail = new syntax_1.SyntaxToken(input[1], /^\s*$/u, 'heading-trail', config, accum, {});
38
38
  this.append(token, trail);
39
39
  }
40
40
  /** @private */
@@ -64,7 +64,7 @@ class HeadingToken extends index_2.Token {
64
64
  if (innerStr.startsWith('=') || innerStr.endsWith('=')) {
65
65
  errors.push((0, lint_1.generateForChild)(firstChild, rect, 'unbalanced-header', index_1.default.msg('unbalanced $1 in a section header', '"="')));
66
66
  }
67
- if (this.closest('html-attrs, table-attrs')) {
67
+ if (this.closest('html-attrs,table-attrs')) {
68
68
  errors.push((0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'section header in a HTML tag'));
69
69
  }
70
70
  if (boldQuotes.length % 2) {
package/dist/src/html.js CHANGED
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.HtmlToken = void 0;
4
4
  const lint_1 = require("../util/lint");
5
- const rect_1 = require("../lib/rect");
6
5
  const string_1 = require("../util/string");
6
+ const rect_1 = require("../lib/rect");
7
7
  const index_1 = require("./index");
8
8
  const magicWords = new Set(['if', 'ifeq', 'ifexpr', 'ifexist', 'iferror', 'switch']), formattingTags = new Set([
9
9
  'b',
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ImagemapToken = void 0;
4
4
  const lint_1 = require("../util/lint");
5
- const rect_1 = require("../lib/rect");
6
5
  const debug_1 = require("../util/debug");
6
+ const rect_1 = require("../lib/rect");
7
7
  const index_1 = require("../index");
8
8
  const index_2 = require("./index");
9
9
  const noinclude_1 = require("./nowiki/noinclude");
@@ -3,7 +3,7 @@ import { Token } from './index';
3
3
  import { NoincludeToken } from './nowiki/noinclude';
4
4
  import { LinkToken } from './link/index';
5
5
  import { ExtLinkToken } from './extLink';
6
- import type { AstText, ImagemapToken } from '../internal';
6
+ import type { AstText, ImagemapToken, GalleryImageToken } from '../internal';
7
7
  /**
8
8
  * `<imagemap>`内的链接
9
9
  * @classdesc `{childNodes: [AstText, LinkToken|ExtLinkToken, NoincludeToken]}`
@@ -13,6 +13,8 @@ export declare abstract class ImagemapLinkToken extends Token {
13
13
  abstract get firstChild(): AstText;
14
14
  abstract get lastChild(): NoincludeToken;
15
15
  abstract get parentNode(): ImagemapToken | undefined;
16
+ abstract get previousSibling(): GalleryImageToken | this | NoincludeToken | AstText;
17
+ abstract get nextSibling(): this | NoincludeToken | AstText | undefined;
16
18
  get type(): 'imagemap-link';
17
19
  /**
18
20
  * @param pre 链接前的文本
package/dist/src/index.js CHANGED
@@ -23,7 +23,7 @@
23
23
  // ~: `{{=}}`专用
24
24
  // a: AttributeToken
25
25
  // b: TableToken
26
- // c: CommentToken、NoIncludeToken和IncludeToken
26
+ // c: CommentToke
27
27
  // d: ListToken
28
28
  // e: ExtToken
29
29
  // f: MagicLinkToken inside ImageParameterToken
@@ -31,11 +31,13 @@
31
31
  // i: RFC/PMID/ISBN
32
32
  // l: LinkToken
33
33
  // m: `{{fullurl:}}`、`{{canonicalurl:}}`或`{{filepath:}}`
34
+ // n: NoIncludeToken和IncludeToken
35
+ // o: RedirectToken
34
36
  // q: QuoteToken
35
37
  // r: HrToken
36
38
  // s: `{{{|subst:}}}`
37
39
  // t: ArgToken或TranscludeToken
38
- // u: DoubleUnderscoreToken
40
+ // u: `__toc__`
39
41
  // v: ConverterToken
40
42
  // w: ExtLinkToken
41
43
  // x: HtmlToken
@@ -157,7 +159,7 @@ class Token extends element_1.AstElement {
157
159
  /** @private */
158
160
  build() {
159
161
  this.#stage = constants_1.MAX_STAGE;
160
- const { length, firstChild } = this, str = String(firstChild);
162
+ const { length, firstChild } = this, str = firstChild?.toString();
161
163
  if (length === 1 && firstChild.type === 'text' && str.includes('\0')) {
162
164
  this.replaceChildren(...this.buildFromStr(str));
163
165
  this.normalize();
@@ -335,27 +337,38 @@ class Token extends element_1.AstElement {
335
337
  lint(start = this.getAbsoluteIndex(), re) {
336
338
  let errors = super.lint(start, re);
337
339
  if (this.type === 'root') {
338
- const record = {};
339
- for (const cat of this.querySelectorAll('category')) {
340
- const thisCat = record[cat.name];
340
+ const record = {}, selector = 'category,html-attr#id,ext-attr#id,table-attr#id';
341
+ for (const cat of this.querySelectorAll(selector)) {
342
+ let key;
343
+ if (cat.type === 'category') {
344
+ key = cat.name;
345
+ }
346
+ else {
347
+ const value = cat.getValue();
348
+ key = `#${value === true ? '' : value}`;
349
+ }
350
+ const thisCat = record[key];
341
351
  if (thisCat) {
342
352
  thisCat.add(cat);
343
353
  }
344
354
  else {
345
- record[cat.name] = new Set([cat]);
355
+ record[key] = new Set([cat]);
346
356
  }
347
357
  }
348
- for (const value of Object.values(record)) {
349
- if (value.size > 1) {
358
+ for (const [key, value] of Object.entries(record)) {
359
+ if (value.size > 1 && !key.startsWith('#mw-customcollapsible-')) {
360
+ const isCat = !key.startsWith('#'), msg = `duplicated ${isCat ? 'category' : 'id'}`, severity = isCat ? 'error' : 'warning';
350
361
  errors.push(...[...value].map(cat => {
351
- const e = (0, lint_1.generateForSelf)(cat, { start: cat.getAbsoluteIndex() }, 'no-duplicate', 'duplicated category');
352
- e.suggestions = [
353
- {
354
- desc: 'remove',
355
- range: [e.startIndex, e.endIndex],
356
- text: '',
357
- },
358
- ];
362
+ const e = (0, lint_1.generateForSelf)(cat, { start: cat.getAbsoluteIndex() }, 'no-duplicate', msg, severity);
363
+ if (isCat) {
364
+ e.suggestions = [
365
+ {
366
+ desc: 'remove',
367
+ range: [e.startIndex, e.endIndex],
368
+ text: '',
369
+ },
370
+ ];
371
+ }
359
372
  return e;
360
373
  }));
361
374
  }
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MagicLinkToken = void 0;
4
4
  const lint_1 = require("../util/lint");
5
- const rect_1 = require("../lib/rect");
6
5
  const string_1 = require("../util/string");
6
+ const rect_1 = require("../lib/rect");
7
7
  const index_1 = require("../index");
8
8
  const index_2 = require("./index");
9
9
  const space = String.raw `(?:[\p{Zs}\t]|&nbsp;|&#0*160;|&#[xX]0*[aA]0;)`, spaceRegex = new RegExp(`${space}+`, 'gu');
@@ -30,11 +30,13 @@ class MagicLinkToken extends index_2.Token {
30
30
  }
31
31
  /** 和内链保持一致 */
32
32
  get link() {
33
- let { innerText } = this;
34
- if (this.type === 'magic-link' && innerText.startsWith('ISBN')) {
35
- innerText = `ISBN ${innerText.slice(5).replace(/[- ]/gu, '').replace(/x$/u, 'X')}`;
33
+ const { innerText } = this;
34
+ if (this.type === 'magic-link') {
35
+ return innerText.startsWith('ISBN')
36
+ ? `ISBN ${innerText.slice(5).replace(/[- ]/gu, '').replace(/x$/u, 'X')}`
37
+ : innerText;
36
38
  }
37
- return innerText;
39
+ return (0, string_1.decodeNumber)(innerText);
38
40
  }
39
41
  /**
40
42
  * @param url 网址
@@ -33,10 +33,10 @@ class NestedToken extends index_2.Token {
33
33
  new comment_1.CommentToken(comment.slice(4, closed ? -3 : undefined), closed, config, accum);
34
34
  }
35
35
  return str;
36
- }).replace(/(^|\0\d+[ce]\x7F)([^\0]+)(?=$|\0\d+[ce]\x7F)/gu, (_, lead, substr) => {
36
+ }).replace(/(^|\0\d+[cne]\x7F)([^\0]+)(?=$|\0\d+[cne]\x7F)/gu, (_, lead, substr) => {
37
37
  // @ts-expect-error abstract class
38
38
  new noinclude_1.NoincludeToken(substr, config, accum);
39
- return `${lead}\0${accum.length}c\x7F`;
39
+ return `${lead}\0${accum.length}n\x7F`;
40
40
  });
41
41
  super(wikitext, config, accum, {});
42
42
  }
@@ -1,5 +1,5 @@
1
+ import Parser from '../../index';
1
2
  import { NowikiBaseToken } from './base';
2
- import type { Config } from '../../base';
3
3
  import type { Token } from '../index';
4
4
  /** 状态开关 */
5
5
  export declare abstract class DoubleUnderscoreToken extends NowikiBaseToken {
@@ -8,5 +8,5 @@ export declare abstract class DoubleUnderscoreToken extends NowikiBaseToken {
8
8
  * @param word 状态开关名
9
9
  * @param sensitive 是否固定大小写
10
10
  */
11
- constructor(word: string, sensitive: boolean, config?: Config, accum?: Token[]);
11
+ constructor(word: string, sensitive: boolean, config?: Parser.Config, accum?: Token[]);
12
12
  }
@@ -36,6 +36,7 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
37
  exports.DoubleUnderscoreToken = void 0;
38
38
  const hidden_1 = require("../../mixin/hidden");
39
+ const index_1 = require("../../index");
39
40
  const base_1 = require("./base");
40
41
  /** 状态开关 */
41
42
  let DoubleUnderscoreToken = (() => {
@@ -60,7 +61,7 @@ let DoubleUnderscoreToken = (() => {
60
61
  * @param word 状态开关名
61
62
  * @param sensitive 是否固定大小写
62
63
  */
63
- constructor(word, sensitive, config, accum) {
64
+ constructor(word, sensitive, config = index_1.default.getConfig(), accum) {
64
65
  super(word, config, accum);
65
66
  }
66
67
  /** @private */
@@ -33,7 +33,8 @@ class ParameterToken extends index_2.Token {
33
33
  }
34
34
  /** @private */
35
35
  trimName(name, set = true) {
36
- const trimmed = (0, string_1.trimPHP)(typeof name === 'string' ? name : name.toString(true));
36
+ const trimmed = (typeof name === 'string' ? name : name.toString(true))
37
+ .replace(/^[ \t\n\0\v]+|([^ \t\n\0\v])[ \t\n\0\v]+$/gu, '$1');
37
38
  this.setAttribute('name', trimmed);
38
39
  return trimmed;
39
40
  }
package/dist/src/pre.js CHANGED
@@ -23,7 +23,7 @@ class PreToken extends index_2.Token {
23
23
  new noinclude_1.NoincludeToken(opening, config, accum);
24
24
  // @ts-expect-error abstract class
25
25
  new noinclude_1.NoincludeToken(closing, config, accum);
26
- str += `${wikitext.slice(0, i)}\0${accum.length - 1}c\x7F${wikitext.slice(i + length, j)}\0${accum.length}c\x7F`;
26
+ str += `${wikitext.slice(0, i)}\0${accum.length - 1}n\x7F${wikitext.slice(i + length, j)}\0${accum.length}n\x7F`;
27
27
  wikitext = wikitext.slice(j + length + 1);
28
28
  i = wikitext.indexOf(opening);
29
29
  j = wikitext.indexOf(closing, i + length);
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TableToken = exports.Layout = exports.isRowEnd = void 0;
4
4
  const lint_1 = require("../../util/lint");
5
- const rect_1 = require("../../lib/rect");
6
5
  const debug_1 = require("../../util/debug");
6
+ const rect_1 = require("../../lib/rect");
7
7
  const index_1 = require("../../index");
8
8
  const trBase_1 = require("./trBase");
9
9
  const syntax_1 = require("../syntax");
@@ -91,8 +91,7 @@ class TableToken extends trBase_1.TrBaseToken {
91
91
  */
92
92
  getLayout(stop) {
93
93
  const rows = this.getAllRows(), { length } = rows, layout = new Layout(...(0, debug_1.emptyArray)(length, () => []));
94
- for (let i = 0; i < length; i++) {
95
- const rowLayout = layout[i];
94
+ for (const [i, rowLayout] of layout.entries()) {
96
95
  let j = 0, k = 0, last;
97
96
  for (const cell of rows[i].childNodes.slice(2)) {
98
97
  if (cell.type === 'td') {
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TdToken = void 0;
4
4
  const lint_1 = require("../../util/lint");
5
- const rect_1 = require("../../lib/rect");
6
5
  const constants_1 = require("../../util/constants");
7
6
  const debug_1 = require("../../util/debug");
7
+ const rect_1 = require("../../lib/rect");
8
8
  const index_1 = require("../../index");
9
9
  const index_2 = require("../index");
10
10
  const base_1 = require("./base");
@@ -7,6 +7,12 @@ const index_1 = require("../../index");
7
7
  const index_2 = require("../index");
8
8
  const index_3 = require("./index");
9
9
  const attributes_1 = require("../attributes");
10
+ const pre_1 = require("../pre");
11
+ const index_4 = require("../paramTag/index");
12
+ const inputbox_1 = require("../paramTag/inputbox");
13
+ const gallery_1 = require("../gallery");
14
+ const imagemap_1 = require("../imagemap");
15
+ const index_5 = require("../nowiki/index");
10
16
  /**
11
17
  * 从数组中删除指定元素
12
18
  * @param arr 数组
@@ -53,25 +59,19 @@ class ExtToken extends index_3.TagPairToken {
53
59
  }
54
60
  innerToken = new index_2.Token(inner, newConfig, accum);
55
61
  break;
56
- case 'pre': {
57
- const { PreToken } = require('../pre');
62
+ case 'pre':
58
63
  // @ts-expect-error abstract class
59
- innerToken = new PreToken(inner, newConfig, accum);
64
+ innerToken = new pre_1.PreToken(inner, newConfig, accum);
60
65
  break;
61
- }
62
- case 'dynamicpagelist': {
63
- const { ParamTagToken } = require('../paramTag/index');
66
+ case 'dynamicpagelist':
64
67
  // @ts-expect-error abstract class
65
- innerToken = new ParamTagToken(inner, newConfig, accum);
68
+ innerToken = new index_4.ParamTagToken(inner, newConfig, accum);
66
69
  break;
67
- }
68
- case 'inputbox': {
70
+ case 'inputbox':
69
71
  newConfig.excludes.push('heading');
70
- const { InputboxToken } = require('../paramTag/inputbox');
71
72
  // @ts-expect-error abstract class
72
- innerToken = new InputboxToken(inner, newConfig, accum);
73
+ innerToken = new inputbox_1.InputboxToken(inner, newConfig, accum);
73
74
  break;
74
- }
75
75
  case 'references': {
76
76
  const { NestedToken } = require('../nested');
77
77
  // @ts-expect-error abstract class
@@ -90,18 +90,14 @@ class ExtToken extends index_3.TagPairToken {
90
90
  innerToken = new NestedToken(inner, /<(combooption)(\s[^>]*?)?(?:\/>|>(.*?)<\/(combooption\s*)>)/gisu, ['combooption'], newConfig, accum);
91
91
  break;
92
92
  }
93
- case 'gallery': {
94
- const { GalleryToken } = require('../gallery');
93
+ case 'gallery':
95
94
  // @ts-expect-error abstract class
96
- innerToken = new GalleryToken(inner, newConfig, accum);
95
+ innerToken = new gallery_1.GalleryToken(inner, newConfig, accum);
97
96
  break;
98
- }
99
- case 'imagemap': {
100
- const { ImagemapToken } = require('../imagemap');
97
+ case 'imagemap':
101
98
  // @ts-expect-error abstract class
102
- innerToken = new ImagemapToken(inner, newConfig, accum);
99
+ innerToken = new imagemap_1.ImagemapToken(inner, newConfig, accum);
103
100
  break;
104
- }
105
101
  // 更多定制扩展的代码示例:
106
102
  // ```
107
103
  // case 'extensionName': {
@@ -110,11 +106,9 @@ class ExtToken extends index_3.TagPairToken {
110
106
  // break;
111
107
  // }
112
108
  // ```
113
- default: {
114
- const { NowikiToken } = require('../nowiki/index');
109
+ default:
115
110
  // @ts-expect-error abstract class
116
- innerToken = new NowikiToken(inner, newConfig, accum);
117
- }
111
+ innerToken = new index_5.NowikiToken(inner, newConfig, accum);
118
112
  }
119
113
  innerToken.setAttribute('name', lcName);
120
114
  if (innerToken.type === 'plain') {
@@ -126,7 +120,7 @@ class ExtToken extends index_3.TagPairToken {
126
120
  /** @private */
127
121
  lint(start = this.getAbsoluteIndex(), re) {
128
122
  const errors = super.lint(start, re), rect = new rect_1.BoundingRect(this, start);
129
- if (this.name !== 'nowiki' && this.closest('html-attrs, table-attrs')) {
123
+ if (this.name !== 'nowiki' && this.closest('html-attrs,table-attrs')) {
130
124
  errors.push((0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'extension tag in HTML tag attributes'));
131
125
  }
132
126
  if (this.name === 'ref' && this.closest('heading-title')) {