wikiparser-node 1.26.0 → 1.27.1

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.
@@ -390,9 +390,18 @@
390
390
  "label": "NOSEP",
391
391
  "const": true
392
392
  }
393
+ ],
394
+ [
395
+ {
396
+ "label": "unformatted number"
397
+ },
398
+ {
399
+ "label": "LOSSLESS",
400
+ "const": true
401
+ }
393
402
  ]
394
403
  ],
395
- "description": "Takes an unformatted number (Arabic, no group separators and `.` as decimal separator) and outputs it in the localized digit script and formatted with decimal and decimal group separators, according to the page language.\n\nThe `|R` parameter can be used to reverse the behavior, for use in mathematical situations: it's reliable and should be used only to deformat numbers which are known to be formatted exactly as formatnum formats them with the wiki's locale.\n\nThe `NOSEP` (\"no separators\") parameter means that no group / decimal separators are changed; formatnum will only transform the digits themselves in languages which don't use the [Hindu–Arabic numeral system](https://en.wikipedia.org/wiki/Hindu%E2%80%93Arabic_numeral_system). `NOSEP` can also prevent non-standard digit groupings you wouldn't expect."
404
+ "description": "Takes an unformatted number (Arabic, no group separators and `.` as decimal separator) and outputs it in the localized digit script and formatted with decimal and decimal group separators, according to the page language.\n\nThe `|R` parameter can be used to reverse the behavior, for use in mathematical situations: it's reliable and should be used only to deformat numbers which are known to be formatted exactly as formatnum formats them with the wiki's locale.\n\nThe `NOSEP` (\"no separators\") parameter means that no group / decimal separators are changed; formatnum will only transform the digits themselves in languages which don't use the [Hindu–Arabic numeral system](https://en.wikipedia.org/wiki/Hindu%E2%80%93Arabic_numeral_system). `NOSEP` can also prevent non-standard digit groupings you wouldn't expect.\n\nBy default, the formatted number may be slightly imprecise. The `LOSSLESS` parameter can be added to instead use the unformatted (exact) number in this case."
396
405
  },
397
406
  {
398
407
  "aliases": [
@@ -611,7 +620,7 @@
611
620
  }
612
621
  ]
613
622
  ],
614
- "description": "Outputs a plural form appropriate for the given language. For English, the singular form (second parameter) is used if the absolute value of the first parameter is an expression equalling one; and the the plural form (third parameter) is used otherwise. See further documentation [on translatewiki.net](https://translatewiki.net/wiki/Plural#Plural_in_MediaWiki)."
623
+ "description": "Outputs a plural form appropriate for the given language. For English, the singular form (second parameter) is used if the absolute value of the first parameter is an expression equalling one; and the plural form (third parameter) is used otherwise. See further documentation [on translatewiki.net](https://translatewiki.net/wiki/Plural#Plural_in_MediaWiki)."
615
624
  },
616
625
  {
617
626
  "aliases": [
@@ -639,7 +648,21 @@
639
648
  "label": "username"
640
649
  },
641
650
  {
642
- "label": "text for every gender"
651
+ "label": "gender-neutral text"
652
+ }
653
+ ],
654
+ [
655
+ {
656
+ "label": "username"
657
+ },
658
+ {
659
+ "label": "male text"
660
+ },
661
+ {
662
+ "label": "female text"
663
+ },
664
+ {
665
+ "label": "text for unspecified gender"
643
666
  }
644
667
  ],
645
668
  [
@@ -654,7 +677,7 @@
654
677
  "label": "female text"
655
678
  },
656
679
  {
657
- "label": "text for unspecified"
680
+ "label": "text for unspecified gender"
658
681
  }
659
682
  ],
660
683
  [
@@ -669,11 +692,27 @@
669
692
  "label": "female text"
670
693
  },
