wikilint 2.26.0 → 2.27.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/data/.schema.json CHANGED
@@ -10,7 +10,8 @@
10
10
  "description": "An array of aliases for the magic word",
11
11
  "type": "array",
12
12
  "items": {
13
- "type": "string"
13
+ "type": "string",
14
+ "pattern": "^[^A-Z]+$"
14
15
  },
15
16
  "minItems": 1,
16
17
  "uniqueItems": true
@@ -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
@@ -266,8 +266,8 @@ export interface LanguageService {
266
266
  */
267
267
  setTargetWikipedia(wiki: string, user: string): Promise<void>;
268
268
  }
269
- export type SeverityLevel = 0 | 1 | 2;
270
- export type LintConfigValue = SeverityLevel | [SeverityLevel, Record<string, SeverityLevel>];
269
+ export type SeverityLevel = 0 | 1 | 2 | false | 'off' | 'warning' | 'error';
270
+ export type LintConfigValue = SeverityLevel | [SeverityLevel, Record<string, SeverityLevel>?];
271
271
  export type LintRuleConfig = Partial<Record<LintError.Rule, LintConfigValue>>;
272
272
  export interface FullLintConfig {
273
273
  rules: LintRuleConfig;
package/dist/base.d.ts CHANGED
@@ -266,8 +266,8 @@ export interface LanguageService {
266
266
  */
267
267
  setTargetWikipedia(wiki: string, user: string): Promise<void>;
268
268
  }
269
- export type SeverityLevel = 0 | 1 | 2;
270
- export type LintConfigValue = SeverityLevel | [SeverityLevel, Record<string, SeverityLevel>];
269
+ export type SeverityLevel = 0 | 1 | 2 | false | 'off' | 'warning' | 'error';
270
+ export type LintConfigValue = SeverityLevel | [SeverityLevel, Record<string, SeverityLevel>?];
271
271
  export type LintRuleConfig = Partial<Record<LintError.Rule, LintConfigValue>>;
272
272
  export interface FullLintConfig {
273
273
  rules: LintRuleConfig;
@@ -77,7 +77,7 @@ const mw = {
77
77
  },
78
78
  },
79
79
  };
80
- const pkg = "wikilint", version = "2.26.0";
80
+ const pkg = "wikilint", version = "2.27.0";
81
81
  let mwConfig;
82
82
  /**
83
83
  * Get the parser configuration for a Wikimedia Foundation project.
@@ -30,6 +30,7 @@ const loadMathJax = (id = 'mathjax') => {
30
30
  return MathJax;
31
31
  }
32
32
  catch {
33
+ /* istanbul ignore next */
33
34
  return undefined;
34
35
  }
35
36
  };
@@ -56,6 +57,7 @@ exports.jsonLSP = (() => {
56
57
  };
57
58
  }
58
59
  catch {
60
+ /* istanbul ignore next */
59
61
  return false;
60
62
  }
61
63
  }).filter(Boolean),
@@ -63,6 +65,7 @@ exports.jsonLSP = (() => {
63
65
  return lsp;
64
66
  }
65
67
  catch {
68
+ /* istanbul ignore next */
66
69
  return undefined;
67
70
  }
68
71
  })();
@@ -72,6 +75,7 @@ exports.cssLSP = (() => {
72
75
  .getCSSLanguageService();
73
76
  }
74
77
  catch {
78
+ /* istanbul ignore next */
75
79
  return undefined;
76
80
  }
77
81
  })();
@@ -81,6 +85,7 @@ exports.htmlData = (() => {
81
85
  .getDefaultHTMLDataProvider();
82
86
  }
83
87
  catch {
88
+ /* istanbul ignore next */
84
89
  return undefined;
85
90
  }
86
91
  })();
@@ -89,6 +94,7 @@ exports.stylelint = (async () => {
89
94
  return (await import('stylelint')).default;
90
95
  }
91
96
  catch {
97
+ /* istanbul ignore next */
92
98
  return undefined;
93
99
  }
94
100
  })();
