wikilint 2.32.0 → 2.33.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.
Files changed (40) hide show
  1. package/dist/bin/config.js +1 -1
  2. package/dist/lib/lintConfig.js +2 -0
  3. package/dist/lib/lsp.js +7 -0
  4. package/dist/lib/text.js +4 -4
  5. package/dist/src/attribute.d.ts +3 -4
  6. package/dist/src/attribute.js +7 -4
  7. package/dist/src/attributes.js +1 -1
  8. package/dist/src/imageParameter.d.ts +7 -3
  9. package/dist/src/imageParameter.js +14 -4
  10. package/dist/src/index.d.ts +8 -0
  11. package/dist/src/index.js +22 -20
  12. package/dist/src/link/base.d.ts +1 -1
  13. package/dist/src/link/base.js +7 -1
  14. package/dist/src/link/categorytree.d.ts +21 -0
  15. package/dist/src/link/categorytree.js +93 -0
  16. package/dist/src/link/file.d.ts +3 -2
  17. package/dist/src/link/file.js +3 -2
  18. package/dist/src/link/galleryImage.js +5 -4
  19. package/dist/src/multiLine/gallery.d.ts +1 -3
  20. package/dist/src/multiLine/gallery.js +1 -3
  21. package/dist/src/multiLine/imagemap.js +2 -3
  22. package/dist/src/multiLine/inputbox.d.ts +3 -3
  23. package/dist/src/multiLine/inputbox.js +3 -7
  24. package/dist/src/multiLine/paramTag.d.ts +3 -4
  25. package/dist/src/multiLine/paramTag.js +5 -47
  26. package/dist/src/paramLine.d.ts +3 -0
  27. package/dist/src/paramLine.js +43 -2
  28. package/dist/src/table/base.d.ts +1 -1
  29. package/dist/src/table/index.d.ts +1 -1
  30. package/dist/src/table/index.js +1 -7
  31. package/dist/src/table/tr.d.ts +1 -1
  32. package/dist/src/tagPair/ext.js +19 -10
  33. package/dist/util/debug.js +10 -3
  34. package/dist/util/sharable.d.mts +1 -0
  35. package/dist/util/sharable.js +62 -1
  36. package/dist/util/sharable.mjs +62 -0
  37. package/i18n/en.json +2 -0
  38. package/i18n/zh-hans.json +2 -0
  39. package/i18n/zh-hant.json +2 -0
  40. package/package.json +2 -1
@@ -77,7 +77,7 @@ const mw = {
77
77
  },
78
78
  },
79
79
  };
80
- const pkg = "wikilint", version = "2.32.0";
80
+ const pkg = "wikilint", version = "2.33.0";
81
81
  let mwConfig;
82
82
  /**
83
83
  * Get the parser configuration for a Wikimedia Foundation project.
@@ -52,6 +52,7 @@ const defaultLintRuleConfig = {
52
52
  {
53
53
  // extension: 2,
54
54
  // image: 2,
55
+ // link: 2,
55
56
  parameter: 1,
56
57
  // thumb: 2,
57
58
  },
@@ -128,6 +129,7 @@ const defaultLintRuleConfig = {
128
129
  // invalidAttributes: 2,
129
130
  nonWordAttributes: 1,
130
131
  redirect: 1,
132
+ // categorytree: 2,
131
133
  // choose: 2,
132
134
  // combobox: 2,
133
135
  // dynamicpagelist: 2,
package/dist/lib/lsp.js CHANGED
@@ -741,6 +741,13 @@ class LanguageService {
741
741
  return token.parentNode.module === mod && token.parentNode.function === func;
742
742
  }).map(({ name }) => name), 'Variable', key, position, type === 'parameter-value' ? '=' : '')
743
743
  : undefined;
744
+ }
745
+ else if (type === 'param-line') {
746
+ // parameter line of `<dynamicpagelist>` or `<inputbox>`
747
+ const key = this.#text.slice(cur.getAbsoluteIndex(), root.indexFromPos(line, character)).trimStart();
748
+ return /^[a-z]+$/iu.test(key)
749
+ ? getCompletion(sharable_1.extParams[cur.name], 'Property', key, position)
750
+ : undefined;
744
751
  /* NOT FOR BROWSER ONLY */
745
752
  }
