wikilint 2.12.7 → 2.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/default.json +9 -11
- package/config/enwiki.json +10 -11
- package/config/zhwiki.json +14 -2
- package/dist/base.d.ts +28 -1
- package/dist/base.js +28 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +8 -4
- package/dist/lib/element.js +4 -11
- package/dist/lib/title.js +1 -2
- package/dist/parser/selector.js +14 -0
- package/dist/src/attributes.js +15 -12
- package/dist/src/paramTag/index.js +1 -1
- package/dist/src/paramTag/inputbox.js +14 -0
- package/dist/src/pre.js +18 -10
- package/dist/src/tagPair/include.js +24 -11
- package/dist/src/transclude.js +2 -2
- package/i18n/zh-hans.json +1 -0
- package/i18n/zh-hant.json +1 -0
- package/package.json +3 -3
package/config/default.json
CHANGED
|
@@ -140,10 +140,6 @@
|
|
|
140
140
|
"711": "TimedText talk",
|
|
141
141
|
"828": "Module",
|
|
142
142
|
"829": "Module talk",
|
|
143
|
-
"2300": "Gadget",
|
|
144
|
-
"2301": "Gadget talk",
|
|
145
|
-
"2302": "Gadget definition",
|
|
146
|
-
"2303": "Gadget definition talk",
|
|
147
143
|
"2600": "Topic"
|
|
148
144
|
},
|
|
149
145
|
"nsid": {
|
|
@@ -300,11 +296,7 @@
|
|
|
300
296
|
"模組討論": 829,
|
|
301
297
|
"模组对话": 829,
|
|
302
298
|
"模组讨论": 829,
|
|
303
|
-
"モジュール・トーク": 829
|
|
304
|
-
"gadget": 2300,
|
|
305
|
-
"gadget talk": 2301,
|
|
306
|
-
"gadget definition": 2302,
|
|
307
|
-
"gadget definition talk": 2303
|
|
299
|
+
"モジュール・トーク": 829
|
|
308
300
|
},
|
|
309
301
|
"parserFunction": [
|
|
310
302
|
{
|
|
@@ -704,6 +696,8 @@
|
|
|
704
696
|
"PAGELANGUAGE",
|
|
705
697
|
"=",
|
|
706
698
|
"#FORMAL",
|
|
699
|
+
"#bcp47",
|
|
700
|
+
"#dir",
|
|
707
701
|
"#timef",
|
|
708
702
|
"#timefl"
|
|
709
703
|
],
|
|
@@ -740,7 +734,9 @@
|
|
|
740
734
|
"静态重定向",
|
|
741
735
|
"靜態重新導向",
|
|
742
736
|
"NOGLOBAL",
|
|
743
|
-
"
|
|
737
|
+
"禁用全域用户页",
|
|
738
|
+
"EXPECTED_UNCONNECTED_PAGE",
|
|
739
|
+
"EXPECTUNUSEDTEMPLATE"
|
|
744
740
|
],
|
|
745
741
|
{
|
|
746
742
|
"forcetoc": "forcetoc",
|
|
@@ -768,7 +764,9 @@
|
|
|
768
764
|
"目录": "toc",
|
|
769
765
|
"目錄": "toc",
|
|
770
766
|
"archivedtalk": "archivedtalk",
|
|
771
|
-
"
|
|
767
|
+
"已存档讨论": "archivedtalk",
|
|
768
|
+
"notalk": "notalk",
|
|
769
|
+
"禁用讨论": "notalk"
|
|
772
770
|
}
|
|
773
771
|
],
|
|
774
772
|
"protocol": "bitcoin:|ftp://|ftps://|geo:|git://|gopher://|http://|https://|irc://|ircs://|magnet:|mailto:|matrix:|mms://|news:|nntp://|redis://|sftp://|sip:|sips:|sms:|ssh://|svn://|tel:|telnet://|urn:|worldwind://|xmpp:",
|
package/config/enwiki.json
CHANGED
|
@@ -120,14 +120,12 @@
|
|
|
120
120
|
"101": "Portal talk",
|
|
121
121
|
"118": "Draft",
|
|
122
122
|
"119": "Draft talk",
|
|
123
|
+
"126": "MOS",
|
|
124
|
+
"127": "MOS talk",
|
|
123
125
|
"710": "TimedText",
|
|
124
126
|
"711": "TimedText talk",
|
|
125
127
|
"828": "Module",
|
|
126
|
-
"829": "Module talk"
|
|
127
|
-
"2300": "Gadget",
|
|
128
|
-
"2301": "Gadget talk",
|
|
129
|
-
"2302": "Gadget definition",
|
|
130
|
-
"2303": "Gadget definition talk"
|
|
128
|
+
"829": "Module talk"
|
|
131
129
|
},
|
|
132
130
|
"nsid": {
|
|
133
131
|
"": 0,
|
|
@@ -158,14 +156,12 @@
|
|
|
158
156
|
"portal talk": 101,
|
|
159
157
|
"draft": 118,
|
|
160
158
|
"draft talk": 119,
|
|
159
|
+
"mos": 126,
|
|
160
|
+
"mos talk": 127,
|
|
161
161
|
"timedtext": 710,
|
|
162
162
|
"timedtext talk": 711,
|
|
163
163
|
"module": 828,
|
|
164
|
-
"module talk": 829
|
|
165
|
-
"gadget": 2300,
|
|
166
|
-
"gadget talk": 2301,
|
|
167
|
-
"gadget definition": 2302,
|
|
168
|
-
"gadget definition talk": 2303
|
|
164
|
+
"module talk": 829
|
|
169
165
|
},
|
|
170
166
|
"parserFunction": [
|
|
171
167
|
{
|
|
@@ -333,6 +329,8 @@
|
|
|
333
329
|
"PAGELANGUAGE",
|
|
334
330
|
"=",
|
|
335
331
|
"#FORMAL",
|
|
332
|
+
"#bcp47",
|
|
333
|
+
"#dir",
|
|
336
334
|
"#timef",
|
|
337
335
|
"#timefl"
|
|
338
336
|
],
|
|
@@ -357,7 +355,8 @@
|
|
|
357
355
|
"NONEWSECTIONLINK",
|
|
358
356
|
"STATICREDIRECT",
|
|
359
357
|
"NOGLOBAL",
|
|
360
|
-
"EXPECTED_UNCONNECTED_PAGE"
|
|
358
|
+
"EXPECTED_UNCONNECTED_PAGE",
|
|
359
|
+
"EXPECTUNUSEDTEMPLATE"
|
|
361
360
|
],
|
|
362
361
|
{
|
|
363
362
|
"forcetoc": "forcetoc",
|
package/config/zhwiki.json
CHANGED
|
@@ -122,6 +122,8 @@
|
|
|
122
122
|
"103": "WikiProject talk",
|
|
123
123
|
"118": "Draft",
|
|
124
124
|
"119": "Draft talk",
|
|
125
|
+
"126": "MOS",
|
|
126
|
+
"127": "MOS talk",
|
|
125
127
|
"710": "TimedText",
|
|
126
128
|
"711": "TimedText talk",
|
|
127
129
|
"828": "Module",
|
|
@@ -260,6 +262,8 @@
|
|
|
260
262
|
"draft talk": 119,
|
|
261
263
|
"草稿讨论": 119,
|
|
262
264
|
"草稿討論": 119,
|
|
265
|
+
"mos": 126,
|
|
266
|
+
"mos talk": 127,
|
|
263
267
|
"timedtext": 710,
|
|
264
268
|
"timedtext talk": 711,
|
|
265
269
|
"module": 828,
|
|
@@ -646,6 +650,8 @@
|
|
|
646
650
|
"PAGELANGUAGE",
|
|
647
651
|
"=",
|
|
648
652
|
"#FORMAL",
|
|
653
|
+
"#bcp47",
|
|
654
|
+
"#dir",
|
|
649
655
|
"#timef",
|
|
650
656
|
"#timefl"
|
|
651
657
|
],
|
|
@@ -682,7 +688,9 @@
|
|
|
682
688
|
"静态重定向",
|
|
683
689
|
"靜態重新導向",
|
|
684
690
|
"NOGLOBAL",
|
|
685
|
-
"
|
|
691
|
+
"禁用全域用户页",
|
|
692
|
+
"EXPECTED_UNCONNECTED_PAGE",
|
|
693
|
+
"EXPECTUNUSEDTEMPLATE"
|
|
686
694
|
],
|
|
687
695
|
{
|
|
688
696
|
"forcetoc": "forcetoc",
|
|
@@ -708,7 +716,11 @@
|
|
|
708
716
|
"無目錄": "notoc",
|
|
709
717
|
"toc": "toc",
|
|
710
718
|
"目录": "toc",
|
|
711
|
-
"目錄": "toc"
|
|
719
|
+
"目錄": "toc",
|
|
720
|
+
"archivedtalk": "archivedtalk",
|
|
721
|
+
"已存档讨论": "archivedtalk",
|
|
722
|
+
"notalk": "notalk",
|
|
723
|
+
"禁用讨论": "notalk"
|
|
712
724
|
}
|
|
713
725
|
],
|
|
714
726
|
"protocol": "bitcoin:|ftp://|ftps://|geo:|git://|gopher://|http://|https://|irc://|ircs://|magnet:|mailto:|matrix:|mms://|news:|nntp://|redis://|sftp://|sip:|sips:|sms:|ssh://|svn://|tel:|telnet://|urn:|worldwind://|xmpp:",
|
package/dist/base.d.ts
CHANGED
|
@@ -12,6 +12,33 @@ export interface Config {
|
|
|
12
12
|
readonly excludes?: string[];
|
|
13
13
|
}
|
|
14
14
|
export type TokenTypes = 'root' | 'plain' | 'redirect' | 'redirect-syntax' | 'redirect-target' | 'onlyinclude' | 'noinclude' | 'include' | 'comment' | 'ext' | 'ext-attrs' | 'ext-attr-dirty' | 'ext-attr' | 'attr-key' | 'attr-value' | 'ext-inner' | 'arg' | 'arg-name' | 'arg-default' | 'hidden' | 'magic-word' | 'magic-word-name' | 'invoke-function' | 'invoke-module' | 'template' | 'template-name' | 'parameter' | 'parameter-key' | 'parameter-value' | 'heading' | 'heading-title' | 'heading-trail' | 'html' | 'html-attrs' | 'html-attr-dirty' | 'html-attr' | 'table' | 'tr' | 'td' | 'table-syntax' | 'table-attrs' | 'table-attr-dirty' | 'table-attr' | 'table-inter' | 'td-inner' | 'hr' | 'double-underscore' | 'link' | 'link-target' | 'link-text' | 'category' | 'file' | 'gallery-image' | 'imagemap-image' | 'image-parameter' | 'quote' | 'ext-link' | 'ext-link-text' | 'ext-link-url' | 'free-ext-link' | 'magic-link' | 'list' | 'dd' | 'list-range' | 'converter' | 'converter-flags' | 'converter-flag' | 'converter-rule' | 'converter-rule-variant' | 'converter-rule-to' | 'converter-rule-from' | 'param-line' | 'imagemap-link';
|
|
15
|
+
export declare const stages: {
|
|
16
|
+
redirect: number;
|
|
17
|
+
onlyinclude: number;
|
|
18
|
+
noinclude: number;
|
|
19
|
+
include: number;
|
|
20
|
+
comment: number;
|
|
21
|
+
ext: number;
|
|
22
|
+
arg: number;
|
|
23
|
+
'magic-word': number;
|
|
24
|
+
template: number;
|
|
25
|
+
heading: number;
|
|
26
|
+
html: number;
|
|
27
|
+
table: number;
|
|
28
|
+
hr: number;
|
|
29
|
+
'double-underscore': number;
|
|
30
|
+
link: number;
|
|
31
|
+
category: number;
|
|
32
|
+
file: number;
|
|
33
|
+
quote: number;
|
|
34
|
+
'ext-link': number;
|
|
35
|
+
'free-ext-link': number;
|
|
36
|
+
'magic-link': number;
|
|
37
|
+
list: number;
|
|
38
|
+
dd: number;
|
|
39
|
+
converter: number;
|
|
40
|
+
};
|
|
41
|
+
export type Stage = keyof typeof stages;
|
|
15
42
|
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"];
|
|
16
43
|
export declare namespace LintError {
|
|
17
44
|
type Severity = 'error' | 'warning';
|
|
@@ -63,6 +90,6 @@ export interface Parser {
|
|
|
63
90
|
* @param include 是否嵌入
|
|
64
91
|
* @param maxStage 最大解析层级
|
|
65
92
|
*/
|
|
66
|
-
parse(wikitext: string, include?: boolean, maxStage?: number, config?: Config): Token;
|
|
93
|
+
parse(wikitext: string, include?: boolean, maxStage?: number | Stage | Stage[], config?: Config): Token;
|
|
67
94
|
}
|
|
68
95
|
export {};
|
package/dist/base.js
CHANGED
|
@@ -1,6 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.rules = void 0;
|
|
3
|
+
exports.rules = exports.stages = void 0;
|
|
4
|
+
exports.stages = {
|
|
5
|
+
redirect: 1,
|
|
6
|
+
onlyinclude: 1,
|
|
7
|
+
noinclude: 1,
|
|
8
|
+
include: 1,
|
|
9
|
+
comment: 1,
|
|
10
|
+
ext: 1,
|
|
11
|
+
arg: 2,
|
|
12
|
+
'magic-word': 2,
|
|
13
|
+
template: 2,
|
|
14
|
+
heading: 2,
|
|
15
|
+
html: 3,
|
|
16
|
+
table: 4,
|
|
17
|
+
hr: 5,
|
|
18
|
+
'double-underscore': 5,
|
|
19
|
+
link: 6,
|
|
20
|
+
category: 6,
|
|
21
|
+
file: 6,
|
|
22
|
+
quote: 7,
|
|
23
|
+
'ext-link': 8,
|
|
24
|
+
'free-ext-link': 9,
|
|
25
|
+
'magic-link': 9,
|
|
26
|
+
list: 10,
|
|
27
|
+
dd: 10,
|
|
28
|
+
converter: 11,
|
|
29
|
+
};
|
|
30
|
+
Object.setPrototypeOf(exports.stages, null);
|
|
4
31
|
exports.rules = [
|
|
5
32
|
'bold-header',
|
|
6
33
|
'format-leakage',
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Config, LintError, TokenTypes, Parser as ParserBase } from './base';
|
|
1
|
+
import type { Config, LintError, TokenTypes, Parser as ParserBase, Stage } from './base';
|
|
2
2
|
import type { Title } from './lib/title';
|
|
3
3
|
import type { Token } from './internal';
|
|
4
4
|
declare interface Parser extends ParserBase {
|
|
@@ -10,7 +10,7 @@ declare interface Parser extends ParserBase {
|
|
|
10
10
|
* @param include 是否嵌入
|
|
11
11
|
*/
|
|
12
12
|
normalizeTitle(title: string, defaultNs?: number, include?: boolean, config?: Config): Title;
|
|
13
|
-
parse(wikitext: string, include?: boolean, maxStage?: number, config?: Config): Token;
|
|
13
|
+
parse(wikitext: string, include?: boolean, maxStage?: number | Stage | Stage[], config?: Config): Token;
|
|
14
14
|
}
|
|
15
15
|
declare const Parser: Parser;
|
|
16
16
|
// @ts-expect-error mixed export styles
|
package/dist/index.js
CHANGED
|
@@ -22,13 +22,13 @@ const Parser = {
|
|
|
22
22
|
getConfig() {
|
|
23
23
|
if (typeof this.config === 'string') {
|
|
24
24
|
this.config = rootRequire(this.config, 'config');
|
|
25
|
+
if (this.config.doubleUnderscore.length < 3) {
|
|
26
|
+
(0, diff_1.error)(`The schema (${path.resolve(__dirname, '..', 'config', '.schema.json')}) of parser configuration is updated.`);
|
|
27
|
+
}
|
|
25
28
|
return this.getConfig();
|
|
26
29
|
}
|
|
27
30
|
const { doubleUnderscore } = this.config;
|
|
28
|
-
if (doubleUnderscore.length ===
|
|
29
|
-
(0, diff_1.error)(`The schema (${path.resolve(__dirname, '..', 'config', '.schema.json')}) of parser configuration is updated.`);
|
|
30
|
-
}
|
|
31
|
-
else if (doubleUnderscore[0].length === 0) {
|
|
31
|
+
if (doubleUnderscore.length > 2 && doubleUnderscore[0].length === 0) {
|
|
32
32
|
doubleUnderscore[0] = Object.keys(doubleUnderscore[2]);
|
|
33
33
|
}
|
|
34
34
|
return {
|
|
@@ -78,6 +78,10 @@ const Parser = {
|
|
|
78
78
|
/** @implements */
|
|
79
79
|
parse(wikitext, include, maxStage = constants_1.MAX_STAGE, config = Parser.getConfig()) {
|
|
80
80
|
wikitext = (0, string_1.tidy)(wikitext);
|
|
81
|
+
if (typeof maxStage !== 'number') {
|
|
82
|
+
const types = Array.isArray(maxStage) ? maxStage : [maxStage];
|
|
83
|
+
maxStage = Math.max(...types.map(t => base_1.stages[t] || constants_1.MAX_STAGE));
|
|
84
|
+
}
|
|
81
85
|
const { Token } = require('./src/index');
|
|
82
86
|
const root = debug_1.Shadow.run(() => {
|
|
83
87
|
const token = new Token(wikitext, config);
|
package/dist/lib/element.js
CHANGED
|
@@ -3,15 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.AstElement = void 0;
|
|
4
4
|
const string_1 = require("../util/string");
|
|
5
5
|
const debug_1 = require("../util/debug");
|
|
6
|
+
const selector_1 = require("../parser/selector");
|
|
6
7
|
const node_1 = require("./node");
|
|
7
|
-
/**
|
|
8
|
-
* 将选择器转化为类型谓词
|
|
9
|
-
* @param selector 选择器
|
|
10
|
-
*/
|
|
11
|
-
const getCondition = (selector) => (({ type, name }) => selector.split(',').some(str => {
|
|
12
|
-
const [t, ...ns] = str.trim().split('#');
|
|
13
|
-
return (!t || t === type) && ns.every(n => n === name);
|
|
14
|
-
}));
|
|
15
8
|
/** 类似HTMLElement */
|
|
16
9
|
class AstElement extends node_1.AstNode {
|
|
17
10
|
/** 子节点总数 */
|
|
@@ -64,7 +57,7 @@ class AstElement extends node_1.AstNode {
|
|
|
64
57
|
* @param selector 选择器
|
|
65
58
|
*/
|
|
66
59
|
closest(selector) {
|
|
67
|
-
const condition = getCondition(selector);
|
|
60
|
+
const condition = (0, selector_1.getCondition)(selector, this);
|
|
68
61
|
let { parentNode } = this;
|
|
69
62
|
while (parentNode) {
|
|
70
63
|
if (condition(parentNode)) {
|
|
@@ -98,7 +91,7 @@ class AstElement extends node_1.AstNode {
|
|
|
98
91
|
* @param selector 选择器
|
|
99
92
|
*/
|
|
100
93
|
querySelector(selector) {
|
|
101
|
-
const condition = getCondition(selector);
|
|
94
|
+
const condition = (0, selector_1.getCondition)(selector, this);
|
|
102
95
|
return this.#getElementBy(condition);
|
|
103
96
|
}
|
|
104
97
|
/**
|
|
@@ -123,7 +116,7 @@ class AstElement extends node_1.AstNode {
|
|
|
123
116
|
* @param selector 选择器
|
|
124
117
|
*/
|
|
125
118
|
querySelectorAll(selector) {
|
|
126
|
-
const condition = getCondition(selector);
|
|
119
|
+
const condition = (0, selector_1.getCondition)(selector, this);
|
|
127
120
|
return this.#getElementsBy(condition);
|
|
128
121
|
}
|
|
129
122
|
/**
|
package/dist/lib/title.js
CHANGED
|
@@ -52,7 +52,6 @@ class Title {
|
|
|
52
52
|
*/
|
|
53
53
|
constructor(title, defaultNs, config, decode, selfLink) {
|
|
54
54
|
const subpage = title.trim().startsWith('../');
|
|
55
|
-
title = (0, string_1.decodeHtml)(title);
|
|
56
55
|
if (decode && title.includes('%')) {
|
|
57
56
|
try {
|
|
58
57
|
const encoded = /%(?!21|3[ce]|5[bd]|7[b-d])[\da-f]{2}/iu.test(title);
|
|
@@ -61,7 +60,7 @@ class Title {
|
|
|
61
60
|
}
|
|
62
61
|
catch { }
|
|
63
62
|
}
|
|
64
|
-
title = title.replace(/[_ ]+/gu, ' ').trim();
|
|
63
|
+
title = (0, string_1.decodeHtml)(title).replace(/[_ ]+/gu, ' ').trim();
|
|
65
64
|
if (subpage) {
|
|
66
65
|
this.#ns = 0;
|
|
67
66
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getCondition = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* 将选择器转化为类型谓词
|
|
6
|
+
* @param selector 选择器
|
|
7
|
+
* @param scope 作用对象
|
|
8
|
+
* @param has `:has()`伪选择器
|
|
9
|
+
*/
|
|
10
|
+
const getCondition = (selector, scope, has) => (({ type, name }) => selector.split(',').some(str => {
|
|
11
|
+
const [t, ...ns] = str.trim().split('#');
|
|
12
|
+
return (!t || t === type) && ns.every(n => n === name);
|
|
13
|
+
}));
|
|
14
|
+
exports.getCondition = getCondition;
|
package/dist/src/attributes.js
CHANGED
|
@@ -104,18 +104,7 @@ class AttributesToken extends index_2.Token {
|
|
|
104
104
|
errors.push(e);
|
|
105
105
|
}
|
|
106
106
|
for (const attr of childNodes) {
|
|
107
|
-
if (attr instanceof
|
|
108
|
-
const e = (0, lint_1.generateForChild)(attr, rect, 'no-ignored', 'containing invalid attribute');
|
|
109
|
-
e.suggestions = [
|
|
110
|
-
{
|
|
111
|
-
desc: 'remove',
|
|
112
|
-
range: [e.startIndex, e.endIndex],
|
|
113
|
-
text: ' ',
|
|
114
|
-
},
|
|
115
|
-
];
|
|
116
|
-
errors.push(e);
|
|
117
|
-
}
|
|
118
|
-
else if (attr instanceof attribute_1.AttributeToken) {
|
|
107
|
+
if (attr instanceof attribute_1.AttributeToken) {
|
|
119
108
|
const { name } = attr;
|
|
120
109
|
if (attrs.has(name)) {
|
|
121
110
|
duplicated.add(name);
|
|
@@ -125,6 +114,20 @@ class AttributesToken extends index_2.Token {
|
|
|
125
114
|
attrs.set(name, [attr]);
|
|
126
115
|
}
|
|
127
116
|
}
|
|
117
|
+
else {
|
|
118
|
+
const str = attr.text().trim();
|
|
119
|
+
if (str) {
|
|
120
|
+
const e = (0, lint_1.generateForChild)(attr, rect, 'no-ignored', 'containing invalid attribute', /[\p{L}\d]/u.test(str) ? 'error' : 'warning');
|
|
121
|
+
e.suggestions = [
|
|
122
|
+
{
|
|
123
|
+
desc: 'remove',
|
|
124
|
+
range: [e.startIndex, e.endIndex],
|
|
125
|
+
text: ' ',
|
|
126
|
+
},
|
|
127
|
+
];
|
|
128
|
+
errors.push(e);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
128
131
|
}
|
|
129
132
|
if (duplicated.size > 0) {
|
|
130
133
|
for (const key of duplicated) {
|
|
@@ -38,7 +38,7 @@ class ParamTagToken extends index_2.Token {
|
|
|
38
38
|
lint(start = this.getAbsoluteIndex()) {
|
|
39
39
|
const rect = new rect_1.BoundingRect(this, start);
|
|
40
40
|
return this.childNodes.filter(child => {
|
|
41
|
-
const
|
|
41
|
+
const childNodes = child.childNodes.filter(({ type }) => type !== 'comment'), i = childNodes.findIndex(({ type }) => type !== 'text'), str = childNodes.slice(0, i >= 0 ? i : undefined).map(String).join('');
|
|
42
42
|
return str && !(i >= 0 ? /^[a-z]+(?:\[\])?\s*(?:=|$)/iu : /^[a-z]+(?:\[\])?\s*=/iu).test(str);
|
|
43
43
|
}).map(child => {
|
|
44
44
|
const e = (0, lint_1.generateForChild)(child, rect, 'no-ignored', index_1.default.msg('invalid parameter of <$1>', this.name));
|
|
@@ -4,10 +4,24 @@ exports.InputboxToken = void 0;
|
|
|
4
4
|
const braces_1 = require("../../parser/braces");
|
|
5
5
|
const index_1 = require("../../index");
|
|
6
6
|
const index_2 = require("./index");
|
|
7
|
+
const comment_1 = require("../nowiki/comment");
|
|
8
|
+
/**
|
|
9
|
+
* 解析注释
|
|
10
|
+
* @param wikitext 维基文本
|
|
11
|
+
* @param config
|
|
12
|
+
* @param accum
|
|
13
|
+
*/
|
|
14
|
+
const parseComment = (wikitext, config, accum) => wikitext.replace(/<!--.*?(?:-->|$)/gsu, comment => {
|
|
15
|
+
const str = `\0${accum.length + 1}c\x7F`, closed = comment.endsWith('-->');
|
|
16
|
+
// @ts-expect-error abstract class
|
|
17
|
+
new comment_1.CommentToken(comment.slice(4, closed ? -3 : undefined), closed, config, accum);
|
|
18
|
+
return str;
|
|
19
|
+
});
|
|
7
20
|
/** `<inputbox>` */
|
|
8
21
|
class InputboxToken extends index_2.ParamTagToken {
|
|
9
22
|
/** @class */
|
|
10
23
|
constructor(wikitext, config = index_1.default.getConfig(), accum = []) {
|
|
24
|
+
wikitext &&= parseComment(wikitext, config, accum);
|
|
11
25
|
const placeholder = Symbol('InputboxToken'), { length } = accum;
|
|
12
26
|
accum.push(placeholder);
|
|
13
27
|
wikitext &&= (0, braces_1.parseBraces)(wikitext, config, accum);
|
package/dist/src/pre.js
CHANGED
|
@@ -16,19 +16,27 @@ class PreToken extends index_2.Token {
|
|
|
16
16
|
/** @class */
|
|
17
17
|
constructor(wikitext, config = index_1.default.getConfig(), accum = []) {
|
|
18
18
|
if (wikitext) {
|
|
19
|
-
const opening =
|
|
20
|
-
let i =
|
|
21
|
-
|
|
19
|
+
const opening = /<nowiki>/giu, closing = /<\/nowiki>/giu, { length } = opening.source;
|
|
20
|
+
let i = opening.exec(wikitext);
|
|
21
|
+
if (i) {
|
|
22
|
+
closing.lastIndex = i.index + length;
|
|
23
|
+
}
|
|
24
|
+
let j = closing.exec(wikitext), lastIndex = 0, str = '';
|
|
25
|
+
while (i && j) {
|
|
22
26
|
// @ts-expect-error abstract class
|
|
23
|
-
new noinclude_1.NoincludeToken(
|
|
27
|
+
new noinclude_1.NoincludeToken(i[0], config, accum);
|
|
24
28
|
// @ts-expect-error abstract class
|
|
25
|
-
new noinclude_1.NoincludeToken(
|
|
26
|
-
str += `${wikitext.slice(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
new noinclude_1.NoincludeToken(j[0], config, accum);
|
|
30
|
+
str += `${wikitext.slice(lastIndex, i.index)}\0${accum.length - 1}n\x7F${wikitext.slice(i.index + length, j.index)}\0${accum.length}n\x7F`;
|
|
31
|
+
lastIndex = j.index + length + 1;
|
|
32
|
+
opening.lastIndex = lastIndex;
|
|
33
|
+
i = opening.exec(wikitext);
|
|
34
|
+
if (i) {
|
|
35
|
+
closing.lastIndex = i.index + length;
|
|
36
|
+
}
|
|
37
|
+
j = closing.exec(wikitext);
|
|
30
38
|
}
|
|
31
|
-
wikitext = str + wikitext;
|
|
39
|
+
wikitext = str + wikitext.slice(lastIndex);
|
|
32
40
|
}
|
|
33
41
|
super(wikitext, config, accum, {});
|
|
34
42
|
this.setAttribute('stage', constants_1.MAX_STAGE - 1);
|
|
@@ -36,6 +36,7 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
|
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
37
|
exports.IncludeToken = void 0;
|
|
38
38
|
const lint_1 = require("../../util/lint");
|
|
39
|
+
const rect_1 = require("../../lib/rect");
|
|
39
40
|
const hidden_1 = require("../../mixin/hidden");
|
|
40
41
|
const index_1 = require("../../index");
|
|
41
42
|
const index_2 = require("./index");
|
|
@@ -76,18 +77,30 @@ let IncludeToken = (() => {
|
|
|
76
77
|
}
|
|
77
78
|
/** @private */
|
|
78
79
|
lint(start = this.getAbsoluteIndex()) {
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
const errors = [], { firstChild, closed, name } = this, rect = new rect_1.BoundingRect(this, start);
|
|
81
|
+
if (firstChild.data.trim()) {
|
|
82
|
+
const e = (0, lint_1.generateForChild)(firstChild, rect, 'no-ignored', 'useless attribute', 'warning');
|
|
83
|
+
e.suggestions = [
|
|
84
|
+
{
|
|
85
|
+
desc: 'remove',
|
|
86
|
+
range: [e.startIndex, e.endIndex],
|
|
87
|
+
text: '',
|
|
88
|
+
},
|
|
89
|
+
];
|
|
90
|
+
errors.push(e);
|
|
81
91
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
92
|
+
if (!closed) {
|
|
93
|
+
const e = (0, lint_1.generateForSelf)(this, rect, 'unclosed-comment', index_1.default.msg('unclosed $1', `<${name}>`));
|
|
94
|
+
e.suggestions = [
|
|
95
|
+
{
|
|
96
|
+
desc: 'close',
|
|
97
|
+
range: [e.endIndex, e.endIndex],
|
|
98
|
+
text: `</${name}>`,
|
|
99
|
+
},
|
|
100
|
+
];
|
|
101
|
+
errors.push(e);
|
|
102
|
+
}
|
|
103
|
+
return errors;
|
|
91
104
|
}
|
|
92
105
|
};
|
|
93
106
|
return IncludeToken = _classThis;
|
package/dist/src/transclude.js
CHANGED
|
@@ -265,7 +265,7 @@ class TranscludeToken extends index_2.Token {
|
|
|
265
265
|
getPossibleValues() {
|
|
266
266
|
const { type, name, childNodes } = this;
|
|
267
267
|
if (type === 'template') {
|
|
268
|
-
throw new Error(
|
|
268
|
+
throw new Error('TranscludeToken.getPossibleValues method is only for specific magic words!');
|
|
269
269
|
}
|
|
270
270
|
let start;
|
|
271
271
|
switch (name) {
|
|
@@ -279,7 +279,7 @@ class TranscludeToken extends index_2.Token {
|
|
|
279
279
|
start = 3;
|
|
280
280
|
break;
|
|
281
281
|
default:
|
|
282
|
-
throw new Error(
|
|
282
|
+
throw new Error('TranscludeToken.getPossibleValues method is only for specific magic words!');
|
|
283
283
|
}
|
|
284
284
|
const queue = childNodes.slice(start, start + 2).map(({ childNodes: [, value] }) => value);
|
|
285
285
|
for (let i = 0; i < queue.length;) {
|
package/i18n/zh-hans.json
CHANGED
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"unexpected template argument": "未预期的模板参数",
|
|
54
54
|
"unmatched closing tag": "未匹配的闭合标签",
|
|
55
55
|
"unnecessary URL encoding in an internal link": "内链中不必要的URL编码",
|
|
56
|
+
"useless attribute": "无用的属性",
|
|
56
57
|
"useless fragment": "无用的fragment",
|
|
57
58
|
"useless link text": "无用的链接文字",
|
|
58
59
|
"variable anchor in a section header": "段落标题中可变的锚点",
|
package/i18n/zh-hant.json
CHANGED
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"unexpected template argument": "未預期的模板參數",
|
|
54
54
|
"unmatched closing tag": "未匹配的閉合標籤",
|
|
55
55
|
"unnecessary URL encoding in an internal link": "內部連結中不必要的URL編碼",
|
|
56
|
+
"useless attribute": "無用的屬性",
|
|
56
57
|
"useless fragment": "無用的fragment",
|
|
57
58
|
"useless link text": "無用的連結文字",
|
|
58
59
|
"variable anchor in a section header": "段落標題中可變的錨點",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wikilint",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.13.1",
|
|
4
4
|
"description": "A Node.js linter for MediaWiki markup",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mediawiki",
|
|
@@ -51,11 +51,11 @@
|
|
|
51
51
|
"chalk": "^4.1.2"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@bhsd/common": "^0.
|
|
54
|
+
"@bhsd/common": "^0.3.0",
|
|
55
55
|
"@types/node": "^20.11.6",
|
|
56
56
|
"v8r": "^3.0.0"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
59
|
-
"node": "
|
|
59
|
+
"node": ">=20.9.0"
|
|
60
60
|
}
|
|
61
61
|
}
|