wikilint 2.18.2 → 2.18.4

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 (48) hide show
  1. package/README.md +1 -1
  2. package/bin/cli.js +1 -1
  3. package/config/minimum.json +7 -0
  4. package/dist/base.d.mts +2 -0
  5. package/dist/base.d.ts +2 -0
  6. package/dist/base.js +1 -0
  7. package/dist/base.mjs +2 -1
  8. package/dist/bin/config.js +3 -2
  9. package/dist/index.d.ts +12 -1
  10. package/dist/index.js +45 -28
  11. package/dist/lib/lsp.d.ts +1 -0
  12. package/dist/lib/lsp.js +19 -14
  13. package/dist/lib/text.js +2 -2
  14. package/dist/lib/title.d.ts +18 -4
  15. package/dist/lib/title.js +12 -4
  16. package/dist/parser/braces.js +79 -37
  17. package/dist/parser/commentAndExt.js +5 -16
  18. package/dist/parser/links.js +1 -1
  19. package/dist/parser/redirect.js +1 -3
  20. package/dist/src/arg.js +1 -1
  21. package/dist/src/attribute.js +1 -1
  22. package/dist/src/converter.js +1 -1
  23. package/dist/src/gallery.js +1 -1
  24. package/dist/src/heading.js +3 -3
  25. package/dist/src/imageParameter.js +9 -9
  26. package/dist/src/imagemap.js +3 -2
  27. package/dist/src/index.d.ts +1 -1
  28. package/dist/src/index.js +7 -5
  29. package/dist/src/link/base.js +1 -1
  30. package/dist/src/link/file.d.ts +2 -0
  31. package/dist/src/link/file.js +15 -13
  32. package/dist/src/link/galleryImage.js +1 -1
  33. package/dist/src/link/redirectTarget.js +1 -2
  34. package/dist/src/magicLink.js +1 -1
  35. package/dist/src/nested.js +5 -5
  36. package/dist/src/nowiki/index.js +3 -2
  37. package/dist/src/redirect.js +1 -2
  38. package/dist/src/syntax.d.ts +4 -2
  39. package/dist/src/syntax.js +4 -2
  40. package/dist/src/table/base.js +1 -1
  41. package/dist/src/table/index.d.ts +1 -0
  42. package/dist/src/table/index.js +3 -6
  43. package/dist/src/table/trBase.js +31 -14
  44. package/dist/src/transclude.js +14 -6
  45. package/dist/util/debug.js +11 -1
  46. package/dist/util/diff.js +1 -1
  47. package/dist/util/string.js +3 -4
  48. package/package.json +2 -2
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  # WikiLint
8
8
 
