wikilint 2.9.0 → 2.9.2

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 (94) hide show
  1. package/dist/base.d.ts +2 -0
  2. package/dist/index.d.ts +2 -4
  3. package/dist/index.js +6 -6
  4. package/dist/lib/element.d.ts +0 -7
  5. package/dist/lib/element.js +2 -5
  6. package/dist/lib/node.js +1 -4
  7. package/dist/lib/rect.d.ts +18 -0
  8. package/dist/lib/rect.js +32 -0
  9. package/dist/lib/text.js +2 -9
  10. package/dist/mixin/attributesParent.js +2 -1
  11. package/dist/mixin/hidden.d.ts +2 -0
  12. package/dist/mixin/hidden.js +9 -4
  13. package/dist/parser/braces.js +19 -12
  14. package/dist/parser/commentAndExt.js +1 -8
  15. package/dist/parser/converter.js +2 -3
  16. package/dist/parser/externalLinks.js +1 -8
  17. package/dist/parser/hrAndDoubleUnderscore.js +1 -1
  18. package/dist/parser/html.js +1 -1
  19. package/dist/parser/links.js +1 -1
  20. package/dist/parser/magicLinks.js +6 -12
  21. package/dist/parser/redirect.js +1 -1
  22. package/dist/src/arg.d.ts +0 -2
  23. package/dist/src/arg.js +4 -3
  24. package/dist/src/atom.d.ts +2 -2
  25. package/dist/src/atom.js +3 -4
  26. package/dist/src/attribute.d.ts +0 -2
  27. package/dist/src/attribute.js +5 -16
  28. package/dist/src/attributes.js +8 -12
  29. package/dist/src/converter.d.ts +0 -2
  30. package/dist/src/converter.js +1 -1
  31. package/dist/src/converterFlags.d.ts +0 -2
  32. package/dist/src/converterFlags.js +4 -2
  33. package/dist/src/converterRule.d.ts +0 -2
  34. package/dist/src/converterRule.js +1 -1
  35. package/dist/src/extLink.d.ts +0 -2
  36. package/dist/src/extLink.js +1 -1
  37. package/dist/src/gallery.d.ts +0 -2
  38. package/dist/src/gallery.js +1 -1
  39. package/dist/src/heading.d.ts +0 -2
  40. package/dist/src/heading.js +3 -8
  41. package/dist/src/hidden.d.ts +1 -1
  42. package/dist/src/hidden.js +53 -3
  43. package/dist/src/html.d.ts +2 -5
  44. package/dist/src/html.js +14 -34
  45. package/dist/src/imageParameter.d.ts +0 -2
  46. package/dist/src/imageParameter.js +5 -4
  47. package/dist/src/imagemap.d.ts +0 -2
  48. package/dist/src/imagemap.js +4 -3
  49. package/dist/src/index.d.ts +0 -11
  50. package/dist/src/index.js +16 -25
  51. package/dist/src/link/base.d.ts +0 -2
  52. package/dist/src/link/base.js +4 -7
  53. package/dist/src/link/file.js +6 -6
  54. package/dist/src/link/galleryImage.js +1 -0
  55. package/dist/src/link/redirectTarget.d.ts +0 -2
  56. package/dist/src/link/redirectTarget.js +1 -1
  57. package/dist/src/magicLink.js +6 -8
  58. package/dist/src/nested.js +2 -2
  59. package/dist/src/nowiki/base.d.ts +2 -2
  60. package/dist/src/nowiki/base.js +3 -4
  61. package/dist/src/nowiki/comment.d.ts +3 -4
  62. package/dist/src/nowiki/comment.js +78 -28
  63. package/dist/src/nowiki/doubleUnderscore.d.ts +3 -3
  64. package/dist/src/nowiki/doubleUnderscore.js +68 -19
  65. package/dist/src/nowiki/index.js +1 -1
  66. package/dist/src/nowiki/noinclude.d.ts +1 -1
  67. package/dist/src/nowiki/noinclude.js +53 -3
  68. package/dist/src/nowiki/quote.js +18 -24
  69. package/dist/src/paramTag/index.d.ts +0 -2
  70. package/dist/src/paramTag/index.js +3 -3
  71. package/dist/src/parameter.js +3 -1
  72. package/dist/src/redirect.d.ts +4 -1
  73. package/dist/src/redirect.js +83 -33
  74. package/dist/src/syntax.d.ts +2 -2
  75. package/dist/src/syntax.js +3 -4
  76. package/dist/src/table/base.d.ts +4 -2
  77. package/dist/src/table/base.js +3 -2
  78. package/dist/src/table/index.d.ts +2 -3
  79. package/dist/src/table/index.js +11 -10
  80. package/dist/src/table/td.d.ts +0 -2
  81. package/dist/src/table/td.js +15 -6
  82. package/dist/src/table/tr.d.ts +2 -2
  83. package/dist/src/table/tr.js +2 -3
  84. package/dist/src/tagPair/ext.js +5 -7
  85. package/dist/src/tagPair/include.d.ts +6 -4
  86. package/dist/src/tagPair/include.js +76 -26
  87. package/dist/src/tagPair/index.d.ts +2 -4
  88. package/dist/src/tagPair/index.js +4 -5
  89. package/dist/src/transclude.d.ts +0 -2
  90. package/dist/src/transclude.js +9 -12
  91. package/dist/util/debug.js +15 -1
  92. package/dist/util/lint.js +3 -2
  93. package/dist/util/string.js +5 -5
  94. package/package.json +11 -11