@@ -2,10 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LintConfiguration = void 0;
4
4
  const base_1 = require("../base");
5
- const severities = new Set([0, 1, 2]), dict = new Map([
5
+ const dict = new Map([
6
6
  [0, false],
7
7
  [1, 'warning'],
8
8
  [2, 'error'],
9
+ [false, false],
10
+ ['off', false],
11
+ ['warning', 'warning'],
12
+ ['error', 'error'],
9
13
  ]);
10
14
  const defaultLintRuleConfig = {
11
15
  'bold-header': [
@@ -45,6 +49,7 @@ const defaultLintRuleConfig = {
45
49
  'invalid-gallery': [
46
50
  2,
47
51
  {
52
+ // extension: 2,
48
53
  // image: 2,
49
54
  parameter: 1,
50
55
  },
@@ -223,14 +228,13 @@ Object.freeze(defaultLintConfig);
223
228
  * 验证错误级别是否符合规范
224
229
  * @param severity 错误级别
225
230
  */
226
- const validateSeverity = (severity) => typeof severity === 'number' && severities.has(severity);
231
+ const validateSeverity = (severity) => dict.has(severity);
227
232
  /**
228
233
  * 验证设置值是否符合规范
229
234
  * @param value 设置值
230
235
  */
231
236
  const validateConfigValue = (value) => validateSeverity(value)
232
- || Array.isArray(value) && value.length === 2
233
- && validateSeverity(value[0]) && value[1] && typeof value[1] === 'object';
237
+ || Array.isArray(value) && validateSeverity(value[0]) && (value.length === 1 || typeof value[1] === 'object');
234
238
  /**
235
239
  * 设置语法检查规则
236
240
  * @param obj 语法检查设置对象
@@ -239,16 +243,18 @@ const validateConfigValue = (value) => validateSeverity(value)
239
243
  * @throws `RangeError` 未知的规则或无效的值
240
244
  */
241
245
  const set = (obj, key, value) => {
246
+ /* istanbul ignore if */
242
247
  if (!base_1.rules.includes(key)) {
243
248
  throw new RangeError(`Unknown lint rule: ${key}`);
244
249
  }
245
- else if (value === undefined) {
250
+ else /* istanbul ignore if */ if (value === undefined) {
246
251
  return false;
247
252
  }
248
253
  else if (validateConfigValue(value)) {
249
254
  obj[key] = value;
250
255
  return true;
251
256
  }
257
+ /* istanbul ignore next */
252
258
  throw new RangeError(`Invalid lint config for ${key}: ${JSON.stringify(value)}`);
253
259
  };
254
260
  /** 语法规则设置 */
@@ -266,10 +272,10 @@ class LintRuleConfiguration {
266
272
  /** @implements */
267
273
  getSeverity(rule, key) {
268
274
  const value = this[rule];
269
- if (typeof value === 'number') {
275
+ if (typeof value !== 'object') {
270
276
  return dict.get(value);
271
277
  }
272
- return key ? dict.get(value[1][key]) ?? dict.get(value[0]) : dict.get(value[0]);
278
+ return key ? dict.get(value[1]?.[key]) ?? dict.get(value[0]) : dict.get(value[0]);
273
279
  }
274
280
  }
275
281
  /** 语法检查设置 */
@@ -284,6 +290,7 @@ class LintConfiguration {
284
290
  set,
285
291
  /** @ignore */
286
292
  deleteProperty() {
293
+ /* istanbul ignore next */
287
294
  return false;
288
295
  },
289
296
  });
package/dist/lib/text.js CHANGED
@@ -106,9 +106,9 @@ class AstText extends node_1.AstNode {
106
106
  return [];
107
107
  }
108
108
  errorRegex.lastIndex = 0;
109
- 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'
110
- ? new Set()
111
- : new Set(Object.keys(tagLike[1]).filter(tag => tag !== 'invalid' && tag !== 'disallowed')), tags = new Set([
109
+ 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]
110
+ ? new Set(Object.keys(tagLike[1]).filter(tag => tag !== 'invalid' && tag !== 'disallowed'))
111
+ : new Set(), tags = new Set([
112
112
  'onlyinclude',
113
113
  'noinclude',
114
114
  'includeonly',
@@ -161,15 +161,6 @@ class AttributeToken extends index_2.Token {
161
161
  }
162
162
  }
163
163
  }
164
- else if (simple && type !== 'ext-attr') {
165
- const data = (0, lint_1.provideValues)(tag, name), v = String(value).toLowerCase();
166
- if (data.length > 0 && data.every(n => n !== v)) {
167
- LINT: { // eslint-disable-line no-unused-labels
168
- const s = lintConfig.getSeverity(rule, 'value');
169
- return s && (0, lint_1.generateForChild)(lastChild, rect, rule, 'illegal-attribute-value', s);
170
- }
171
- }
172
- }
173
164
  else if (typeof value === 'string' && ((/^xmlns:[\w:.-]+$/u.test(name) || urlAttrs.has(name)) && evil.test(value)
174
165
  || simple
175
166
  && (name === 'href' || tag === 'img' && name === 'src')
@@ -180,6 +171,15 @@ class AttributeToken extends index_2.Token {
180
171
  return s && (0, lint_1.generateForChild)(lastChild, rect, rule, 'illegal-attribute-value', s);
181
172
  }
182
173
  }
174
+ else if (simple && type !== 'ext-attr') {
175
+ const data = (0, lint_1.provideValues)(tag, name), v = String(value).toLowerCase();
176
+ if (data.length > 0 && data.every(n => n !== v)) {
177
+ LINT: { // eslint-disable-line no-unused-labels
178
+ const s = lintConfig.getSeverity(rule, 'value');
179
+ return s && (0, lint_1.generateForChild)(lastChild, rect, rule, 'illegal-attribute-value', s);
180
+ }
181
+ }
182
+ }
183
183
  return false;
184
184
  }
185
185
  /** @private */
@@ -187,7 +187,7 @@ class AttributeToken extends index_2.Token {
187
187
  LINT: { // eslint-disable-line no-unused-labels
188
188
  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));
189
189
  if (s[0] && !balanced) {
190
- const e = (0, lint_1.generateForChild)(lastChild, rect, rules[0], index_1.default.msg('unclosed', 'quotes'), s[0]);
190
+ const e = (0, lint_1.generateForChild)(lastChild, rect, rules[0], 'unclosed-quotes', s[0]);
191
191
  e.startIndex--;
192
192
  e.startCol--;
193
193
  if (lintConfig.computeEditInfo) {
@@ -7,6 +7,7 @@ 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
  const getUrlLikeRegex = (0, common_1.getRegex)(protocol => new RegExp(String.raw `^(?:${protocol}|//|\0\d+m\x7F)`, 'iu'));
@@ -80,6 +81,9 @@ class ImageParameterToken extends index_2.Token {
80
81
  this.#syntax = mt[1] + param[0] + mt[3];
81
82
  }
82
83
  this.setAttribute('name', param[1]);
84
+ if (param[1] === 'alt') {
85
+ this.setAttribute('stage', constants_1.MAX_STAGE - 1);
86
+ }
83
87
  return;
84
88
  }
85
89
  super(str, config.excludes.includes('list')
@@ -108,7 +112,7 @@ class ImageParameterToken extends index_2.Token {
108
112
  }
109
113
  /** @private */
110
114
  isPlain() {
111
- return this.name === 'caption';
115
+ return this.name === 'caption' || this.name === 'alt';
112
116
  }
113
117
  /** @private */
114
118
  getAttribute(key) {
package/dist/src/index.js CHANGED
@@ -475,7 +475,7 @@ class Token extends element_1.AstElement {
475
475
  && (severity === 1 ? s : sWarn))
476
476
  .map(({ range: { start: { line, character }, end }, message, severity, code }) => ({
477
477
  code: code,
478
- rule: 'invalid-css',
478
+ rule,
479
479
  message,
480
480
  severity: (severity === 1 ? s : sWarn),
481
481
  startLine: line,
@@ -65,7 +65,7 @@ class FileToken extends base_1.LinkBaseToken {
65
65
  * @since v1.5.3
66
66
  */
67
67
  get extension() {
68
- return this.getAttribute('title').extension;
68
+ LSP: return this.getAttribute('title').extension; // eslint-disable-line no-unused-labels
69
69
  }
70
70
  /**
71
71
  * @param link 文件名
@@ -82,7 +82,7 @@ class FileToken extends base_1.LinkBaseToken {
82
82
  /** @private */
83
83
  lint(start = this.getAbsoluteIndex(), re) {
84
84
  LINT: { // eslint-disable-line no-unused-labels
85
- 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;
85
+ 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, } = this.getAttribute('title'), { firstChild } = this;
86
86
  let rule = 'nested-link', s = lintConfig.getSeverity(rule, 'file');
87
87
  if (s
88
88
  && extensions.has(extension)
@@ -106,6 +106,10 @@ class FileToken extends base_1.LinkBaseToken {
106
106
  errors.push(e);
107
107
  }
108
108
  rule = 'invalid-gallery';
109
+ s = lintConfig.getSeverity(rule, 'extension');
110
+ if (s && ns === 6 && !extension && !firstChild.querySelector('arg,magic-word,template')) {
111
+ errors.push((0, lint_1.generateForSelf)(this, rect, rule, 'missing-extension', s));
112
+ }
109
113
  s = lintConfig.getSeverity(rule, 'parameter');
110
114
  if (s && unscaled) {
111
115
  for (const arg of args.filter(({ name }) => name === 'width')) {
@@ -82,7 +82,7 @@ let CommentToken = (() => {
82
82
  if (!s) {
83
83
  return [];
84
84
  }
85
- const e = (0, lint_1.generateForSelf)(this, { start }, rule, index_1.default.msg('unclosed', 'html-comment'), s);
85
+ const e = (0, lint_1.generateForSelf)(this, { start }, rule, 'unclosed-comment', s);
86
86
  if (lintConfig.computeEditInfo) {
87
87
  e.suggestions = [(0, lint_1.fixByClose)(e.endIndex, '-->')];
88
88
  }
@@ -98,7 +98,7 @@ let TableToken = (() => {
98
98
  LINT: { // eslint-disable-line no-unused-labels
99
99
  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));
100
100
  if (s[0] && !this.closed) {
101
- errors.push((0, lint_1.generateForChild)(this.firstChild, rect, rules[0], index_1.default.msg('unclosed', 'table'), s[0]));
101
+ errors.push((0, lint_1.generateForChild)(this.firstChild, rect, rules[0], 'unclosed-table', s[0]));
102
102
  }
103
103
  if (s[1]) {
104
104
  const layout = this.getLayout(), { length } = layout;
package/i18n/en.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "attributes-of-closing-tag": "attributes of a closing tag",
3
3
  "bold-apostrophes": "bold apostrophes",
4
- "bold-in-header": "bold in section header",
4
+ "bold-in-header": "bold text in a section header",
5
5
  "close": null,
6
6
  "closing-and-self-closing": "tag that is both closing and self-closing",
7
7
  "comment": null,
@@ -11,9 +11,9 @@
11
11
  "delink": null,
12
12
  "duplicate-attribute": "duplicate $1 attribute",
13
13
  "duplicate-category": "duplicate category",
14
- "duplicate-id": "duplicate id",
14
+ "duplicate-id": "duplicate HTML id",
15
15
  "duplicate-image-parameter": "duplicate image $1 parameter",
16
- "duplicate-parameter": "duplicate parameter",
16
+ "duplicate-parameter": "duplicate template parameter",
17
17
  "encode": null,
18
18
  "escape": null,
19
19
  "expand": null,
@@ -22,16 +22,15 @@
22
22
  "full-width-punctuation": "full-width punctuation",
23
23
  "header-in-html": "section header in HTML tag attributes",
24
24
  "horizontal-alignment": null,
25
- "html-comment": "HTML comment",
26
25
  "html-in-table": "HTML tag in table attributes",
27
- "illegal-attribute-name": "illegal attribute name",
28
- "illegal-attribute-value": "illegal attribute value",
29
- "illegal-module": "illegal module name",
26
+ "illegal-attribute-name": "invalid attribute name",
27
+ "illegal-attribute-value": "invalid attribute value",
28
+ "illegal-module": "invalid Scribunto module name",
30
29
  "imagemap-without-image": "<imagemap> without an image",
31
30
  "in-url": "$1 in URL",
32
31
  "inconsistent-table": "inconsistent table layout",
33
32
  "insecure-style": "insecure style",
34
- "invalid-attribute": "containing invalid attribute",
33
+ "invalid-attribute": "element containing an invalid attribute name",
35
34
  "invalid-content": "invalid content in <$1>",
36
35
  "invalid-conversion-flag": "invalid conversion flag",
37
36
  "invalid-gallery": "invalid gallery image",
@@ -42,10 +41,11 @@
42
41
  "invalid-self-closing": "invalid self-closing tag",
43
42
  "invisible-triple-braces": "invisible content inside triple braces",
44
43
  "italic-apostrophes": "italic apostrophes",
45
- "left-bracket": "left bracket",
44
+ "left-bracket": "opening bracket",
46
45
  "link-in-extlink": "internal link in an external link",
47
46
  "lonely": "lonely \"$1\"",
48
- "missing-function": "missing module function",
47
+ "missing-extension": "missing file extension",
48
+ "missing-function": "missing Scribunto module function name",
49
49
  "newline": null,
50
50
  "no-self-closing": "no self-closing",
51
51
  "nonzero-tabindex": "nonzero tabindex",
@@ -56,17 +56,18 @@
56
56
  "prefix": null,
57
57
  "pipe-in-link": "additional \"|\" in the link text",
58
58
  "pipe-in-table": "additional \"|\" in a table cell",
59
- "quotes": null,
60
59
  "remove": null,
61
- "table": null,
62
60
  "template-in-link": "template in an internal link target",
63
61
  "unbalanced-in-section-header": "unbalanced $1 in a section header",
64
62
  "unclosed": "unclosed $1",
63
+ "unclosed-comment": "unclosed HTML comment",
64
+ "unclosed-quotes": "unclosed quotes",
65
+ "unclosed-table": "unclosed table",
65
66
  "unclosed-tag": "unclosed tag",
66
67
  "unescaped-query": "unescaped query string in an anonymous parameter",
67
68
  "unexpected-argument": "unexpected template argument",
68
69
  "unmatched-closing": "unmatched closing tag",
69
- "unnecessary-encoding": "unnecessary URL encoding in an internal link",
70
+ "unnecessary-encoding": "unnecessary percent-encoding in an internal link",
70
71
  "uppercase": null,
71
72
  "useless-attribute": "useless attribute",
72
73
  "useless-fragment": "useless fragment",
package/i18n/zh-hans.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "attributes-of-closing-tag": "位于闭合标签的属性",
2
+ "attributes-of-closing-tag": "闭合标签的属性",
3
3
  "bold-apostrophes": "粗体单引号",
4
- "bold-in-header": "段落标题中的粗体",
4
+ "bold-in-header": "章节标题中的粗体文本",
5
5
  "close": "闭合",
6
6
  "closing-and-self-closing": "同时闭合和自封闭的标签",
7
7
  "comment": "注释",
@@ -11,32 +11,31 @@
11
11
  "delink": "移除链接",
12
12
  "duplicate-attribute": "重复的$1属性",
13
13
  "duplicate-category": "重复的分类",
14
- "duplicate-id": "重复的id",
14
+ "duplicate-id": "重复的HTML id属性",
15
15
  "duplicate-image-parameter": "重复的图片$1参数",
16
- "duplicate-parameter": "重复参数",
16
+ "duplicate-parameter": "重复的模板参数",
17
17
  "encode": "编码",
18
18
  "escape": "转义",
19
19
  "expand": "展开",
20
20
  "ext-in-html": "HTML标签属性中的扩展标签",
21
21
  "frame": "框架",
22
22
  "full-width-punctuation": "全角标点",
23
- "header-in-html": "HTML标签属性中的段落标题",
23
+ "header-in-html": "HTML标签属性中的章节标题",
24
24
  "horizontal-alignment": "水平对齐",
25
- "html-comment": "HTML注释",
26
25
  "html-in-table": "表格属性中的HTML标签",
27
- "illegal-attribute-name": "非法的属性名",
28
- "illegal-attribute-value": "非法的属性值",
29
- "illegal-module": "非法的模块名称",
26
+ "illegal-attribute-name": "无效的属性名",
27
+ "illegal-attribute-value": "无效的属性值",
28
+ "illegal-module": "无效的Scribunto模块名称",
30
29
  "imagemap-without-image": "缺少图片的<imagemap>",
31
30
  "in-url": "URL中的$1",
32
31
  "inconsistent-table": "不一致的表格布局",
33
32
  "insecure-style": "不安全的样式",
34
- "invalid-attribute": "包含无效属性",
33
+ "invalid-attribute": "包含无效属性名的元素",
35
34
  "invalid-content": "<$1>内的无效内容",
36
35
  "invalid-conversion-flag": "无效的转换标记",
37
36
  "invalid-gallery": "无效的图库图片",
38
37
  "invalid-image-parameter": "无效的图片参数",
39
- "invalid-imagemap-link": "无效的<imagemap>链接",
38
+ "invalid-imagemap-link": "<imagemap>内的无效链接",
40
39
  "invalid-isbn": "无效的ISBN",
41
40
  "invalid-parameter": "<$1>的无效参数",
42
41
  "invalid-self-closing": "无效自封闭标签",
@@ -45,10 +44,11 @@
45
44
  "left-bracket": "左括号",
46
45
  "link-in-extlink": "外链中的内链",
47
46
  "lonely": "孤立的\"$1\"",
48
- "missing-function": "缺少模块函数",
47
+ "missing-extension": "缺少文件扩展名",
48
+ "missing-function": "缺少Scribunto模块函数名",
49
49
  "newline": "换行",
50
50
  "no-self-closing": "移除自封闭",
51
- "nonzero-tabindex": "不为0的tabindex",
51
+ "nonzero-tabindex": "非零的tabindex",
52
52
  "nothing-in": "<$1>标签内不应有任何内容",
53
53
  "obsolete-attribute": "过时的属性",
54
54
  "obsolete-tag": "过时的HTML标签",
@@ -56,22 +56,23 @@
56
56
  "prefix": "前缀",
57
57
  "pipe-in-link": "链接文本中多余的\"|\"",
58
58
  "pipe-in-table": "表格单元格中多余的\"|\"",
59
- "quotes": "引号",
60
59
  "remove": "移除",
61
- "table": "表格",
62
60
  "template-in-link": "内链目标包含模板",
63
- "unbalanced-in-section-header": "段落标题中不平衡的$1",
61
+ "unbalanced-in-section-header": "章节标题中未成对的$1",
64
62
  "unclosed": "未闭合的$1",
63
+ "unclosed-comment": "未闭合的HTML注释",
64
+ "unclosed-quotes": "未闭合的引号",
65
+ "unclosed-table": "未闭合的表格",
65
66
  "unclosed-tag": "未闭合的标签",
66
67
  "unescaped-query": "匿名参数中未转义的查询参数",
67
68
  "unexpected-argument": "未预期的模板参数",
68
69
  "unmatched-closing": "未匹配的闭合标签",
69
70
  "unnecessary-encoding": "内链中不必要的URL编码",
70
71
  "uppercase": "大写",
71
- "useless-attribute": "无用的属性",
72
+ "useless-attribute": "无用属性",
72
73
  "useless-fragment": "无用的fragment",
73
74
  "useless-link-text": "无用的链接文字",
74
- "variable-anchor": "段落标题中可变的锚点",
75
+ "variable-anchor": "章节标题中可变的锚点",
75
76
  "vertical-alignment": "垂直对齐",
76
77
  "whitespace": "空格"
77
78
  }
package/i18n/zh-hant.json CHANGED
@@ -1,77 +1,78 @@
1
1
  {
2
- "attributes-of-closing-tag": "位於閉合標籤的屬性",
2
+ "attributes-of-closing-tag": "結束標籤的屬性",
3
3
  "bold-apostrophes": "粗體撇號",
4
- "bold-in-header": "段落標題中的粗體",
4
+ "bold-in-header": "章節標題中的粗體文本",
5
5
  "close": "閉合",
6
6
  "closing-and-self-closing": "同時閉合和自封閉的標籤",
7
- "comment": "註釋",
8
- "conflicting-image-parameter": "衝突的圖片$1參數",
7
+ "comment": "註解",
8
+ "conflicting-image-parameter": "起衝突的圖片$1參數",
9
9
  "content-outside-table": "將被移出表格的內容",
10
10
  "decode": "解碼",
11
- "delink": "移除連結",
11
+ "delink": "解除連結",
12
12
  "duplicate-attribute": "重複的$1屬性",
13
13
  "duplicate-category": "重複的分類",
14
- "duplicate-id": "重複的id",
14
+ "duplicate-id": "重複的HTML id屬性",
15
15
  "duplicate-image-parameter": "重複的圖片$1參數",
16
- "duplicate-parameter": "重複參數",
16
+ "duplicate-parameter": "重複的模板參數",
17
17
  "encode": "編碼",
18
- "escape": "轉義",
18
+ "escape": "跳脫",
19
19
  "expand": "展開",
20
- "ext-in-html": "HTML標籤屬性中的擴展標籤",
20
+ "ext-in-html": "HTML標籤屬性裡的擴充標籤",
21
21
  "frame": "框架",
22
22
  "full-width-punctuation": "全形標點",
23
- "header-in-html": "HTML標籤屬性中的段落標題",
24
- "horizontal-alignment": "水瓶對齊",
25
- "html-comment": "HTML註釋",
26
- "html-in-table": "表格屬性中的HTML標籤",
27
- "illegal-attribute-name": "非法的屬性名",
28
- "illegal-attribute-value": "非法的屬性值",
29
- "illegal-module": "非法的模組名稱",
30
- "imagemap-without-image": "缺少圖片的<imagemap>",
23
+ "header-in-html": "HTML標籤屬性中的章節標題",
24
+ "horizontal-alignment": "水平對齊",
25
+ "html-in-table": "表格屬性裡的HTML標籤",
26
+ "illegal-attribute-name": "無效的屬性名稱",
27
+ "illegal-attribute-value": "無效的屬性值",
28
+ "illegal-module": "無效的Scribunto模組名稱",
29
+ "imagemap-without-image": "沒有圖片的<imagemap>",
31
30
  "in-url": "URL中的$1",
32
31
  "inconsistent-table": "不一致的表格佈局",
33
32
  "insecure-style": "不安全的樣式",
34
- "invalid-attribute": "包含無效屬性",
35
- "invalid-content": "<$1>內的無效內容",
33
+ "invalid-attribute": "包含無效屬性名稱的元素",
34
+ "invalid-content": "<$1>裡的無效內容",
36
35
  "invalid-conversion-flag": "無效的轉換標記",
37
36
  "invalid-gallery": "無效的圖庫圖片",
38
37
  "invalid-image-parameter": "無效的圖片參數",
39
- "invalid-imagemap-link": "無效的<imagemap>連結",
38
+ "invalid-imagemap-link": "<imagemap>裡的無效連結",
40
39
  "invalid-isbn": "無效的ISBN",
41
40
  "invalid-parameter": "<$1>的無效參數",
42
41
  "invalid-self-closing": "無效自封閉標籤",
43
42
  "invisible-triple-braces": "三重括號內的不可見部分",
44
43
  "italic-apostrophes": "斜體撇號",
45
44
  "left-bracket": "左括號",
46
- "link-in-extlink": "外部連結中的內部連結",
45
+ "link-in-extlink": "外部連結裡的內部連結",
47
46
  "lonely": "孤立的\"$1\"",
48
- "missing-function": "缺少模組函式",
47
+ "missing-extension": "缺少檔案副檔名",
48
+ "missing-function": "缺少Scribunto模組函式名稱",
49
49
  "newline": "換行",
50
50
  "no-self-closing": "移除自封閉",
51
- "nonzero-tabindex": "不為0的tabindex",
51
+ "nonzero-tabindex": "非零的tabindex",
52
52
  "nothing-in": "<$1>標籤內不應有任何內容",
53
53
  "obsolete-attribute": "過時的屬性",
54
54
  "obsolete-tag": "過時的HTML標籤",
55
55
  "open": "起始",
56
56
  "prefix": "前綴",
57
57
  "pipe-in-link": "連結文本中多餘的\"|\"",
58
- "pipe-in-table": "表格單元格中多餘的\"|\"",
59
- "quotes": "引號",
58
+ "pipe-in-table": "表格儲存格中多餘的\"|\"",
60
59
  "remove": "移除",
61
- "table": "表格",
62
60
  "template-in-link": "內部連結目標包含模板",
63
- "unbalanced-in-section-header": "段落標題中不平衡的$1",
61
+ "unbalanced-in-section-header": "章節標題裡未成對的$1",
64
62
  "unclosed": "未閉合的$1",
63
+ "unclosed-comment": "未閉合的HTML註解",
64
+ "unclosed-quotes": "未閉合的引號",
65
+ "unclosed-table": "未閉合的表格",
65
66
  "unclosed-tag": "未閉合的標籤",
66
- "unescaped-query": "匿名參數中未轉義的查詢參數",
67
+ "unescaped-query": "匿名參數裡未跳脫的查詢字元",
67
68
  "unexpected-argument": "未預期的模板參數",
68
69
  "unmatched-closing": "未匹配的閉合標籤",
69
70
  "unnecessary-encoding": "內部連結中不必要的URL編碼",
70
71
  "uppercase": "大寫",
71
- "useless-attribute": "無用的屬性",
72
+ "useless-attribute": "無用屬性",
72
73
  "useless-fragment": "無用的fragment",
73
74
  "useless-link-text": "無用的連結文字",
74
- "variable-anchor": "段落標題中可變的錨點",
75
+ "variable-anchor": "章節標題中可變的錨點",
75
76
  "vertical-alignment": "垂直對齊",
76
77
  "whitespace": "空格"
77
78
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikilint",
3
- "version": "2.26.0",
3
+ "version": "2.27.0",
4
4
  "description": "A Node.js linter for MediaWiki markup",
5
5
  "keywords": [
6
6
  "mediawiki",