wikilint 2.4.4 → 2.4.5
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/README.md +3 -3
- package/dist/base.d.ts +2 -0
- package/dist/bin/cli.js +4 -4
- package/dist/lib/text.js +8 -0
- package/dist/src/arg.js +2 -2
- package/dist/src/attribute.js +5 -5
- package/dist/src/attributes.js +3 -3
- package/dist/src/converterFlags.js +1 -1
- package/dist/src/extLink.js +1 -1
- package/dist/src/gallery.js +1 -0
- package/dist/src/heading.js +5 -5
- package/dist/src/html.js +9 -6
- package/dist/src/imageParameter.js +2 -2
- package/dist/src/imagemap.js +2 -2
- package/dist/src/link/base.js +4 -4
- package/dist/src/link/file.js +2 -2
- package/dist/src/link/galleryImage.js +1 -1
- package/dist/src/link/index.js +1 -1
- package/dist/src/magicLink.js +1 -1
- package/dist/src/nested.js +1 -1
- package/dist/src/nowiki/comment.js +3 -1
- package/dist/src/nowiki/index.js +1 -1
- package/dist/src/nowiki/quote.js +4 -3
- package/dist/src/paramTag/index.js +1 -1
- package/dist/src/parameter.js +1 -1
- package/dist/src/table/index.js +1 -1
- package/dist/src/table/td.js +1 -1
- package/dist/src/table/trBase.js +1 -1
- package/dist/src/tagPair/ext.js +2 -2
- package/dist/src/tagPair/include.js +3 -1
- package/dist/src/transclude.js +4 -4
- package/dist/util/lint.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
[](https://github.com/bhsd-harry/wikiparser-node/actions/workflows/codeql.yml)
|
|
3
3
|
[](https://github.com/bhsd-harry/wikiparser-node/actions/workflows/node.js.yml)
|
|
4
4
|
|
|
5
|
-
#
|
|
5
|
+
# WikiLint
|
|
6
6
|
|
|
7
|
-
This is a minimal version of [
|
|
7
|
+
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).
|
|
8
8
|
|
|
9
9
|
You can also directly lint Wikitext articles in the command line using this package:
|
|
10
10
|
|
|
@@ -19,7 +19,7 @@ npx wikilint --config zhwiki --include --lang zh-hans *.wiki
|
|
|
19
19
|
| `-c`, `--config` \<path or preset config\> | Choose parser's configuration | `default` |
|
|
20
20
|
| `-h`, `--help` | Print available options | |
|
|
21
21
|
| `-i`, `--include` | Parse for inclusion | no inclusion |
|
|
22
|
-
| `-l`, `--lang` | Choose i18n language | English
|
|
22
|
+
| `-l`, `--lang` | Choose i18n language | English |
|
|
23
23
|
| `-q`, `--quiet` | Report errors only | errors and warnings |
|
|
24
24
|
| `-s`, `--strict` | Exit when there is an error or warning<br>Override `-q` or `--quiet` | Exit `1` only where there is an error |
|
|
25
25
|
| `-v`, `--version` | Print package version | |
|
package/dist/base.d.ts
CHANGED
|
@@ -11,7 +11,9 @@ export interface Config {
|
|
|
11
11
|
readonly excludes?: string[];
|
|
12
12
|
}
|
|
13
13
|
export type Severity = 'error' | 'warning';
|
|
14
|
+
export type Rule = 'bold-header' | 'format-leakage' | 'fostered-content' | 'h1' | 'illegal-attr' | 'insecure-style' | 'invalid-gallery' | 'invalid-imagemap' | 'invalid-invoke' | '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';
|
|
14
15
|
export interface LintError {
|
|
16
|
+
readonly rule: Rule;
|
|
15
17
|
readonly message: string;
|
|
16
18
|
readonly severity: Severity;
|
|
17
19
|
readonly startIndex: number;
|
package/dist/bin/cli.js
CHANGED
|
@@ -38,7 +38,7 @@ const plural = (n, word) => `${n} ${word}${n > 1 ? 's' : ''}`;
|
|
|
38
38
|
* color the severity
|
|
39
39
|
* @param severity problem severity
|
|
40
40
|
*/
|
|
41
|
-
const coloredSeverity = (severity) => `\x1B[${severity === 'error' ? 31 : 33}m${severity}\x1B[0m
|
|
41
|
+
const coloredSeverity = (severity) => `\x1B[${severity === 'error' ? 31 : 33}m${severity.padEnd(7)}\x1B[0m`;
|
|
42
42
|
for (let i = 2; i < argv.length; i++) {
|
|
43
43
|
option = argv[i];
|
|
44
44
|
switch (option) {
|
|
@@ -116,9 +116,9 @@ for (const file of files) {
|
|
|
116
116
|
}
|
|
117
117
|
if (problems.length > 0) {
|
|
118
118
|
console.error('\x1B[4m%s\x1B[0m', (0, path_1.resolve)(file));
|
|
119
|
-
const { length: maxLineChars } = String(Math.max(...problems.map(({ startLine }) => startLine))), { length: maxColChars } = String(Math.max(...problems.map(({ startCol }) => startCol)));
|
|
120
|
-
for (const { message, severity, startLine, startCol } of problems) {
|
|
121
|
-
console.error(`
|
|
119
|
+
const { length: maxLineChars } = String(Math.max(...problems.map(({ startLine }) => startLine))), { length: maxColChars } = String(Math.max(...problems.map(({ startCol }) => startCol))), maxMessageChars = Math.max(...problems.map(({ message: { length } }) => length));
|
|
120
|
+
for (const { rule, message, severity, startLine, startCol } of problems) {
|
|
121
|
+
console.error(` \x1B[37m%s:%s\x1B[0m %s %s \x1B[37m%s\x1B[0m`, String(startLine).padStart(maxLineChars), String(startCol).padEnd(maxColChars), coloredSeverity(severity), message.padEnd(maxMessageChars), rule);
|
|
122
122
|
}
|
|
123
123
|
console.error();
|
|
124
124
|
}
|
package/dist/lib/text.js
CHANGED
|
@@ -17,6 +17,13 @@ errorSyntax = new RegExp(`${source}|https?[:/]\\/+`, 'giu'), errorSyntaxUrl = ne
|
|
|
17
17
|
'{': /[{}]/u,
|
|
18
18
|
']': /[[\]](?=[^[\]]*$)/u,
|
|
19
19
|
'}': /[{}](?=[^{}]*$)/u,
|
|
20
|
+
}, ruleMap = {
|
|
21
|
+
'<': 'tag-like',
|
|
22
|
+
'[': 'lonely-bracket',
|
|
23
|
+
'{': 'lonely-bracket',
|
|
24
|
+
']': 'lonely-bracket',
|
|
25
|
+
'}': 'lonely-bracket',
|
|
26
|
+
h: 'lonely-http',
|
|
20
27
|
}, disallowedTags = [
|
|
21
28
|
'html',
|
|
22
29
|
'head',
|
|
@@ -144,6 +151,7 @@ class AstText extends node_1.AstNode {
|
|
|
144
151
|
}
|
|
145
152
|
const lines = data.slice(0, index).split('\n'), startLine = lines.length + top - 1, line = lines[lines.length - 1], startCol = lines.length === 1 ? left + line.length : line.length;
|
|
146
153
|
errors.push({
|
|
154
|
+
rule: ruleMap[char],
|
|
147
155
|
message: index_1.default.msg('lonely "$1"', char === 'h' ? error : char),
|
|
148
156
|
severity,
|
|
149
157
|
startIndex,
|
package/dist/src/arg.js
CHANGED
|
@@ -56,7 +56,7 @@ class ArgToken extends index_2.Token {
|
|
|
56
56
|
/** @override */
|
|
57
57
|
lint(start = this.getAbsoluteIndex()) {
|
|
58
58
|
if (!this.getAttribute('include')) {
|
|
59
|
-
return [(0, lint_1.generateForSelf)(this, { start }, 'unexpected template argument')];
|
|
59
|
+
return [(0, lint_1.generateForSelf)(this, { start }, 'no-arg', 'unexpected template argument')];
|
|
60
60
|
}
|
|
61
61
|
const { childNodes: [argName, argDefault, ...rest] } = this, errors = argName.lint(start + 3);
|
|
62
62
|
if (argDefault) {
|
|
@@ -65,7 +65,7 @@ class ArgToken extends index_2.Token {
|
|
|
65
65
|
if (rest.length > 0) {
|
|
66
66
|
const rect = { start, ...this.getRootNode().posFromIndex(start) };
|
|
67
67
|
errors.push(...rest.map(child => {
|
|
68
|
-
const error = (0, lint_1.generateForChild)(child, rect, 'invisible content inside triple braces');
|
|
68
|
+
const error = (0, lint_1.generateForChild)(child, rect, 'no-ignored', 'invisible content inside triple braces');
|
|
69
69
|
return {
|
|
70
70
|
...error,
|
|
71
71
|
startIndex: error.startIndex - 1,
|
package/dist/src/attribute.js
CHANGED
|
@@ -260,7 +260,7 @@ class AttributeToken extends index_2.Token {
|
|
|
260
260
|
if (!balanced) {
|
|
261
261
|
const root = this.getRootNode();
|
|
262
262
|
rect = { start, ...root.posFromIndex(start) };
|
|
263
|
-
const e = (0, lint_1.generateForChild)(lastChild, rect, index_1.default.msg('unclosed $1', 'quotes'), 'warning');
|
|
263
|
+
const e = (0, lint_1.generateForChild)(lastChild, rect, 'unclosed-quote', index_1.default.msg('unclosed $1', 'quotes'), 'warning');
|
|
264
264
|
errors.push({
|
|
265
265
|
...e,
|
|
266
266
|
startIndex: e.startIndex - 1,
|
|
@@ -274,19 +274,19 @@ class AttributeToken extends index_2.Token {
|
|
|
274
274
|
&& !/^(?:xmlns:[\w:.-]+|data-[^:]*)$/u.test(name)
|
|
275
275
|
&& (tag === 'meta' || tag === 'link' || !commonHtmlAttrs.has(name))) {
|
|
276
276
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
277
|
-
errors.push((0, lint_1.generateForChild)(firstChild, rect, 'illegal attribute name'));
|
|
277
|
+
errors.push((0, lint_1.generateForChild)(firstChild, rect, 'illegal-attr', 'illegal attribute name'));
|
|
278
278
|
}
|
|
279
279
|
else if (obsoleteAttrs[tag]?.has(name)) {
|
|
280
280
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
281
|
-
errors.push((0, lint_1.generateForChild)(firstChild, rect, 'obsolete attribute', 'warning'));
|
|
281
|
+
errors.push((0, lint_1.generateForChild)(firstChild, rect, 'obsolete-attr', 'obsolete attribute', 'warning'));
|
|
282
282
|
}
|
|
283
283
|
else if (name === 'style' && typeof value === 'string' && insecureStyle.test(value)) {
|
|
284
284
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
285
|
-
errors.push((0, lint_1.generateForChild)(lastChild, rect, 'insecure style'));
|
|
285
|
+
errors.push((0, lint_1.generateForChild)(lastChild, rect, 'insecure-style', 'insecure style'));
|
|
286
286
|
}
|
|
287
287
|
else if (name === 'tabindex' && typeof value === 'string' && value.trim() !== '0') {
|
|
288
288
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
289
|
-
errors.push((0, lint_1.generateForChild)(lastChild, rect, 'nonzero tabindex'));
|
|
289
|
+
errors.push((0, lint_1.generateForChild)(lastChild, rect, 'illegal-attr', 'nonzero tabindex'));
|
|
290
290
|
}
|
|
291
291
|
return errors;
|
|
292
292
|
}
|
package/dist/src/attributes.js
CHANGED
|
@@ -100,13 +100,13 @@ class AttributesToken extends index_2.Token {
|
|
|
100
100
|
let rect;
|
|
101
101
|
if (parentNode?.type === 'html' && parentNode.closing && this.text().trim()) {
|
|
102
102
|
rect = { start, ...this.getRootNode().posFromIndex(start) };
|
|
103
|
-
errors.push((0, lint_1.generateForSelf)(this, rect, 'attributes of a closing tag'));
|
|
103
|
+
errors.push((0, lint_1.generateForSelf)(this, rect, 'no-ignored', 'attributes of a closing tag'));
|
|
104
104
|
}
|
|
105
105
|
for (let i = 0; i < length; i++) {
|
|
106
106
|
const attr = childNodes[i];
|
|
107
107
|
if (attr instanceof atom_1.AtomToken && attr.text().trim()) {
|
|
108
108
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
109
|
-
errors.push((0, lint_1.generateForChild)(attr, rect, 'containing invalid attribute'));
|
|
109
|
+
errors.push((0, lint_1.generateForChild)(attr, rect, 'no-ignored', 'containing invalid attribute'));
|
|
110
110
|
}
|
|
111
111
|
else if (attr instanceof attribute_1.AttributeToken) {
|
|
112
112
|
const { name } = attr;
|
|
@@ -122,7 +122,7 @@ class AttributesToken extends index_2.Token {
|
|
|
122
122
|
if (duplicated.size > 0) {
|
|
123
123
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
124
124
|
for (const key of duplicated) {
|
|
125
|
-
errors.push(...attrs.get(key).map(attr => (0, lint_1.generateForChild)(attr, rect, index_1.default.msg('duplicated $1 attribute', key))));
|
|
125
|
+
errors.push(...attrs.get(key).map(attr => (0, lint_1.generateForChild)(attr, rect, 'no-duplicate', index_1.default.msg('duplicated $1 attribute', key))));
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
return errors;
|
|
@@ -56,7 +56,7 @@ class ConverterFlagsToken extends index_2.Token {
|
|
|
56
56
|
&& !variantFlags.has(flag)
|
|
57
57
|
&& !unknownFlags.has(flag)
|
|
58
58
|
&& (variantFlags.size > 0 || !validFlags.has(flag))) {
|
|
59
|
-
errors.push((0, lint_1.generateForChild)(child, rect, 'invalid conversion flag'));
|
|
59
|
+
errors.push((0, lint_1.generateForChild)(child, rect, 'no-ignored', 'invalid conversion flag'));
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
return errors;
|
package/dist/src/extLink.js
CHANGED
|
@@ -53,7 +53,7 @@ class ExtLinkToken extends index_2.Token {
|
|
|
53
53
|
lint(start = this.getAbsoluteIndex()) {
|
|
54
54
|
const errors = super.lint(start);
|
|
55
55
|
if (this.length === 1 && this.closest('heading-title')) {
|
|
56
|
-
errors.push((0, lint_1.generateForSelf)(this, { start }, 'variable anchor in a section header'));
|
|
56
|
+
errors.push((0, lint_1.generateForSelf)(this, { start }, 'var-anchor', 'variable anchor in a section header'));
|
|
57
57
|
}
|
|
58
58
|
return errors;
|
|
59
59
|
}
|
package/dist/src/gallery.js
CHANGED
|
@@ -58,6 +58,7 @@ class GalleryToken extends index_2.Token {
|
|
|
58
58
|
const child = this.childNodes[i], str = String(child), { length } = str, trimmed = str.trim(), startLine = top + i, startCol = i ? 0 : left;
|
|
59
59
|
if (child.type === 'noinclude' && trimmed && !/^<!--.*-->$/u.test(trimmed)) {
|
|
60
60
|
errors.push({
|
|
61
|
+
rule: 'no-ignored',
|
|
61
62
|
message: index_1.default.msg('invalid content in <$1>', 'gallery'),
|
|
62
63
|
severity: 'error',
|
|
63
64
|
startIndex: start,
|
package/dist/src/heading.js
CHANGED
|
@@ -57,23 +57,23 @@ class HeadingToken extends index_2.Token {
|
|
|
57
57
|
let rect;
|
|
58
58
|
if (this.level === 1) {
|
|
59
59
|
rect = { start, ...this.getRootNode().posFromIndex(start) };
|
|
60
|
-
errors.push((0, lint_1.generateForChild)(firstChild, rect, '<h1>'));
|
|
60
|
+
errors.push((0, lint_1.generateForChild)(firstChild, rect, 'h1', '<h1>'));
|
|
61
61
|
}
|
|
62
62
|
if (innerStr.startsWith('=') || innerStr.endsWith('=')) {
|
|
63
63
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
64
|
-
errors.push((0, lint_1.generateForChild)(firstChild, rect, index_1.default.msg('unbalanced $1 in a section header', '"="')));
|
|
64
|
+
errors.push((0, lint_1.generateForChild)(firstChild, rect, 'unbalanced-header', index_1.default.msg('unbalanced $1 in a section header', '"="')));
|
|
65
65
|
}
|
|
66
66
|
if (this.closest('html-attrs, table-attrs')) {
|
|
67
67
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
68
|
-
errors.push((0, lint_1.generateForSelf)(this, rect, 'section header in a HTML tag'));
|
|
68
|
+
errors.push((0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'section header in a HTML tag'));
|
|
69
69
|
}
|
|
70
70
|
if (boldQuotes.length % 2) {
|
|
71
71
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
72
|
-
errors.push((0, lint_1.generateForChild)(boldQuotes[boldQuotes.length - 1], { ...rect, start: start + level, left: rect.left + level }, index_1.default.msg('unbalanced $1 in a section header', 'bold apostrophes')));
|
|
72
|
+
errors.push((0, lint_1.generateForChild)(boldQuotes[boldQuotes.length - 1], { ...rect, start: start + level, left: rect.left + level }, 'format-leakage', index_1.default.msg('unbalanced $1 in a section header', 'bold apostrophes')));
|
|
73
73
|
}
|
|
74
74
|
if (italicQuotes.length % 2) {
|
|
75
75
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
76
|
-
errors.push((0, lint_1.generateForChild)(italicQuotes[italicQuotes.length - 1], { start: start + level }, index_1.default.msg('unbalanced $1 in a section header', 'italic apostrophes')));
|
|
76
|
+
errors.push((0, lint_1.generateForChild)(italicQuotes[italicQuotes.length - 1], { start: start + level }, 'format-leakage', index_1.default.msg('unbalanced $1 in a section header', 'italic apostrophes')));
|
|
77
77
|
}
|
|
78
78
|
return errors;
|
|
79
79
|
}
|
package/dist/src/html.js
CHANGED
|
@@ -79,13 +79,14 @@ class HtmlToken extends index_2.Token {
|
|
|
79
79
|
const errors = super.lint(start);
|
|
80
80
|
let refError;
|
|
81
81
|
if (this.name === 'h1' && !this.closing) {
|
|
82
|
-
refError = (0, lint_1.generateForSelf)(this, { start }, '<h1>');
|
|
82
|
+
refError = (0, lint_1.generateForSelf)(this, { start }, 'h1', '<h1>');
|
|
83
83
|
errors.push(refError);
|
|
84
84
|
}
|
|
85
85
|
if (this.closest('table-attrs')) {
|
|
86
|
-
refError ??= (0, lint_1.generateForSelf)(this, { start }, '');
|
|
86
|
+
refError ??= (0, lint_1.generateForSelf)(this, { start }, 'h1', '');
|
|
87
87
|
errors.push({
|
|
88
88
|
...refError,
|
|
89
|
+
rule: 'parsing-order',
|
|
89
90
|
message: index_1.default.msg('HTML tag in table attributes'),
|
|
90
91
|
});
|
|
91
92
|
}
|
|
@@ -95,8 +96,8 @@ class HtmlToken extends index_2.Token {
|
|
|
95
96
|
catch (e) {
|
|
96
97
|
if (e instanceof SyntaxError) {
|
|
97
98
|
const { message } = e;
|
|
98
|
-
refError ??= (0, lint_1.generateForSelf)(this, { start }, '');
|
|
99
|
-
const [msg] = message.split(':'), error = { ...refError, message: index_1.default.msg(msg) };
|
|
99
|
+
refError ??= (0, lint_1.generateForSelf)(this, { start }, 'h1', '');
|
|
100
|
+
const [msg] = message.split(':'), error = { ...refError, rule: 'unmatched-tag', message: index_1.default.msg(msg) };
|
|
100
101
|
if (msg === 'unclosed tag' && !this.closest('heading-title')) {
|
|
101
102
|
if (formattingTags.has(this.name)) {
|
|
102
103
|
const childNodes = this.parentNode?.childNodes, i = childNodes?.indexOf(this);
|
|
@@ -118,17 +119,19 @@ class HtmlToken extends index_2.Token {
|
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
121
|
if (obsoleteTags.has(this.name)) {
|
|
121
|
-
refError ??= (0, lint_1.generateForSelf)(this, { start }, '');
|
|
122
|
+
refError ??= (0, lint_1.generateForSelf)(this, { start }, 'h1', '');
|
|
122
123
|
errors.push({
|
|
123
124
|
...refError,
|
|
125
|
+
rule: 'obsolete-tag',
|
|
124
126
|
message: index_1.default.msg('obsolete HTML tag'),
|
|
125
127
|
severity: 'warning',
|
|
126
128
|
});
|
|
127
129
|
}
|
|
128
130
|
if ((this.name === 'b' || this.name === 'strong') && this.closest('heading-title')) {
|
|
129
|
-
refError ??= (0, lint_1.generateForSelf)(this, { start }, '');
|
|
131
|
+
refError ??= (0, lint_1.generateForSelf)(this, { start }, 'h1', '');
|
|
130
132
|
errors.push({
|
|
131
133
|
...refError,
|
|
134
|
+
rule: 'format-leakage',
|
|
132
135
|
message: index_1.default.msg('bold in section header'),
|
|
133
136
|
severity: 'warning',
|
|
134
137
|
});
|
|
@@ -102,10 +102,10 @@ class ImageParameterToken extends index_2.Token {
|
|
|
102
102
|
lint(start = this.getAbsoluteIndex()) {
|
|
103
103
|
const errors = super.lint(start), { link, name } = this;
|
|
104
104
|
if (name === 'invalid') {
|
|
105
|
-
errors.push((0, lint_1.generateForSelf)(this, { start }, 'invalid gallery image parameter'));
|
|
105
|
+
errors.push((0, lint_1.generateForSelf)(this, { start }, 'invalid-gallery', 'invalid gallery image parameter'));
|
|
106
106
|
}
|
|
107
107
|
else if (typeof link === 'object' && link.encoded) {
|
|
108
|
-
errors.push((0, lint_1.generateForSelf)(this, { start }, 'unnecessary URL encoding in an internal link'));
|
|
108
|
+
errors.push((0, lint_1.generateForSelf)(this, { start }, 'url-encoding', 'unnecessary URL encoding in an internal link'));
|
|
109
109
|
}
|
|
110
110
|
return errors;
|
|
111
111
|
}
|
package/dist/src/imagemap.js
CHANGED
|
@@ -92,10 +92,10 @@ class ImagemapToken extends index_2.Token {
|
|
|
92
92
|
errors.push(...this.childNodes.filter(child => {
|
|
93
93
|
const str = String(child).trim();
|
|
94
94
|
return child.type === 'noinclude' && str && !str.startsWith('#');
|
|
95
|
-
}).map(child => (0, lint_1.generateForChild)(child, rect, 'invalid link in <imagemap>')));
|
|
95
|
+
}).map(child => (0, lint_1.generateForChild)(child, rect, 'invalid-imagemap', 'invalid link in <imagemap>')));
|
|
96
96
|
}
|
|
97
97
|
else {
|
|
98
|
-
errors.push((0, lint_1.generateForSelf)(this, rect, '<imagemap> without an image'));
|
|
98
|
+
errors.push((0, lint_1.generateForSelf)(this, rect, 'invalid-imagemap', '<imagemap> without an image'));
|
|
99
99
|
}
|
|
100
100
|
return errors;
|
|
101
101
|
}
|
package/dist/src/link/base.js
CHANGED
|
@@ -76,20 +76,20 @@ class LinkBaseToken extends index_2.Token {
|
|
|
76
76
|
let rect;
|
|
77
77
|
if (target.childNodes.some(({ type }) => type === 'template')) {
|
|
78
78
|
rect = { start, ...this.getRootNode().posFromIndex(start) };
|
|
79
|
-
errors.push((0, lint_1.generateForChild)(target, rect, 'template in an internal link target', 'warning'));
|
|
79
|
+
errors.push((0, lint_1.generateForChild)(target, rect, 'unknown-page', 'template in an internal link target', 'warning'));
|
|
80
80
|
}
|
|
81
81
|
if (encoded) {
|
|
82
82
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
83
|
-
errors.push((0, lint_1.generateForChild)(target, rect, 'unnecessary URL encoding in an internal link'));
|
|
83
|
+
errors.push((0, lint_1.generateForChild)(target, rect, 'url-encoding', 'unnecessary URL encoding in an internal link'));
|
|
84
84
|
}
|
|
85
85
|
if ((linkType === 'link' || linkType === 'category')
|
|
86
86
|
&& linkText?.childNodes.some(({ type, data }) => type === 'text' && data.includes('|'))) {
|
|
87
87
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
88
|
-
errors.push((0, lint_1.generateForChild)(linkText, rect, 'additional "|" in the link text', 'warning'));
|
|
88
|
+
errors.push((0, lint_1.generateForChild)(linkText, rect, 'pipe-like', 'additional "|" in the link text', 'warning'));
|
|
89
89
|
}
|
|
90
90
|
else if (linkType !== 'link' && fragment !== undefined) {
|
|
91
91
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
92
|
-
errors.push((0, lint_1.generateForChild)(target, rect, 'useless fragment'));
|
|
92
|
+
errors.push((0, lint_1.generateForChild)(target, rect, 'no-ignored', 'useless fragment'));
|
|
93
93
|
}
|
|
94
94
|
return errors;
|
|
95
95
|
}
|
package/dist/src/link/file.js
CHANGED
|
@@ -58,7 +58,7 @@ class FileToken extends base_1.LinkBaseToken {
|
|
|
58
58
|
return visibleNodes.length !== 1 || visibleNodes[0].type !== 'arg';
|
|
59
59
|
}), keys = [...new Set(args.map(({ name }) => name))].filter(key => key !== 'invalid'), frameKeys = keys.filter(key => frame.has(key)), horizAlignKeys = keys.filter(key => horizAlign.has(key)), vertAlignKeys = keys.filter(key => vertAlign.has(key));
|
|
60
60
|
if (this.closest('ext-link-text') && this.getValue('link')?.trim() !== '') {
|
|
61
|
-
errors.push((0, lint_1.generateForSelf)(this, { start }, 'internal link in an external link'));
|
|
61
|
+
errors.push((0, lint_1.generateForSelf)(this, { start }, 'nested-link', 'internal link in an external link'));
|
|
62
62
|
}
|
|
63
63
|
if (args.length === keys.length
|
|
64
64
|
&& frameKeys.length < 2
|
|
@@ -72,7 +72,7 @@ class FileToken extends base_1.LinkBaseToken {
|
|
|
72
72
|
* @param msg 消息键
|
|
73
73
|
* @param p1 替换$1
|
|
74
74
|
*/
|
|
75
|
-
const generate = (msg, p1) => (arg) => (0, lint_1.generateForChild)(arg, rect, index_1.default.msg(`${msg} image $1 parameter`, p1));
|
|
75
|
+
const generate = (msg, p1) => (arg) => (0, lint_1.generateForChild)(arg, rect, 'no-duplicate', index_1.default.msg(`${msg} image $1 parameter`, p1));
|
|
76
76
|
for (const key of keys) {
|
|
77
77
|
let relevantArgs = args.filter(({ name }) => name === key);
|
|
78
78
|
if (key === 'caption') {
|
|
@@ -40,7 +40,7 @@ class GalleryImageToken extends file_1.FileToken {
|
|
|
40
40
|
lint(start = this.getAbsoluteIndex()) {
|
|
41
41
|
const errors = super.lint(start), { ns, interwiki } = this.getAttribute('title');
|
|
42
42
|
if (interwiki || ns !== 6) {
|
|
43
|
-
errors.push((0, lint_1.generateForSelf)(this, { start }, 'invalid gallery image'));
|
|
43
|
+
errors.push((0, lint_1.generateForSelf)(this, { start }, 'invalid-gallery', 'invalid gallery image'));
|
|
44
44
|
}
|
|
45
45
|
return errors;
|
|
46
46
|
}
|
package/dist/src/link/index.js
CHANGED
|
@@ -13,7 +13,7 @@ class LinkToken extends base_1.LinkBaseToken {
|
|
|
13
13
|
lint(start = this.getAbsoluteIndex()) {
|
|
14
14
|
const errors = super.lint(start);
|
|
15
15
|
if (this.closest('ext-link-text')) {
|
|
16
|
-
errors.push((0, lint_1.generateForSelf)(this, { start }, 'internal link in an external link'));
|
|
16
|
+
errors.push((0, lint_1.generateForSelf)(this, { start }, 'nested-link', 'internal link in an external link'));
|
|
17
17
|
}
|
|
18
18
|
return errors;
|
|
19
19
|
}
|
package/dist/src/magicLink.js
CHANGED
|
@@ -27,7 +27,7 @@ class MagicLinkToken extends index_2.Token {
|
|
|
27
27
|
continue;
|
|
28
28
|
}
|
|
29
29
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
30
|
-
const refError = (0, lint_1.generateForChild)(child, rect, '', 'warning');
|
|
30
|
+
const refError = (0, lint_1.generateForChild)(child, rect, 'unterminated-url', '', 'warning');
|
|
31
31
|
regexGlobal.lastIndex = 0;
|
|
32
32
|
for (let mt = regexGlobal.exec(data); mt; mt = regexGlobal.exec(data)) {
|
|
33
33
|
const { index, 0: s } = mt, lines = data.slice(0, index).split('\n'), top = lines.length, left = lines[top - 1].length, startIndex = refError.startIndex + index, startLine = refError.startLine + top - 1, startCol = top === 1 ? refError.startCol + left : left;
|
package/dist/src/nested.js
CHANGED
|
@@ -50,7 +50,7 @@ class NestedToken extends index_2.Token {
|
|
|
50
50
|
return str && !/^<!--.*-->$/su.test(str);
|
|
51
51
|
}).map(child => {
|
|
52
52
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
53
|
-
return (0, lint_1.generateForChild)(child, rect, index_1.default.msg('invalid content in <$1>', this.name));
|
|
53
|
+
return (0, lint_1.generateForChild)(child, rect, 'no-ignored', index_1.default.msg('invalid content in <$1>', this.name));
|
|
54
54
|
}),
|
|
55
55
|
];
|
|
56
56
|
}
|
|
@@ -20,7 +20,9 @@ class CommentToken extends (0, hidden_1.hiddenToken)(base_1.NowikiBaseToken) {
|
|
|
20
20
|
}
|
|
21
21
|
/** @override */
|
|
22
22
|
lint(start = this.getAbsoluteIndex()) {
|
|
23
|
-
return this.closed
|
|
23
|
+
return this.closed
|
|
24
|
+
? []
|
|
25
|
+
: [(0, lint_1.generateForSelf)(this, { start }, 'unclosed-comment', index_1.default.msg('unclosed $1', 'HTML comment'))];
|
|
24
26
|
}
|
|
25
27
|
/** @private */
|
|
26
28
|
toString() {
|
package/dist/src/nowiki/index.js
CHANGED
|
@@ -11,7 +11,7 @@ class NowikiToken extends base_1.NowikiBaseToken {
|
|
|
11
11
|
lint(start = this.getAbsoluteIndex()) {
|
|
12
12
|
const { name, firstChild: { data } } = this;
|
|
13
13
|
return (name === 'templatestyles' || name === 'section') && data
|
|
14
|
-
? [(0, lint_1.generateForSelf)(this, { start }, index_1.default.msg('nothing should be in <$1>', name))]
|
|
14
|
+
? [(0, lint_1.generateForSelf)(this, { start }, 'void-ext', index_1.default.msg('nothing should be in <$1>', name))]
|
|
15
15
|
: super.lint(start);
|
|
16
16
|
}
|
|
17
17
|
}
|
package/dist/src/nowiki/quote.js
CHANGED
|
@@ -20,7 +20,7 @@ class QuoteToken extends base_1.NowikiBaseToken {
|
|
|
20
20
|
const { previousSibling, nextSibling, bold } = this, message = index_1.default.msg('lonely "$1"', `'`), errors = [];
|
|
21
21
|
let refError;
|
|
22
22
|
if (previousSibling?.type === 'text' && previousSibling.data.endsWith(`'`)) {
|
|
23
|
-
refError = (0, lint_1.generateForSelf)(this, { start }, message);
|
|
23
|
+
refError = (0, lint_1.generateForSelf)(this, { start }, 'lonely-apos', message);
|
|
24
24
|
const { startIndex: endIndex, startLine: endLine, startCol: endCol } = refError, [, { length }] = /(?:^|[^'])('+)$/u.exec(previousSibling.data), startIndex = start - length;
|
|
25
25
|
errors.push({
|
|
26
26
|
...refError,
|
|
@@ -32,7 +32,7 @@ class QuoteToken extends base_1.NowikiBaseToken {
|
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
34
|
if (nextSibling?.type === 'text' && nextSibling.data.startsWith(`'`)) {
|
|
35
|
-
refError ??= (0, lint_1.generateForSelf)(this, { start }, message);
|
|
35
|
+
refError ??= (0, lint_1.generateForSelf)(this, { start }, 'lonely-apos', message);
|
|
36
36
|
const { endIndex: startIndex, endLine: startLine, endCol: startCol } = refError, [{ length }] = /^'+/u.exec(nextSibling.data), endIndex = startIndex + length;
|
|
37
37
|
errors.push({
|
|
38
38
|
...refError,
|
|
@@ -44,9 +44,10 @@ class QuoteToken extends base_1.NowikiBaseToken {
|
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
46
|
if (bold && this.closest('heading-title')) {
|
|
47
|
-
refError ??= (0, lint_1.generateForSelf)(this, { start }, message);
|
|
47
|
+
refError ??= (0, lint_1.generateForSelf)(this, { start }, 'lonely-apos', message);
|
|
48
48
|
errors.push({
|
|
49
49
|
...refError,
|
|
50
|
+
rule: 'bold-header',
|
|
50
51
|
message: index_1.default.msg('bold in section header'),
|
|
51
52
|
severity: 'warning',
|
|
52
53
|
});
|
|
@@ -39,7 +39,7 @@ class ParamTagToken extends index_2.Token {
|
|
|
39
39
|
return str && !(i >= 0 ? /^[a-z]+(?:\[\])?\s*(?:=|$)/iu : /^[a-z]+(?:\[\])?\s*=/iu).test(str);
|
|
40
40
|
}).map(child => {
|
|
41
41
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
42
|
-
return (0, lint_1.generateForChild)(child, rect, index_1.default.msg('invalid parameter of <$1>', this.name));
|
|
42
|
+
return (0, lint_1.generateForChild)(child, rect, 'no-ignored', index_1.default.msg('invalid parameter of <$1>', this.name));
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
}
|
package/dist/src/parameter.js
CHANGED
|
@@ -60,7 +60,7 @@ class ParameterToken extends index_2.Token {
|
|
|
60
60
|
/https?:\/\/(?:\[[\da-f:.]+\]|[^[\]<>"\t\n\p{Zs}])(?:[^[\]<>"\0\t\n\p{Zs}]|\0\d+c\x7F)*$/iu;
|
|
61
61
|
const errors = super.lint(start), { firstChild } = this, link = new RegExp(`https?://${string_1.extUrlCharFirst}${string_1.extUrlChar}$`, 'iu').exec(firstChild.text())?.[0];
|
|
62
62
|
if (link && new URL(link).search) {
|
|
63
|
-
const e = (0, lint_1.generateForChild)(firstChild, { start }, 'unescaped query string in an anonymous parameter');
|
|
63
|
+
const e = (0, lint_1.generateForChild)(firstChild, { start }, 'unescaped', 'unescaped query string in an anonymous parameter');
|
|
64
64
|
errors.push({
|
|
65
65
|
...e,
|
|
66
66
|
startIndex: e.endIndex,
|
package/dist/src/table/index.js
CHANGED
|
@@ -28,7 +28,7 @@ class TableToken extends trBase_1.TrBaseToken {
|
|
|
28
28
|
lint(start = this.getAbsoluteIndex()) {
|
|
29
29
|
const errors = super.lint(start);
|
|
30
30
|
if (!this.closed) {
|
|
31
|
-
errors.push((0, lint_1.generateForChild)(this.firstChild, { start }, index_1.default.msg('unclosed $1', 'table')));
|
|
31
|
+
errors.push((0, lint_1.generateForChild)(this.firstChild, { start }, 'unclosed-table', index_1.default.msg('unclosed $1', 'table')));
|
|
32
32
|
}
|
|
33
33
|
return errors;
|
|
34
34
|
}
|
package/dist/src/table/td.js
CHANGED
|
@@ -81,7 +81,7 @@ class TdToken extends base_1.TableBaseToken {
|
|
|
81
81
|
if (child.type === 'text') {
|
|
82
82
|
const { data } = child;
|
|
83
83
|
if (data.includes('|')) {
|
|
84
|
-
errors.push((0, lint_1.generateForChild)(child, { start }, 'additional "|" in a table cell', data.includes('||') ? 'error' : 'warning'));
|
|
84
|
+
errors.push((0, lint_1.generateForChild)(child, { start }, 'pipe-like', 'additional "|" in a table cell', data.includes('||') ? 'error' : 'warning'));
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
}
|
package/dist/src/table/trBase.js
CHANGED
|
@@ -26,7 +26,7 @@ class TrBaseToken extends base_1.TableBaseToken {
|
|
|
26
26
|
}
|
|
27
27
|
catch { }
|
|
28
28
|
}
|
|
29
|
-
const error = (0, lint_1.generateForChild)(inter, { start }, 'content to be moved out from the table');
|
|
29
|
+
const error = (0, lint_1.generateForChild)(inter, { start }, 'fostered-content', 'content to be moved out from the table');
|
|
30
30
|
errors.push({
|
|
31
31
|
...error,
|
|
32
32
|
severity: first.type === 'template' ? 'warning' : 'error',
|
package/dist/src/tagPair/ext.js
CHANGED
|
@@ -124,11 +124,11 @@ class ExtToken extends index_3.TagPairToken {
|
|
|
124
124
|
let rect;
|
|
125
125
|
if (this.name !== 'nowiki' && this.closest('html-attrs, table-attrs')) {
|
|
126
126
|
rect = { start, ...this.getRootNode().posFromIndex(start) };
|
|
127
|
-
errors.push((0, lint_1.generateForSelf)(this, rect, 'extension tag in HTML tag attributes'));
|
|
127
|
+
errors.push((0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'extension tag in HTML tag attributes'));
|
|
128
128
|
}
|
|
129
129
|
if (this.name === 'ref' && this.closest('heading-title')) {
|
|
130
130
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
131
|
-
errors.push((0, lint_1.generateForSelf)(this, rect, 'variable anchor in a section header'));
|
|
131
|
+
errors.push((0, lint_1.generateForSelf)(this, rect, 'var-anchor', 'variable anchor in a section header'));
|
|
132
132
|
}
|
|
133
133
|
return errors;
|
|
134
134
|
}
|
|
@@ -22,7 +22,9 @@ class IncludeToken extends (0, hidden_1.hiddenToken)(index_2.TagPairToken) {
|
|
|
22
22
|
}
|
|
23
23
|
/** @override */
|
|
24
24
|
lint(start = this.getAbsoluteIndex()) {
|
|
25
|
-
return this.closed
|
|
25
|
+
return this.closed
|
|
26
|
+
? []
|
|
27
|
+
: [(0, lint_1.generateForSelf)(this, { start }, 'unclosed-comment', index_1.default.msg('unclosed $1', `<${this.name}>`))];
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
30
|
exports.IncludeToken = IncludeToken;
|
package/dist/src/transclude.js
CHANGED
|
@@ -166,21 +166,21 @@ class TranscludeToken extends index_2.Token {
|
|
|
166
166
|
const title = this.#getTitle();
|
|
167
167
|
if (title.fragment !== undefined) {
|
|
168
168
|
rect = { start, ...this.getRootNode().posFromIndex(start) };
|
|
169
|
-
errors.push((0, lint_1.generateForChild)(childNodes[type === 'template' ? 0 : 1], rect, 'useless fragment'));
|
|
169
|
+
errors.push((0, lint_1.generateForChild)(childNodes[type === 'template' ? 0 : 1], rect, 'no-ignored', 'useless fragment'));
|
|
170
170
|
}
|
|
171
171
|
if (!title.valid) {
|
|
172
172
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
173
|
-
errors.push((0, lint_1.generateForChild)(childNodes[1], rect, 'illegal module name'));
|
|
173
|
+
errors.push((0, lint_1.generateForChild)(childNodes[1], rect, 'invalid-invoke', 'illegal module name'));
|
|
174
174
|
}
|
|
175
175
|
if (type === 'magic-word' && length === 2) {
|
|
176
176
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
177
|
-
errors.push((0, lint_1.generateForSelf)(this, rect, 'missing module function'));
|
|
177
|
+
errors.push((0, lint_1.generateForSelf)(this, rect, 'invalid-invoke', 'missing module function'));
|
|
178
178
|
return errors;
|
|
179
179
|
}
|
|
180
180
|
const duplicatedArgs = this.getDuplicatedArgs();
|
|
181
181
|
if (duplicatedArgs.length > 0) {
|
|
182
182
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
183
|
-
errors.push(...duplicatedArgs.flatMap(([, args]) => args).map(arg => (0, lint_1.generateForChild)(arg, rect, 'duplicated parameter')));
|
|
183
|
+
errors.push(...duplicatedArgs.flatMap(([, args]) => args).map(arg => (0, lint_1.generateForChild)(arg, rect, 'no-duplicate', 'duplicated parameter')));
|
|
184
184
|
}
|
|
185
185
|
return errors;
|
|
186
186
|
}
|
package/dist/util/lint.js
CHANGED
|
@@ -6,9 +6,10 @@ const index_1 = require("../index");
|
|
|
6
6
|
* 生成lint函数
|
|
7
7
|
* @param func lint函数
|
|
8
8
|
*/
|
|
9
|
-
const factory = (func) => (token, boundingRect, msg, severity = 'error') => {
|
|
9
|
+
const factory = (func) => (token, boundingRect, rule, msg, severity = 'error') => {
|
|
10
10
|
const { start } = boundingRect, { top, left } = 'top' in boundingRect ? boundingRect : token.getRootNode().posFromIndex(start), { offsetHeight, offsetWidth } = token, { startIndex, startLine, startCol } = func(token, start, top, left);
|
|
11
11
|
return {
|
|
12
|
+
rule,
|
|
12
13
|
message: index_1.default.msg(msg),
|
|
13
14
|
severity,
|
|
14
15
|
startIndex,
|