wikilint 2.5.1 → 2.5.2

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.
@@ -830,8 +830,7 @@
830
830
  "page=$1": "page",
831
831
  "page $1": "page",
832
832
  "页数=$1": "page",
833
- "$1页": "page",
834
- "lossy=$1": "lossy"
833
+ "$1页": "page"
835
834
  },
836
835
  "variants": [
837
836
  "zh",
@@ -404,8 +404,7 @@
404
404
  "text-bottom": "text-bottom",
405
405
  "lang=$1": "lang",
406
406
  "page=$1": "page",
407
- "page $1": "page",
408
- "lossy=$1": "lossy"
407
+ "page $1": "page"
409
408
  },
410
409
  "variants": []
411
410
  }
@@ -1,9 +1,15 @@
1
1
  import Parser from '../index';
2
2
  /** MediaWiki页面标题对象 */
3
3
  export declare class Title {
4
+ #private;
4
5
  readonly valid: boolean;
5
6
  ns: number;
6
7
  fragment: string | undefined;
8
+ /** 不含命名空间的标题主体部分 */
9
+ get main(): string;
10
+ set main(title: string);
11
+ /** 扩展名 */
12
+ get extension(): string | undefined;
7
13
  /**
8
14
  * @param title 标题(含或不含命名空间前缀)
9
15
  * @param defaultNs 命名空间
package/dist/lib/title.js CHANGED
@@ -10,6 +10,20 @@ class Title {
10
10
  fragment;
11
11
  /** @private */
12
12
  encoded = false;
13
+ #main;
14
+ /** 不含命名空间的标题主体部分 */
15
+ get main() {
16
+ return this.#main;
17
+ }
18
+ set main(title) {
19
+ title = title.replace(/_/gu, ' ').trim();
20
+ this.#main = title && `${title[0].toUpperCase()}${title.slice(1)}`;
21
+ }
22
+ /** 扩展名 */
23
+ get extension() {
24
+ const { main } = this, i = main.lastIndexOf('.');
25
+ return i === -1 ? undefined : main.slice(i + 1).toLowerCase();
26
+ }
13
27
  /**
14
28
  * @param title 标题(含或不含命名空间前缀)
15
29
  * @param defaultNs 命名空间
@@ -61,6 +75,7 @@ class Title {
61
75
  }
62
76
  this.valid = Boolean(title || this.interwiki || selfLink && this.fragment !== undefined)
63
77
  && !/^:|\0\d+[eh!+-]\x7F|[<>[\]{}|]|%[\da-f]{2}/iu.test(title);
78
+ this.main = title;
64
79
  }
65
80
  }
66
81
  exports.Title = Title;
@@ -22,8 +22,8 @@ const parseList = (wikitext, config = index_1.default.getConfig(), accum = []) =
22
22
  if (!dt) {
23
23
  return text;
24
24
  }
25
- const { html: [normalTags] } = config, fullRegex = /:+|-\{|\0\d+x\x7F/gu;
26
- let regex = fullRegex, ex = regex.exec(text), lt = 0, lc = 0;
25
+ const { html: [normalTags] } = config, fullRegex = /:+|-\{|\0\d+[xq]\x7F/gu;
26
+ let regex = fullRegex, ex = regex.exec(text), lt = 0, lb = false, li = false, lc = 0;
27
27
  /**
28
28
  * 创建`DdToken`
29
29
  * @param syntax `:`
@@ -34,6 +34,18 @@ const parseList = (wikitext, config = index_1.default.getConfig(), accum = []) =
34
34
  new dd_1.DdToken(syntax, config, accum);
35
35
  return `${text.slice(0, index)}\0${accum.length - 1}d\x7F${text.slice(index + syntax.length)}`;
36
36
  };
37
+ /**
38
+ * 更新 `lt`
39
+ * @param closing 是否是闭合标签
40
+ */
41
+ const update = (closing) => {
42
+ if (!closing) {
43
+ lt++;
44
+ }
45
+ else if (lt) {
46
+ lt--;
47
+ }
48
+ };
37
49
  while (ex && dt) {
38
50
  const { 0: syntax, index } = ex;
39
51
  if (syntax === '-{') {
@@ -52,15 +64,21 @@ const parseList = (wikitext, config = index_1.default.getConfig(), accum = []) =
52
64
  regex.lastIndex = lastIndex;
53
65
  }
54
66
  }
55
- else if (syntax.startsWith('\0')) {
67
+ else if (syntax.endsWith('x\x7F')) {
56
68
  const { name, closing, selfClosing } = accum[Number(syntax.slice(1, -2))];
57
69
  if (!selfClosing || normalTags.includes(name)) {
58
- if (!closing) {
59
- lt++;
60
- }
61
- else if (lt) {
62
- lt--;
63
- }
70
+ update(closing);
71
+ }
72
+ }
73
+ else if (syntax.endsWith('q\x7F')) {
74
+ const { bold, italic } = accum[Number(syntax.slice(1, -2))];
75
+ if (bold) {
76
+ update(lb);
77
+ lb = !lb;
78
+ }
79
+ if (italic) {
80
+ update(li);
81
+ li = !li;
64
82
  }
65
83
  }
66
84
  else if (lt === 0) { // syntax === ':'
@@ -15,7 +15,7 @@ export declare abstract class ImageParameterToken extends Token {
15
15
  /** 图片链接 */
16
16
  get link(): string | Title | undefined;
17
17
  /** @param str 图片参数 */
18
- constructor(str: string, config?: Parser.Config, accum?: Token[]);
18
+ constructor(str: string, extension: string | undefined, config?: Parser.Config, accum?: Token[]);
19
19
  /** @override */
20
20
  text(): string;
21
21
  /** @override */
@@ -6,7 +6,7 @@ const lint_1 = require("../util/lint");
6
6
  const index_1 = require("../index");
7
7
  const index_2 = require("./index");
8
8
  exports.galleryParams = new Set(['alt', 'link', 'lang', 'page', 'caption']);
9
- function validate(key, val, config = index_1.default.getConfig(), halfParsed = false) {
9
+ function validate(key, val, config, halfParsed = false, ext) {
10
10
  val = val.trim();
11
11
  let value = val.replace(/\0\d+t\x7F/gu, '').trim();
12
12
  switch (key) {
@@ -29,11 +29,13 @@ function validate(key, val, config = index_1.default.getConfig(), halfParsed = f
29
29
  return title.valid && title;
30
30
  }
31
31
  case 'lang':
32
- return !value || config.variants.includes(value);
32
+ return (ext === 'svg' || ext === 'svgz') && !/[^a-z\d-]/u.test(value);
33
33
  case 'alt':
34
34
  case 'class':
35
35
  case 'manualthumb':
36
36
  return true;
37
+ case 'page':
38
+ return (ext === 'djvu' || ext === 'djv') && Number(value) > 0;
37
39
  default:
38
40
  return !Number.isNaN(Number(value));
39
41
  }
@@ -47,7 +49,7 @@ class ImageParameterToken extends index_2.Token {
47
49
  return this.name === 'link' ? validate('link', super.text(), this.getAttribute('config')) : undefined;
48
50
  }
49
51
  /** @param str 图片参数 */
50
- constructor(str, config = index_1.default.getConfig(), accum = []) {
52
+ constructor(str, extension, config = index_1.default.getConfig(), accum = []) {
51
53
  let mt;
52
54
  const regexes = Object.entries(config.img).map(([syntax, param]) => [
53
55
  syntax,
@@ -56,7 +58,8 @@ class ImageParameterToken extends index_2.Token {
56
58
  ]), param = regexes.find(([, key, regex]) => {
57
59
  mt = regex.exec(str);
58
60
  return mt
59
- && (mt.length !== 4 || validate(key, mt[2], config, true) !== false);
61
+ && (mt.length !== 4
62
+ || validate(key, mt[2], config, true, extension) !== false);
60
63
  });
61
64
  // @ts-expect-error mt already assigned
62
65
  if (param && mt) {
@@ -12,6 +12,8 @@ export declare abstract class FileToken extends LinkBaseToken {
12
12
  readonly type: 'file' | 'gallery-image' | 'imagemap-image';
13
13
  readonly childNodes: readonly [AtomToken, ...ImageParameterToken[]];
14
14
  abstract get lastChild(): AtomToken | ImageParameterToken;
15
+ /** 扩展名 */
16
+ get extension(): string | undefined;
15
17
  /**
16
18
  * @param link 文件名
17
19
  * @param text 图片参数
@@ -40,6 +40,10 @@ const explode = (start, end, separator, str) => {
40
40
  */
41
41
  class FileToken extends base_1.LinkBaseToken {
42
42
  type = 'file';
43
+ /** 扩展名 */
44
+ get extension() {
45
+ return this.getTitle().extension;
46
+ }
43
47
  /**
44
48
  * @param link 文件名
45
49
  * @param text 图片参数
@@ -47,9 +51,10 @@ class FileToken extends base_1.LinkBaseToken {
47
51
  */
48
52
  constructor(link, text, config = index_1.default.getConfig(), accum = [], delimiter = '|') {
49
53
  super(link, undefined, config, accum, delimiter);
54
+ const { extension } = this;
50
55
  this.append(...explode('-{', '}-', '|', text).map(
51
56
  // @ts-expect-error abstract class
52
- part => new imageParameter_1.ImageParameterToken(part, config, accum)));
57
+ part => new imageParameter_1.ImageParameterToken(part, extension, config, accum)));
53
58
  }
54
59
  /** @override */
55
60
  lint(start = this.getAbsoluteIndex()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikilint",
3
- "version": "2.5.1",
3
+ "version": "2.5.2",
4
4
  "description": "A Node.js linter for MediaWiki markup",
5
5
  "keywords": [
6
6
  "mediawiki",