9
- This is a minimal version of [WikiParser-Node](https://www.npmjs.com/package/wikiparser-node) customized for [eslint-plugin-wikitext](https://www.npmjs.com/package/eslint-plugin-wikitext).
9
+ This is a minimal version of [WikiParser-Node](https://www.npmjs.com/package/wikiparser-node). The [WikiParser Language Server](https://marketplace.visualstudio.com/items?itemName=Bhsd.vscode-extension-wikiparser) VSCode extension is written based on this package.
10
10
 
11
11
  You can also directly lint Wikitext articles in the command line using this package:
12
12
 
package/bin/cli.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
- require('../dist/bin/cli.js');
3
+ require('../dist/bin/cli.js'); // eslint-disable-line n/no-missing-require
@@ -98,6 +98,13 @@
98
98
  ],
99
99
  "parserFunction": [
100
100
  {
101
+ "msgnw": "msgnw",
102
+ "pageid": "pageid",
103
+ "articlepath": "articlepath",
104
+ "server": "server",
105
+ "servername": "servername",
106
+ "scriptpath": "scriptpath",
107
+ "stylepath": "stylepath",
101
108
  "#language": "language",
102
109
  "#special": "special",
103
110
  "#speciale": "speciale",
package/dist/base.d.mts CHANGED
@@ -41,6 +41,7 @@ export declare const stages: {
41
41
  list: number;
42
42
  dd: number;
43
43
  converter: number;
44
+ 'list-range': number;
44
45
  };
45
46
  export type Stage = keyof typeof stages;
46
47
  export declare const rules: readonly ["bold-header", "format-leakage", "fostered-content", "h1", "illegal-attr", "insecure-style", "invalid-gallery", "invalid-imagemap", "invalid-invoke", "invalid-isbn", "lonely-apos", "lonely-bracket", "lonely-http", "nested-link", "no-arg", "no-duplicate", "no-ignored", "obsolete-attr", "obsolete-tag", "parsing-order", "pipe-like", "table-layout", "tag-like", "unbalanced-header", "unclosed-comment", "unclosed-quote", "unclosed-table", "unescaped", "unknown-page", "unmatched-tag", "unterminated-url", "url-encoding", "var-anchor", "void-ext", "invalid-css"];
@@ -271,6 +272,7 @@ export interface Parser {
271
272
  *
272
273
  * 创建语言服务
273
274
  * @param uri document URI / 文档标识
275
+ * @since v1.16.1
274
276
  */
275
277
  createLanguageService(uri: object): LanguageService;
276
278
  }
package/dist/base.d.ts CHANGED
@@ -41,6 +41,7 @@ export declare const stages: {
41
41
  list: number;
42
42
  dd: number;
43
43
  converter: number;
44
+ 'list-range': number;
44
45
  };
45
46
  export type Stage = keyof typeof stages;
46
47
  export declare const rules: readonly ["bold-header", "format-leakage", "fostered-content", "h1", "illegal-attr", "insecure-style", "invalid-gallery", "invalid-imagemap", "invalid-invoke", "invalid-isbn", "lonely-apos", "lonely-bracket", "lonely-http", "nested-link", "no-arg", "no-duplicate", "no-ignored", "obsolete-attr", "obsolete-tag", "parsing-order", "pipe-like", "table-layout", "tag-like", "unbalanced-header", "unclosed-comment", "unclosed-quote", "unclosed-table", "unescaped", "unknown-page", "unmatched-tag", "unterminated-url", "url-encoding", "var-anchor", "void-ext", "invalid-css"];
@@ -271,6 +272,7 @@ export interface Parser {
271
272
  *
272
273
  * 创建语言服务
273
274
  * @param uri document URI / 文档标识
275
+ * @since v1.16.1
274
276
  */
275
277
  createLanguageService(uri: object): LanguageService;
276
278
  }
package/dist/base.js CHANGED
@@ -27,6 +27,7 @@ exports.stages = (() => {
27
27
  list: 10,
28
28
  dd: 10,
29
29
  converter: 11,
30
+ 'list-range': 11,
30
31
  };
31
32
  Object.setPrototypeOf(obj, null);
32
33
  return obj;
package/dist/base.mjs CHANGED
@@ -23,7 +23,8 @@ const stages = /* @__PURE__ */ (() => {
23
23
  "magic-link": 9,
24
24
  list: 10,
25
25
  dd: 10,
26
- converter: 11
26
+ converter: 11,
27
+ "list-range": 11
27
28
  };
28
29
  Object.setPrototypeOf(obj, null);
29
30
  return obj;
@@ -81,8 +81,9 @@ let mwConfig;
81
81
  * @param site site nickname
82
82
  * @param url script path
83
83
  * @param force whether to overwrite the existing configuration
84
+ * @param internal for internal use
84
85
  */
85
- exports.default = async (site, url, force) => {
86
+ exports.default = async (site, url, force, internal) => {
86
87
  if (!site || !url) {
87
88
  console.error('Usage: npx getParserConfig <site> <script path> [force]');
88
89
  process.exit(1);
@@ -133,7 +134,7 @@ exports.default = async (site, url, force) => {
133
134
  if (force || !fs_1.default.existsSync(file)) {
134
135
  fs_1.default.writeFileSync(file, `${JSON.stringify(config, null, '\t')}\n`);
135
136
  }
136
- else {
137
+ else if (!internal) {
137
138
  assert_1.default.deepStrictEqual(arrToObj(require(file)), arrToObj(config));
138
139
  }
139
140
  return config;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import type { Config, LintError, TokenTypes, Parser as ParserBase, Stage } from './base';
2
- import type { Title } from './lib/title';
2
+ import type { Title, TitleOptions } from './lib/title';
3
3
  import type { LanguageService, QuickFixData } from './lib/lsp';
4
4
  import type { Token } from './internal';
5
5
  declare interface Parser extends ParserBase {
6
+ /** @since v1.5.1 */
6
7
  rules: readonly LintError.Rule[];
7
8
  /**
8
9
  * Normalize page title
@@ -19,8 +20,18 @@ declare interface Parser extends ParserBase {
19
20
  *
20
21
  * 创建语言服务
21
22
  * @param uri document URI / 文档标识
23
+ * @since v1.16.1
22
24
  */
23
25
  createLanguageService(uri: object): LanguageService;
26
+ /**
27
+ * Get the parser configuration for a MediaWiki project with Extension:CodeMirror installed
28
+ *
29
+ * 获取一个安装了CodeMirror扩展的MediaWiki项目的解析设置
30
+ * @param site site nickname / 网站别名
31
+ * @param url script path / 脚本路径
32
+ * @since v1.18.4
33
+ */
34
+ fetchConfig(site: string, url: string): Promise<Config>;
24
35
  }
25
36
  declare const Parser: Parser;
26
37
  // @ts-expect-error mixed export styles
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ const string_1 = require("./util/string");
11
11
  const fs_1 = __importDefault(require("fs"));
12
12
  const path_1 = __importDefault(require("path"));
13
13
  const diff_1 = require("./util/diff");
14
+ const config_1 = __importDefault(require("./bin/config"));
14
15
  /* NOT FOR BROWSER ONLY */
15
16
  /**
16
17
  * 从根路径require
@@ -25,6 +26,9 @@ const Parser = {
25
26
  config: 'default',
26
27
  i18n: undefined,
27
28
  rules: base_1.rules,
29
+ /* NOT FOR BROWSER ONLY */
30
+ lintCSS: true,
31
+ /* NOT FOR BROWSER ONLY END */
28
32
  /** @implements */
29
33
  getConfig(config) {
30
34
  /* NOT FOR BROWSER ONLY */
@@ -39,7 +43,7 @@ const Parser = {
39
43
  return this.getConfig();
40
44
  }
41
45
  /* NOT FOR BROWSER ONLY END */
42
- const parserConfig = config ?? this.config, { doubleUnderscore } = parserConfig;
46
+ const parserConfig = config ?? this.config, { doubleUnderscore, } = parserConfig;
43
47
  for (let i = 0; i < 2; i++) {
44
48
  if (doubleUnderscore.length > i + 2 && doubleUnderscore[i].length === 0) {
45
49
  doubleUnderscore[i] = Object.keys(doubleUnderscore[i + 2]);
@@ -61,11 +65,11 @@ const Parser = {
61
65
  return msg && (this.i18n?.[msg] ?? msg).replace('$1', this.msg(arg));
62
66
  },
63
67
  /** @implements */
64
- normalizeTitle(title, defaultNs = 0, include, config = Parser.getConfig(), temporary = false, halfParsed, decode = false, selfLink = false) {
68
+ normalizeTitle(title, defaultNs = 0, include, config = Parser.getConfig(), opt) {
65
69
  const { Title } = require('./lib/title');
66
70
  let titleObj;
67
- if (halfParsed) {
68
- titleObj = new Title(title, defaultNs, config, temporary, decode, selfLink);
71
+ if (opt?.halfParsed) {
72
+ titleObj = new Title(title, defaultNs, config, opt);
69
73
  }
70
74
  else {
71
75
  const { Token } = require('./src/index');
@@ -73,7 +77,7 @@ const Parser = {
73
77
  const root = new Token(title, config);
74
78
  root.type = 'root';
75
79
  root.parseOnce(0, include).parseOnce();
76
- const t = new Title(root.toString(), defaultNs, config, temporary, decode, selfLink);
80
+ const t = new Title(root.toString(), defaultNs, config, opt);
77
81
  for (const key of ['main', 'fragment']) {
78
82
  const str = t[key];
79
83
  if (str?.includes('\0')) {
@@ -94,8 +98,9 @@ const Parser = {
94
98
  /** @implements */
95
99
  parse(wikitext, include, maxStage = constants_1.MAX_STAGE, config = Parser.getConfig()) {
96
100
  wikitext = (0, string_1.tidy)(wikitext);
101
+ let types;
97
102
  if (typeof maxStage !== 'number') {
98
- const types = Array.isArray(maxStage) ? maxStage : [maxStage];
103
+ types = Array.isArray(maxStage) ? maxStage : [maxStage];
99
104
  maxStage = Math.max(...types.map(t => base_1.stages[t] || constants_1.MAX_STAGE));
100
105
  }
101
106
  const { Token } = require('./src/index');
@@ -132,28 +137,34 @@ const Parser = {
132
137
  const token = new Token((0, string_1.tidy)(wikitext), config);
133
138
  token.type = 'root';
134
139
  let i = 0;
135
- await new Promise(resolve => {
136
- const /** @ignore */ check = () => {
137
- if (watch() === wikitext) {
138
- i++;
139
- set(parseOnce, 0);
140
- }
141
- else {
142
- resolve();
143
- }
144
- },
145
- /** @ignore */ parseOnce = () => {
146
- if (i === constants_1.MAX_STAGE + 1) {
147
- token.afterBuild();
148
- resolve();
149
- }
150
- else {
151
- token[i === constants_1.MAX_STAGE ? 'build' : 'parseOnce'](i, include);
152
- check();
153
- }
154
- };
155
- set(parseOnce, 0);
156
- });
140
+ try {
141
+ await new Promise(resolve => {
142
+ const /** @ignore */ check = () => {
143
+ if (watch() === wikitext) {
144
+ i++;
145
+ set(parseOnce, 0);
146
+ }
147
+ else {
148
+ resolve();
149
+ }
150
+ },
151
+ /** @ignore */ parseOnce = () => {
152
+ if (i === constants_1.MAX_STAGE + 1) {
153
+ token.afterBuild();
154
+ resolve();
155
+ }
156
+ else {
157
+ token[i === constants_1.MAX_STAGE ? 'build' : 'parseOnce'](i, include);
158
+ check();
159
+ }
160
+ };
161
+ set(parseOnce, 0);
162
+ });
163
+ }
164
+ catch (e) /* istanbul ignore next */ {
165
+ debug_1.Shadow.running = running;
166
+ throw e;
167
+ }
157
168
  debug_1.Shadow.running = running;
158
169
  return token;
159
170
  },
@@ -165,6 +176,12 @@ const Parser = {
165
176
  return tasks.get(uri) ?? new LanguageService(uri);
166
177
  }
167
178
  },
179
+ /* NOT FOR BROWSER ONLY */
180
+ /** @implements */
181
+ async fetchConfig(site, url) {
182
+ return this.getConfig(await (0, config_1.default)(site, url, false, true));
183
+ },
184
+ /* NOT FOR BROWSER ONLY */
168
185
  };
169
186
  const def = {
170
187
  default: { value: Parser },
package/dist/lib/lsp.d.ts CHANGED
@@ -20,6 +20,7 @@ export declare const isAttr: ({ type, parentNode, length, firstChild }: Token, s
20
20
  /** VSCode-style language service */
21
21
  export declare class LanguageService implements LanguageServiceBase {
22
22
  #private;
23
+ /** @since v1.17.1 */
23
24
  include: boolean;
24
25
  lilypond: string;
25
26
  /** @param uri 任务标识 */
package/dist/lib/lsp.js CHANGED
@@ -16,13 +16,13 @@ const util_1 = __importDefault(require("util"));
16
16
  const child_process_1 = require("child_process");
17
17
  const crypto_1 = require("crypto");
18
18
  const stylelint_1 = require("@bhsd/common/dist/stylelint");
19
- const config_1 = __importDefault(require("../bin/config"));
20
19
  const document_1 = require("./document");
21
20
  /** @see https://www.npmjs.com/package/stylelint-config-recommended */
22
21
  const cssRules = {
23
22
  'block-no-empty': null,
24
23
  'property-no-unknown': null,
25
24
  }, jsonSelector = document_1.jsonTags.map(s => `ext-inner#${s}`).join(), scores = new Map();
25
+ let colors;
26
26
  /* NOT FOR BROWSER ONLY END */
27
27
  exports.tasks = new WeakMap();
28
28
  const refTags = new Set(['ref']), referencesTags = new Set(['ref', 'references']), nameAttrs = new Set(['name', 'extends', 'follow']), groupAttrs = new Set(['group']), renameTypes = new Set([
@@ -40,6 +40,7 @@ const refTags = new Set(['ref']), referencesTags = new Set(['ref', 'references']
40
40
  'magic-word-name',
41
41
  ...renameTypes,
42
42
  ]), plainTypes = new Set(['text', 'comment', 'noinclude', 'include']), cssSelector = ['ext', 'html', 'table'].map(s => `${s}-attr#style`).join();
43
+ const getLinkRegex = (0, common_1.getRegex)(protocol => new RegExp(`^(?:${protocol}|//)`, 'iu'));
43
44
  /**
44
45
  * Check if a token is a plain attribute.
45
46
  * @param token
@@ -273,6 +274,7 @@ class LanguageService {
273
274
  #config;
274
275
  #include;
275
276
  #completionConfig;
277
+ /** @since v1.17.1 */
276
278
  include = true;
277
279
  /** @private */
278
280
  config;
@@ -406,11 +408,14 @@ class LanguageService {
406
408
  async provideDocumentColors(rgba, text, hsl = true) {
407
409
  const root = await this.#queue(text);
408
410
  /* NOT FOR BROWSER ONLY */
409
- let colors;
411
+ /* eslint-disable require-atomic-updates */
410
412
  try {
411
- colors = new RegExp(String.raw `\b${Object.keys((await import('color-name')).default).join('|')}\b`, 'giu');
413
+ colors ??= new RegExp(String.raw `\b${Object.keys((await import('color-name')).default).join('|')}\b`, 'giu');
412
414
  }
413
- catch { }
415
+ catch {
416
+ colors = false;
417
+ }
418
+ /* eslint-enable require-atomic-updates */
414
419
  /* NOT FOR BROWSER ONLY END */
415
420
  return root.querySelectorAll('attr-value,parameter-value,arg-default').reverse()
416
421
  .flatMap(token => {
@@ -637,7 +642,7 @@ class LanguageService {
637
642
  if (t === 'magic-word' && n !== 'invoke') {
638
643
  return undefined;
639
644
  }
640
- const key = this.#text.slice(cur.getAbsoluteIndex(), root.indexFromPos(line, character)).trimStart(), [module, func] = t === 'magic-word' ? transclusion.getModule() : [];
645
+ const key = this.#text.slice(cur.getAbsoluteIndex(), root.indexFromPos(line, character)).trimStart(), [mod, func] = t === 'magic-word' ? transclusion.getModule() : [];
641
646
  return key
642
647
  ? getCompletion(root.querySelectorAll('parameter').filter(token => {
643
648
  if (token === parentNode
@@ -650,7 +655,7 @@ class LanguageService {
650
655
  return true;
651
656
  }
652
657
  const [m, f] = token.parentNode.getModule();
653
- return m === module && f === func;
658
+ return m === mod && f === func;
654
659
  }).map(({ name }) => name), 'Variable', key, position, type === 'parameter-value' ? '=' : '')
655
660
  : undefined;
656
661
  /* NOT FOR BROWSER ONLY */
@@ -893,7 +898,7 @@ class LanguageService {
893
898
  */
894
899
  async provideLinks(text) {
895
900
  this.config ??= index_1.default.getConfig();
896
- const { articlePath, protocol } = this.config, absolute = articlePath?.includes('//'), protocolRegex = new RegExp(`^(?:${protocol}|//)`, 'iu');
901
+ const { articlePath, protocol } = this.config, absolute = articlePath?.includes('//'), protocolRegex = getLinkRegex(protocol);
897
902
  return (await this.#queue(text))
898
903
  .querySelectorAll(`magic-link,ext-link-url,free-ext-link,attr-value,image-parameter#link${absolute ? ',link-target,template-name,invoke-module,magic-word#filepath,magic-word#widget' : ''}`)
899
904
  .reverse()
@@ -953,8 +958,8 @@ class LanguageService {
953
958
  ns = name === 'filepath' ? 6 : 274;
954
959
  // no default
955
960
  }
956
- const title = index_1.default.normalizeTitle(target, ns, false, this.config, true);
957
- /* istanbul ignore if */
961
+ const title = index_1.default
962
+ .normalizeTitle(target, ns, false, this.config, { temporary: true });
958
963
  if (!title.valid) {
959
964
  return false;
960
965
  }
@@ -1110,13 +1115,13 @@ class LanguageService {
1110
1115
  }
1111
1116
  else if (type === 'magic-word-name') {
1112
1117
  info = this.#getParserFunction(parentNode.name);
1113
- f = offsetNode.toString(true).trim();
1118
+ f = offsetNode.text().trim();
1114
1119
  colon = parentNode.getAttribute('colon');
1115
1120
  }
1116
1121
  else if (offsetNode.is('magic-word') && !offsetNode.modifier && length === 1
1117
1122
  && (offset > 0 || root.posFromIndex(offsetNode.getAbsoluteIndex()).left === position.character)) {
1118
1123
  info = this.#getParserFunction(name);
1119
- f = offsetNode.firstChild.toString(true).trim();
1124
+ f = offsetNode.firstChild.text().trim();
1120
1125
  colon = offsetNode.getAttribute('colon');
1121
1126
  }
1122
1127
  else if ((offsetNode.is('magic-word') || offsetNode.is('template'))
@@ -1203,7 +1208,7 @@ class LanguageService {
1203
1208
  }
1204
1209
  const n = childNodes.length - 1, candidates = info.signatures.filter(params => (params.length >= n || params[params.length - 1]?.rest)
1205
1210
  && params.every(({ label, const: c }, i) => {
1206
- const p = c && i < n && childNodes[i + 1]?.toString(true).trim();
1211
+ const p = c && i < n && childNodes[i + 1]?.text().trim();
1207
1212
  return !p || label.toLowerCase().includes(p.toLowerCase());
1208
1213
  }));
1209
1214
  if (candidates.length === 0) {
@@ -1216,7 +1221,7 @@ class LanguageService {
1216
1221
  break;
1217
1222
  }
1218
1223
  }
1219
- const f = firstChild.toString(true).trim(), colon = lastChild.getAttribute('colon');
1224
+ const f = firstChild.text().trim(), colon = lastChild.getAttribute('colon');
1220
1225
  return {
1221
1226
  signatures: candidates.map((params) => ({
1222
1227
  label: `{{${f}${params.length === 0 ? '' : colon}${params.map(({ label }) => label).join('|')}}}`,
@@ -1331,7 +1336,7 @@ class LanguageService {
1331
1336
  this.config = index_1.default.getConfig(config);
1332
1337
  }
1333
1338
  catch {
1334
- this.config = index_1.default.getConfig(await (0, config_1.default)(site, `${mt[0]}/w`));
1339
+ this.config = await index_1.default.fetchConfig(site, `${mt[0]}/w`);
1335
1340
  }
1336
1341
  Object.assign(this.config, { articlePath: `${mt[0]}/wiki/` });
1337
1342
  }
package/dist/lib/text.js CHANGED
@@ -74,7 +74,6 @@ class AstText extends node_1.AstNode {
74
74
  constructor(text) {
75
75
  super();
76
76
  Object.defineProperties(this, {
77
- childNodes: { enumerable: false, configurable: false },
78
77
  data: {
79
78
  value: text,
80
79
  },
@@ -132,12 +131,13 @@ class AstText extends node_1.AstNode {
132
131
  ]);
133
132
  for (let mt = errorRegex.exec(data); mt; mt = errorRegex.exec(data)) {
134
133
  const [, tag, prefix] = mt;
135
- let { index } = mt, error = mt[0].toLowerCase();
134
+ let { index, 0: error } = mt;
136
135
  if (prefix && prefix !== ']') {
137
136
  const { length } = prefix;
138
137
  index += length;
139
138
  error = error.slice(length);
140
139
  }
140
+ error = error.toLowerCase();
141
141
  const { 0: char, length } = error, magicLink = char === 'r' || char === 'p' || char === 'i';
142
142
  if (char === '<' && !tags.has(tag.toLowerCase())
143
143
  || char === '[' && type === 'ext-link-text' && (/&(?:rbrack|#93|#x5[Dd];);/u.test(data.slice(index + 1))
@@ -1,4 +1,10 @@
1
1
  import type { Config } from '../base';
2
+ export interface TitleOptions {
3
+ temporary?: boolean | undefined;
4
+ decode?: boolean | undefined;
5
+ selfLink?: boolean | undefined;
6
+ halfParsed?: boolean | undefined;
7
+ }
2
8
  /**
3
9
  * title object of a MediaWiki page
4
10
  *
@@ -18,21 +24,28 @@ export declare class Title {
18
24
  get prefix(): string;
19
25
  /** full title / 完整标题 */
20
26
  get title(): string;
21
- /** file extension / 扩展名 */
27
+ /**
28
+ * file extension / 扩展名
29
+ * @since v1.1.0
30
+ */
22
31
  get extension(): string | undefined;
23
32
  /**
24
33
  * @see MediaWikiTitleCodec::splitTitleString
25
34
  *
26
35
  * @param title 标题(含或不含命名空间前缀)
27
36
  * @param defaultNs 命名空间
28
- * @param decode 是否需要解码
29
- * @param selfLink 是否允许selfLink
37
+ * @param config
38
+ * @param opt 选项
39
+ * @param opt.temporary 是否是临时标题
40
+ * @param opt.decode 是否需要解码
41
+ * @param opt.selfLink 是否允许selfLink
30
42
  */
31
- constructor(title: string, defaultNs: number, config: Config, temporary: boolean, decode: boolean, selfLink: boolean);
43
+ constructor(title: string, defaultNs: number, config: Config, { temporary, decode, selfLink }?: TitleOptions);
32
44
  /**
33
45
  * Check if the title is a redirect
34
46
  *
35
47
  * 检测是否是重定向
48
+ * @since v1.12.2
36
49
  */
37
50
  getRedirection(): [boolean, string];
38
51
  /**
@@ -40,6 +53,7 @@ export declare class Title {
40
53
  *
41
54
  * 生成URL
42
55
  * @param articlePath article path / 条目路径
56
+ * @since v1.10.0
43
57
  */
44
58
  getUrl(articlePath?: string): string;
45
59
  }
package/dist/lib/title.js CHANGED
@@ -41,7 +41,10 @@ class Title {
41
41
  get title() {
42
42
  return this.getRedirection()[1];
43
43
  }
44
- /** file extension / 扩展名 */
44
+ /**
45
+ * file extension / 扩展名
46
+ * @since v1.1.0
47
+ */
45
48
  get extension() {
46
49
  const { main } = this, i = main.lastIndexOf('.');
47
50
  return i === -1 ? undefined : main.slice(i + 1).toLowerCase();
@@ -51,10 +54,13 @@ class Title {
51
54
  *
52
55
  * @param title 标题(含或不含命名空间前缀)
53
56
  * @param defaultNs 命名空间
54
- * @param decode 是否需要解码
55
- * @param selfLink 是否允许selfLink
57
+ * @param config
58
+ * @param opt 选项
59
+ * @param opt.temporary 是否是临时标题
60
+ * @param opt.decode 是否需要解码
61
+ * @param opt.selfLink 是否允许selfLink
56
62
  */
57
- constructor(title, defaultNs, config, temporary, decode, selfLink) {
63
+ constructor(title, defaultNs, config, { temporary, decode, selfLink } = {}) {
58
64
  const subpage = title.trim().startsWith('../');
59
65
  if (decode && title.includes('%')) {
60
66
  try {
@@ -116,6 +122,7 @@ class Title {
116
122
  * Check if the title is a redirect
117
123
  *
118
124
  * 检测是否是重定向
125
+ * @since v1.12.2
119
126
  */
120
127
  getRedirection() {
121
128
  // eslint-disable-next-line @typescript-eslint/prefer-destructuring
@@ -133,6 +140,7 @@ class Title {
133
140
  *
134
141
  * 生成URL
135
142
  * @param articlePath article path / 条目路径
143
+ * @since v1.10.0
136
144
  */
137
145
  getUrl(articlePath) {
138
146
  LSP: { // eslint-disable-line no-unused-labels