671
694
  {
672
- "label": "text for unspecified"
695
+ "label": "text for unspecified gender"
696
+ }
697
+ ]
698
+ ],
699
+ "description": "A switch for the gender set by the user in Special:Preferences.\n\nIf only two parameters are used (for male and female text) but the 3rd parameter is omitted, and user hasn't defined their gender, then the first parameter (`male text`) is returned as a default.\n\nA blank username field (`{{GENDER:|`) means the current user, but can be used only in interface messages (MediaWiki namespace).\n\nUsing a dot (`.`) in the username field produces the output corresponding to the default user gender on this wiki."
700
+ },
701
+ {
702
+ "aliases": [
703
+ "#formal"
704
+ ],
705
+ "signatures": [
706
+ [
707
+ {
708
+ "label": "informal text"
709
+ },
710
+ {
711
+ "label": "formal text"
673
712
  }
674
713
  ]
675
714
  ],
676
- "description": "A switch for the gender set in Special:Preferences.\n\n**Note:** If 3rd parameter is omitted and user hasn't defined their gender, then `male text` is returned.\n\nA blank username field (`{{GENDER:|`) means the current user, but can be used only in interface messages (MediaWiki namespace).\n\nA dot username (`.`) means the default user gender on this wiki."
715
+ "description": "A switch for the formality index set by the configuration for certain languages. The default formality index is 0 (informal), but some language codes have the formality index 1 (formal). For these languages, what is displayed for the end user depends on whether their interface language is set to the formal or informal language code."
677
716
  },
678
717
  {
679
718
  "aliases": [
@@ -1848,7 +1887,7 @@
1848
1887
  }
1849
1888
  ]
1850
1889
  ],
1851
- "description": "Outputs the protection level (e.g. \"autoconfirmed\", \"sysop\") for a given action (e.g. \"edit\", \"move\") on the current page. Returns an empty string if not protected.\n\n**[Expensive]** Outputs the protection level on the specified page."
1890
+ "description": "Outputs the protection level (e.g. `autoconfirmed`, `sysop`) for a given action (e.g. `edit`, `move`) on the current page. Returns an empty string if not protected.\n\n**[Expensive]** Outputs the protection level on the specified page."
1852
1891
  },
1853
1892
  {
1854
1893
  "aliases": [
@@ -1885,6 +1924,33 @@
1885
1924
  ],
1886
1925
  "description": "**[Expensive]** Returns the sources of any cascading protection acting on the current page or the specified page. Pages will not return their own title unless they transclude themselves."
1887
1926
  },
1927
+ {
1928
+ "aliases": [
1929
+ "#contentmodel"
1930
+ ],
1931
+ "signatures": [
1932
+ [],
1933
+ [
1934
+ {
1935
+ "label": "canonical",
1936
+ "const": true
1937
+ },
1938
+ {
1939
+ "label": "page name"
1940
+ }
1941
+ ],
1942
+ [
1943
+ {
1944
+ "label": "local",
1945
+ "const": true
1946
+ },
1947
+ {
1948
+ "label": "page name"
1949
+ }
1950
+ ]
1951
+ ],
1952
+ "description": "The canonical or localized name of the content model of the specified page."
1953
+ },
1888
1954
  {
1889
1955
  "aliases": [
1890
1956
  "revisionid"
@@ -1897,7 +1963,7 @@
1897
1963
  }
1898
1964
  ]
1899
1965
  ],
1900
- "description": "Unique revision ID. It is always empty in preview, thus one can show an error message only in preview. May be disabled in [miser mode (all WMF wikis)](https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgMiserMode) returning `-` instead when not in preview.\n\n**[Expensive]** Unique revision ID of the last revision on the specified page."
1966
+ "description": "Unique revision ID.\n\nIt is always empty in preview, thus one can show an error message only in preview. May be disabled in [miser mode (all WMF wikis)](https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgMiserMode) returning `-` instead when not in preview.\n\n**Warning**: This variable **cannot** be [substituted](https://www.mediawiki.org/wiki/Help:Substitution).\n\n**[Expensive]** Unique revision ID of the last revision on the specified page."
1901
1967
  },
1902
1968
  {
1903
1969
  "aliases": [
@@ -2257,7 +2323,7 @@
2257
2323
  }
2258
2324
  ]
2259
2325
  ],
2260
- "description": "Namespace and full page title (including all subpage levels)."
2326
+ "description": "Namespace and full page name (including all subpage levels)."
2261
2327
  },
2262
2328
  {
2263
2329
  "aliases": [
@@ -2271,7 +2337,7 @@
2271
2337
  }
2272
2338
  ]
2273
2339
  ],
2274
- "description": "URL encoded namespace and full page title (including all subpage levels)."
2340
+ "description": "URL encoded namespace and full page name (including all subpage levels)."
2275
2341
  },