746
753
  else if (isAttr(cur, true)) {
package/dist/lib/text.js CHANGED
@@ -88,10 +88,10 @@ class AstText extends node_1.AstNode {
88
88
  }
89
89
  const { type, parentNode: grandparent } = parentNode;
90
90
  if (type === 'attr-value') {
91
- const { name: grandName, tag } = grandparent;
92
- if (tag === 'ref' && (grandName === 'name' || grandName === 'follow')
93
- || grandName === 'group' && (tag === 'ref' || tag === 'references')
94
- || tag === 'choose' && (grandName === 'before' || grandName === 'after')) {
91
+ const { name, tag } = grandparent;
92
+ if (tag === 'ref' && (name === 'name' || name === 'follow')
93
+ || name === 'group' && (tag === 'ref' || tag === 'references')
94
+ || tag === 'choose' && (name === 'before' || name === 'after')) {
95
95
  return [];
96
96
  }
97
97
  }
@@ -1,7 +1,6 @@
1
- import Parser from '../index';
2
1
  import { Token } from './index';
3
2
  import { AtomToken } from './atom';
4
- import type { LintError } from '../base';
3
+ import type { LintError, Config } from '../base';
5
4
  import type { AttributesToken } from '../internal';
6
5
  export type AttributeTypes = 'ext-attr' | 'html-attr' | 'table-attr';
7
6
  /**
@@ -28,11 +27,11 @@ export declare abstract class AttributeToken extends Token {
28
27
  * @param type 标签类型
29
28
  * @param tag 标签名
30
29
  * @param key 属性名
30
+ * @param quotes 引号
31
31
  * @param equal 等号
32
32
  * @param value 属性值
33
- * @param quotes 引号
34
33
  */
35
- constructor(type: AttributeTypes, tag: string, key: string, equal?: string, value?: string, quotes?: readonly [string?, string?], config?: Parser.Config, accum?: Token[]);
34
+ constructor(type: AttributeTypes, tag: string, key: string, quotes: readonly [string?, string?], config: Config, equal?: string, value?: string, accum?: Token[]);
36
35
  /**
37
36
  * Get the attribute value
38
37
  *
@@ -52,11 +52,11 @@ class AttributeToken extends index_2.Token {
52
52
  * @param type 标签类型
53
53
  * @param tag 标签名
54
54
  * @param key 属性名
55
+ * @param quotes 引号
55
56
  * @param equal 等号
56
57
  * @param value 属性值
57
- * @param quotes 引号
58
58
  */
59
- constructor(type, tag, key, equal = '', value, quotes = [], config = index_1.default.getConfig(), accum = []) {
59
+ constructor(type, tag, key, quotes, config, equal = '', value, accum = []) {
60
60
  const keyToken = new atom_1.AtomToken(key, 'attr-key', config, accum);
61
61
  let valueToken;
62
62
  if (key === 'title' || tag === 'img' && key === 'alt') {
@@ -129,9 +129,12 @@ class AttributeToken extends index_2.Token {
129
129
  }
130
130
  if (!attrs?.has(name)
131
131
  && !attrs2?.has(name)
132
- // 不是未定义的扩展标签或包含嵌入的HTML标签
132
+ // 已知定义的扩展标签或不包含嵌入的HTML标签
133
133
  && (type === 'ext-attr' ? attrs || attrs2 : !/\{\{[^{]+\}\}/u.test(name))
134
- && (type === 'ext-attr' && !attrs2
134
+ && (
135
+ // 不支持通用HTML属性的扩展标签
136
+ type === 'ext-attr' && !attrs2
137
+ // 或非通用HTML属性
135
138
  || !/^(?:xmlns:[\w:.-]+|data-(?!ooui|mw|parsoid)[^:]*)$/u.test(name)
136
139
  && (tag === 'meta' || tag === 'link' || !sharable_1.commonHtmlAttrs.has(name)))
137
140
  || (name === 'itemtype' || name === 'itemid' || name === 'itemref')
@@ -66,7 +66,7 @@ class AttributesToken extends index_2.Token {
66
66
  if (/^(?:[\w:]|\0\d+t\x7F)(?:[\w:.-]|\0\d+t\x7F)*$/u.test((0, string_1.removeComment)(key).trim())) {
67
67
  const value = quoted ?? unquoted, quotes = [quoteStart, quoteEnd],
68
68
  // @ts-expect-error abstract class
69
- token = new attribute_1.AttributeToken((0, exports.toAttributeType)(type), name, key, equal, value, quotes, config, accum);
69
+ token = new attribute_1.AttributeToken((0, exports.toAttributeType)(type), name, key, quotes, config, equal, value, accum);
70
70
  insertDirty();
71
71
  super.insertAt(token);
72
72
  }
@@ -1,5 +1,5 @@
1
1
  import { Token } from './index';
2
- import type { LintError, Config } from '../base';
2
+ import type { LintError, Config, TokenTypes } from '../base';
3
3
  import type { Title } from '../lib/title';
4
4
  import type { AtomToken, FileToken } from '../internal';
5
5
  /**
@@ -23,8 +23,12 @@ export declare abstract class ImageParameterToken extends Token {
23
23
  get thumb(): Title | undefined;
24
24
  /** image link / 图片链接 */
25
25
  get link(): string | Title | undefined;
26
- /** @param str 图片参数 */
27
- constructor(str: string, extension: string | undefined, config: Config, accum?: Token[]);
26
+ /**
27
+ * @param str 图片参数
28
+ * @param extension 文件扩展名
29
+ * @param type 父节点类型
30
+ */
31
+ constructor(str: string, extension: string | undefined, type: TokenTypes | undefined, config: Config, accum?: Token[]);
28
32
  /**
29
33
  * Get the parameter value
30
34
  *
@@ -147,15 +147,19 @@ let ImageParameterToken = (() => {
147
147
  }, index_1.default);
148
148
  }
149
149
  }
150
- /** @param str 图片参数 */
151
- constructor(str, extension, config, accum) {
150
+ /**
151
+ * @param str 图片参数
152
+ * @param extension 文件扩展名
153
+ * @param type 父节点类型
154
+ */
155
+ constructor(str, extension, type, config, accum) {
152
156
  let mt;
153
157
  const regexes = Object.entries(config.img)
154
158
  .map(([syntax, param]) => [syntax, param, getSyntaxRegex(syntax)]), param = regexes.find(([, key, regex]) => {
155
159
  mt = regex.exec(str);
156
160
  return mt
157
161
  && (mt.length !== 4
158
- || validate(key, mt[2], config, extension, true) !== false);
162
+ || validate(key, mt[2], config, key === 'link' ? type : extension, true) !== false);
159
163
  });
160
164
  // @ts-expect-error mt already assigned
161
165
  if (param && mt) {
@@ -222,7 +226,13 @@ let ImageParameterToken = (() => {
222
226
  }
223
227
  }
224
228
  else if (name === 'link') {
225
- if (typeof link === 'string') {
229
+ if (link === undefined) {
230
+ const rule = 'invalid-gallery', s = lintConfig.getSeverity(rule, 'link');
231
+ if (s) {
232
+ errors.push((0, lint_1.generateForSelf)(this, { start }, rule, 'invalid-gallery-link', s));
233
+ }
234
+ }
235
+ else if (typeof link === 'string') {
226
236
  const rule = 'invalid-url', s = lintConfig.getSeverity(rule);
227
237
  if (s && !this.querySelector('magic-word')) {
228
238
  try {
@@ -34,5 +34,13 @@ export declare class Token extends AstElement {
34
34
  */
35
35
  insertAt(child: string, i?: number): AstText;
36
36
  insertAt<T extends AstNodes>(child: T, i?: number): T;
37
+ /**
38
+ * Normalize page title
39
+ *
40
+ * 规范化页面标题
41
+ * @param title title (with or without the namespace prefix) / 标题(含或不含命名空间前缀)
42
+ * @param defaultNs default namespace number / 命名空间
43
+ */
44
+ normalizeTitle(title: string, defaultNs?: number, opt?: TitleOptions): Title;
37
45
  }
38
46
  export {};
package/dist/src/index.js CHANGED
@@ -112,7 +112,7 @@ class Token extends element_1.AstElement {
112
112
  if (n < this.#stage || this.length !== 1 || !this.isPlain()) {
113
113
  return this;
114
114
  }
115
- else if (this.#stage >= constants_1.MAX_STAGE) {
115
+ else /* istanbul ignore if */ if (this.#stage >= constants_1.MAX_STAGE) {
116
116
  return this;
117
117
  }
118
118
  switch (n) {
@@ -170,10 +170,8 @@ class Token extends element_1.AstElement {
170
170
  if (i % 2 === 0) {
171
171
  return s && new text_1.AstText(s);
172
172
  }
173
- else if (isNaN(s.slice(-1))) {
174
- return this.#accum[Number(s.slice(0, -1))];
175
- }
176
- throw new Error(`Failed to build! Unrecognized token: ${s}`);
173
+ const n = Number(s.slice(0, -1));
174
+ return this.#accum[n];
177
175
  }).filter(node => node !== '');
178
176
  if (type === constants_1.BuildMethod.String) {
179
177
  return nodes.map(String).join('');
@@ -221,7 +219,7 @@ class Token extends element_1.AstElement {
221
219
  #parseRedirect() {
222
220
  const { parseRedirect } = require('../parser/redirect');
223
221
  const wikitext = this.firstChild.toString(), parsed = parseRedirect(wikitext, this.#config, this.#accum);
224
- if (parsed) {
222
+ if (parsed !== false) {
225
223
  this.setText(parsed);
226
224
  }
227
225
  return Boolean(parsed);
@@ -277,9 +275,6 @@ class Token extends element_1.AstElement {
277
275
  * @param tidy 是否整理
278
276
  */
279
277
  #parseQuotes(tidy) {
280
- if (this.#config.excludes.includes('quote')) {
281
- return;
282
- }
283
278
  const { parseQuotes } = require('../parser/quotes');
284
279
  const lines = this.firstChild.toString().split('\n');
285
280
  for (let i = 0; i < lines.length; i++) {
@@ -289,17 +284,11 @@ class Token extends element_1.AstElement {
289
284
  }
290
285
  /** 解析外部链接 */
291
286
  #parseExternalLinks() {
292
- if (this.#config.excludes.includes('extLink')) {
293
- return;
294
- }
295
287
  const { parseExternalLinks } = require('../parser/externalLinks');
296
288
  this.setText(parseExternalLinks(this.firstChild.toString(), this.#config, this.#accum));
297
289
  }
298
290
  /** 解析自由外链 */
299
291
  #parseMagicLinks() {
300
- if (this.#config.excludes.includes('magicLink')) {
301
- return;
302
- }
303
292
  const { parseMagicLinks } = require('../parser/magicLinks');
304
293
  this.setText(parseMagicLinks(this.firstChild.toString(), this.#config, this.#accum));
305
294
  }
@@ -338,6 +327,7 @@ class Token extends element_1.AstElement {
338
327
  return this.#accum;
339
328
  case 'built':
340
329
  return this.#built;
330
+ /* istanbul ignore next */
341
331
  case 'stage':
342
332
  return this.#stage;
343
333
  default:
@@ -358,7 +348,8 @@ class Token extends element_1.AstElement {
358
348
  }
359
349
  }
360
350
  insertAt(child, i = this.length) {
361
- const token = typeof child === 'string' ? new text_1.AstText(child) : child;
351
+ const token = typeof child === 'string' ? new text_1.AstText(child) : child, { length } = this;
352
+ i += i < 0 ? length : 0;
362
353
  super.insertAt(token, i);
363
354
  const { type, } = token;
364
355
  if (type === 'root') {
@@ -366,7 +357,14 @@ class Token extends element_1.AstElement {
366
357
  }
367
358
  return token;
368
359
  }
369
- /** @private */
360
+ // eslint-disable-next-line jsdoc/require-param
361
+ /**
362
+ * Normalize page title
363
+ *
364
+ * 规范化页面标题
365
+ * @param title title (with or without the namespace prefix) / 标题(含或不含命名空间前缀)
366
+ * @param defaultNs default namespace number / 命名空间
367
+ */
370
368
  normalizeTitle(title, defaultNs = 0, opt) {
371
369
  return index_1.default.normalizeTitle(title, defaultNs, this.getAttribute('include'), this.#config, { page: this.pageName, ...opt });
372
370
  }
@@ -427,8 +425,12 @@ class Token extends element_1.AstElement {
427
425
  let mt = regex.exec(wikitext);
428
426
  while (mt) {
429
427
  const { 1: type, index } = mt, detail = mt[2]?.trim();
428
+ let line;
429
+ if (type === 'disable-line' || type === 'disable-next-line') {
430
+ line = this.posFromIndex(index).top + (type === 'disable-line' ? 0 : 1);
431
+ }
430
432
  ignores.push({
431
- line: this.posFromIndex(index).top + (type === 'disable-line' ? 0 : 1),
433
+ line,
432
434
  from: type === 'disable' ? regex.lastIndex : undefined,
433
435
  to: type === 'enable' ? regex.lastIndex : undefined,
434
436
  rules: detail ? new Set(detail.split(',').map(rule => rule.trim())) : undefined,
@@ -438,13 +440,13 @@ class Token extends element_1.AstElement {
438
440
  errors = errors.filter(({ rule, startLine, startIndex }) => {
439
441
  const nearest = { pos: 0 };
440
442
  for (const { line, from, to, rules } of ignores) {
441
- if (line > startLine + 1) {
443
+ if (line && line > startLine + 1) {
442
444
  break;
443
445
  }
444
446
  else if (rules && !rules.has(rule)) {
445
447
  continue;
446
448
  }
447
- else if (line === startLine && from === undefined && to === undefined) {
449
+ else if (line === startLine) {
448
450
  return false;
449
451
  }
450
452
  else if (from <= startIndex && from > nearest.pos) {
@@ -11,7 +11,7 @@ import type { Title } from '../../lib/title';
11
11
  export declare abstract class LinkBaseToken extends Token {
12
12
  #private;
13
13
  readonly name: string;
14
- abstract get type(): 'link' | 'category' | 'file' | 'gallery-image' | 'imagemap-image' | 'redirect-target';
14
+ abstract get type(): 'link' | 'category' | 'file' | 'gallery-image' | 'imagemap-image' | 'redirect-target' | 'ext-inner';
15
15
  readonly childNodes: readonly [AtomToken, ...Token[]];
16
16
  abstract get firstChild(): AtomToken;
17
17
  abstract get lastChild(): Token;
@@ -91,13 +91,19 @@ let LinkBaseToken = (() => {
91
91
  }
92
92
  this.#delimiter = delimiter;
93
93
  }
94
+ /** 更新name */
95
+ #setName() {
96
+ if (this.type !== 'ext-inner') {
97
+ this.setAttribute('name', this.#title.title);
98
+ }
99
+ }
94
100
  /** @private */
95
101
  afterBuild() {
96
102
  this.#title = this.getTitle();
97
103
  if (this.#delimiter.includes('\0')) {
98
104
  this.#delimiter = this.buildFromStr(this.#delimiter, constants_1.BuildMethod.String);
99
105
  }
100
- this.setAttribute('name', this.#title.title);
106
+ this.#setName();
101
107
  super.afterBuild();
102
108
  }
103
109
  /** @private */
@@ -0,0 +1,21 @@
1
+ import { LinkBaseToken } from './base';
2
+ import type { Config, LintError } from '../../base';
3
+ import type { Title } from '../../lib/title';
4
+ import type { Token, AtomToken, AttributesToken, ExtToken } from '../../internal';
5
+ /**
6
+ * `<categorytree>`
7
+ * @classdesc `{childNodes: [AtomToken]}`
8
+ */
9
+ export declare abstract class CategorytreeToken extends LinkBaseToken {
10
+ readonly childNodes: readonly [AtomToken];
11
+ abstract get lastChild(): AtomToken;
12
+ abstract get nextSibling(): undefined;
13
+ abstract get previousSibling(): AttributesToken | undefined;
14
+ abstract get parentNode(): ExtToken | undefined;
15
+ abstract get link(): Title;
16
+ get type(): 'ext-inner';
17
+ /** @param link 链接标题 */
18
+ constructor(link: string, linkText?: undefined, config?: Config, accum?: Token[]);
19
+ getTitle(): Title;
20
+ lint(start?: number): LintError[];
21
+ }
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
3
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
4
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
5
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
6
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
7
+ var _, done = false;
8
+ for (var i = decorators.length - 1; i >= 0; i--) {
9
+ var context = {};
10
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
11
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
12
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
13
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
14
+ if (kind === "accessor") {
15
+ if (result === void 0) continue;
16
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
17
+ if (_ = accept(result.get)) descriptor.get = _;
18
+ if (_ = accept(result.set)) descriptor.set = _;
19
+ if (_ = accept(result.init)) initializers.unshift(_);
20
+ }
21
+ else if (_ = accept(result)) {
22
+ if (kind === "field") initializers.unshift(_);
23
+ else descriptor[key] = _;
24
+ }
25
+ }
26
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
27
+ done = true;
28
+ };
29
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
30
+ var useValue = arguments.length > 2;
31
+ for (var i = 0; i < initializers.length; i++) {
32
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
33
+ }
34
+ return useValue ? value : void 0;
35
+ };
36
+ var __importDefault = (this && this.__importDefault) || function (mod) {
37
+ return (mod && mod.__esModule) ? mod : { "default": mod };
38
+ };
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.CategorytreeToken = void 0;
41
+ const lint_1 = require("../../util/lint");
42
+ const padded_1 = require("../../mixin/padded");
43
+ const index_1 = __importDefault(require("../../index"));
44
+ const base_1 = require("./base");
45
+ /**
46
+ * `<categorytree>`
47
+ * @classdesc `{childNodes: [AtomToken]}`
48
+ */
49
+ let CategorytreeToken = (() => {
50
+ let _classDecorators = [(0, padded_1.padded)('')];
51
+ let _classDescriptor;
52
+ let _classExtraInitializers = [];
53
+ let _classThis;
54
+ let _classSuper = base_1.LinkBaseToken;
55
+ var CategorytreeToken = class extends _classSuper {
56
+ static { _classThis = this; }
57
+ static {
58
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
59
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
60
+ CategorytreeToken = _classThis = _classDescriptor.value;
61
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
62
+ __runInitializers(_classThis, _classExtraInitializers);
63
+ }
64
+ get type() {
65
+ return 'ext-inner';
66
+ }
67
+ /** @param link 链接标题 */
68
+ constructor(link, linkText, config, accum = []) {
69
+ super(link, linkText, config, accum);
70
+ this.setAttribute('bracket', false);
71
+ }
72
+ getTitle() {
73
+ const target = this.firstChild.toString().trim(), opt = { halfParsed: true }, title = this.normalizeTitle(target, 14, opt);
74
+ return title.valid && title.ns === 14
75
+ ? title
76
+ : this.normalizeTitle(`Category:${target}`, 0, opt);
77
+ }
78
+ lint(start = this.getAbsoluteIndex()) {
79
+ LINT: {
80
+ const rule = 'no-ignored', s = index_1.default.lintConfig.getSeverity(rule, 'categorytree');
81
+ if (s) {
82
+ const { link } = this;
83
+ if (!link.valid || link.ns !== 14) {
84
+ return [(0, lint_1.generateForSelf)(this, { start }, rule, 'invalid-category', s)];
85
+ }
86
+ }
87
+ return super.lint(start, false);
88
+ }
89
+ }
90
+ };
91
+ return CategorytreeToken = _classThis;
92
+ })();
93
+ exports.CategorytreeToken = CategorytreeToken;
@@ -1,6 +1,6 @@
1
1
  import { LinkBaseToken } from './base';
2
2
  import { ImageParameterToken } from '../imageParameter';
3
- import type { Config, LintError } from '../../base';
3
+ import type { TokenTypes, Config, LintError } from '../../base';
4
4
  import type { Token, AtomToken } from '../../internal';
5
5
  /**
6
6
  * image
@@ -23,8 +23,9 @@ export declare abstract class FileToken extends LinkBaseToken {
23
23
  * @param link 文件名
24
24
  * @param text 图片参数
25
25
  * @param delimiter `|`
26
+ * @param type 节点类型
26
27
  */
27
- constructor(link: string, text?: string, config?: Config, accum?: Token[], delimiter?: string);
28
+ constructor(link: string, text?: string, config?: Config, accum?: Token[], delimiter?: string, type?: TokenTypes);
28
29
  /**
29
30
  * Get all image parameter tokens
30
31
  *
@@ -69,13 +69,14 @@ class FileToken extends base_1.LinkBaseToken {
69
69
  * @param link 文件名
70
70
  * @param text 图片参数
71
71
  * @param delimiter `|`
72
+ * @param type 节点类型
72
73
  */
73
- constructor(link, text, config, accum = [], delimiter = '|') {
74
+ constructor(link, text, config, accum = [], delimiter = '|', type) {
74
75
  super(link, undefined, config, accum, delimiter);
75
76
  const { extension } = this.getTitle(true, true);
76
77
  this.safeAppend(explode(text).map(
77
78
  // @ts-expect-error abstract class
78
- (part) => new imageParameter_1.ImageParameterToken(part, extension, config, accum)));
79
+ (part) => new imageParameter_1.ImageParameterToken(part, extension, type, config, accum)));
79
80
  }
80
81
  /** @private */
81
82
  lint(start = this.getAbsoluteIndex(), re) {
@@ -84,9 +84,10 @@ let GalleryImageToken = (() => {
84
84
  }
85
85
  accum.splice(length, 1);
86
86
  }
87
- super(link, token?.firstChild.toString(), config, accum);
87
+ const privateType = `${type}-image`;
88
+ super(link, token?.firstChild.toString(), config, accum, undefined, privateType);
88
89
  this.setAttribute('bracket', false);
89
- this.privateType = `${type}-image`;
90
+ this.privateType = privateType;
90
91
  }
91
92
  /** @private */
92
93
  getTitle(temporary) {
@@ -95,9 +96,9 @@ let GalleryImageToken = (() => {
95
96
  }
96
97
  /** 判定无效的图片 */
97
98
  #lint() {
98
- const { ns, } = this.getAttribute('title');
99
+ const title = this.getAttribute('title');
99
100
  // eslint-disable-next-line @stylistic/semi
100
- return ns !== 6;
101
+ return title.ns !== 6;
101
102
  }
102
103
  /** @private */
103
104
  lint(start = this.getAbsoluteIndex(), re) {
@@ -4,9 +4,7 @@ import { CommentLineToken } from '../nowiki/commentLine';
4
4
  import type { Config, LintError } from '../../base';
5
5
  import type { AstText, Token } from '../../internal';
6
6
  /**
7
- * gallery tag
8
- *
9
- * gallery标签
7
+ * `<gallery>`
10
8
  * @classdesc `{childNodes: (GalleryImageToken|CommentLineToken|AstText)[]}`
11
9
  */
12
10
  export declare abstract class GalleryToken extends MultiLineToken {
@@ -10,9 +10,7 @@ const index_2 = require("./index");
10
10
  const galleryImage_1 = require("../link/galleryImage");
11
11
  const commentLine_1 = require("../nowiki/commentLine");
12
12
  /**
13
- * gallery tag
14
- *
15
- * gallery标签
13
+ * `<gallery>`
16
14
  * @classdesc `{childNodes: (GalleryImageToken|CommentLineToken|AstText)[]}`
17
15
  */
18
16
  class GalleryToken extends index_2.MultiLineToken {
@@ -35,9 +35,8 @@ class ImagemapToken extends index_2.MultiLineToken {
35
35
  //
36
36
  }
37
37
  else if (first) {
38
- const pipe = line.indexOf('|'), file = pipe === -1 ? line : line.slice(0, pipe), { valid, ns, } = this.normalizeTitle(file, 0, { halfParsed: true, temporary: true, page: '' });
39
- if (valid
40
- && ns === 6) {
38
+ const pipe = line.indexOf('|'), file = pipe === -1 ? line : line.slice(0, pipe), title = this.normalizeTitle(file, 0, { halfParsed: true, temporary: true, page: '' });
39
+ if (title.valid && title.ns === 6) {
41
40
  // @ts-expect-error abstract class
42
41
  const token = new galleryImage_1.GalleryImageToken('imagemap', file, pipe === -1 ? undefined : line.slice(pipe + 1), config, accum);
43
42
  super.insertAt(token);
@@ -1,8 +1,8 @@
1
- import Parser from '../../index';
2
1
  import { ParamTagToken } from './paramTag';
2
+ import type { Config } from '../../base';
3
3
  import type { Token } from '../../internal';
4
4
  /** `<inputbox>` */
5
5
  export declare abstract class InputboxToken extends ParamTagToken {
6
- /** @class */
7
- constructor(include: boolean, wikitext?: string, config?: Parser.Config, accum?: Token[]);
6
+ /** @param name 扩展标签名 */
7
+ constructor(name: string, include: boolean, wikitext: string | undefined, config: Config, accum?: Token[]);
8
8
  }
@@ -1,17 +1,13 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.InputboxToken = void 0;
7
4
  const commentAndExt_1 = require("../../parser/commentAndExt");
8
5
  const braces_1 = require("../../parser/braces");
9
- const index_1 = __importDefault(require("../../index"));
10
6
  const paramTag_1 = require("./paramTag");
11
7
  /** `<inputbox>` */
12
8
  class InputboxToken extends paramTag_1.ParamTagToken {
13
- /** @class */
14
- constructor(include, wikitext, config = index_1.default.getConfig(), accum = []) {
9
+ /** @param name 扩展标签名 */
10
+ constructor(name, include, wikitext, config, accum = []) {
15
11
  const placeholder = Symbol('InputboxToken'), newConfig = config.excludes.includes('heading')
16
12
  ? config
17
13
  : {
@@ -22,7 +18,7 @@ class InputboxToken extends paramTag_1.ParamTagToken {
22
18
  wikitext &&= (0, commentAndExt_1.parseCommentAndExt)(wikitext, newConfig, accum, include);
23
19
  wikitext &&= (0, braces_1.parseBraces)(wikitext, newConfig, accum);
24
20
  accum.splice(length, 1);
25
- super(include, wikitext, newConfig, accum, {});
21
+ super(name, include, wikitext, newConfig, accum, {});
26
22
  }
27
23
  }
28
24
  exports.InputboxToken = InputboxToken;
@@ -1,7 +1,6 @@
1
- import Parser from '../../index';
2
1
  import { MultiLineToken } from './index';
3
2
  import { ParamLineToken } from '../paramLine';
4
- import type { LintError } from '../../base';
3
+ import type { Config } from '../../base';
5
4
  import type { Token } from '../../internal';
6
5
  /**
7
6
  * `<dynamicpagelist>`
@@ -11,6 +10,6 @@ export declare abstract class ParamTagToken extends MultiLineToken {
11
10
  readonly childNodes: readonly ParamLineToken[];
12
11
  abstract get firstChild(): ParamLineToken | undefined;
13
12
  abstract get lastChild(): ParamLineToken | undefined;
14
- /** @class */
15
- constructor(include: boolean, wikitext?: string, config?: Parser.Config, accum?: Token[], acceptable?: WikiParserAcceptable);
13
+ /** @param name 扩展标签名 */
14
+ constructor(name: string, include: boolean, wikitext: string | undefined, config: Config, accum?: Token[], acceptable?: WikiParserAcceptable);
16
15
  }
@@ -1,67 +1,25 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.ParamTagToken = void 0;
7
- const lint_1 = require("../../util/lint");
8
- const rect_1 = require("../../lib/rect");
9
4
  const commentAndExt_1 = require("../../parser/commentAndExt");
10
- const index_1 = __importDefault(require("../../index"));
11
- const index_2 = require("./index");
5
+ const index_1 = require("./index");
12
6
  const paramLine_1 = require("../paramLine");
13
7
  /**
14
8
  * `<dynamicpagelist>`
15
9
  * @classdesc `{childNodes: ParamLineToken[]}`
16
10
  */
17
- class ParamTagToken extends index_2.MultiLineToken {
18
- /** @class */
19
- constructor(include, wikitext, config = index_1.default.getConfig(), accum = [], acceptable) {
11
+ class ParamTagToken extends index_1.MultiLineToken {
12
+ /** @param name 扩展标签名 */
13
+ constructor(name, include, wikitext, config, accum = [], acceptable) {
20
14
  super(undefined, config, accum, {});
21
15
  if (wikitext) {
22
16
  this.safeAppend(wikitext.split('\n')
23
17
  .map(line => acceptable ? line : (0, commentAndExt_1.parseCommentAndExt)(line, config, accum, include))
24
18
  // @ts-expect-error abstract class
25
- .map((line) => new paramLine_1.ParamLineToken(line, config, accum, {})));
19
+ .map((line) => new paramLine_1.ParamLineToken(name, line, config, accum, {})));
26
20
  }
27
21
  accum.splice(accum.indexOf(this), 1);
28
22
  accum.push(this);
29
23
  }
30
- /** @private */
31
- lint(start = this.getAbsoluteIndex()) {
32
- LINT: {
33
- const rule = 'no-ignored', { lintConfig } = index_1.default, s = lintConfig.getSeverity(rule, this.name);
34
- if (!s) {
35
- return [];
36
- }
37
- const rect = new rect_1.BoundingRect(this, start), msg = index_1.default.msg('invalid-parameter', this.name), errors = [];
38
- for (const child of this.childNodes) {
39
- child.setAttribute('aIndex', start);
40
- const grandChildren = child.childNodes
41
- .filter(({ type }) => type !== 'comment' && type !== 'include' && type !== 'noinclude');
42
- if (grandChildren.some(({ type }) => type === 'ext')) {
43
- errors.push((0, lint_1.generateForChild)(child, rect, rule, msg, s));
44
- }
45
- else {
46
- const i = grandChildren.findIndex(({ type }) => type !== 'text'), str = grandChildren.slice(0, i === -1 ? undefined : i).map(String).join('');
47
- if (str && !(i === -1 ? /^[a-z]+(?:\[\])?\s*=/iu : /^[a-z]+(?:\[\])?\s*(?:=|$)/iu).test(str)) {
48
- const e = (0, lint_1.generateForChild)(child, rect, rule, msg, s);
49
- if (lintConfig.computeEditInfo) {
50
- e.suggestions = [(0, lint_1.fixByRemove)(e)];
51
- }
52
- errors.push(e);
53
- }
54
- else {
55
- const childErrors = child.lint(start, false);
56
- if (childErrors.length > 0) {
57
- Array.prototype.push.apply(errors, childErrors);
58
- }
59
- }
60
- }
61
- start += child.toString().length + 1;
62
- }
63
- return errors;
64
- }
65
- }
66
24
  }
67
25
  exports.ParamTagToken = ParamTagToken;
@@ -1,4 +1,5 @@
1
1
  import { Token } from './index';
2
+ import type { Config, LintError } from '../base';
2
3
  import type { ParamTagToken } from '../internal';
3
4
  /**
4
5
  * parameter of certain extension tags
@@ -10,4 +11,6 @@ export declare abstract class ParamLineToken extends Token {
10
11
  abstract get nextSibling(): this | undefined;
11
12
  abstract get previousSibling(): this | undefined;
12
13
  get type(): 'param-line';
14
+ /** @param name 扩展标签名 */
15
+ constructor(name: string, wikitext: string | undefined, config: Config, accum: Token[], acceptable: WikiParserAcceptable);
13
16
  }
@@ -1,15 +1,56 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.ParamLineToken = void 0;
4
- const index_1 = require("./index");
7
+ const lint_1 = require("../util/lint");
8
+ const sharable_1 = require("../util/sharable");
9
+ const index_1 = __importDefault(require("../index"));
10
+ const index_2 = require("./index");
5
11
  /**
6
12
  * parameter of certain extension tags
7
13
  *
8
14
  * 某些扩展标签的参数
9
15
  */
10
- class ParamLineToken extends index_1.Token {
16
+ class ParamLineToken extends index_2.Token {
11
17
  get type() {
12
18
  return 'param-line';
13
19
  }
20
+ /** @param name 扩展标签名 */
21
+ constructor(name, wikitext, config, accum, acceptable) {
22
+ super(wikitext, config, accum, acceptable);
23
+ this.setAttribute('name', name);
24
+ }
25
+ /** @private */
26
+ lint(start = this.getAbsoluteIndex()) {
27
+ LINT: {
28
+ const rule = 'no-ignored', { lintConfig } = index_1.default, { name, childNodes } = this, s = lintConfig.getSeverity(rule, name);
29
+ if (!s) {
30
+ return [];
31
+ }
32
+ const msg = index_1.default.msg('invalid-parameter', name);
33
+ if (childNodes.some(({ type }) => type === 'ext')) {
34
+ return [(0, lint_1.generateForSelf)(this, { start }, rule, msg, s)];
35
+ }
36
+ const children = childNodes
37
+ .filter(({ type }) => type !== 'comment' && type !== 'include' && type !== 'noinclude'), isInputbox = name === 'inputbox', i = isInputbox ? children.findIndex(({ type }) => type !== 'text') : -1;
38
+ let str = children.slice(0, i === -1 ? undefined : i).map(String).join('').trim();
39
+ if (str) {
40
+ if (isInputbox) {
41
+ str = str.toLowerCase();
42
+ }
43
+ const j = str.indexOf('='), key = str.slice(0, j === -1 ? undefined : j).trim(), params = sharable_1.extParams[name];
44
+ if (j === -1 ? i === -1 || !params.some(p => p.startsWith(key)) : !params.includes(key)) {
45
+ const e = (0, lint_1.generateForSelf)(this, { start }, rule, msg, s);
46
+ if (lintConfig.computeEditInfo) {
47
+ e.suggestions = [(0, lint_1.fixByRemove)(e)];
48
+ }
49
+ return [e];
50
+ }
51
+ }
52
+ return super.lint(start, false);
53
+ }
54
+ }
14
55
  }
15
56
  exports.ParamLineToken = ParamLineToken;
@@ -23,7 +23,7 @@ export declare abstract class TableBaseToken extends Token {
23
23
  * @param type 节点类型
24
24
  * @param attr 表格属性
25
25
  */
26
- constructor(pattern: RegExp, syntax: string, type: TableTypes, attr?: string, config?: Config, accum?: Token[], acceptable?: WikiParserAcceptable);
26
+ constructor(pattern: RegExp, syntax: string | undefined, type: TableTypes, attr?: string, config?: Config, accum?: Token[], acceptable?: WikiParserAcceptable);
27
27
  escape(): void;
28
28
  }
29
29
  export {};
@@ -24,7 +24,7 @@ export declare abstract class TableToken extends TrBaseToken {
24
24
  * @param syntax 表格语法
25
25
  * @param attr 表格属性
26
26
  */
27
- constructor(syntax: string, attr?: string, config?: Config, accum?: Token[]);
27
+ constructor(syntax?: string, attr?: string, config?: Config, accum?: Token[]);
28
28
  /**
29
29
  * Close the table syntax
30
30
  *
@@ -45,12 +45,6 @@ const cached_1 = require("../../mixin/cached");
45
45
  const index_1 = __importDefault(require("../../index"));
46
46
  const trBase_1 = require("./trBase");
47
47
  const syntax_1 = require("../syntax");
48
- /**
49
- * 生成一个指定长度的空数组
50
- * @param length 数组长度
51
- * @param callback 回调函数
52
- */
53
- const emptyArray = (length, callback) => Array.from({ length }, (_, i) => callback(i));
54
48
  /** @extends {Array<TableCoords[]>} */
55
49
  class Layout extends Array {
56
50
  }
@@ -147,7 +141,7 @@ let TableToken = (() => {
147
141
  */
148
142
  getLayout(stop) {
149
143
  LINT: {
150
- const rows = this.getAllRows(), { length } = rows, layout = Layout.from(emptyArray(length, () => []));
144
+ const rows = this.getAllRows(), { length } = rows, layout = Layout.from((0, debug_1.emptyArray)(length, () => []));
151
145
  for (let i = 0; i < layout.length; i++) {
152
146
  const rowLayout = layout[i];
153
147
  let j = 0, k = 0, last;
@@ -18,5 +18,5 @@ export declare abstract class TrToken extends TrBaseToken {
18
18
  * @param syntax 表格语法
19
19
  * @param attr 表格属性
20
20
  */
21
- constructor(syntax: string, attr?: string, config?: Config, accum?: Token[]);
21
+ constructor(syntax?: string, attr?: string, config?: Config, accum?: Token[]);
22
22
  }
@@ -87,14 +87,20 @@ let ExtToken = (() => {
87
87
  };
88
88
  let innerToken;
89
89
  switch (lcName) {
90
- case 'tab':
91
- newConfig.ext = newConfig.ext.filter(e => e !== 'tabs');
90
+ case 'pre':
91
+ if (attrToken.getAttr('format') !== 'wikitext') {
92
+ const { PreToken } = require('../pre');
93
+ // @ts-expect-error abstract class
94
+ innerToken = new PreToken(inner, newConfig, accum);
95
+ break;
96
+ }
92
97
  // fall through
93
98
  case 'indicator':
94
99
  case 'poem':
95
100
  case 'ref':
96
101
  case 'option':
97
102
  case 'combooption':
103
+ case 'tab':
98
104
  case 'tabs':
99
105
  case 'poll':
100
106
  case 'seo':
@@ -103,24 +109,21 @@ let ExtToken = (() => {
103
109
  if (lcName === 'poem') {
104
110
  newConfig.excludes.push('heading');
105
111
  }
112
+ else if (lcName === 'tab') {
113
+ newConfig.ext = newConfig.ext.filter(e => e !== 'tabs');
114
+ }
106
115
  innerToken = new index_2.Token(inner, newConfig, accum);
107
116
  break;
108
- case 'pre': {
109
- const { PreToken } = require('../pre');
110
- // @ts-expect-error abstract class
111
- innerToken = new PreToken(inner, newConfig, accum);
112
- break;
113
- }
114
117
  case 'dynamicpagelist': {
115
118
  const { ParamTagToken } = require('../multiLine/paramTag');
116
119
  // @ts-expect-error abstract class
117
- innerToken = new ParamTagToken(include, inner, newConfig, accum);
120
+ innerToken = new ParamTagToken(lcName, include, inner, newConfig, accum);
118
121
  break;
119
122
  }
120
123
  case 'inputbox': {
121
124
  const { InputboxToken } = require('../multiLine/inputbox');
122
125
  // @ts-expect-error abstract class
123
- innerToken = new InputboxToken(include, inner, newConfig, accum);
126
+ innerToken = new InputboxToken(lcName, include, inner, newConfig, accum);
124
127
  break;
125
128
  }
126
129
  case 'references': {
@@ -163,6 +166,12 @@ let ExtToken = (() => {
163
166
  innerToken = new CommentedToken(inner, newConfig, accum);
164
167
  break;
165
168
  }
169
+ case 'categorytree': {
170
+ const { CategorytreeToken } = require('../link/categorytree');
171
+ // @ts-expect-error abstract class
172
+ innerToken = new CategorytreeToken(inner, undefined, newConfig, accum);
173
+ break;
174
+ }
166
175
  // 更多定制扩展的代码示例:
167
176
  // ```
168
177
  // case 'extensionName': {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mixin = exports.getMagicWordInfo = exports.setChildNodes = exports.isLink = exports.isRowEnd = exports.isToken = exports.Shadow = void 0;
3
+ exports.mixin = exports.emptyArray = exports.getMagicWordInfo = exports.setChildNodes = exports.isLink = exports.isRowEnd = exports.isToken = exports.Shadow = void 0;
4
4
  exports.Shadow = {
5
5
  running: false,
6
6
  /** @private */
@@ -12,9 +12,9 @@ exports.Shadow = {
12
12
  this.running = running;
13
13
  };
14
14
  try {
15
- const { Token: AnyToken } = require('../src/index');
15
+ const { Token } = require('../src/index');
16
16
  const result = callback();
17
- if (result instanceof AnyToken && !result.getAttribute('built')) {
17
+ if (result instanceof Token && !result.getAttribute('built')) {
18
18
  result.afterBuild();
19
19
  }
20
20
  finish();
@@ -97,6 +97,13 @@ const getMagicWordInfo = (name, parserFunction) => {
97
97
  ];
98
98
  };
99
99
  exports.getMagicWordInfo = getMagicWordInfo;
100
+ /**
101
+ * 生成一个指定长度的空数组
102
+ * @param length 数组长度
103
+ * @param callback 回调函数
104
+ */
105
+ const emptyArray = (length, callback) => Array.from({ length }, (_, i) => callback(i));
106
+ exports.emptyArray = emptyArray;
100
107
  /* NOT FOR BROWSER ONLY */
101
108
  /**
102
109
  * 同步混入的类名
@@ -2,3 +2,4 @@ export declare const commonHtmlAttrs: Set<string>;
2
2
  export declare const htmlAttrs: Record<string, Set<string>>;
3
3
  export declare const extAttrs: Record<string, Set<string>>;
4
4
  export declare const obsoleteAttrs: Record<string, Set<string>>;
5
+ export declare const extParams: Record<string, string[]>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.obsoleteAttrs = exports.extAttrs = exports.htmlAttrs = exports.commonHtmlAttrs = void 0;
3
+ exports.extParams = exports.obsoleteAttrs = exports.extAttrs = exports.htmlAttrs = exports.commonHtmlAttrs = void 0;
4
4
  /* eslint-disable unicorn/no-unreadable-iife */
5
5
  const blockAttrs = new Set(['align']), citeAttrs = new Set(['cite']), citeAndAttrs = new Set(['cite', 'datetime']), widthAttrs = new Set(['width']), obsoleteTdAttrs = new Set(['axis', 'align', 'bgcolor', 'height', 'width', 'valign']), tdAttrs = new Set([...obsoleteTdAttrs, 'abbr', 'headers', 'scope', 'rowspan', 'colspan']), typeAttrs = new Set(['type']), obsoleteTableAttrs = new Set(['summary', 'align', 'bgcolor', 'cellpadding', 'cellspacing', 'frame', 'rules', 'width']), brAttrs = new Set(['clear']), trAttrs = new Set(['bgcolor', 'align', 'valign']), chemAttrs = new Set(['id', 'qid', 'forcemathmode', 'type', 'display']), syntaxHighlightAttrs = new Set([
6
6
  'enclose',
@@ -90,6 +90,7 @@ exports.htmlAttrs = (() => ({
90
90
  img: new Set(['alt', 'src', 'width', 'height', 'loading', 'srcset']),
91
91
  }))();
92
92
  exports.extAttrs = (() => ({
93
+ pre: new Set(['format']),
93
94
  gallery: new Set(['mode', 'showfilename', 'caption', 'perrow', 'widths', 'heights', 'showthumbnails']),
94
95
  poem: new Set(['compact']),
95
96
  categorytree: new Set([
@@ -214,3 +215,63 @@ exports.obsoleteAttrs = (() => ({
214
215
  tr: trAttrs,
215
216
  ul: typeAttrs,
216
217
  }))();
218
+ exports.extParams = (() => ({
219
+ dynamicpagelist: [
220
+ 'category',
221
+ 'notcategory',
222
+ 'namespace',
223
+ 'count',
224
+ 'offset',
225
+ 'imagewidth',
226
+ 'imageheight',
227
+ 'imagesperrow',
228
+ 'mode',
229
+ 'gallerycaption',
230
+ 'galleryshowfilesize',
231
+ 'galleryshowfilename',
232
+ 'order',
233
+ 'ordermethod',
234
+ 'redirects',
235
+ 'stablepages',
236
+ 'qualitypages',
237
+ 'suppresserrors',
238
+ 'addfirstcategorydate',
239
+ 'shownamespace',
240
+ 'ignoresubpages',
241
+ 'googlehack',
242
+ 'nofollow',
243
+ ],
244
+ inputbox: [
245
+ 'preloadparams[]',
246
+ 'type',
247
+ 'width',
248
+ 'preload',
249
+ 'preloadtitle',
250
+ 'page',
251
+ 'editintro',
252
+ 'useve',
253
+ 'usedt',
254
+ 'summary',
255
+ 'nosummary',
256
+ 'minor',
257
+ 'break',
258
+ 'default',
259
+ 'placeholder',
260
+ 'bgcolor',
261
+ 'buttonlabel',
262
+ 'searchbuttonlabel',
263
+ 'fulltextbutton',
264
+ 'namespaces',
265
+ 'labeltext',
266
+ 'hidden',
267
+ 'id',
268
+ 'inline',
269
+ 'prefix',
270
+ 'dir',
271
+ 'searchengine',
272
+ 'searchtype',
273
+ 'searchfilter',
274
+ 'tour',
275
+ 'arialabel',
276
+ ],
277
+ }))();
@@ -88,6 +88,7 @@ const htmlAttrs = /* @__PURE__ */ (() => ({
88
88
  img: /* @__PURE__ */ new Set(["alt", "src", "width", "height", "loading", "srcset"])
89
89
  }))();
90
90
  const extAttrs = /* @__PURE__ */ (() => ({
91
+ pre: /* @__PURE__ */ new Set(["format"]),
91
92
  gallery: /* @__PURE__ */ new Set(["mode", "showfilename", "caption", "perrow", "widths", "heights", "showthumbnails"]),
92
93
  poem: /* @__PURE__ */ new Set(["compact"]),
93
94
  categorytree: /* @__PURE__ */ new Set([
@@ -212,9 +213,70 @@ const obsoleteAttrs = /* @__PURE__ */ (() => ({
212
213
  tr: trAttrs,
213
214
  ul: typeAttrs
214
215
  }))();
216
+ const extParams = /* @__PURE__ */ (() => ({
217
+ dynamicpagelist: [
218
+ "category",
219
+ "notcategory",
220
+ "namespace",
221
+ "count",
222
+ "offset",
223
+ "imagewidth",
224
+ "imageheight",
225
+ "imagesperrow",
226
+ "mode",
227
+ "gallerycaption",
228
+ "galleryshowfilesize",
229
+ "galleryshowfilename",
230
+ "order",
231
+ "ordermethod",
232
+ "redirects",
233
+ "stablepages",
234
+ "qualitypages",
235
+ "suppresserrors",
236
+ "addfirstcategorydate",
237
+ "shownamespace",
238
+ "ignoresubpages",
239
+ "googlehack",
240
+ "nofollow"
241
+ ],
242
+ inputbox: [
243
+ "preloadparams[]",
244
+ "type",
245
+ "width",
246
+ "preload",
247
+ "preloadtitle",
248
+ "page",
249
+ "editintro",
250
+ "useve",
251
+ "usedt",
252
+ "summary",
253
+ "nosummary",
254
+ "minor",
255
+ "break",
256
+ "default",
257
+ "placeholder",
258
+ "bgcolor",
259
+ "buttonlabel",
260
+ "searchbuttonlabel",
261
+ "fulltextbutton",
262
+ "namespaces",
263
+ "labeltext",
264
+ "hidden",
265
+ "id",
266
+ "inline",
267
+ "prefix",
268
+ "dir",
269
+ "searchengine",
270
+ "searchtype",
271
+ "searchfilter",
272
+ "tour",
273
+ "arialabel"
274
+ ]
275
+ }))();
215
276
  export {
216
277
  commonHtmlAttrs,
217
278
  extAttrs,
279
+ extParams,
218
280
  htmlAttrs,
219
281
  obsoleteAttrs
220
282
  };
package/i18n/en.json CHANGED
@@ -34,9 +34,11 @@
34
34
  "inconsistent-table": "inconsistent table layout",
35
35
  "insecure-style": "insecure style",
36
36
  "invalid-attribute": "element containing an invalid attribute name",
37
+ "invalid-category": "invalid category name",
37
38
  "invalid-content": "invalid content in <$1>",
38
39
  "invalid-conversion-flag": "invalid conversion flag",
39
40
  "invalid-gallery": "invalid gallery image",
41
+ "invalid-gallery-link": "invalid link in gallery image",
40
42
  "invalid-image-parameter": "invalid image parameter",
41
43
  "invalid-imagemap-link": "invalid link in <imagemap>",
42
44
  "invalid-isbn": "invalid ISBN",
package/i18n/zh-hans.json CHANGED
@@ -34,9 +34,11 @@
34
34
  "inconsistent-table": "不一致的表格布局",
35
35
  "insecure-style": "不安全的样式",
36
36
  "invalid-attribute": "包含无效属性名称的元素",
37
+ "invalid-category": "无效的分类名",
37
38
  "invalid-content": "<$1>中的无效内容",
38
39
  "invalid-conversion-flag": "无效的转换旗标",
39
40
  "invalid-gallery": "无效的图库图像",
41
+ "invalid-gallery-link": "图库图像中的无效链接",
40
42
  "invalid-image-parameter": "无效的图像参数",
41
43
  "invalid-imagemap-link": "<imagemap>中的无效链接",
42
44
  "invalid-isbn": "无效的ISBN",
package/i18n/zh-hant.json CHANGED
@@ -34,9 +34,11 @@
34
34
  "inconsistent-table": "表格版面不一致",
35
35
  "insecure-style": "不安全的樣式",
36
36
  "invalid-attribute": "包含無效屬性名稱的元素",
37
+ "invalid-category": "無效的分類名",
37
38
  "invalid-content": "<$1>有無效內容",
38
39
  "invalid-conversion-flag": "無效的轉換旗標",
39
40
  "invalid-gallery": "無效的圖庫圖片",
41
+ "invalid-gallery-link": "圖庫圖片裡有無效連結",
40
42
  "invalid-image-parameter": "無效的圖片參數",
41
43
  "invalid-imagemap-link": "<imagemap>裡有無效連結",
42
44
  "invalid-isbn": "無效的ISBN",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikilint",
3
- "version": "2.32.0",
3
+ "version": "2.33.0",
4
4
  "description": "A Node.js linter for MediaWiki markup",
5
5
  "keywords": [
6
6
  "mediawiki",
@@ -53,6 +53,7 @@
53
53
  "test:unit": "mocha dist/test/test.js",
54
54
  "test:parser": "LC_ALL=en.UTF-8 mocha dist/test/parserTests.js",
55
55
  "test": "npm run test:unit && npm run test:parser",
56
+ "test:parseronly": "LSP=0 npm run test:parser",
56
57
  "test:ci": "LSP=0 npm test",
57
58
  "test:end": "pkill -x http-server",
58
59
  "test:real": "node dist/test/real.js"