wikilint 2.46.2 → 2.46.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.
package/README.md CHANGED
@@ -40,6 +40,7 @@ npm i mathoid-texvcjs vscode-css-languageservice
40
40
 
41
41
  | Option | Argument | Description | Default |
42
42
  | :----- | :------- | :---------- | :------ |
43
+ | `--` | | End of options | |
43
44
  | `-c`, `--config` | \<path or preset config\> | Choose parser's [configuration](https://github.com/bhsd-harry/wikiparser-node/wiki/Parser-%28EN%29#config) | `default` |
44
45
  | `--cache` | | Enable caching | `false` |
45
46
  | `--cache-file` | \<path\> | Specify cache file and enable caching | `.wikilintcache` |
@@ -74,3 +75,20 @@ The generated configuration file will be saved in the `config` directory. You ca
74
75
  # For example:
75
76
  npx wikilint --config frwiki *.wiki
76
77
  ```
78
+
79
+ ## Use with pre-commit
80
+
81
+ To use `wikilint` with [pre-commit](https://pre-commit.com/), add the following to your [`.pre-commit-config.yaml`](https://pre-commit.com/#adding-pre-commit-plugins-to-your-project):
82
+
83
+ ```yaml
84
+ repos:
85
+ - repo: local
86
+ hooks:
87
+ - id: wikilint
88
+ name: WikiLint
89
+ # You can add any CLI options as needed
90
+ entry: wikilint
91
+ language: node
92
+ additional_dependencies: ['wikilint@2.46.2']
93
+ files: \.(mediawiki|wiki|wikitext)$
94
+ ```
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="98" height="20" role="img" aria-label="Coverage: 96%"><title>Coverage: 96%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="98" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="35" height="20" fill="#4c1"/><rect width="98" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Coverage</text><text x="325" y="140" transform="scale(.1)" fill="#fff" textLength="530">Coverage</text><text aria-hidden="true" x="795" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="250">96%</text><text x="795" y="140" transform="scale(.1)" fill="#fff" textLength="250">96%</text></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="98" height="20" aria-label="Coverage: 95%"><title>Coverage: 95%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="98" height="20" fill="#fff" rx="3"/></clipPath><g clip-path="url(#r)"><path fill="#555" d="M0 0h63v20H0z"/><path fill="#4c1" d="M63 0h35v20H63z"/><path fill="url(#s)" d="M0 0h98v20H0z"/></g><g fill="#fff" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" font-size="110" text-anchor="middle" text-rendering="geometricPrecision"><text x="325" y="150" fill="#010101" fill-opacity=".3" aria-hidden="true" textLength="530" transform="scale(.1)">Coverage</text><text x="325" y="140" textLength="530" transform="scale(.1)">Coverage</text><text x="795" y="150" fill="#010101" fill-opacity=".3" aria-hidden="true" textLength="250" transform="scale(.1)">95%</text><text x="795" y="140" textLength="250" transform="scale(.1)">95%</text></g></svg>
package/dist/base.d.mts CHANGED
@@ -128,11 +128,10 @@ export interface LanguageService {
128
128
  * Provide color decorators
129
129
  *
130
130
  * 提供颜色指示
131
- * @param rgba color parser / 颜色解析函数
132
131
  * @param text source Wikitext / 源代码
133
- * @param hsl whether HSL colors are treated / 是否允许HSL颜色
132
+ * @param rgba color parser / 颜色解析函数
134
133
  */
135
- provideDocumentColors(rgba: (s: string) => [number, number, number, number] | [], text: string, hsl?: boolean): Promise<ColorInformation[]>;
134
+ provideDocumentColors(text: string, rgba?: (s: string) => [number, number, number, number] | []): Promise<ColorInformation[]>;
136
135
  /**
137
136
  * Provide color pickers
138
137
  *
package/dist/base.d.ts CHANGED
@@ -128,11 +128,10 @@ export interface LanguageService {
128
128
  * Provide color decorators
129
129
  *
130
130
  * 提供颜色指示
131
- * @param rgba color parser / 颜色解析函数
132
131
  * @param text source Wikitext / 源代码
133
- * @param hsl whether HSL colors are treated / 是否允许HSL颜色
132
+ * @param rgba color parser / 颜色解析函数
134
133
  */
135
- provideDocumentColors(rgba: (s: string) => [number, number, number, number] | [], text: string, hsl?: boolean): Promise<ColorInformation[]>;
134
+ provideDocumentColors(text: string, rgba?: (s: string) => [number, number, number, number] | []): Promise<ColorInformation[]>;
136
135
  /**
137
136
  * Provide color pickers
138
137
  *
package/dist/bin/cli.js CHANGED
@@ -11,6 +11,7 @@ const util_1 = __importDefault(require("util"));
11
11
  const index_1 = __importDefault(require("../index"));
12
12
  const man = `