2276
2342
  {
2277
2343
  "aliases": [
@@ -2285,7 +2351,7 @@
2285
2351
  }
2286
2352
  ]
2287
2353
  ],
2288
- "description": "Full page title (including all subpage levels) without the namespace."
2354
+ "description": "The page name, including all subpage levels, but without the namespace."
2289
2355
  },
2290
2356
  {
2291
2357
  "aliases": [
@@ -2299,7 +2365,7 @@
2299
2365
  }
2300
2366
  ]
2301
2367
  ],
2302
- "description": "URL encoded full page title (including all subpage levels) without the namespace."
2368
+ "description": "URL encoded page name, including all subpage levels, but without the namespace."
2303
2369
  },
2304
2370
  {
2305
2371
  "aliases": [
@@ -2313,7 +2379,7 @@
2313
2379
  }
2314
2380
  ]
2315
2381
  ],
2316
- "description": "Page title of the page in the immediately superior [subpage](https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Subpages) level without the namespace."
2382
+ "description": "Page name of the page in the immediately superior [subpage](https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Subpages) level without the namespace."
2317
2383
  },
2318
2384
  {
2319
2385
  "aliases": [
@@ -2327,7 +2393,7 @@
2327
2393
  }
2328
2394
  ]
2329
2395
  ],
2330
- "description": "URL encoded page title of the page in the immediately superior [subpage](https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Subpages) level without the namespace."
2396
+ "description": "URL encoded page name of the page in the immediately superior [subpage](https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Subpages) level without the namespace."
2331
2397
  },
2332
2398
  {
2333
2399
  "aliases": [
@@ -2369,7 +2435,7 @@
2369
2435
  }
2370
2436
  ]
2371
2437
  ],
2372
- "description": "The [subpage](https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Subpages) title. If no subpage exists the value of `{{PAGENAME}}` is returned."
2438
+ "description": "The [subpage](https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Subpages) title. If no subpage exists, the value of `{{PAGENAME}}` is returned."
2373
2439
  },
2374
2440
  {
2375
2441
  "aliases": [
@@ -2383,7 +2449,7 @@
2383
2449
  }
2384
2450
  ]
2385
2451
  ],
2386
- "description": "The URL encoded [subpage](https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Subpages) title. If no subpage exists the value of `{{PAGENAME}}` is returned."
2452
+ "description": "The URL encoded [subpage](https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Subpages) title. If no subpage exists, the value of `{{PAGENAME}}` is returned."
2387
2453
  },
2388
2454
  {
2389
2455
  "aliases": [
package/dist/base.d.mts CHANGED
@@ -294,8 +294,8 @@ export interface LanguageService {
294
294
  */
295
295
  setTargetWikipedia(wiki: string, user: string): Promise<void>;
296
296
  }
297
- export type SeverityLevel = 0 | 1 | 2;
298
- export type LintConfigValue = SeverityLevel | [SeverityLevel, Record<string, SeverityLevel>];
297
+ export type SeverityLevel = 0 | 1 | 2 | false | 'off' | 'warning' | 'error';
298
+ export type LintConfigValue = SeverityLevel | [SeverityLevel, Record<string, SeverityLevel>?];
299
299
  export type LintRuleConfig = Partial<Record<LintError.Rule, LintConfigValue>>;
300
300
  export interface FullLintConfig {
301
301
  rules: LintRuleConfig;
package/dist/base.d.ts CHANGED
@@ -294,8 +294,8 @@ export interface LanguageService {
294
294
  */
295
295
  setTargetWikipedia(wiki: string, user: string): Promise<void>;
296
296
  }
297
- export type SeverityLevel = 0 | 1 | 2;
298
- export type LintConfigValue = SeverityLevel | [SeverityLevel, Record<string, SeverityLevel>];
297
+ export type SeverityLevel = 0 | 1 | 2 | false | 'off' | 'warning' | 'error';
298
+ export type LintConfigValue = SeverityLevel | [SeverityLevel, Record<string, SeverityLevel>?];
299
299
  export type LintRuleConfig = Partial<Record<LintError.Rule, LintConfigValue>>;
300
300
  export interface FullLintConfig {
301
301
  rules: LintRuleConfig;
@@ -77,7 +77,7 @@ const mw = {
77
77
  },
78
78
  },
79
79
  };
80
- const pkg = "wikiparser-node", version = "1.26.0";
80
+ const pkg = "wikiparser-node", version = "1.27.1";
81
81
  let mwConfig;
82
82
  /**
83
83
  * Get the parser configuration for a Wikimedia Foundation project.
@@ -32,6 +32,7 @@ const loadMathJax = (id = 'mathjax') => {
32
32
  return MathJax;
33
33
  }
34
34
  catch {
35
+ /* istanbul ignore next */
35
36
  return undefined;
36
37
  }
37
38
  };