package/dist/base.d.ts CHANGED
@@ -49,6 +49,8 @@ interface AstElement extends AstNode {
49
49
  export interface Parser {
50
50
  config: Config | string;
51
51
  i18n: Record<string, string> | string | undefined;
52
+ /** 获取当前的解析设置 */
53
+ getConfig(): Config;
52
54
  /**
53
55
  * 解析wikitext
54
56
  * @param include 是否嵌入
package/dist/index.d.ts CHANGED
@@ -8,16 +8,14 @@ declare interface Parser extends ParserBase {
8
8
  * @param title 标题(含或不含命名空间前缀)
9
9
  * @param defaultNs 命名空间
10
10
  * @param include 是否嵌入
11
- * @param halfParsed 是否是半解析状态
12
- * @param decode 是否需要解码
13
- * @param selfLink 是否允许selfLink
14
11
  */
15
- normalizeTitle(title: string, defaultNs?: number, include?: boolean, config?: Config, halfParsed?: boolean, decode?: boolean, selfLink?: boolean): Title;
12
+ normalizeTitle(title: string, defaultNs?: number, include?: boolean, config?: Config): Title;
16
13
  parse(wikitext: string, include?: boolean, maxStage?: number, config?: Config): Token;
17
14
  }
18
15
  declare const Parser: Parser;
19
16
  // @ts-expect-error mixed export styles
20
17
  export = Parser;
18
+ export default Parser;
21
19
  export type { Config, LintError };
22
20
  export type * from './internal';
23
21
  declare global { type Acceptable = unknown; }
package/dist/index.js CHANGED
@@ -43,20 +43,19 @@ const Parser = {
43
43
  return new Title(title, defaultNs, config, decode, selfLink);
44
44
  }
45
45
  const { Token } = require('./src/index');
46
- const token = debug_1.Shadow.run(() => {
46
+ return debug_1.Shadow.run(() => {
47
47
  const root = new Token(title, config);
48
48
  root.type = 'root';
49
- return root.parseOnce(0, include).parseOnce();
50
- }), titleObj = new Title(token.toString(), defaultNs, config, decode, selfLink);
51
- debug_1.Shadow.run(() => {
49
+ root.parseOnce(0, include).parseOnce();
50
+ const titleObj = new Title(root.toString(), defaultNs, config, decode, selfLink);
52
51
  for (const key of ['main', 'fragment']) {
53
52
  const str = titleObj[key];
54
53
  if (str?.includes('\0')) {
55
- titleObj[key] = token.buildFromStr(str, constants_1.BuildMethod.Text);
54
+ titleObj[key] = root.buildFromStr(str, constants_1.BuildMethod.Text);
56
55
  }
57
56
  }
57
+ return titleObj;
58
58
  });
59
- return titleObj;
60
59
  },
61
60
  /** @implements */
62
61
  parse(wikitext, include, maxStage = constants_1.MAX_STAGE, config = Parser.getConfig()) {
@@ -93,4 +92,5 @@ for (const key in Parser) {
93
92
  }
94
93
  }
95
94
  Object.defineProperties(Parser, def);
95
+ exports.default = Parser;
96
96
  module.exports = Parser;
@@ -8,13 +8,6 @@ export declare abstract class AstElement extends AstNode {
8
8
  readonly data: undefined;
9
9
  /** 子节点总数 */
10
10
  get length(): number;
11
- /**
12
- * 可见部分
13
- * @param separator 子节点间的连接符
14
- */
15
- text(separator?: string): string;
16
- /** 合并相邻的文本子节点 */
17
- normalize(): void;
18
11
  /**
19
12
  * 移除子节点
20
13
  * @param i 移除位置
@@ -10,14 +10,11 @@ class AstElement extends node_1.AstNode {
10
10
  get length() {
11
11
  return this.childNodes.length;
12
12
  }
13
- /**
14
- * 可见部分
15
- * @param separator 子节点间的连接符
16
- */
13
+ /** @private */
17
14
  text(separator) {
18
15
  return (0, string_1.text)(this.childNodes, separator);
19
16
  }
20
- /** 合并相邻的文本子节点 */
17
+ /** @private */
21
18
  normalize() {
22
19
  const childNodes = [...this.childNodes];
23
20
  /**
package/dist/lib/node.js CHANGED
@@ -52,10 +52,7 @@ class AstNode {
52
52
  }
53
53
  /** @private */
54
54
  getAttribute(key) {
55
- if (key === 'padding') {
56
- return 0;
57
- }
58
- return this[key];
55
+ return (key === 'padding' ? 0 : this[key]);
59
56
  }
60
57
  /** @private */
61
58
  setAttribute(key, value) {
@@ -0,0 +1,18 @@
1
+ import type { AstNodes, Position } from './node';
2
+ /** 节点位置 */
3
+ export declare class BoundingRect {
4
+ #private;
5
+ readonly token: AstNodes;
6
+ readonly start: number;
7
+ /** 起点行 */
8
+ get top(): number;
9
+ /** 起点列 */
10
+ get left(): number;
11
+ /**
12
+ * @param token 节点
13
+ * @param start 起点
14
+ */
15
+ constructor(token: AstNodes, start: number);
16
+ /** 计算位置 */
17
+ getPosition(): Position;
18
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BoundingRect = void 0;
4
+ /** 节点位置 */
5
+ class BoundingRect {
6
+ #pos;
7
+ token;
8
+ start;
9
+ /** 起点行 */
10
+ get top() {
11
+ this.#pos ??= this.getPosition();
12
+ return this.#pos.top;
13
+ }
14
+ /** 起点列 */
15
+ get left() {
16
+ this.#pos ??= this.getPosition();
17
+ return this.#pos.left;
18
+ }
19
+ /**
20
+ * @param token 节点
21
+ * @param start 起点
22
+ */
23
+ constructor(token, start) {
24
+ this.token = token;
25
+ this.start = start;
26
+ }
27
+ /** 计算位置 */
28
+ getPosition() {
29
+ return this.token.getRootNode().posFromIndex(this.start);
30
+ }
31
+ }
32
+ exports.BoundingRect = BoundingRect;
package/dist/lib/text.js CHANGED
@@ -4,14 +4,7 @@ exports.AstText = void 0;
4
4
  const string_1 = require("../util/string");
5
5
  const index_1 = require("../index");
6
6
  const node_1 = require("./node");
7
- const source = '<\\s*(?:\\/\\s*)?([a-z]\\w*)' // 疑似标签
8
- + '|'
9
- + '\\{+|\\}+' // `{`、`}`
10
- + '|'
11
- + '\\[{2,}|\\[(?![^[]*?\\])' // `[`
12
- + '|'
13
- + '((?:^|\\])[^[]*?)\\]+', // `]`
14
- errorSyntax = new RegExp(`${source}|https?[:/]\\/+`, 'giu'), errorSyntaxUrl = new RegExp(source, 'giu'), extImage = new RegExp(`^https?:\\/\\/${string_1.extUrlCharFirst}${string_1.extUrlChar}\\.(?:gif|png|jpg|jpeg)$`, 'iu'), regexes = {
7
+ const source = String.raw `<\s*(?:/\s*)?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*?\])|((?:^|\])[^[]*?)\]+`, errorSyntax = new RegExp(String.raw `${source}|https?[:/]/+`, 'giu'), errorSyntaxUrl = new RegExp(source, 'giu'), extImage = new RegExp(String.raw `^https?://${string_1.extUrlCharFirst}${string_1.extUrlChar}\.(?:gif|png|jpg|jpeg)$`, 'iu'), regexes = {
15
8
  '[': /[[\]]/u,
16
9
  '{': /[{}]/u,
17
10
  ']': /[[\]](?=[^[\]]*$)/u,
@@ -77,7 +70,7 @@ class AstText extends node_1.AstNode {
77
70
  lint(start = this.getAbsoluteIndex(), errorRegex) {
78
71
  const { data, parentNode, nextSibling, previousSibling } = this;
79
72
  if (!parentNode) {
80
- throw new Error('无法对孤立文本节点进行语法分析!');
73
+ throw new Error('An isolated text node cannot be linted!');
81
74
  }
82
75
  const { type, name, parentNode: grandparent } = parentNode;
83
76
  let isHtmlAttrVal = false;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.attributesParent = void 0;
4
+ const debug_1 = require("../util/debug");
4
5
  /**
5
6
  * 子节点含有AttributesToken的类
6
7
  * @param i AttributesToken子节点的位置
@@ -19,7 +20,7 @@ const attributesParent = (i = 0) => (constructor, _) => {
19
20
  return this.#attributesChild.getAttr(key);
20
21
  }
21
22
  }
22
- Object.defineProperty(AttributesParent, 'name', { value: constructor.name });
23
+ (0, debug_1.mixin)(AttributesParent, constructor);
23
24
  return AttributesParent;
24
25
  };
25
26
  exports.attributesParent = attributesParent;
@@ -1,4 +1,6 @@
1
1
  /**
2
2
  * 解析后不可见的类
3
+ * @param linter 是否覆写 lint 方法
3
4
  * @param constructor 基类
5
+ * @param _ context
4
6
  */
@@ -1,22 +1,27 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.hiddenToken = void 0;
4
+ const debug_1 = require("../util/debug");
4
5
  /**
5
6
  * 解析后不可见的类
7
+ * @param linter 是否覆写 lint 方法
6
8
  * @param constructor 基类
9
+ * @param _ context
7
10
  */
8
- const hiddenToken = (constructor) => {
11
+ const hiddenToken = (linter) => (constructor, _) => {
9
12
  /** 解析后不可见的类 */
10
13
  class AnyHiddenToken extends constructor {
11
14
  /** 没有可见部分 */
12
15
  text() {
13
16
  return '';
14
17
  }
15
- /** @override */
16
- lint() {
17
- return [];
18
+ /** @private */
19
+ lint(start) {
20
+ // @ts-expect-error private argument
21
+ return linter ? [] : super.lint(start);
18
22
  }
19
23
  }
24
+ (0, debug_1.mixin)(AnyHiddenToken, constructor);
20
25
  return AnyHiddenToken;
21
26
  };
22
27
  exports.hiddenToken = hiddenToken;
@@ -5,6 +5,12 @@ const string_1 = require("../util/string");
5
5
  const heading_1 = require("../src/heading");
6
6
  const transclude_1 = require("../src/transclude");
7
7
  const arg_1 = require("../src/arg");
8
+ const closes = {
9
+ '=': '\n',
10
+ '{': String.raw `\}{2,}|\|`,
11
+ '-': String.raw `\}-`,
12
+ '[': String.raw `\]\]`,
13
+ }, marks = new Map([['!', '!'], ['!!', '+'], ['(!', '{'], ['!)', '}'], ['!-', '-'], ['=', '~']]), re = new RegExp(String.raw `\{\{\s*(${[...marks.keys()].map(string_1.escapeRegExp).join('|')})\s*\}\}(?!\})`, 'gu');
8
14
  /**
9
15
  * 解析花括号
10
16
  * @param wikitext
@@ -13,17 +19,14 @@ const arg_1 = require("../src/arg");
13
19
  * @throws TranscludeToken.constructor()
14
20
  */
15
21
  const parseBraces = (wikitext, config, accum) => {
16
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
17
- /\{\{\s*([!=]|!!|\(!|!\)|!-)\s*\}\}(?!\})/gu;
18
- const source = `${config.excludes?.includes('heading') ? '' : '^(\0\\d+c\x7F)*={1,6}|'}\\[\\[|\\{{2,}|-\\{(?!\\{)`, { parserFunction: [, , , subst] } = config, stack = [], closes = { '=': '\n', '{': '\\}{2,}|\\|', '-': '\\}-', '[': '\\]\\]' }, marks = new Map([['!', '!'], ['!!', '+'], ['(!', '{'], ['!)', '}'], ['!-', '-'], ['=', '~']]), re = new RegExp(`\\{\\{\\s*(${[...marks.keys()].map(string_1.escapeRegExp).join('|')})\\s*\\}\\}(?!\\})`, 'gu');
22
+ const source = String.raw `${config.excludes?.includes('heading') ? '' : String.raw `^(\0\d+c\x7F)*={1,6}|`}\[\[|-\{(?!\{)`, openBraces = String.raw `|\{{2,}`, { parserFunction: [, , , subst] } = config, stack = [];
19
23
  wikitext = wikitext.replace(re, (m, p1) => {
20
24
  // @ts-expect-error abstract class
21
25
  new transclude_1.TranscludeToken(m.slice(2, -2), [], config, accum);
22
26
  return `\0${accum.length - 2}${marks.get(p1)}\x7F`;
23
27
  });
24
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions
25
- /^(\0\d+c\x7F)*={1,6}|\[\[|\{{2,}|-\{(?!\{)|[\n|=]|\}{2,}|\}-|\]\]/gmu;
26
- let regex = new RegExp(source, 'gmu'), mt = regex.exec(wikitext), moreBraces = wikitext.includes('}}'), lastIndex;
28
+ const lastBraces = wikitext.lastIndexOf('}}') - wikitext.length;
29
+ let moreBraces = lastBraces + wikitext.length !== -1, regex = new RegExp(source + (moreBraces ? openBraces : ''), 'gmu'), mt = regex.exec(wikitext), lastIndex;
27
30
  while (mt
28
31
  || lastIndex !== undefined && lastIndex <= wikitext.length && stack[stack.length - 1]?.[0]?.startsWith('=')) {
29
32
  if (mt?.[1]) {
@@ -95,7 +98,7 @@ const parseBraces = (wikitext, config, accum) => {
95
98
  }
96
99
  }
97
100
  catch (e) {
98
- if (e instanceof SyntaxError && e.message === '非法的模板名称') {
101
+ if (e instanceof SyntaxError && e.message === 'Invalid template name') {
99
102
  skip = true;
100
103
  }
101
104
  else {
@@ -122,13 +125,17 @@ const parseBraces = (wikitext, config, accum) => {
122
125
  }
123
126
  stack.push(...'0' in top ? [top] : [], mt);
124
127
  }
125
- moreBraces &&= wikitext.slice(lastIndex).includes('}}');
126
128
  let curTop = stack[stack.length - 1];
127
- if (!moreBraces && curTop?.[0]?.startsWith('{')) {
128
- stack.pop();
129
- curTop = stack[stack.length - 1];
129
+ if (moreBraces && lastBraces + wikitext.length < lastIndex) {
130
+ moreBraces = false;
131
+ while (curTop?.[0]?.startsWith('{')) {
132
+ stack.pop();
133
+ curTop = stack[stack.length - 1];
134
+ }
130
135
  }
131
- regex = new RegExp(source + (curTop ? `|${closes[curTop[0][0]]}${curTop.findEqual ? '|=' : ''}` : ''), 'gmu');
136
+ regex = new RegExp(source
137
+ + (moreBraces ? openBraces : '')
138
+ + (curTop ? `|${closes[curTop[0][0]]}${curTop.findEqual ? '|=' : ''}` : ''), 'gmu');
132
139
  regex.lastIndex = lastIndex;
133
140
  mt = regex.exec(wikitext);
134
141
  }
@@ -49,14 +49,7 @@ const parseCommentAndExt = (wikitext, config, accum, includeOnly) => {
49
49
  return str;
50
50
  }
51
51
  }
52
- const ext = config.ext.join('|'), noincludeRegex = includeOnly ? 'includeonly' : '(?:no|only)include', includeRegex = includeOnly ? 'noinclude' : 'includeonly', regex = new RegExp('<!--.*?(?:-->|$)' // comment
53
- + '|'
54
- + `<${noincludeRegex}(?:\\s[^>]*)?/?>|</${noincludeRegex}\\s*>` // <noinclude>
55
- + '|'
56
- + `<(${ext})(\\s[^>]*?)?(?:/>|>(.*?)</(\\1\\s*)>)` // 扩展标签
57
- + '|'
58
- + `<(${includeRegex})(\\s[^>]*?)?(?:/>|>(.*?)(?:</(${includeRegex}\\s*)>|$))`, // <includeonly>
59
- 'gisu');
52
+ const ext = config.ext.join('|'), noincludeRegex = includeOnly ? 'includeonly' : '(?:no|only)include', includeRegex = includeOnly ? 'noinclude' : 'includeonly', regex = new RegExp(String.raw `<!--.*?(?:-->|$)|<${noincludeRegex}(?:\s[^>]*)?/?>|</${noincludeRegex}\s*>|<(${ext})(\s[^>]*?)?(?:/>|>(.*?)</(\1\s*)>)|<(${includeRegex})(\s[^>]*?)?(?:/>|>(.*?)(?:</(${includeRegex}\s*)>|$))`, 'gisu');
60
53
  return wikitext.replace(regex, (substr, name, attr, inner, closing, include, includeAttr, includeInner, includeClosing) => {
61
54
  const str = `\0${accum.length}${name ? 'e' : 'c'}\x7F`;
62
55
  if (name) {
@@ -9,13 +9,12 @@ const converter_1 = require("../src/converter");
9
9
  * @param accum
10
10
  */
11
11
  const parseConverter = (text, config, accum) => {
12
- const regex1 = /-\{/gu, regex2 = /-\{|\}-/gu, stack = [];
12
+ const variants = `(?:${config.variants.join('|')})`, regex1 = /-\{/gu, regex2 = /-\{|\}-/gu, regex3 = new RegExp(String.raw `;(?=(?:[^;]*?=>)?\s*${variants}\s*:|(?:\s|\0\d+c\x7F)*$)`, 'u'), stack = [];
13
13
  let regex = regex1, mt = regex.exec(text);
14
14
  while (mt) {
15
15
  const { 0: syntax, index } = mt;
16
16
  if (syntax === '}-') {
17
- const top = stack.pop(), { length } = accum, str = text.slice(top.index + 2, index), i = str.indexOf('|'), [flags, raw] = i === -1 ? [[], str] : [str.slice(0, i).split(';'), str.slice(i + 1)], temp = raw.replace(/(&[#a-z\d]+);/giu, '$1\x01'), variants = `(?:${config.variants.join('|')})`, rules = temp.split(new RegExp(`;(?=(?:[^;]*?=>)?\\s*${variants}\\s*:|(?:\\s|\0\\d+c\x7F)*$)`, 'u'))
18
- .map(rule => rule.replace(/\x01/gu, ';'));
17
+ const top = stack.pop(), { length } = accum, str = text.slice(top.index + 2, index), i = str.indexOf('|'), [flags, raw] = i === -1 ? [[], str] : [str.slice(0, i).split(';'), str.slice(i + 1)], temp = raw.replace(/(&[#a-z\d]+);/giu, '$1\x01'), rules = temp.split(regex3).map(rule => rule.replace(/\x01/gu, ';'));
19
18
  // @ts-expect-error abstract class
20
19
  new converter_1.ConverterToken(flags, rules, config, accum);
21
20
  text = `${text.slice(0, top.index)}\0${length}v\x7F${text.slice(index + 2)}`;
@@ -12,14 +12,7 @@ const magicLink_1 = require("../src/magicLink");
12
12
  * @param inFile 是否在图链中
13
13
  */
14
14
  const parseExternalLinks = (wikitext, config, accum, inFile) => {
15
- const regex = new RegExp('\\[' // 左括号
16
- + `(${'\0\\d+f\x7F' // 预先解析的MagicLinkToken
17
- + '|'
18
- + `(?:(?:${config.protocol}|//)${string_1.extUrlCharFirst}|\0\\d+m\x7F)${string_1.extUrlChar}(?=[[\\]<>"\\t\\p{Zs}]|\0\\d)`})` // 链接网址
19
- + '(\\p{Zs}*(?=\\P{Zs}))' // 空格
20
- + '([^\\]\x01-\x08\x0A-\x1F\uFFFD]*)' // 链接文字
21
- + '\\]', // 右括号
22
- 'giu');
15
+ const regex = new RegExp(String.raw `\[(\0\d+f\x7F|(?:(?:${config.protocol}|//)${string_1.extUrlCharFirst}|\0\d+m\x7F)${string_1.extUrlChar}(?=[[\]<>"\t\p{Zs}]|\0\d))(\p{Zs}*(?!\p{Zs}))([^\]\x01-\x08\x0A-\x1F\uFFFD]*)\]`, 'giu');
23
16
  return wikitext.replace(regex, (_, url, space, text) => {
24
17
  const { length } = accum, mt = /&[lg]t;/u.exec(url);
25
18
  if (mt) {
@@ -19,7 +19,7 @@ const parseHrAndDoubleUnderscore = ({ firstChild: { data }, type, name }, config
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.flat().join('|')})__`, 'giu'), (m, p1) => {
22
+ }).replace(new RegExp(`__(${[...doubleUnderscore[0], ...doubleUnderscore[1]].join('|')})__`, 'giu'), (m, p1) => {
23
23
  const caseSensitive = sensitive.has(p1);
24
24
  if (caseSensitive || insensitive.has(p1.toLowerCase())) {
25
25
  // @ts-expect-error abstract class
@@ -10,7 +10,7 @@ const html_1 = require("../src/html");
10
10
  * @param accum
11
11
  */
12
12
  const parseHtml = (wikitext, config, accum) => {
13
- const regex = /^(\/?)([a-z][^\s/>]*)((?:\s|\/(?!>))[^>]*?)?(\/?>)([^<]*)$/iu, elements = new Set(config.html.flat()), bits = wikitext.split('<');
13
+ const regex = /^(\/?)([a-z][^\s/>]*)((?:\s|\/(?!>))[^>]*?)?(\/?>)([^<]*)$/iu, { html } = config, elements = new Set([...html[0], ...html[1], ...html[2]]), bits = wikitext.split('<');
14
14
  let text = bits.shift();
15
15
  for (const x of bits) {
16
16
  const mt = regex.exec(x), t = mt?.[2], name = t?.toLowerCase();
@@ -16,7 +16,7 @@ const category_1 = require("../src/link/category");
16
16
  const parseLinks = (wikitext, config, accum) => {
17
17
  const regex = true // eslint-disable-line no-constant-condition, @typescript-eslint/no-unnecessary-condition
18
18
  ? /^((?:(?!\0\d+!\x7F)[^\n[\]{}|])+)(?:(\||\0\d+!\x7F)(.*?[^\]]))?\]\](.*)$/su
19
- : /^((?:(?!\0\d+!\x7F)[^\n[\]{}|])+)(?:(\||\0\d+!\x7F)(.*?[^\]])?)?\]\](.*)$/su, regexImg = /^((?:(?!\0\d+!\x7F)[^\n[\]{}|])+)(\||\0\d+!\x7F)(.*)$/su, regexExt = new RegExp(`^\\s*(?:${config.protocol}|//)`, 'iu'), bits = wikitext.split('[[');
19
+ : /^((?:(?!\0\d+!\x7F)[^\n[\]{}|])+)(?:(\||\0\d+!\x7F)(.*?[^\]])?)?\]\](.*)$/su, regexImg = /^((?:(?!\0\d+!\x7F)[^\n[\]{}|])+)(\||\0\d+!\x7F)(.*)$/su, regexExt = new RegExp(String.raw `^\s*(?:${config.protocol}|//)`, 'iu'), bits = wikitext.split('[[');
20
20
  let s = bits.shift();
21
21
  for (let i = 0; i < bits.length; i++) {
22
22
  let mightBeImg = false, link, delimiter, text, after;
@@ -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 sepRegex = /[^,;\\.:!?)][,;\\.:!?)]+$/u, sepLparRegex = /[^,;\\.:!?][,;\\.:!?]+$/u;
6
7
  /**
7
8
  * 解析自由外链
8
9
  * @param wikitext
@@ -10,14 +11,7 @@ const magicLink_1 = require("../src/magicLink");
10
11
  * @param accum
11
12
  */
12
13
  const parseMagicLinks = (wikitext, config, accum) => {
13
- const space = '[\\p{Zs}\\t]|&nbsp;|&#0*160;|&#x0*a0;', spdash = `(?:${space}|-)`, regex = new RegExp('(^|[^\\p{L}\\d_])' // lead
14
- + '(?:'
15
- + `(?:${config.protocol})(${string_1.extUrlCharFirst}${string_1.extUrlChar})` // free external link
16
- + '|'
17
- + `(?:RFC|PMID)(?:${space})+\\d+\\b` // RFC or PMID
18
- + '|'
19
- + `ISBN(?:${space})+(?:97[89]${spdash}?)?(?:\\d${spdash}?){9}[\\dx]\\b` // ISBN
20
- + ')', 'giu');
14
+ const space = String.raw `[\p{Zs}\t]|&nbsp;|&#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');
21
15
  return wikitext.replace(regex, (m, lead, p1) => {
22
16
  let url = lead ? m.slice(lead.length) : m;
23
17
  if (p1) {
@@ -27,12 +21,12 @@ const parseMagicLinks = (wikitext, config, accum) => {
27
21
  trail = url.slice(m2.index);
28
22
  url = url.slice(0, m2.index);
29
23
  }
30
- const sep = new RegExp(`[,;\\\\.:!?${url.includes('(') ? '' : ')'}]+$`, 'u'), sepChars = sep.exec(url);
24
+ const sep = url.includes('(') ? sepLparRegex : sepRegex, sepChars = sep.exec(url);
31
25
  if (sepChars) {
32
- let correction = 0;
33
- if (sepChars[0].startsWith(';')
26
+ let correction = 1;
27
+ if (sepChars[0][1] === ';'
34
28
  && /&(?:[a-z]+|#x[\da-f]+|#\d+)$/iu.test(url.slice(0, sepChars.index))) {
35
- correction = 1;
29
+ correction = 2;
36
30
  }
37
31
  trail = url.slice(sepChars.index + correction) + trail;
38
32
  url = url.slice(0, sepChars.index + correction);
@@ -10,7 +10,7 @@ const redirect_1 = require("../src/redirect");
10
10
  * @param accum
11
11
  */
12
12
  const parseRedirect = (text, config, accum) => {
13
- const re = new RegExp(`^(\\s*)((?:${config.redirection.join('|')})\\s*(?::\\s*)?)\\[\\[([^\\n|\\]]+)(\\|.*?)?\\]\\](\\s*)`, 'iu'), mt = re.exec(text);
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
15
  text = `\0${accum.length}c\x7F${text.slice(mt[0].length)}`;
16
16
  // @ts-expect-error abstract class
package/dist/src/arg.d.ts CHANGED
@@ -16,6 +16,4 @@ export declare abstract class ArgToken extends Token {
16
16
  get default(): string | false;
17
17
  /** @param parts 以'|'分隔的各部分 */
18
18
  constructor(parts: readonly string[], config?: Parser.Config, accum?: Token[]);
19
- /** @override */
20
- text(): string;
21
19
  }
package/dist/src/arg.js CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ArgToken = void 0;
4
4
  const string_1 = require("../util/string");
5
5
  const lint_1 = require("../util/lint");
6
+ const rect_1 = require("../lib/rect");
6
7
  const index_1 = require("../index");
7
8
  const index_2 = require("./index");
8
9
  const atom_1 = require("./atom");
@@ -26,7 +27,7 @@ class ArgToken extends index_2.Token {
26
27
  super.insertAt(token);
27
28
  }
28
29
  else if (i > 1) {
29
- const token = new hidden_1.HiddenToken(parts[i], config, accum, {});
30
+ const token = new hidden_1.HiddenToken(parts[i], config, accum);
30
31
  super.insertAt(token);
31
32
  }
32
33
  else {
@@ -41,7 +42,7 @@ class ArgToken extends index_2.Token {
41
42
  toString() {
42
43
  return `{{{${super.toString('|')}}}}`;
43
44
  }
44
- /** @override */
45
+ /** @private */
45
46
  text() {
46
47
  return `{{{${(0, string_1.text)(this.childNodes.slice(0, 2), '|')}}}}`;
47
48
  }
@@ -71,7 +72,7 @@ class ArgToken extends index_2.Token {
71
72
  errors.push(...argDefault.lint(start + 4 + argName.toString().length, re));
72
73
  }
73
74
  if (rest.length > 0) {
74
- const rect = { start, ...this.getRootNode().posFromIndex(start) };
75
+ const rect = new rect_1.BoundingRect(this, start);
75
76
  errors.push(...rest.map(child => {
76
77
  const e = (0, lint_1.generateForChild)(child, rect, 'no-ignored', 'invisible content inside triple braces');
77
78
  e.startIndex--;
@@ -1,10 +1,10 @@
1
- import Parser from '../index';
2
1
  import { Token } from './index';
2
+ import type { Config } from '../base';
3
3
  declare type AtomTypes = 'arg-name' | 'attr-key' | 'attr-value' | 'ext-attr-dirty' | 'html-attr-dirty' | 'table-attr-dirty' | 'converter-flag' | 'converter-rule-variant' | 'converter-rule-to' | 'converter-rule-from' | 'invoke-function' | 'invoke-module' | 'template-name' | 'link-target' | 'param-line';
4
4
  /** 不会被继续解析的plain Token */
5
5
  export declare class AtomToken extends Token {
6
6
  type: AtomTypes;
7
7
  /** @class */
8
- constructor(wikitext: string | undefined, type: AtomTypes, config?: Parser.Config, accum?: Token[], acceptable?: Acceptable);
8
+ constructor(wikitext: string | undefined, type: AtomTypes, config?: Config, accum?: Token[], acceptable?: Acceptable);
9
9
  }
10
10
  export {};
package/dist/src/atom.js CHANGED
@@ -1,12 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AtomToken = void 0;
4
- const index_1 = require("../index");
5
- const index_2 = require("./index");
4
+ const index_1 = require("./index");
6
5
  /** 不会被继续解析的plain Token */
7
- class AtomToken extends index_2.Token {
6
+ class AtomToken extends index_1.Token {
8
7
  /** @class */
9
- constructor(wikitext, type, config = index_1.default.getConfig(), accum = [], acceptable) {
8
+ constructor(wikitext, type, config, accum, acceptable) {
10
9
  super(wikitext, config, accum, acceptable);
11
10
  this.type = type;
12
11
  }
@@ -31,8 +31,6 @@ export declare abstract class AttributeToken extends Token {
31
31
  * @param quotes 引号
32
32
  */
33
33
  constructor(type: AttributeTypes, tag: string, key: string, equal?: string, value?: string, quotes?: readonly [string?, string?], config?: Parser.Config, accum?: Token[]);
34
- /** @override */
35
- text(): string;
36
34
  /** 获取属性值 */
37
35
  getValue(): string | true;
38
36
  }
@@ -2,6 +2,7 @@
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");
5
6
  const string_1 = require("../util/string");
6
7
  const constants_1 = require("../util/constants");
7
8
  const index_1 = require("../index");
@@ -144,13 +145,7 @@ const commonHtmlAttrs = new Set([
144
145
  ]),
145
146
  tabs: new Set(['plain', 'class', 'container', 'id', 'title', 'style']),
146
147
  combobox: new Set(['placeholder', 'value', 'id', 'class', 'text', 'dropdown', 'style']),
147
- }, insecureStyle = new RegExp('expression'
148
- + '|'
149
- + '(?:accelerator|-o-link(?:-source)?|-o-replace)\\s*:'
150
- + '|'
151
- + '(?:url|image(?:-set)?)\\s*\\('
152
- + '|'
153
- + 'attr\\s*\\([^)]+[\\s,]url', 'u'), obsoleteAttrs = {
148
+ }, insecureStyle = /expression|(?:accelerator|-o-link(?:-source)?|-o-replace)\s*:|(?:url|image(?:-set)?)\s*\(|attr\s*\([^)]+[\s,]url/u, obsoleteAttrs = {
154
149
  table: obsoleteTableAttrs,
155
150
  td: new Set([...obsoleteTdAttrs, 'scope']),
156
151
  th: obsoleteTdAttrs,
@@ -240,13 +235,14 @@ class AttributeToken extends index_2.Token {
240
235
  this.#tag = this.parentNode.name;
241
236
  }
242
237
  this.setAttribute('name', this.firstChild.text().trim().toLowerCase());
238
+ super.afterBuild();
243
239
  }
244
240
  /** @private */
245
241
  toString() {
246
242
  const [quoteStart = '', quoteEnd = ''] = this.#quotes;
247
243
  return this.#equal ? super.toString(this.#equal + quoteStart) + quoteEnd : this.firstChild.toString();
248
244
  }
249
- /** @override */
245
+ /** @private */
250
246
  text() {
251
247
  return this.#equal ? `${super.text(`${this.#equal.trim()}"`)}"` : this.firstChild.text();
252
248
  }
@@ -256,11 +252,8 @@ class AttributeToken extends index_2.Token {
256
252
  }
257
253
  /** @private */
258
254
  lint(start = this.getAbsoluteIndex(), re) {
259
- const errors = super.lint(start, re), { balanced, firstChild, lastChild, type, name, tag } = this, value = this.getValue();
260
- let rect;
255
+ const errors = super.lint(start, re), { balanced, firstChild, lastChild, type, name, tag } = this, value = this.getValue(), rect = new rect_1.BoundingRect(this, start);
261
256
  if (!balanced) {
262
- const root = this.getRootNode();
263
- rect = { start, ...root.posFromIndex(start) };
264
257
  const e = (0, lint_1.generateForChild)(lastChild, rect, 'unclosed-quote', index_1.default.msg('unclosed $1', 'quotes'), 'warning');
265
258
  e.startIndex--;
266
259
  e.startCol--;
@@ -287,19 +280,15 @@ class AttributeToken extends index_2.Token {
287
280
  && !htmlAttrs[tag]?.has(name)
288
281
  && !/^(?:xmlns:[\w:.-]+|data-[^:]*)$/u.test(name)
289
282
  && (tag === 'meta' || tag === 'link' || !commonHtmlAttrs.has(name))) {
290
- rect ??= { start, ...this.getRootNode().posFromIndex(start) };
291
283
  errors.push((0, lint_1.generateForChild)(firstChild, rect, 'illegal-attr', 'illegal attribute name'));
292
284
  }
293
285
  else if (obsoleteAttrs[tag]?.has(name)) {
294
- rect ??= { start, ...this.getRootNode().posFromIndex(start) };
295
286
  errors.push((0, lint_1.generateForChild)(firstChild, rect, 'obsolete-attr', 'obsolete attribute', 'warning'));
296
287
  }
297
288
  else if (name === 'style' && typeof value === 'string' && insecureStyle.test(value)) {
298
- rect ??= { start, ...this.getRootNode().posFromIndex(start) };
299
289
  errors.push((0, lint_1.generateForChild)(lastChild, rect, 'insecure-style', 'insecure style'));
300
290
  }
301
291
  else if (name === 'tabindex' && typeof value === 'string' && value.trim() !== '0') {
302
- rect ??= { start, ...this.getRootNode().posFromIndex(start) };
303
292
  const e = (0, lint_1.generateForChild)(lastChild, rect, 'illegal-attr', 'nonzero tabindex');
304
293
  e.suggestions = [
305
294
  {