13
13
  Available options:
14
+ -- End of options
14
15
  -c, --config <path or preset config> Choose parser's configuration
15
16
  --cache Enable caching
16
17
  --cache-file <path> Specify cache file
@@ -228,6 +229,10 @@ for (let i = 2; i < argv.length; i++) {
228
229
  process.exit(0);
229
230
  break;
230
231
  }
232
+ case '--':
233
+ files = [...files, ...argv.slice(i + 1)];
234
+ i = argv.length;
235
+ break;
231
236
  default: {
232
237
  let known = true;
233
238
  if (option.includes('=')) {
@@ -277,6 +282,9 @@ if (quiet && strict) {
277
282
  }
278
283
  if (recursive) {
279
284
  files = files.flatMap(file => {
285
+ if (!fs_1.default.existsSync(file)) {
286
+ return [];
287
+ }
280
288
  if (fs_1.default.statSync(file).isFile()) {
281
289
  return file;
282
290
  }
@@ -347,6 +355,9 @@ const { mtimeMs } = fs_1.default.statSync(config), obj = cache?.[include ? 'incl
347
355
  process.exit(0);
348
356
  }
349
357
  for (const file of new Set(files.map(f => path_1.default.resolve(f)))) {
358
+ if (!fs_1.default.existsSync(file)) {
359
+ continue;
360
+ }
350
361
  const stat = fs_1.default.statSync(file);
351
362
  if (stat.isDirectory()) {
352
363
  console.error(`"${file}" is a directory. Please use -r or --recursive to lint directories.`);
@@ -41,7 +41,7 @@ const filterGadget = (id) => {
41
41
  const n = Number(id);
42
42
  return n < 2300 || n > 2303; // Gadget, Gadget talk, Gadget definition, Gadget definition talk
43
43
  };
44
- const pkg = 'wikilint', version = '2.46.2';
44
+ const pkg = 'wikilint', version = '2.46.3';
45
45
  /**
46
46
  * Get the parser configuration for a Wikimedia Foundation project.
47
47
  * @param site site nickname
package/dist/lib/lsp.d.ts CHANGED
@@ -22,10 +22,10 @@ export declare class LanguageService implements LanguageServiceBase {
22
22
  * Provide color decorators
23
23
  *
24
24
  * 提供颜色指示
25
- * @param rgba color parser / 颜色解析函数
26
25
  * @param text source Wikitext / 源代码
26
+ * @param rgba color parser / 颜色解析函数
27
27
  */
28
- provideDocumentColors(rgba: (s: string) => [number, number, number, number] | [], text: string): Promise<ColorInformation[]>;
28
+ provideDocumentColors(text: string, rgba?: (color: string) => [number, number, number, number] | []): Promise<ColorInformation[]>;
29
29
  /**
30
30
  * Provide color pickers
31
31
  *
package/dist/lib/lsp.js CHANGED
@@ -498,10 +498,13 @@ class LanguageService {
498
498
  * Provide color decorators
499
499
  *
500
500
  * 提供颜色指示
501
- * @param rgba color parser / 颜色解析函数
502
501
  * @param text source Wikitext / 源代码
502
+ * @param rgba color parser / 颜色解析函数
503
503
  */
504
- async provideDocumentColors(rgba, text) {
504
+ async provideDocumentColors(text, rgba = color_1.rgba) {
505
+ if (typeof text === 'function' && typeof rgba === 'string') {
506
+ [rgba, text] = [text, rgba];
507
+ }
505
508
  const root = await this.#queue(text);
506
509
  return root.querySelectorAll('attr-value,parameter-value,arg-default').reverse().flatMap(token => {
507
510
  const { type, childNodes,
@@ -608,7 +611,7 @@ class LanguageService {
608
611
  const { re, allTags, functions, switches, jaSwitches, protocols, params, tags, ext, } = this.#prepareCompletionConfig(), { line, character } = position, curLine = text.split(/\r?\n/u, line + 1)[line], mt = re.exec(curLine?.slice(0, character) ?? ''), [, , iAlias, sAlias] = this.config.doubleUnderscore;
609
612
  if (mt?.[1] !== undefined) { // tag
610
613
  const closing = mt[1].startsWith('/');
611
- return getCompletion(allTags, 'Class', mt[1].slice(closing ? 1 : 0), position, closing && !curLine?.slice(character).trim().startsWith('>') ? '>' : '');
614
+ return getCompletion(allTags, 'Class', mt[1].slice(closing ? 1 : 0), position, closing && !curLine?.slice(character).trimStart().startsWith('>') ? '>' : '');
612
615
  }
613
616
  else if (mt?.[4] || mt?.[5] && jaSwitches.length > 0) { // behavior switch
614
617
  const isJa = mt[5] !== undefined;
package/dist/lib/title.js CHANGED
@@ -8,7 +8,7 @@ const string_1 = require("../util/string");
8
8
  * @param title 标题
9
9
  */
10
10
  const resolve = (title) => {
11
- const [, { length }, sub] = /^((?:\.\.\/)*)([\s\S]*)/u.exec(title);
11
+ const [, { length }, sub] = /^((?:\.\.\/)*)(.*)/su.exec(title);
12
12
  return [length / 3, sub];
13
13
  };
14
14
  /**
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.attributesParent = void 0;
4
+ /* NOT FOR BROWSER ONLY */
4
5
  const debug_1 = require("../util/debug");
5
6
  /**
6
7
  * 子节点含有AttributesToken的类
@@ -20,7 +21,9 @@ const attributesParent = (i = 0) => (constructor) => {
20
21
  return this.#getAttributesChild().getAttr(key);
21
22
  }
22
23
  }
24
+ /* NOT FOR BROWSER ONLY */
23
25
  (0, debug_1.mixin)(AttributesParent, constructor);
26
+ /* NOT FOR BROWSER ONLY END */
24
27
  return AttributesParent;
25
28
  }
26
29
  };
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.elementLike = void 0;
4
- const debug_1 = require("../util/debug");
5
4
  const selector_1 = require("../util/selector");
5
+ /* NOT FOR BROWSER ONLY */
6
+ const debug_1 = require("../util/debug");
6
7
  /** @ignore */
7
8
  const elementLike = (constructor) => {
8
9
  LINT: {
@@ -67,7 +68,9 @@ const elementLike = (constructor) => {
67
68
  }
68
69
  }
69
70
  }
71
+ /* NOT FOR BROWSER ONLY */
70
72
  (0, debug_1.mixin)(ElementLike, constructor);
73
+ /* NOT FOR BROWSER ONLY END */
71
74
  return ElementLike;
72
75
  }
73
76
  };
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ /* NOT FOR BROWSER ONLY */
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.gapped = void 0;
4
5
  const debug_1 = require("../util/debug");
6
+ /* NOT FOR BROWSER ONLY END */
5
7
  /**
6
8
  * 给定 gap 的类
7
9
  * @param gap
@@ -12,7 +14,9 @@ const gapped = (gap = 1) => (constructor) => {
12
14
  return gap;
13
15
  }
14
16
  }
17
+ /* NOT FOR BROWSER ONLY */
15
18
  (0, debug_1.mixin)(GappedToken, constructor);
19
+ /* NOT FOR BROWSER ONLY END */
16
20
  return GappedToken;
17
21
  };
18
22
  exports.gapped = gapped;
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.hiddenToken = void 0;
4
+ /* NOT FOR BROWSER ONLY */
4
5
  const debug_1 = require("../util/debug");
6
+ /* NOT FOR BROWSER ONLY END */
5
7
  /**
6
8
  * 解析后不可见的类
7
9
  * @param linter 是否覆写 lint 方法
@@ -16,7 +18,9 @@ const hiddenToken = (linter = true, html = true) => (constructor) => {
16
18
  LINT: return linter ? [] : super.lint(start);
17
19
  }
18
20
  }
21
+ /* NOT FOR BROWSER ONLY */
19
22
  (0, debug_1.mixin)(AnyHiddenToken, constructor);
23
+ /* NOT FOR BROWSER ONLY END */
20
24
  return AnyHiddenToken;
21
25
  };
22
26
  exports.hiddenToken = hiddenToken;
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ /* NOT FOR BROWSER ONLY */
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.noEscape = void 0;
4
5
  const debug_1 = require("../util/debug");
6
+ /* NOT FOR BROWSER ONLY END */
5
7
  /**
6
8
  * 不需要转义的类
7
9
  * @ignore
@@ -13,7 +15,9 @@ const noEscape = (constructor) => {
13
15
  //
14
16
  }
15
17
  }
18
+ /* NOT FOR BROWSER ONLY */
16
19
  (0, debug_1.mixin)(NoEscapeToken, constructor);
20
+ /* NOT FOR BROWSER ONLY END */
17
21
  return NoEscapeToken;
18
22
  }
19
23
  };
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.nodeLike = void 0;
4
+ /* NOT FOR BROWSER ONLY */
4
5
  const debug_1 = require("../util/debug");
5
6
  /** @ignore */
6
7
  const nodeLike = (constructor) => {
@@ -18,7 +19,9 @@ const nodeLike = (constructor) => {
18
19
  LINT: return this.getDimension().width;
19
20
  }
20
21
  }
22
+ /* NOT FOR BROWSER ONLY */
21
23
  (0, debug_1.mixin)(NodeLike, constructor);
24
+ /* NOT FOR BROWSER ONLY END */
22
25
  return NodeLike;
23
26
  };
24
27
  exports.nodeLike = nodeLike;
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ /* NOT FOR BROWSER ONLY */
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.padded = void 0;
4
5
  const debug_1 = require("../util/debug");
6
+ /* NOT FOR BROWSER ONLY END */
5
7
  /**
6
8
  * 给定 padding 的类
7
9
  * @param padding padding 字符串
@@ -13,7 +15,9 @@ const padded = ({ length }) => (constructor) => {
13
15
  return key === 'padding' ? length : super.getAttribute(key);
14
16
  }
15
17
  }
18
+ /* NOT FOR BROWSER ONLY */
16
19
  (0, debug_1.mixin)(PaddedToken, constructor);
20
+ /* NOT FOR BROWSER ONLY END */
17
21
  return PaddedToken;
18
22
  };
19
23
  exports.padded = padded;
@@ -4,10 +4,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.paramLineParent = void 0;
7
- const debug_1 = require("../util/debug");
8
7
  const lint_1 = require("../util/lint");
9
8
  const rect_1 = require("../lib/rect");
10
9
  const index_1 = __importDefault(require("../index"));
10
+ /* NOT FOR BROWSER ONLY */
11
+ const debug_1 = require("../util/debug");
11
12
  /**
12
13
  * 子节点为ParamLineToken的类
13
14
  * @ignore
@@ -44,7 +45,9 @@ const paramLineParent = (constructor) => {
44
45
  return errors;
45
46
  }
46
47
  }
48
+ /* NOT FOR BROWSER ONLY */
47
49
  (0, debug_1.mixin)(ParamLineParent, constructor);
50
+ /* NOT FOR BROWSER ONLY END */
48
51
  return ParamLineParent;
49
52
  }
50
53
  };
@@ -10,8 +10,8 @@ const ext_1 = require("../src/tagPair/ext");
10
10
  const comment_1 = require("../src/nowiki/comment");
11
11
  const onlyincludeLeft = '<onlyinclude>', onlyincludeRight = '</onlyinclude>', { length } = onlyincludeLeft, getExtRegex = [false, true].map(includeOnly => {
12
12
  const noincludeRegex = includeOnly ? 'includeonly' : '(?:no|only)include', includeRegex = includeOnly ? 'noinclude' : 'includeonly';
13
- return (0, common_1.getRegex)(exts => new RegExp(String.raw `<!--[\s\S]*?(?:-->|$)|<${noincludeRegex}(?:\s[^>]*)?/?>|</${noincludeRegex}\s*>|<(${exts // eslint-disable-next-line unicorn/prefer-string-raw
14
- })(\s[^>]*?)?(?:/>|>([\s\S]*?)</(${'\\1'}\s*)>)|<(${includeRegex})(\s[^>]*?)?(?:/>|>([\s\S]*?)(?:</(${includeRegex}\s*)>|$))`, 'giu'));
13
+ return (0, common_1.getRegex)(exts => new RegExp(String.raw `<!--.*?(?:-->|$)|<${noincludeRegex}(?:\s[^>]*)?/?>|</${noincludeRegex}\s*>|<(${exts // eslint-disable-next-line unicorn/prefer-string-raw
14
+ })(\s[^>]*?)?(?:/>|>(.*?)</(${'\\1'}\s*)>)|<(${includeRegex})(\s[^>]*?)?(?:/>|>(.*?)(?:</(${includeRegex}\s*)>|$))`, 'gisu'));
15
15
  });
16
16
  /**
17
17
  * 更新`<onlyinclude>`和`</onlyinclude>`的位置
@@ -65,10 +65,10 @@ const parseCommentAndExt = (wikitext, config, accum, includeOnly) => {
65
65
  const stack = [];
66
66
  newExt = ext.filter(e => e !== 'translate' && e !== 'tvar');
67
67
  newConfig = { ...config, ext: newExt };
68
- wikitext = wikitext.replace(/<nowiki>[\s\S]*?<\/nowiki>/giu, m => {
68
+ wikitext = wikitext.replace(/<nowiki>.*?<\/nowiki>/gisu, m => {
69
69
  stack.push(m);
70
70
  return `\0${stack.length - 1}\x7F`;
71
- }).replace(/<translate( nowrap)?>([\s\S]*?)<\/translate>/gu, (_, p1, p2) => {
71
+ }).replace(/<translate( nowrap)?>(.*?)<\/translate>/gsu, (_, p1, p2) => {
72
72
  const l = accum.length;
73
73
  // @ts-expect-error abstract class
74
74
  new TranslateToken(p1, p2 && (0, string_1.restore)(p2, stack), newConfig, accum);
@@ -11,7 +11,7 @@ const externalLinks_1 = require("./externalLinks");
11
11
  const index_2 = require("../src/link/index");
12
12
  const file_1 = require("../src/link/file");
13
13
  const category_1 = require("../src/link/category");
14
- const regexImg = /^((?:(?!\0\d+!\x7F)[^\n[\]{}|])+)(\||\0\d+!\x7F)([\s\S]*)$/u;
14
+ const regexImg = /^((?:(?!\0\d+!\x7F)[^\n[\]{}|])+)(\||\0\d+!\x7F)(.*)$/su;
15
15
  /**
16
16
  * 解析内部链接
17
17
  * @param wikitext
@@ -23,8 +23,8 @@ const regexImg = /^((?:(?!\0\d+!\x7F)[^\n[\]{}|])+)(\||\0\d+!\x7F)([\s\S]*)$/u;
23
23
  const parseLinks = (wikitext, config, accum, page, tidy) => {
24
24
  config.regexLinks ??= new RegExp(String.raw `^\s*(?:${config.protocol}|//)`, 'iu');
25
25
  const regex = config.inExt
26
- ? /^((?:(?!\0\d+!\x7F)[^\n[\]{}|])+)(?:(\||\0\d+!\x7F)([\s\S]*?[^\]]))?\]\]([\s\S]*)$/u
27
- : /^((?:(?!\0\d+!\x7F)[^\n[\]{}|])*)(?:(\||\0\d+!\x7F)([\s\S]*?[^\]])?)?\]\]([\s\S]*)$/u, bits = wikitext.split('[[');
26
+ ? /^((?:(?!\0\d+!\x7F)[^\n[\]{}|])+)(?:(\||\0\d+!\x7F)(.*?[^\]]))?\]\](.*)$/su
27
+ : /^((?:(?!\0\d+!\x7F)[^\n[\]{}|])*)(?:(\||\0\d+!\x7F)(.*?[^\]])?)?\]\](.*)$/su, bits = wikitext.split('[[');
28
28
  let s = bits.shift();
29
29
  for (let i = 0; i < bits.length; i++) {
30
30
  let mightBeImg = false, link, delimiter, text, after;
@@ -62,7 +62,7 @@ class AttributesToken extends index_2.Token {
62
62
  this.#type = type;
63
63
  this.setAttribute('name', name);
64
64
  if (attr) {
65
- const regex = /([^\s/](?:(?!\0\d+~\x7F)[^\s/=])*)(?:((?:\s(?:\s|\0\d+[cn]\x7F)*)?(?:=|\0\d+~\x7F)(?:\s|\0\d+[cn]\x7F)*)(?:(["'])([\s\S]*?)(\3|$)|(\S*)))?/gu;
65
+ const regex = /([^\s/](?:(?!\0\d+~\x7F)[^\s/=])*)(?:((?:\s(?:\s|\0\d+[cn]\x7F)*)?(?:=|\0\d+~\x7F)(?:\s|\0\d+[cn]\x7F)*)(?:(["'])(.*?)(\3|$)|(\S*)))?/gsu;
66
66
  let out = '', mt = regex.exec(attr), lastIndex = 0;
67
67
  const insertDirty = /** 插入无效属性 */ () => {
68
68
  if (out) {
@@ -131,18 +131,12 @@ let LinkBaseToken = (() => {
131
131
  }
132
132
  /** @private */
133
133
  text() {
134
- const { length, firstChild, childNodes, type, } = this, target = firstChild.text();
135
- let str;
136
- if (length === 1) {
137
- str =
138
- type === 'link' ?
139
- (0, string_1.trimStart)(target) :
140
- target.trim();
141
- }
142
- else {
143
- str = `${target.trim()}|${(0, string_1.text)(childNodes.slice(1)
134
+ const { length, firstChild, childNodes, type, } = this, target = firstChild.text(), str = length === 1
135
+ ? target[type === 'link' ?
136
+ 'trimStart' :
137
+ 'trim']()
138
+ : `${target.trim()}|${(0, string_1.text)(childNodes.slice(1)
144
139
  .filter(({ type: t, name }) => t !== 'image-parameter' || name !== 'invalid'), '|')}`;
145
- }
146
140
  if (this.#bracket) {
147
141
  return `[[${str}]]`;
148
142
  }
@@ -17,24 +17,26 @@ class GalleryToken extends index_2.MultiLineToken {
17
17
  /** @param inner 标签内部wikitext */
18
18
  constructor(inner, config, accum = []) {
19
19
  super(undefined, config, accum, {});
20
- for (const line of inner?.split('\n') ?? []) {
21
- const matches = /^([^|]+)(?:\|(.*))?/u.exec(line);
22
- if (!matches) {
23
- super.insertAt((line.trim()
20
+ if (inner) {
21
+ for (const line of inner.split('\n')) {
22
+ const matches = /^([^|]+)(?:\|(.*))?/u.exec(line);
23
+ if (!matches) {
24
+ super.insertAt((line.trim()
25
+ // @ts-expect-error abstract class
26
+ ? new commentLine_1.CommentLineToken(line, config, accum)
27
+ : line));
28
+ continue;
29
+ }
30
+ const [, file, alt] = matches;
31
+ if (this.#checkFile(file)) {
24
32
  // @ts-expect-error abstract class
25
- ? new commentLine_1.CommentLineToken(line, config, accum)
26
- : line));
27
- continue;
28
- }
29
- const [, file, alt] = matches;
30
- if (this.#checkFile(file)) {
31
- // @ts-expect-error abstract class
32
- super.insertAt(new galleryImage_1.GalleryImageToken('gallery', file, alt, config, accum));
33
- }
34
- else {
35
- super.insertAt(
36
- // @ts-expect-error abstract class
37
- new commentLine_1.CommentLineToken(line, config, accum));
33
+ super.insertAt(new galleryImage_1.GalleryImageToken('gallery', file, alt, config, accum));
34
+ }
35
+ else {
36
+ super.insertAt(
37
+ // @ts-expect-error abstract class
38
+ new commentLine_1.CommentLineToken(line, config, accum));
39
+ }
38
40
  }
39
41
  }
40
42
  }
@@ -64,7 +64,7 @@ class NestedToken extends index_2.Token {
64
64
  if (!s) {
65
65
  return errors;
66
66
  }
67
- const rect = new rect_1.BoundingRect(this, start), msg = index_1.default.msg('invalid-content', name), regex = typeof this.#regex === 'boolean' ? lintRegex[this.#regex ? 1 : 0] : /^<!--[\s\S]*-->$/u, ignored = childNodes.filter(child => {
67
+ const rect = new rect_1.BoundingRect(this, start), msg = index_1.default.msg('invalid-content', name), regex = typeof this.#regex === 'boolean' ? lintRegex[this.#regex ? 1 : 0] : /^<!--.*-->$/su, ignored = childNodes.filter(child => {
68
68
  const { type, name: n } = child;
69
69
  if (type === 'ext') {
70
70
  return !this.#tags.includes(n);
@@ -152,14 +152,14 @@ let ExtToken = (() => {
152
152
  // NestedToken 依赖 ExtToken
153
153
  const { NestedToken } = require('../nested');
154
154
  // @ts-expect-error abstract class
155
- innerToken = new NestedToken(inner, /<(option|choicetemplate)(\s[^>]*?)?(?:\/>|>([\s\S]*?)<\/(\1)>)/gu, ['option', 'choicetemplate'], newConfig, accum);
155
+ innerToken = new NestedToken(inner, /<(option|choicetemplate)(\s[^>]*?)?(?:\/>|>(.*?)<\/(\1)>)/gsu, ['option', 'choicetemplate'], newConfig, accum);
156
156
  break;
157
157
  }
158
158
  case 'combobox': {
159
159
  // NestedToken 依赖 ExtToken
160
160
  const { NestedToken } = require('../nested');
161
161
  // @ts-expect-error abstract class
162
- innerToken = new NestedToken(inner, /<(combooption)(\s[^>]*?)?(?:\/>|>([\s\S]*?)<\/(combooption\s*)>)/giu, ['combooption'], newConfig, accum);
162
+ innerToken = new NestedToken(inner, /<(combooption)(\s[^>]*?)?(?:\/>|>(.*?)<\/(combooption\s*)>)/gisu, ['combooption'], newConfig, accum);
163
163
  break;
164
164
  }
165
165
  case 'gallery': {
@@ -22,13 +22,13 @@ class TranslateToken extends index_2.TagPairToken {
22
22
  */
23
23
  constructor(attr, inner, config, accum = []) {
24
24
  const attrToken = new syntax_1.SyntaxToken(attr, 'translate-attr', config, accum);
25
- inner = inner?.replace(/<tvar(\|[^>]+)>([\s\S]*?)<\/>/gu, (_, p1, p2) => {
25
+ inner = inner?.replace(/<tvar(\|[^>]+)>(.*?)<\/>/gsu, (_, p1, p2) => {
26
26
  // @ts-expect-error abstract class
27
27
  new tvar_1.TvarToken('tvar', p1, false, config, accum);
28
28
  // @ts-expect-error abstract class
29
29
  new tvar_1.TvarToken('', '', true, config, accum);
30
30
  return `\0${accum.length - 2}n\x7F${p2}\0${accum.length}n\x7F`;
31
- }).replace(/<(tvar)(\s+name\s*=(?:\s*(?:(["'])[\s\S]*?\3|[^"'\s>]+))?\s*)>([\s\S]*?)<\/(tvar)(\s*)>/giu, (_, p1, p2, __, p3, p4, p5) => {
31
+ }).replace(/<(tvar)(\s+name\s*=(?:\s*(?:(["']).*?\3|[^"'\s>]+))?\s*)>(.*?)<\/(tvar)(\s*)>/gisu, (_, p1, p2, __, p3, p4, p5) => {
32
32
  // @ts-expect-error abstract class
33
33
  new tvar_1.TvarToken(p1, p2, false, config, accum);
34
34
  // @ts-expect-error abstract class
@@ -129,7 +129,7 @@ let TranscludeToken = (() => {
129
129
  }
130
130
  const colon = title.search(/[::]/u), fullWidth = title[colon] === ':', isFunction = colon !== -1;
131
131
  if (isFunction || parts.length === 0 && !this.#raw) {
132
- const magicWord = isFunction ? title.slice(0, colon) : title, arg = isFunction && title.slice(colon + 1), cleaned = (0, string_1.removeComment)(magicWord), name = isFunction ? (0, string_1.trimStart)(cleaned) + (fullWidth ? ':' : '') : cleaned.trim(),
132
+ const magicWord = isFunction ? title.slice(0, colon) : title, arg = isFunction && title.slice(colon + 1), cleaned = (0, string_1.removeComment)(magicWord), name = isFunction ? cleaned.trimStart() + (fullWidth ? ':' : '') : cleaned.trim(),
133
133
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
134
134
  [, isSensitive, canonicalName] = (0, debug_1.getMagicWordInfo)(name, parserFunction), isFunc = !('functionHook' in config) || functionHook.includes(canonicalName), isVar = variable.includes(canonicalName);
135
135
  if (isFunction ? canonicalName && isFunc : isVar) {
package/dist/util/lint.js CHANGED
@@ -16,7 +16,7 @@ const tableTags = new Set(['tr', 'td', 'th', 'caption']), tableTemplates = new S
16
16
  const isFostered = (token) => {
17
17
  const first = token.childNodes.find(child => child.text().trim());
18
18
  if (!first
19
- || first.type === 'text' && first.data.trim().startsWith('!')
19
+ || first.type === 'text' && first.data.trimStart().startsWith('!')
20
20
  || first.is('magic-word') && first.name === '!'
21
21
  || first.is('template') && tableTemplates.has(first.name)
22
22
  || first.is('html') && tableTags.has(first.name)) {
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toLowerCase = exports.decodeNumber = exports.decodeHtml = exports.decodeHtmlBasic = exports.text = exports.removeCommentLine = exports.removeComment = exports.tidy = exports.trimStart = exports.trimLc = exports.extUrlChar = exports.extUrlCharFirst = exports.zs = void 0;
3
+ exports.toLowerCase = exports.decodeNumber = exports.decodeHtml = exports.decodeHtmlBasic = exports.text = exports.removeCommentLine = exports.removeComment = exports.tidy = exports.trimLc = exports.extUrlChar = exports.extUrlCharFirst = exports.zs = void 0;
4
4
  exports.restore = restore;
5
- const common_1 = require("@bhsd/common");
6
5
  exports.zs = String.raw ` \xA0\u1680\u2000-\u200A\u202F\u205F\u3000`;
7
6
  const commonExtUrlChar = String.raw `[^[\]<>"\0-\x1F\x7F${exports.zs}\uFFFD]`;
8
7
  exports.extUrlCharFirst = String.raw `(?:\[[\da-f:.]+\]|${commonExtUrlChar})`;
@@ -13,12 +12,6 @@ exports.extUrlChar = String.raw `(?:${commonExtUrlChar}|\0\d+[cn!~]\x7F)*`;
13
12
  */
14
13
  const trimLc = (s) => s.trim().toLowerCase();
15
14
  exports.trimLc = trimLc;
16
- /**
17
- * trim starting whitespaces
18
- * @param s 字符串
19
- */
20
- const trimStart = (s) => s.slice((0, common_1.numLeadingSpaces)(s));
21
- exports.trimStart = trimStart;
22
15
  function restore(s, stack, translate) {
23
16
  if (translate === 1) {
24
17
  return s.replace(/\0(\d+)g\x7F/gu, (_, p1) => restore(String(stack[p1]), stack, 2));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikilint",
3
- "version": "2.46.2",
3
+ "version": "2.46.3",
4
4
  "description": "A Node.js linter for MediaWiki markup",
5
5
  "keywords": [
6
6
  "mediawiki",
@@ -98,22 +98,22 @@
98
98
  }
99
99
  },
100
100
  "dependencies": {
101
- "@bhsd/cm-util": "^2.4.0",
102
- "@bhsd/common": "^4.0.1",
101
+ "@bhsd/cm-util": "^2.4.1",
102
+ "@bhsd/common": "^4.1.0",
103
103
  "@bhsd/stylelint-util": "^1.1.0",
104
104
  "culori": "^4.0.2",
105
105
  "entities": "^8.0.0",
106
106
  "vscode-languageserver-types": "^3.18.0"
107
107
  },
108
108
  "devDependencies": {
109
- "@bhsd/code-standard": "^4.0.0",
109
+ "@bhsd/code-standard": "^4.1.0",
110
110
  "@bhsd/nodejs": "^1.2.1",
111
- "@bhsd/test-util": "^3.1.0",
111
+ "@bhsd/test-util": "^3.1.1",
112
112
  "c8": "^12.0.0",
113
113
  "diff2html-cli": "^5.2.15",
114
- "esbuild": "^0.28.1",
115
- "eslint": "^10.8.0",
116
- "markdownlint-cli2": "^0.23.1",
114
+ "esbuild": "^0.28.2",
115
+ "eslint": "^10.8.1",
116
+ "markdownlint-cli2": "^0.23.2",
117
117
  "mathoid-texvcjs": "^0.6.0",
118
118
  "stylelint": "^17.14.1",
119
119
  "typescript": "^6.0.3",