@@ -58,6 +59,7 @@ exports.jsonLSP = (() => {
58
59
  };
59
60
  }
60
61
  catch {
62
+ /* istanbul ignore next */
61
63
  return false;
62
64
  }
63
65
  }).filter(Boolean),
@@ -65,6 +67,7 @@ exports.jsonLSP = (() => {
65
67
  return lsp;
66
68
  }
67
69
  catch {
70
+ /* istanbul ignore next */
68
71
  return undefined;
69
72
  }
70
73
  })();
@@ -74,6 +77,7 @@ exports.cssLSP = (() => {
74
77
  .getCSSLanguageService();
75
78
  }
76
79
  catch {
80
+ /* istanbul ignore next */
77
81
  return undefined;
78
82
  }
79
83
  })();
@@ -83,6 +87,7 @@ exports.htmlData = (() => {
83
87
  .getDefaultHTMLDataProvider();
84
88
  }
85
89
  catch {
90
+ /* istanbul ignore next */
86
91
  return undefined;
87
92
  }
88
93
  })();
@@ -91,6 +96,7 @@ exports.stylelint = (async () => {
91
96
  return (await import('stylelint')).default;
92
97
  }
93
98
  catch {
99
+ /* istanbul ignore next */
94
100
  return undefined;
95
101
  }
96
102
  })();
@@ -5,10 +5,14 @@ const base_1 = require("../base");
5
5
  /* NOT FOR BRWOSER */
6
6
  const constants_1 = require("../util/constants");
7
7
  /* NOT FOR BROWSER END */
