wikilint 2.38.0 → 2.39.0

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
@@ -23,13 +23,16 @@ npx wikilint --config zhwiki --include --lang zh-hans *.wiki
23
23
  | `-c`, `--config` | \<path or preset config\> | Choose parser's [configuration](https://github.com/bhsd-harry/wikiparser-node/wiki/Parser-%28EN%29#config) | `default` |
24
24
  | `--cache` | | Enable caching | `false` |
25
25
  | `--cache-file` | \<path\> | Specify cache file and enable caching | `.wikilintcache` |
26
- | `--ext` | \<extension\> | Specify file extension<br>Can be used multiple times | all files |
26
+ | `-e`, `--ext` | \<extension\> | Specify file extension<br>Can be used multiple times | all files |
27
27
  | `--fix` | | Automatically fix problems | `false` |
28
28
  | `-h`, `--help` | | Print available options | |
29
29
  | `-i`, `--include` | | Parse for inclusion | `false` |
30
+ | `--id`, `--ignore-disables` | | Ignore inline configuration comments | `false` |
30
31
  | `--ignore` | \<pattern\> | Ignore files matching the glob pattern<br>Can be used multiple times | |
31
32
  | `-l`, `--lang` | \<path or preset language\> | Choose [i18n](https://github.com/bhsd-harry/wikiparser-node/wiki/Parser-%28EN%29#i18n) language | English |
32
33
  | `--lc`, `--lint-config` | \<path\> | Specify [lint config](https://github.com/bhsd-harry/wikiparser-node/wiki/Rules#configuration) file | `.wikilintrc.json`<br>`.wikilintrc.js`<br>`.wikilintrc.cjs`<br>`.wikilintrc.mjs` |
34
+ | `--nc`, `--no-color` | | Disable colored output | `false` |
35
+ | `--print-config`, `--print-lint-config` | | Print the resolved lint config and exit | |
33
36
  | `-q`, `--quiet` | | Report errors only | errors and warnings |
34
37
  | `-r`, `--recursive` | | Recursively lint files | `false` |
35
38
  | `-s`, `--strict` | | Exit when there is an error or warning<br>Override `-q` or `--quiet` | Exit `1` only where there is an error |
@@ -42,12 +45,12 @@ For MediaWiki sites with the [CodeMirror extension](https://mediawiki.org/wiki/E
42
45
  ```sh
43
46
  npx getParserConfig <site> <script path> [user] [force]
44
47
  # For example:
45
- npx getParserConfig jawiki https://ja.wikipedia.org/w user@example.net
48
+ npx getParserConfig frwiki https://fr.wikipedia.org/w user@example.net
46
49
  ```
47
50
 
48
51
  The generated configuration file will be saved in the `config` directory. You can then use the site name as the `--config` option.
49
52
 
50
53
  ```sh
51
54
  # For example:
52
- npx wikilint --config jawiki *.wiki
55
+ npx wikilint --config frwiki *.wiki
53
56
  ```
package/dist/base.d.mts CHANGED
@@ -7,7 +7,7 @@ export interface Config {
7
7
  readonly variable: string[];
8
8
  readonly functionHook: string[];
9
9
  readonly parserFunction: [Record<string, string>, Record<string, string>, string[], string[]];
10
- readonly doubleUnderscore: [string[], string[], Record<string, string>?, Record<string, string>?];
10
+ readonly doubleUnderscore: [string[], string[], Record<string, string>, Record<string, string>];
11
11
  readonly protocol: string;
12
12
  readonly interwiki: string[];
13
13
  readonly img: Record<string, string>;
@@ -124,7 +124,7 @@ export interface LanguageService {
124
124
  *
125
125
  * 销毁实例
126
126
  */
127
- destroy(): void;
127
+ destroy(): Promise<void>;
128
128
  /**
129
129
  * Provide color decorators
130
130
  *
@@ -264,6 +264,7 @@ export interface LanguageService {
264
264
  * @param user URI for wiki userpage or email address of the user / 维基用户页面地址或用户的电子邮件地址
265
265
  */
266
266
  setTargetWikipedia(wiki: string, user: string): Promise<void>;
267
+ [Symbol.dispose](): void;
267
268
  }
268
269
  export type SeverityLevel = 0 | 1 | 2 | false | 'off' | 'warning' | 'error';
269
270
  export type LintConfigValue = SeverityLevel | [SeverityLevel, Record<string, SeverityLevel>?];
package/dist/base.d.ts CHANGED
@@ -7,7 +7,7 @@ export interface Config {
7
7
  readonly variable: string[];
8
8
  readonly functionHook: string[];
9
9
  readonly parserFunction: [Record<string, string>, Record<string, string>, string[], string[]];
10
- readonly doubleUnderscore: [string[], string[], Record<string, string>?, Record<string, string>?];
10
+ readonly doubleUnderscore: [string[], string[], Record<string, string>, Record<string, string>];
11
11
  readonly protocol: string;
12
12
  readonly interwiki: string[];
13
13
  readonly img: Record<string, string>;
@@ -124,7 +124,7 @@ export interface LanguageService {
124
124
  *
125
125
  * 销毁实例
126
126
  */
127
- destroy(): void;
127
+ destroy(): Promise<void>;
128
128
  /**
129
129
  * Provide color decorators
130
130
  *
@@ -264,6 +264,7 @@ export interface LanguageService {
264
264
  * @param user URI for wiki userpage or email address of the user / 维基用户页面地址或用户的电子邮件地址
265
265
  */
266
266
  setTargetWikipedia(wiki: string, user: string): Promise<void>;
267
+ [Symbol.dispose](): void;
267
268
  }
268
269
  export type SeverityLevel = 0 | 1 | 2 | false | 'off' | 'warning' | 'error';
269
270
  export type LintConfigValue = SeverityLevel | [SeverityLevel, Record<string, SeverityLevel>?];
package/dist/bin/cli.js CHANGED
@@ -14,13 +14,16 @@ Available options:
14
14
  -c, --config <path or preset config> Choose parser's configuration
15
15
  --cache Enable caching
16
16
  --cache-file <path> Specify cache file
17
- --ext <extension> Specify file extension
17
+ -e, --ext <extension> Specify file extension
18
18
  --fix Automatically fix problems
19
19
  -h, --help Print available options
20
20
  -i, --include Parse for inclusion
21
+ --id, --ignore-disables Ignore inline configuration comments
21
22
  --ignore <pattern> Ignore files that match the pattern
22
23
  -l, --lang <path or preset language> Choose i18n language
23
24
  --lc, --lint-config <path> Specify lint config file
25
+ --nc, --no-color Disable colored output
26
+ --print-config, --print-lint-config Print resolved lint config and exit
24
27
  -q, --quiet Report errors only
25
28
  -r, --recursive Lint files in directories recursively
26
29
  -s, --strict Exit when there is an error or warning
@@ -28,8 +31,8 @@ Available options:
28
31
  -v, --version Print package version
29
32
  `, root = path_1.default.join(__dirname, '..', '..'), configPath = path_1.default.join(root, 'config'), preset = new Set(fs_1.default.readdirSync(configPath).filter(file => file.endsWith('.json'))
30
33
  .map(file => file.slice(0, -5))), lintConfigDefaults = ['.wikilintrc.json', '.wikilintrc.js', '.wikilintrc.cjs', '.wikilintrc.mjs'], i18n = new Set(fs_1.default.readdirSync(path_1.default.join(root, 'i18n')).filter(file => file.endsWith('.json'))
31
- .map(file => file.slice(0, -5))), { argv } = process, exts = [], ignorePatterns = [], jobs = [];
32
- let files = [], lintConfigFile, cacheFile = '.wikilintcache', cache, exiting = false, fixing = false, include = false, quiet = false, recursive = false, strict = false, caching = false, nErr = 0, nWarn = 0, nFixableErr = 0, nFixableWarn = 0, option;
34
+ .map(file => file.slice(0, -5))), colorSet = new Set(['red', 'yellow']), { argv } = process, exts = [], ignorePatterns = [], jobs = [];
35
+ let files = [], lintConfigFile, cacheFile = '.wikilintcache', cache, caching = false, colors = true, exiting = false, fixing = false, include = false, ignoreDisables = false, printLintConfig = false, quiet = false, recursive = false, strict = false, nErr = 0, nWarn = 0, nFixableErr = 0, nFixableWarn = 0, option;
33
36
  /**
34
37
  * exit with message
35
38
  * @param msg message
@@ -138,8 +141,17 @@ const throwOnCacheFile = (input) => {
138
141
  * @param word item name
139
142
  */
140
143
  const plural = (n, word) => `${n} ${word}${n === 1 ? '' : 's'}`;
141
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
142
- const styleText = util_1.default.styleText ?? ((_, text) => text);
144
+ /**
145
+ * style text if possible
146
+ * @param format style format
147
+ * @param text text to style
148
+ */
149
+ const styleText = (format, text) => {
150
+ if (!colors) {
151
+ format = (Array.isArray(format) ? format : [format]).filter(f => !colorSet.has(f));
152
+ }
153
+ return util_1.default.styleText(format, text);
154
+ };
143
155
  /**
144
156
  * color the severity
145
157
  * @param severity problem severity
@@ -152,16 +164,13 @@ for (let i = 2; i < argv.length; i++) {
152
164
  case '--config':
153
165
  throwOnConfig(argv[++i]);
154
166
  break;
155
- case '--lc':
156
- case '--lint-config':
157
- throwOnLintConfig(argv[++i]);
158
- break;
159
167
  case '--cache':
160
168
  caching = true;
161
169
  break;
162
170
  case '--cache-file':
163
171
  throwOnCacheFile(argv[++i]);
164
172
  break;
173
+ case '-e':
165
174
  case '--ext':
166
175
  throwOnExt(argv[++i]);
167
176
  break;
@@ -177,6 +186,10 @@ for (let i = 2; i < argv.length; i++) {
177
186
  case '--include':
178
187
  include = true;
179
188
  break;
189
+ case '--id':
190
+ case '--ignore-disables':
191
+ ignoreDisables = true;
192
+ break;
180
193
  case '--ignore':
181
194
  throwOnIgnore(argv[++i]);
182
195
  break;
@@ -184,6 +197,18 @@ for (let i = 2; i < argv.length; i++) {
184
197
  case '--lang':
185
198
  throwOnLang(argv[++i]);
186
199
  break;
200
+ case '--lc':
201
+ case '--lint-config':
202
+ throwOnLintConfig(argv[++i]);
203
+ break;
204
+ case '--nc':
205
+ case '--no-color':
206
+ colors = false;
207
+ break;
208
+ case '--print-config':
209
+ case '--print-lint-config':
210
+ printLintConfig = true;
211
+ break;
187
212
  case '-q':
188
213
  case '--quiet':
189
214
  quiet = true;
@@ -223,6 +248,10 @@ for (let i = 2; i < argv.length; i++) {
223
248
  case '--lang':
224
249
  throwOnLang(value);
225
250
  break;
251
+ case '--lc':
252
+ case '--lint-config':
253
+ throwOnLintConfig(value);
254
+ break;
226
255
  default:
227
256
  known = false;
228
257
  }
@@ -307,8 +336,16 @@ const { mtimeMs } = fs_1.default.statSync(config), obj = cache?.[include ? 'incl
307
336
  cur = path_1.default.dirname(cur);
308
337
  }
309
338
  }
310
- index_1.default.lintConfig.computeEditInfo = false;
311
- index_1.default.lintConfig.fix = true;
339
+ index_1.default.lintConfig.computeEditInfo = true;
340
+ index_1.default.lintConfig.fix = fixing;
341
+ index_1.default.lintConfig.ignoreDisables = ignoreDisables;
342
+ if (printLintConfig) {
343
+ console.log(util_1.default.inspect({
344
+ ...index_1.default.lintConfig, // eslint-disable-line @typescript-eslint/no-misused-spread
345
+ rules: index_1.default.lintConfig.rules,
346
+ }, { depth: null, colors }));
347
+ process.exit(0);
348
+ }
312
349
  for (const file of new Set(files.map(f => path_1.default.resolve(f)))) {
313
350
  const stat = fs_1.default.statSync(file);
314
351
  if (stat.isDirectory()) {
@@ -16,7 +16,8 @@ const diff_1 = require("../util/diff");
16
16
  * @param config.articlePath article path
17
17
  */
18
18
  const arrToObj = ({ articlePath, ...obj }) => {
19
- for (const [k, v] of Object.entries(obj)) {
19
+ for (const k in obj) {
20
+ const v = obj[k];
20
21
  if (Array.isArray(v) && v.every(x => typeof x === 'string')) {
21
22
  Object.assign(obj, { [k]: Object.fromEntries(v.map(x => [x, true])) });
22
23
  }
@@ -39,7 +40,7 @@ const filterGadget = (id) => {
39
40
  const n = Number(id);
40
41
  return n < 2300 || n > 2303; // Gadget, Gadget talk, Gadget definition, Gadget definition talk
41
42
  };
42
- const pkg = "wikilint", version = "2.38.0";
43
+ const pkg = "wikilint", version = "2.39.0";
43
44
  /**
44
45
  * Get the parser configuration for a Wikimedia Foundation project.
45
46
  * @param site site nickname
@@ -147,9 +148,9 @@ exports.default = async (site, url, user, force, internal) => {
147
148
  }
148
149
  else {
149
150
  const oldConfig = arrToObj(require(file)), newConfig = arrToObj(config);
150
- for (const [k, v] of Object.entries(newConfig)) {
151
+ for (const k in newConfig) {
151
152
  try {
152
- strict_1.default.deepStrictEqual(oldConfig[k], v);
153
+ strict_1.default.deepStrictEqual(oldConfig[k], newConfig[k]);
153
154
  }
154
155
  catch (e) {
155
156
  if (e instanceof strict_1.default.AssertionError) {
package/dist/index.js CHANGED
@@ -26,6 +26,7 @@ const jsonRequire = (file) => {
26
26
  if (fullPath.endsWith('.json')) {
27
27
  return require(fullPath);
28
28
  }
29
+ /* c8 ignore next */
29
30
  throw new RangeError('Only JSON files are supported!');
30
31
  };
31
32
  /**
@@ -107,7 +108,7 @@ const Parser = {
107
108
  this.config = rootRequire(this.config, 'config');
108
109
  }
109
110
  /* c8 ignore next 3 */
110
- if (this.config.doubleUnderscore.length < 3 || !('functionHook' in this.config)) {
111
+ if (!('functionHook' in this.config)) {
111
112
  (0, diff_1.error)(`The schema (${path_1.default.join(__dirname, '..', 'config', '.schema.json')}) of parser configuration is updated.`);
112
113
  }
113
114
  return this.getConfig();
@@ -115,7 +116,7 @@ const Parser = {
115
116
  /* NOT FOR BROWSER ONLY END */
116
117
  const parserConfig = config ?? this.config, { doubleUnderscore, ext, parserFunction, variable, } = parserConfig;
117
118
  for (let i = 0; i < 2; i++) {
118
- if (doubleUnderscore.length > i + 2 && doubleUnderscore[i].length === 0) {
119
+ if (doubleUnderscore[i].length === 0) {
119
120
  doubleUnderscore[i] = Object.keys(doubleUnderscore[i + 2]);
120
121
  }
121
122
  }
@@ -200,7 +201,7 @@ const Parser = {
200
201
  catch (e) /* c8 ignore start */ {
201
202
  if (e instanceof Error) {
202
203
  const file = path_1.default.join(__dirname, '..', 'errors', new Date().toISOString()), stage = token.getAttribute('stage');
203
- for (const k of Object.keys(config)) {
204
+ for (const k in config) {
204
205
  if (k.startsWith('regex') || config[k] instanceof Set) {
205
206
  delete config[k];
206
207
  }
@@ -263,7 +264,7 @@ const def = {
263
264
  /* NOT FOR BROWSER ONLY */
264
265
  'fetchConfig',
265
266
  ]);
266
- for (const key of Object.keys(Parser)) {
267
+ for (const key in Parser) {
267
268
  if (!enumerable.has(key)) {
268
269
  def[key] = { enumerable: false };
269
270
  }
@@ -287,8 +287,8 @@ class LintRuleConfiguration {
287
287
  if (!config) {
288
288
  return;
289
289
  }
290
- for (const [key, value] of Object.entries(config)) {
291
- set(this, key, value);
290
+ for (const key in config) {
291
+ set(this, key, config[key]);
292
292
  }
293
293
  }
294
294
  /** @implements */
@@ -330,7 +330,8 @@ class LintConfiguration {
330
330
  else {
331
331
  const { rules: ruleConfig, ...other } = (config ?? {});
332
332
  this.rules = ruleConfig;
333
- for (const [key, value] of Object.entries(other)) {
333
+ for (const key in other) {
334
+ const value = other[key];
334
335
  if (value !== undefined && Object.prototype.hasOwnProperty.call(defaultLintConfig, key)) {
335
336
  this[key] = value;
336
337
  }
package/dist/lib/lsp.d.ts CHANGED
@@ -16,7 +16,7 @@ export declare class LanguageService implements LanguageServiceBase {
16
16
  /** @param uri 任务标识 */
17
17
  constructor(uri: object);
18
18
  /** @implements */
19
- destroy(): void;
19
+ destroy(): Promise<void>;
20
20
  /**
21
21
  * Provide color decorators
22
22
  *
@@ -160,4 +160,6 @@ export declare class LanguageService implements LanguageServiceBase {
160
160
  * @since v1.18.1
161
161
  */
162
162
  setTargetWikipedia(wiki: string, user: string): Promise<void>;
163
+ /** @implements */
164
+ [Symbol.dispose](): void;
163
165
  }
package/dist/lib/lsp.js CHANGED
@@ -254,6 +254,7 @@ const partialParse = async (wikitext, watch, include, config = index_1.default.g
254
254
  set(parseOnce, 0);
255
255
  }
256
256
  else {
257
+ /* c8 ignore next */
257
258
  resolve();
258
259
  }
259
260
  },
@@ -393,19 +394,12 @@ class LanguageService {
393
394
  });
394
395
  }
395
396
  /** @implements */
396
- destroy() {
397
+ async destroy() {
397
398
  Object.setPrototypeOf(this, null);
398
399
  /* NOT FOR BROWSER ONLY */
399
400
  const dir = path_1.default.join(__dirname, 'lilypond');
400
401
  if (fs_1.default.existsSync(dir)) {
401
- for (const file of fs_1.default.readdirSync(dir)) {
402
- (async () => {
403
- try {
404
- await fs_1.default.promises.unlink(path_1.default.join(dir, file));
405
- }
406
- catch { }
407
- })();
408
- }
402
+ await Promise.allSettled(fs_1.default.readdirSync(dir).map(file => fs_1.default.promises.unlink(path_1.default.join(dir, file))));
409
403
  }
410
404
  }
411
405
  /** 检查解析设置有无更新 */
@@ -505,6 +499,7 @@ class LanguageService {
505
499
  colors = new RegExp(String.raw `\b${Object.keys(colorName).join('|')}\b`, 'giu');
506
500
  }
507
501
  catch {
502
+ /* c8 ignore next */
508
503
  colors = false;
509
504
  }
510
505
  }
@@ -616,7 +611,7 @@ class LanguageService {
616
611
  * @param position position / 位置
617
612
  */
618
613
  async provideCompletionItems(text, position) {
619
- 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;
614
+ 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;
620
615
  if (mt?.[1] !== undefined) { // tag
621
616
  const closing = mt[1].startsWith('/');
622
617
  return getCompletion(allTags, 'Class', mt[1].slice(closing ? 1 : 0), position, closing && !curLine?.slice(character).trim().startsWith('>') ? '>' : '');
@@ -930,8 +925,9 @@ class LanguageService {
930
925
  let lilypondDiagnostics = [];
931
926
  if (this.lilypond) {
932
927
  const tokens = root.querySelectorAll('ext#score').filter(token => {
933
- const lang = token.getAttr('lang');
934
- return (lang === undefined || lang === 'lilypond') && token.innerText;
928
+ const lang = token.getAttr('lang'), { innerText } = token;
929
+ return (lang === undefined || lang === 'lilypond') && innerText?.trim()
930
+ && !/[#$](?!@?\s*(?:'\s*)?(?:[#"]|-?\.?\d|[a-z_][-:\w]*(?![^)\]}\s])))/iu.test(innerText);
935
931
  });
936
932
  if (tokens.length > 0) {
937
933
  const dir = path_1.default.join(__dirname, 'lilypond');
@@ -949,7 +945,7 @@ class LanguageService {
949
945
  fs_1.default.writeFileSync(file, score);
950
946
  try {
951
947
  // eslint-disable-next-line @typescript-eslint/strict-void-return
952
- await util_1.default.promisify(child_process_1.execFile)(this.lilypond, ['-s', '-o', dir, file]);
948
+ await util_1.default.promisify(child_process_1.execFile)(this.lilypond, ['-dno-print-pages', '-s', '-o', dir, file]);
953
949
  scores.set(score, []);
954
950
  }
955
951
  catch (e) {
@@ -1609,5 +1605,9 @@ class LanguageService {
1609
1605
  }
1610
1606
  Object.assign(this.config, { articlePath: `${host}/wiki/` });
1611
1607
  }
1608
+ /** @implements */
1609
+ [Symbol.dispose]() {
1610
+ void this.destroy();
1611
+ }
1612
1612
  }
1613
1613
  exports.LanguageService = LanguageService;
@@ -46,9 +46,9 @@ export declare class Title {
46
46
  */
47
47
  constructor(title: string, defaultNs: number, config: Config, { temporary, decode, selfLink, page }?: TitleOptions);
48
48
  /**
49
- * Check if the title is a redirect
49
+ * Check if the title is a redirect and get the redirect target
50
50
  *
51
- * 检测是否是重定向
51
+ * 检测是否是重定向并获取重定向目标
52
52
  * @since v1.12.2
53
53
  */
54
54
  getRedirection(): [boolean, string];
package/dist/lib/title.js CHANGED
@@ -134,8 +134,9 @@ class Title {
134
134
  /**
135
135
  * 生成标题
136
136
  * @param prefix 前缀
137
+ * @param redirect 是否允许重定向
137
138
  */
138
- #getTitle(prefix) {
139
+ #getTitle(prefix, redirect = true) {
139
140
  let title = (prefix + this.main).replace(/ /gu, '_');
140
141
  if (title.startsWith('/')) {
141
142
  title = (this.page ?? '') + title.replace(/(.)\/$/u, '$1');
@@ -149,9 +150,9 @@ class Title {
149
150
  return [false, title];
150
151
  }
151
152
  /**
152
- * Check if the title is a redirect
153
+ * Check if the title is a redirect and get the redirect target
153
154
  *
154
- * 检测是否是重定向
155
+ * 检测是否是重定向并获取重定向目标
155
156
  * @since v1.12.2
156
157
  */
157
158
  getRedirection() {
@@ -29,7 +29,7 @@ const parseHrAndDoubleUnderscore = ({ firstChild: { data }, type, name }, config
29
29
  if (caseSensitive || caseInsensitive) {
30
30
  // @ts-expect-error abstract class
31
31
  new doubleUnderscore_1.DoubleUnderscoreToken(key, caseSensitive, Boolean(p4), config, accum);
32
- return `\0${accum.length - 1}${caseInsensitive && (aliases?.[lc] ?? /* c8 ignore next */ lc) === 'toc' ? 'u' : 'n'}\x7F`;
32
+ return `\0${accum.length - 1}${caseInsensitive && (aliases[lc] ?? /* c8 ignore next */ lc) === 'toc' ? 'u' : 'n'}\x7F`;
33
33
  }
34
34
  return m;
35
35
  });
@@ -89,7 +89,7 @@ const parseTable = ({ firstChild: { data }, type, name }, config, accum) => {
89
89
  else if (row) {
90
90
  top = pop(top, stack);
91
91
  if (top.is('tr')) {
92
- top = stack.pop();
92
+ top = stack.pop(); // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion
93
93
  }
94
94
  // @ts-expect-error abstract class
95
95
  const tr = new tr_1.TrToken(`\n${spaces}${row}`, attr, config, accum);
@@ -135,7 +135,7 @@ class AttributeToken extends index_2.Token {
135
135
  // 不支持通用HTML属性的扩展标签
136
136
  type === 'ext-attr' && !attrs2
137
137
  // 或非通用HTML属性
138
- || !/^(?:xmlns:[\w:.-]+|data-(?!ooui|mw|parsoid)[^:]*)$/u.test(name)
138
+ || !/^(?:xmlns:[\w:.-]+|data-(?!ooui|mw|parsoid)[^:_]*)$/u.test(name)
139
139
  && (tag === 'meta' || tag === 'link' || !sharable_1.commonHtmlAttrs.has(name)))
140
140
  || (name === 'itemtype' || name === 'itemid' || name === 'itemref')
141
141
  && !parentNode?.hasAttr('itemscope')) {
@@ -1,6 +1,7 @@
1
+ import Parser from '../../index';
1
2
  import { Token } from '../index';
2
3
  import { AtomToken } from '../atom';
3
- import type { Config, LintError } from '../../base';
4
+ import type { LintError } from '../../base';
4
5
  import type { Title } from '../../lib/title';
5
6
  /**
6
7
  * internal link
@@ -22,5 +23,5 @@ export declare abstract class LinkBaseToken extends Token {
22
23
  * @param linkText 链接显示文字
23
24
  * @param delimiter `|`
24
25
  */
25
- constructor(link: string, linkText?: string, config?: Config, accum?: Token[], delimiter?: string);
26
+ constructor(link: string, linkText?: string, config?: Parser.Config, accum?: Token[], delimiter?: string);
26
27
  }
@@ -81,11 +81,11 @@ let LinkBaseToken = (() => {
81
81
  * @param linkText 链接显示文字
82
82
  * @param delimiter `|`
83
83
  */
84
- constructor(link, linkText, config, accum = [], delimiter = '|') {
84
+ constructor(link, linkText, config = index_1.default.getConfig(), accum = [], delimiter = '|') {
85
85
  super(undefined, config, accum, {});
86
86
  this.insertAt(new atom_1.AtomToken(link, 'link-target', config, accum, {}));
87
87
  if (linkText !== undefined) {
88
- const inner = new index_2.Token(linkText, config, accum, {});
88
+ const inner = new index_2.Token(linkText, { ...config, excludes: [...config.excludes, 'list'] }, accum);
89
89
  inner.type = 'link-text';
90
90
  inner.setAttribute('stage', constants_1.MAX_STAGE - 1);
91
91
  this.insertAt(inner);
@@ -70,7 +70,7 @@ let DoubleUnderscoreToken = (() => {
70
70
  constructor(word, sensitive, fullWidth, config, accum) {
71
71
  super(word, config, accum);
72
72
  const lc = word.toLowerCase(), [, , iAlias, sAlias] = config.doubleUnderscore;
73
- this.setAttribute('name', (sensitive ? sAlias?.[word]?.toLowerCase() : iAlias?.[lc]) ?? lc);
73
+ this.setAttribute('name', (sensitive ? sAlias[word]?.toLowerCase() : iAlias[lc]) ?? lc);
74
74
  this.#fullWidth = fullWidth;
75
75
  }
76
76
  /** @private */
@@ -55,7 +55,7 @@ const decodeHtml = (str) => {
55
55
  if (typeof process === 'object' && typeof process.versions?.node === 'string') {
56
56
  try {
57
57
  const { decodeHTMLStrict } = require('entities');
58
- return (s) => decodeHTMLStrict(s).replace(/\xA0/gu, ' ');
58
+ return (s) => decodeHTMLStrict(s).replaceAll('\xA0', ' ');
59
59
  }
60
60
  catch /* c8 ignore next */ { }
61
61
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikilint",
3
- "version": "2.38.0",
3
+ "version": "2.39.0",
4
4
  "description": "A Node.js linter for MediaWiki markup",
5
5
  "keywords": [
6
6
  "mediawiki",
@@ -39,6 +39,7 @@
39
39
  "url": "git+https://github.com/bhsd-harry/wikiparser-node.git"
40
40
  },
41
41
  "scripts": {
42
+ "ls": "npm i --package-lock-only && npm ls --package-lock-only --all --omit=dev",
42
43
  "prepublishOnly": "npm run build:core",
43
44
  "build:core": "bash build.sh",
44
45
  "build:define": "bash sed.sh -i \"s/pkg = \\$PKG/pkg = $(npm pkg get name)/; s/version = \\$VERSION/version = $(npm pkg get version)/\" dist/bin/config.js",
@@ -75,7 +76,7 @@
75
76
  "dependencies": {
76
77
  "@bhsd/cm-util": "^1.0.0",
77
78
  "@bhsd/common": "^2.0.0",
78
- "@bhsd/stylelint-util": "^1.0.1",
79
+ "@bhsd/stylelint-util": "^1.0.2",
79
80
  "binary-search": "^1.3.6",
80
81
  "vscode-languageserver-types": "^3.17.5"
81
82
  },
@@ -83,40 +84,43 @@
83
84
  "color-name": "^2.0.0",
84
85
  "entities": "^8.0.0",
85
86
  "mathoid-texvcjs": "^0.6.0",
86
- "stylelint": "^17.6.0",
87
+ "stylelint": "^17.9.0",
87
88
  "vscode-css-languageservice": "^6.3.10",
88
89
  "vscode-html-languageservice": "^5.6.2",
89
90
  "vscode-json-languageservice": "^5.7.2"
90
91
  },
91
92
  "devDependencies": {
92
- "@bhsd/code-standard": "^2.1.1",
93
+ "@bhsd/code-standard": "^2.2.0",
93
94
  "@bhsd/nodejs": "^1.0.0",
94
- "@bhsd/test-util": "^1.0.0",
95
+ "@bhsd/test-util": "^1.1.0",
96
+ "@eslint-community/eslint-plugin-eslint-comments": "^4.7.1",
95
97
  "@stylistic/eslint-plugin": "^5.10.0",
96
98
  "@types/color-name": "^2.0.0",
97
99
  "@types/color-rgba": "^2.1.3",
98
100
  "@types/mocha": "^10.0.10",
99
101
  "@types/node": "^24.11.0",
100
- "@typescript-eslint/eslint-plugin": "^8.58.0",
101
- "@typescript-eslint/parser": "^8.58.0",
102
+ "@typescript-eslint/eslint-plugin": "^8.59.0",
103
+ "@typescript-eslint/parser": "^8.59.0",
102
104
  "c8": "^11.0.0",
103
105
  "color-rgba": "^3.0.0",
104
106
  "diff2html-cli": "^5.2.15",
105
- "esbuild": "^0.27.4",
106
- "eslint": "^9.39.4",
107
- "eslint-plugin-eslint-comments": "^3.2.0",
108
- "eslint-plugin-jsdoc": "^62.7.1",
109
- "eslint-plugin-jsonc": "^3.1.1",
107
+ "esbuild": "^0.28.0",
108
+ "eslint": "^10.2.1",
109
+ "eslint-plugin-jsdoc": "^62.9.0",
110
+ "eslint-plugin-jsonc": "^3.1.2",
110
111
  "eslint-plugin-n": "^17.24.0",
111
112
  "eslint-plugin-promise": "^7.2.1",
112
113
  "eslint-plugin-regexp": "^3.1.0",
113
- "eslint-plugin-unicorn": "^63.0.0",
114
- "markdownlint-cli2": "^0.21.0",
114
+ "eslint-plugin-unicorn": "^64.0.0",
115
+ "markdownlint-cli2": "^0.22.1",
115
116
  "mocha": "^11.7.5",
116
- "typescript": "^6.0.2",
117
+ "typescript": "^6.0.3",
117
118
  "v8r": "^6.0.0",
118
119
  "vscode-languageserver-textdocument": "^1.0.12"
119
120
  },
121
+ "overrides": {
122
+ "eslint": "^10.2.1"
123
+ },
120
124
  "engines": {
121
125
  "node": "^20.19.0 || ^22.13.0 || >=24.11.0"
122
126
  }