8
- const severities = new Set([0, 1, 2]), dict = new Map([
8
+ const dict = new Map([
9
9
  [0, false],
10
10
  [1, 'warning'],
11
11
  [2, 'error'],
12
+ [false, false],
13
+ ['off', false],
14
+ ['warning', 'warning'],
15
+ ['error', 'error'],
12
16
  ]);
13
17
  const defaultLintRuleConfig = {
14
18
  'bold-header': [
@@ -48,6 +52,7 @@ const defaultLintRuleConfig = {
48
52
  'invalid-gallery': [
49
53
  2,
50
54
  {
55
+ // extension: 2,
51
56
  // image: 2,
52
57
  parameter: 1,
53
58
  },
@@ -226,14 +231,13 @@ Object.freeze(defaultLintConfig);
226
231
  * 验证错误级别是否符合规范
227
232
  * @param severity 错误级别
228
233
  */
229
- const validateSeverity = (severity) => typeof severity === 'number' && severities.has(severity);
234
+ const validateSeverity = (severity) => dict.has(severity);
230
235
  /**
231
236
  * 验证设置值是否符合规范
232
237
  * @param value 设置值
233
238
  */
234
239
  const validateConfigValue = (value) => validateSeverity(value)
235
- || Array.isArray(value) && value.length === 2
236
- && validateSeverity(value[0]) && value[1] && typeof value[1] === 'object';
240
+ || Array.isArray(value) && validateSeverity(value[0]) && (value.length === 1 || typeof value[1] === 'object');
237
241
  /**
238
242
  * 设置语法检查规则
239
243
  * @param obj 语法检查设置对象
@@ -242,16 +246,18 @@ const validateConfigValue = (value) => validateSeverity(value)
242
246
  * @throws `RangeError` 未知的规则或无效的值
243
247
  */
244
248
  const set = (obj, key, value) => {
249
+ /* istanbul ignore if */
245
250
  if (!base_1.rules.includes(key)) {
246
251
  throw new RangeError(`Unknown lint rule: ${key}`);
247
252
  }
248
- else if (value === undefined) {
253
+ else /* istanbul ignore if */ if (value === undefined) {
249
254
  return false;
250
255
  }
251
256
  else if (validateConfigValue(value)) {
252
257
  obj[key] = value;
253
258
  return true;
254
259
  }
260
+ /* istanbul ignore next */
255
261
  throw new RangeError(`Invalid lint config for ${key}: ${JSON.stringify(value)}`);
256
262
  };
257
263
  /** 语法规则设置 */
@@ -269,10 +275,10 @@ class LintRuleConfiguration {
269
275
  /** @implements */
270
276
  getSeverity(rule, key) {
271
277
  const value = this[rule];
272
- if (typeof value === 'number') {
278
+ if (typeof value !== 'object') {
273
279
  return dict.get(value);
274
280
  }
275
- return key ? dict.get(value[1][key]) ?? dict.get(value[0]) : dict.get(value[0]);
281
+ return key ? dict.get(value[1]?.[key]) ?? dict.get(value[0]) : dict.get(value[0]);
276
282
  }
277
283
  }
278
284
  /** 语法检查设置 */
@@ -287,6 +293,7 @@ class LintConfiguration {
287
293
  set,
288
294
  /** @ignore */
289
295
  deleteProperty() {
296
+ /* istanbul ignore next */
290
297
  return false;
291
298
  },
292
299
  });
package/dist/lib/text.js CHANGED
@@ -221,9 +221,9 @@ let AstText = (() => {
221
221
  return [];
222
222
  }
223
223
  errorRegex.lastIndex = 0;
224
- const errors = [], nextType = nextSibling?.type, nextName = nextSibling?.name, previousType = previousSibling?.type, root = this.getRootNode(), rootStr = root.toString(), { ext, html, variants } = root.getAttribute('config'), { top, left } = root.posFromIndex(start), { lintConfig } = index_1.default, tagLike = lintConfig.rules['tag-like'], specified = typeof tagLike === 'number'
225
- ? new Set()
226
- : new Set(Object.keys(tagLike[1]).filter(tag => tag !== 'invalid' && tag !== 'disallowed')), tags = new Set([
224
+ const errors = [], nextType = nextSibling?.type, nextName = nextSibling?.name, previousType = previousSibling?.type, root = this.getRootNode(), rootStr = root.toString(), { ext, html, variants } = root.getAttribute('config'), { top, left } = root.posFromIndex(start), { lintConfig } = index_1.default, tagLike = lintConfig.rules['tag-like'], specified = typeof tagLike === 'object' && tagLike[1]
225
+ ? new Set(Object.keys(tagLike[1]).filter(tag => tag !== 'invalid' && tag !== 'disallowed'))
226
+ : new Set(), tags = new Set([
227
227
  'onlyinclude',
228
228
  'noinclude',
229
229
  'includeonly',
@@ -78,30 +78,34 @@ const parseCommentAndExt = (wikitext, config, accum, includeOnly) => {
78
78
  });
79
79
  wikitext = (0, string_1.restore)(wikitext, stack);
80
80
  }
81
- return wikitext.replace(getRegex[includeOnly ? 1 : 0](newExt), (substr, name, attr, inner, closing, include, includeAttr, includeInner, includeClosing) => {
82
- const l = accum.length;
83
- let ch = 'n';
84
- if (name) {
85
- ch = 'e';
86
- // @ts-expect-error abstract class
87
- new ext_1.ExtToken(name, attr, inner, closing, newConfig, include, accum);
88
- }
89
- else if (substr.startsWith('<!--')) {
90
- ch = 'c';
91
- const closed = substr.endsWith('-->');
92
- // @ts-expect-error abstract class
93
- new comment_1.CommentToken((0, string_1.restore)(substr, accum, 1).slice(4, closed ? -3 : undefined), closed, config, accum);
94
- }
95
- else if (include) {
96
- // @ts-expect-error abstract class
97
- new include_1.IncludeToken(include, includeAttr && (0, string_1.restore)(includeAttr, accum, 1), includeInner && (0, string_1.restore)(includeInner, accum, 1), includeClosing, config, accum);
98
- }
99
- else {
100
- // @ts-expect-error abstract class
101
- new noinclude_1.NoincludeToken(substr, config, accum);
102
- }
103
- return `\0${l}${ch}\x7F`;
104
- });
81
+ const re = getRegex[includeOnly ? 1 : 0](newExt);
82
+ re.lastIndex = 0;
83
+ return re.test(wikitext)
84
+ ? wikitext.replace(re, (substr, name, attr, inner, closing, include, includeAttr, includeInner, includeClosing) => {
85
+ const l = accum.length;
86
+ let ch = 'n';
87
+ if (name) {
88
+ ch = 'e';
89
+ // @ts-expect-error abstract class
90
+ new ext_1.ExtToken(name, attr, inner, closing, newConfig, include, accum);
91
+ }
92
+ else if (substr.startsWith('<!--')) {
93
+ ch = 'c';
94
+ const closed = substr.endsWith('-->');
95
+ // @ts-expect-error abstract class
96
+ new comment_1.CommentToken((0, string_1.restore)(substr, accum, 1).slice(4, closed ? -3 : undefined), closed, config, accum);
97
+ }
98
+ else if (include) {
99
+ // @ts-expect-error abstract class
100
+ new include_1.IncludeToken(include, includeAttr && (0, string_1.restore)(includeAttr, accum, 1), includeInner && (0, string_1.restore)(includeInner, accum, 1), includeClosing, config, accum);
101
+ }
102
+ else {
103
+ // @ts-expect-error abstract class
104
+ new noinclude_1.NoincludeToken(substr, config, accum);
105
+ }
106
+ return `\0${l}${ch}\x7F`;
107
+ })
108
+ : wikitext;
105
109
  };
106
110
  exports.parseCommentAndExt = parseCommentAndExt;
107
111
  constants_1.parsers['parseCommentAndExt'] = __filename;
@@ -259,20 +259,6 @@ let AttributeToken = (() => {
259
259
  }
260
260
  }
261
261
  }
262
- else if (simple && type !== 'ext-attr') {
263
- const data = (0, lint_1.provideValues)(tag, name), v = String(value).toLowerCase();
264
- if (data.length > 0 && data.every(n => n !== v)) {
265
- /* PRINT ONLY */
266
- if (start === undefined) {
267
- return true;
268
- }
269
- /* PRINT ONLY END */
270
- LINT: { // eslint-disable-line no-unused-labels
271
- const s = lintConfig.getSeverity(rule, 'value');
272
- return s && (0, lint_1.generateForChild)(lastChild, rect, rule, 'illegal-attribute-value', s);
273
- }
274
- }
275
- }
276
262
  else if (typeof value === 'string' && ((/^xmlns:[\w:.-]+$/u.test(name) || urlAttrs.has(name)) && evil.test(value)
277
263
  || simple
278
264
  && (name === 'href' || tag === 'img' && name === 'src')
@@ -288,6 +274,20 @@ let AttributeToken = (() => {
288
274
  return s && (0, lint_1.generateForChild)(lastChild, rect, rule, 'illegal-attribute-value', s);
289
275
  }
290
276
  }
277
+ else if (simple && type !== 'ext-attr') {
278
+ const data = (0, lint_1.provideValues)(tag, name), v = String(value).toLowerCase();
279
+ if (data.length > 0 && data.every(n => n !== v)) {
280
+ /* PRINT ONLY */
281
+ if (start === undefined) {
282
+ return true;
283
+ }
284
+ /* PRINT ONLY END */
285
+ LINT: { // eslint-disable-line no-unused-labels
286
+ const s = lintConfig.getSeverity(rule, 'value');
287
+ return s && (0, lint_1.generateForChild)(lastChild, rect, rule, 'illegal-attribute-value', s);
288
+ }
289
+ }
290
+ }
291
291
  return false;
292
292
  }
293
293
  /** @private */
@@ -295,7 +295,7 @@ let AttributeToken = (() => {
295
295
  LINT: { // eslint-disable-line no-unused-labels
296
296
  const errors = super.lint(start, re), { balanced, firstChild, lastChild, name, tag } = this, rect = new rect_1.BoundingRect(this, start), rules = ['unclosed-quote', 'obsolete-attr'], { lintConfig } = index_1.default, s = rules.map(rule => lintConfig.getSeverity(rule, name));
297
297
  if (s[0] && !balanced) {
298
- const e = (0, lint_1.generateForChild)(lastChild, rect, rules[0], index_1.default.msg('unclosed', 'quotes'), s[0]);
298
+ const e = (0, lint_1.generateForChild)(lastChild, rect, rules[0], 'unclosed-quotes', s[0]);
299
299
  e.startIndex--;
300
300
  e.startCol--;
301
301
  if (lintConfig.computeEditInfo) {
@@ -7,11 +7,11 @@ exports.ImageParameterToken = exports.galleryParams = void 0;
7
7
  const common_1 = require("@bhsd/common");
8
8
  const string_1 = require("../util/string");
9
9
  const lint_1 = require("../util/lint");
10
+ const constants_1 = require("../util/constants");
10
11
  const index_1 = __importDefault(require("../index"));
11
12
  const index_2 = require("./index");
12
13
  /* NOT FOR BROWSER */
13
14
  const debug_1 = require("../util/debug");
14
- const constants_1 = require("../util/constants");
15
15
  /* NOT FOR BROWSER END */
16
16
  /^(?:ftp:\/\/|\/\/|\0\d+m\x7F)/iu; // eslint-disable-line @typescript-eslint/no-unused-expressions
17
17
  const getUrlLikeRegex = (0, common_1.getRegex)(protocol => new RegExp(String.raw `^(?:${protocol}|//|\0\d+m\x7F)`, 'iu'));
@@ -151,6 +151,9 @@ class ImageParameterToken extends index_2.Token {
151
151
  this.#syntax = mt[1] + param[0] + mt[3];
152
152
  }
153
153
  this.setAttribute('name', param[1]);
154
+ if (param[1] === 'alt') {
155
+ this.setAttribute('stage', constants_1.MAX_STAGE - 1);
156
+ }
154
157
  return;
155
158
  }
156
159
  super(str, config.excludes.includes('list')
@@ -181,7 +184,7 @@ class ImageParameterToken extends index_2.Token {
181
184
  }
182
185
  /** @private */
183
186
  isPlain() {
184
- return this.name === 'caption';
187
+ return this.name === 'caption' || this.name === 'alt';
185
188
  }
186
189
  /** @private */
187
190
  getAttribute(key) {
package/dist/src/index.js CHANGED
@@ -630,7 +630,7 @@ let Token = (() => {
630
630
  && (severity === 1 ? s : sWarn))
631
631
  .map(({ range: { start: { line, character }, end }, message, severity, code }) => ({
632
632
  code: code,
633
- rule: 'invalid-css',
633
+ rule,
634
634
  message,
635
635
  severity: (severity === 1 ? s : sWarn),
636
636
  startLine: line,
@@ -116,7 +116,7 @@ let FileToken = (() => {
116
116
  * @since v1.5.3
117
117
  */
118
118
  get extension() {
119
- return this.getAttribute('title').extension;
119
+ LSP: return this.getAttribute('title').extension; // eslint-disable-line no-unused-labels
120
120
  }
121
121
  /* NOT FOR BROWSER */
122
122
  /** image link / 图片链接 */
@@ -185,7 +185,9 @@ let FileToken = (() => {
185
185
  /** @private */
186
186
  lint(start = this.getAbsoluteIndex(), re) {
187
187
  LINT: { // eslint-disable-line no-unused-labels
188
- const errors = super.lint(start, re), args = filterArgs(this.getAllArgs(), argTypes), keys = [...new Set(args.map(({ name }) => name))], frameKeys = keys.filter(key => frame.has(key)), horizAlignKeys = keys.filter(key => horizAlign.has(key)), vertAlignKeys = keys.filter(key => vertAlign.has(key)), [fr] = frameKeys, unscaled = fr === 'framed' || fr === 'manualthumb', rect = new rect_1.BoundingRect(this, start), { lintConfig } = index_1.default, { computeEditInfo, fix } = lintConfig, { extension } = this;
188
+ const errors = super.lint(start, re), args = filterArgs(this.getAllArgs(), argTypes), keys = [...new Set(args.map(({ name }) => name))], frameKeys = keys.filter(key => frame.has(key)), horizAlignKeys = keys.filter(key => horizAlign.has(key)), vertAlignKeys = keys.filter(key => vertAlign.has(key)), [fr] = frameKeys, unscaled = fr === 'framed' || fr === 'manualthumb', rect = new rect_1.BoundingRect(this, start), { lintConfig } = index_1.default, { computeEditInfo, fix } = lintConfig, { ns, extension,
189
+ /* NOT FOR BROWSER */
190
+ interwiki, } = this.getAttribute('title'), { firstChild } = this;
189
191
  let rule = 'nested-link', s = lintConfig.getSeverity(rule, 'file');
190
192
  if (s
191
193
  && extensions.has(extension)
@@ -209,6 +211,11 @@ let FileToken = (() => {
209
211
  errors.push(e);
210
212
  }
211
213
  rule = 'invalid-gallery';
214
+ s = lintConfig.getSeverity(rule, 'extension');
215
+ if (s && ns === 6 && !extension && !firstChild.querySelector('arg,magic-word,template')
216
+ && !interwiki) {
217
+ errors.push((0, lint_1.generateForSelf)(this, rect, rule, 'missing-extension', s));
218
+ }
212
219
  s = lintConfig.getSeverity(rule, 'parameter');
213
220
  if (s && unscaled) {
214
221
  for (const arg of args.filter(({ name }) => name === 'width')) {
@@ -95,7 +95,7 @@ let CommentToken = (() => {
95
95
  if (!s) {
96
96
  return [];
97
97
  }
98
- const e = (0, lint_1.generateForSelf)(this, { start }, rule, index_1.default.msg('unclosed', 'html-comment'), s);
98
+ const e = (0, lint_1.generateForSelf)(this, { start }, rule, 'unclosed-comment', s);
99
99
  if (lintConfig.computeEditInfo) {
100
100
  e.suggestions = [(0, lint_1.fixByClose)(e.endIndex, '-->')];
101
101
  }
@@ -141,7 +141,7 @@ let TableToken = (() => {
141
141
  LINT: { // eslint-disable-line no-unused-labels
142
142
  const errors = super.lint(start, re), rect = new rect_1.BoundingRect(this, start), rules = ['unclosed-table', 'table-layout'], s = rules.map(rule => index_1.default.lintConfig.getSeverity(rule));
143
143
  if (s[0] && !this.closed) {
144
- errors.push((0, lint_1.generateForChild)(this.firstChild, rect, rules[0], index_1.default.msg('unclosed', 'table'), s[0]));
144
+ errors.push((0, lint_1.generateForChild)(this.firstChild, rect, rules[0], 'unclosed-table', s[0]));
145
145
  }
146
146
  if (s[1]) {
147
147
  const layout = this.getLayout(), { length } = layout;
package/dist/util/html.js CHANGED
@@ -144,7 +144,8 @@ exports.html = html;
144
144
  * @param tokens inner tokens of a section heading
145
145
  */
146
146
  const getId = (tokens) => {
147
- const opt = { nocc: true }, content = Array.isArray(tokens) ? (0, exports.html)(tokens, '', opt) : tokens.toHtmlInternal(opt), id = (0, string_1.decodeHtml)((0, string_1.sanitizeAlt)(content)).replace(/[\s_]+/gu, '_');
147
+ const opt = { nocc: true }, content = Array.isArray(tokens) ? (0, exports.html)(tokens, '', opt) : tokens.toHtmlInternal(opt), id = (0, string_1.decodeHtml)((0, string_1.sanitizeAlt)(content.replaceAll('_', ' ')))
148
+ .replace(/[\s_]+/gu, '_');
148
149
  return id.endsWith('_') ? id.slice(0, -1) : id;
149
150
  };
150
151
  exports.getId = getId;
@@ -1,6 +1,6 @@
1
1
  (() => {
2
2
  var _a;
3
- const version = '1.26.0', src = (_a = document.currentScript) === null || _a === void 0 ? void 0 : _a.src, file = /\/extensions\/dist\/base\.(?:min\.)?js$/u, CDN = src && file.test(src)
3
+ const version = '1.27.1', src = (_a = document.currentScript) === null || _a === void 0 ? void 0 : _a.src, file = /\/extensions\/dist\/base\.(?:min\.)?js$/u, CDN = src && file.test(src)
4
4
  ? src.replace(file, '')
5
5
  : `https://testingcf.jsdelivr.net/npm/wikiparser-node@${version}`;
6
6
  const workerJS = () => {