wikilint 2.21.0 → 2.21.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 +1 -0
- package/config/minimum.json +1 -0
- package/config/moegirl.json +1 -0
- package/dist/parser/list.js +2 -2
- package/dist/src/attribute.js +27 -15
- package/dist/src/attributes.js +6 -1
- package/dist/src/converterFlags.js +7 -4
- package/dist/src/heading.js +3 -3
- package/dist/src/html.js +6 -4
- package/dist/src/index.js +9 -1
- package/dist/src/link/galleryImage.d.ts +1 -0
- package/dist/src/link/galleryImage.js +8 -2
- package/dist/src/magicLink.js +18 -10
- package/dist/src/nowiki/index.d.ts +1 -0
- package/dist/src/nowiki/index.js +7 -2
- package/dist/src/table/trBase.js +1 -29
- package/dist/src/tagPair/ext.js +5 -2
- package/dist/util/lint.js +30 -1
- package/package.json +3 -5
package/config/default.json
CHANGED
package/config/minimum.json
CHANGED
package/config/moegirl.json
CHANGED
package/dist/parser/list.js
CHANGED
|
@@ -40,7 +40,7 @@ const parseList = (wikitext, state, config, accum) => {
|
|
|
40
40
|
if (!dt) {
|
|
41
41
|
return text;
|
|
42
42
|
}
|
|
43
|
-
const { html: [normalTags] } = config, fullRegex = /:+|-\{|\0\d+[xq]\x7F/gu;
|
|
43
|
+
const { html: [normalTags, , voidTags] } = config, fullRegex = /:+|-\{|\0\d+[xq]\x7F/gu;
|
|
44
44
|
let regex = fullRegex, ex = regex.exec(text), lt = 0, lb = false, li = false, lc = 0;
|
|
45
45
|
/**
|
|
46
46
|
* 创建`DdToken`
|
|
@@ -84,7 +84,7 @@ const parseList = (wikitext, state, config, accum) => {
|
|
|
84
84
|
}
|
|
85
85
|
else if (syntax.endsWith('x\x7F')) {
|
|
86
86
|
const { name, closing, selfClosing } = accum[Number(syntax.slice(1, -2))];
|
|
87
|
-
if (!selfClosing
|
|
87
|
+
if (normalTags.includes(name) || !selfClosing && !voidTags.includes(name)) {
|
|
88
88
|
update(closing);
|
|
89
89
|
}
|
|
90
90
|
}
|
package/dist/src/attribute.js
CHANGED
|
@@ -96,17 +96,13 @@ class AttributeToken extends index_2.Token {
|
|
|
96
96
|
getGaps() {
|
|
97
97
|
return this.#equal ? this.#equal.length + (this.#quotes[0]?.length ?? 0) : 0;
|
|
98
98
|
}
|
|
99
|
-
/**
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
e.suggestions = [{ range: [e.endIndex, e.endIndex], text: this.#quotes[0], desc: 'close' }];
|
|
107
|
-
errors.push(e);
|
|
108
|
-
}
|
|
109
|
-
const attrs = sharable_1.extAttrs[tag], attrs2 = sharable_1.htmlAttrs[tag], { length } = this.toString();
|
|
99
|
+
/**
|
|
100
|
+
* 判定无效的属性名或值
|
|
101
|
+
* @param start 起始位置
|
|
102
|
+
* @param rect 位置
|
|
103
|
+
*/
|
|
104
|
+
#lint(start, rect) {
|
|
105
|
+
const { firstChild, lastChild, type, name, tag } = this, value = this.getValue(), attrs = sharable_1.extAttrs[tag], attrs2 = sharable_1.htmlAttrs[tag], { length } = this.toString();
|
|
110
106
|
if (!attrs?.has(name)
|
|
111
107
|
&& !attrs2?.has(name)
|
|
112
108
|
// 不是未定义的扩展标签或包含嵌入的HTML标签
|
|
@@ -116,10 +112,10 @@ class AttributeToken extends index_2.Token {
|
|
|
116
112
|
&& (tag === 'meta' || tag === 'link' || !sharable_1.commonHtmlAttrs.has(name)))) {
|
|
117
113
|
const e = (0, lint_1.generateForChild)(firstChild, rect, 'illegal-attr', 'illegal attribute name');
|
|
118
114
|
e.suggestions = [{ desc: 'remove', range: [start, start + length], text: '' }];
|
|
119
|
-
|
|
115
|
+
return e;
|
|
120
116
|
}
|
|
121
117
|
else if (name === 'style' && typeof value === 'string' && insecureStyle.test(value)) {
|
|
122
|
-
|
|
118
|
+
return (0, lint_1.generateForChild)(lastChild, rect, 'insecure-style', 'insecure style');
|
|
123
119
|
}
|
|
124
120
|
else if (name === 'tabindex' && typeof value === 'string' && value !== '0') {
|
|
125
121
|
const e = (0, lint_1.generateForChild)(lastChild, rect, 'illegal-attr', 'nonzero tabindex');
|
|
@@ -127,14 +123,30 @@ class AttributeToken extends index_2.Token {
|
|
|
127
123
|
{ desc: 'remove', range: [start, start + length], text: '' },
|
|
128
124
|
{ desc: '0 tabindex', range: [e.startIndex, e.endIndex], text: '0' },
|
|
129
125
|
];
|
|
130
|
-
|
|
126
|
+
return e;
|
|
131
127
|
}
|
|
132
128
|
else if (type !== 'ext-attr' && !lastChild.childNodes.some(({ type: t }) => complexTypes.has(t))) {
|
|
133
129
|
const data = (0, lint_1.provideValues)(tag, name), v = String(value).toLowerCase();
|
|
134
130
|
if (data.length > 0 && data.every(n => n !== v)) {
|
|
135
|
-
|
|
131
|
+
return (0, lint_1.generateForChild)(lastChild, rect, 'illegal-attr', 'illegal attribute value', 'warning');
|
|
136
132
|
}
|
|
137
133
|
}
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
/** @private */
|
|
137
|
+
lint(start = this.getAbsoluteIndex(), re) {
|
|
138
|
+
const errors = super.lint(start, re), { balanced, firstChild, lastChild, name, tag } = this, rect = new rect_1.BoundingRect(this, start);
|
|
139
|
+
if (!balanced) {
|
|
140
|
+
const e = (0, lint_1.generateForChild)(lastChild, rect, 'unclosed-quote', index_1.default.msg('unclosed $1', 'quotes'), 'warning');
|
|
141
|
+
e.startIndex--;
|
|
142
|
+
e.startCol--;
|
|
143
|
+
e.suggestions = [{ range: [e.endIndex, e.endIndex], text: this.#quotes[0], desc: 'close' }];
|
|
144
|
+
errors.push(e);
|
|
145
|
+
}
|
|
146
|
+
const e = this.#lint(start, rect);
|
|
147
|
+
if (e) {
|
|
148
|
+
errors.push(e);
|
|
149
|
+
}
|
|
138
150
|
if (sharable_1.obsoleteAttrs[tag]?.has(name)) {
|
|
139
151
|
errors.push((0, lint_1.generateForChild)(firstChild, rect, 'obsolete-attr', 'obsolete attribute', 'warning'));
|
|
140
152
|
}
|
package/dist/src/attributes.js
CHANGED
|
@@ -114,10 +114,15 @@ class AttributesToken extends index_2.Token {
|
|
|
114
114
|
getAttr(key) {
|
|
115
115
|
return this.getAttrToken(key)?.getValue();
|
|
116
116
|
}
|
|
117
|
+
/** 是否位于闭合标签内 */
|
|
118
|
+
#lint() {
|
|
119
|
+
const { parentNode } = this;
|
|
120
|
+
return parentNode?.type === 'html' && parentNode.closing && this.text().trim() !== '';
|
|
121
|
+
}
|
|
117
122
|
/** @private */
|
|
118
123
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
119
124
|
const errors = super.lint(start, re), { parentNode, childNodes } = this, attrs = new Map(), duplicated = new Set(), rect = new rect_1.BoundingRect(this, start);
|
|
120
|
-
if (
|
|
125
|
+
if (this.#lint()) {
|
|
121
126
|
const e = (0, lint_1.generateForSelf)(this, rect, 'no-ignored', 'attributes of a closing tag'), index = parentNode.getAbsoluteIndex();
|
|
122
127
|
e.suggestions = [
|
|
123
128
|
{ desc: 'remove', range: [start, e.endIndex], text: '' },
|
|
@@ -102,6 +102,12 @@ let ConverterFlagsToken = (() => {
|
|
|
102
102
|
return new Set(this.#flags.filter(flag => variants.has(flag)));
|
|
103
103
|
}
|
|
104
104
|
/** @private */
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/class-methods-use-this
|
|
106
|
+
isInvalidFlag(flag, variant, unknown, valid) {
|
|
107
|
+
// @ts-expect-error flag is string
|
|
108
|
+
return Boolean(flag) && !variant.has(flag) && !unknown.has(flag) && (variant.size > 0 || !valid.has(flag));
|
|
109
|
+
}
|
|
110
|
+
/** @private */
|
|
105
111
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
106
112
|
const variantFlags = this.getVariantFlags(), unknownFlags = this.getUnknownFlags(), validFlags = new Set(this.#flags.filter(flag => definedFlags.has(flag))), emptyFlagCount = this.#flags.filter(flag => !flag).length, knownFlagCount = this.#flags.length - unknownFlags.size - emptyFlagCount, errors = super.lint(start, re);
|
|
107
113
|
if (variantFlags.size === knownFlagCount || validFlags.size === knownFlagCount) {
|
|
@@ -110,10 +116,7 @@ let ConverterFlagsToken = (() => {
|
|
|
110
116
|
const rect = new rect_1.BoundingRect(this, start);
|
|
111
117
|
for (let i = 0; i < this.length; i++) {
|
|
112
118
|
const child = this.childNodes[i], flag = child.text().trim();
|
|
113
|
-
if (flag
|
|
114
|
-
&& !variantFlags.has(flag)
|
|
115
|
-
&& !unknownFlags.has(flag)
|
|
116
|
-
&& (variantFlags.size > 0 || !validFlags.has(flag))) {
|
|
119
|
+
if (this.isInvalidFlag(flag, variantFlags, unknownFlags, validFlags)) {
|
|
117
120
|
const e = (0, lint_1.generateForChild)(child, rect, 'no-ignored', 'invalid conversion flag');
|
|
118
121
|
if (variantFlags.size === 0 && definedFlags.has(flag.toUpperCase())) {
|
|
119
122
|
e.fix = { range: [e.startIndex, e.endIndex], text: flag.toUpperCase(), desc: 'uppercase' };
|
package/dist/src/heading.js
CHANGED
|
@@ -62,7 +62,7 @@ class HeadingToken extends index_2.Token {
|
|
|
62
62
|
}
|
|
63
63
|
/** @private */
|
|
64
64
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
65
|
-
const errors = super.lint(start, re), { firstChild, level } = this, innerStr = firstChild.toString(), unbalancedStart = innerStr.startsWith('='), unbalanced = unbalancedStart || innerStr.endsWith('='), quotes = firstChild.childNodes.filter((0, debug_1.isToken)('quote')), boldQuotes = quotes.filter(({ bold }) => bold), italicQuotes = quotes.filter(({ italic }) => italic), rect = new rect_1.BoundingRect(this, start);
|
|
65
|
+
const errors = super.lint(start, re), { firstChild, level } = this, innerStr = firstChild.toString(), unbalancedStart = innerStr.startsWith('='), unbalanced = unbalancedStart || innerStr.endsWith('='), quotes = firstChild.childNodes.filter((0, debug_1.isToken)('quote')), boldQuotes = quotes.filter(({ bold }) => bold), italicQuotes = quotes.filter(({ italic }) => italic), rect = new rect_1.BoundingRect(this, start), s = this.inHtmlAttrs();
|
|
66
66
|
if (this.level === 1) {
|
|
67
67
|
const e = (0, lint_1.generateForChild)(firstChild, rect, 'h1', '<h1>');
|
|
68
68
|
if (!unbalanced) {
|
|
@@ -91,8 +91,8 @@ class HeadingToken extends index_2.Token {
|
|
|
91
91
|
}
|
|
92
92
|
errors.push(e);
|
|
93
93
|
}
|
|
94
|
-
if (
|
|
95
|
-
errors.push((0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'section header in an HTML tag'));
|
|
94
|
+
if (s) {
|
|
95
|
+
errors.push((0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'section header in an HTML tag', s));
|
|
96
96
|
}
|
|
97
97
|
const rootStr = this.getRootNode().toString();
|
|
98
98
|
if (boldQuotes.length % 2) {
|
package/dist/src/html.js
CHANGED
|
@@ -134,15 +134,17 @@ let HtmlToken = (() => {
|
|
|
134
134
|
}
|
|
135
135
|
/** @private */
|
|
136
136
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
137
|
-
const errors = super.lint(start, re), { name, parentNode, closing, selfClosing } = this, rect = new rect_1.BoundingRect(this, start);
|
|
137
|
+
const errors = super.lint(start, re), { name, parentNode, closing, selfClosing } = this, rect = new rect_1.BoundingRect(this, start), s = this.inTableAttrs();
|
|
138
138
|
if (name === 'h1' && !closing) {
|
|
139
139
|
const e = (0, lint_1.generateForSelf)(this, rect, 'h1', '<h1>');
|
|
140
140
|
e.suggestions = [{ desc: 'h2', range: [start + 2, start + 3], text: '2' }];
|
|
141
141
|
errors.push(e);
|
|
142
142
|
}
|
|
143
|
-
if (
|
|
144
|
-
const e = (0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'HTML tag in table attributes');
|
|
145
|
-
|
|
143
|
+
if (s) {
|
|
144
|
+
const e = (0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'HTML tag in table attributes', s);
|
|
145
|
+
if (s === 'error') {
|
|
146
|
+
e.fix = { desc: 'remove', range: [start, e.endIndex], text: '' };
|
|
147
|
+
}
|
|
146
148
|
errors.push(e);
|
|
147
149
|
}
|
|
148
150
|
if (obsoleteTags.has(name)) {
|
package/dist/src/index.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// 6. 内链,含文件和分类,参见Parser::handleInternalLinks2
|
|
12
12
|
// 7. `'`,参见Parser::doQuotes
|
|
13
13
|
// 8. 外链,参见Parser::handleExternalLinks
|
|
14
|
-
// 9. ISBN、RFC
|
|
14
|
+
// 9. ISBN、RFC和自由外链,参见Parser::handleMagicLinks
|
|
15
15
|
// 10. 段落和列表,参见BlockLevelPass::execute
|
|
16
16
|
// 11. 转换,参见LanguageConverter::recursiveConvertTopLevel
|
|
17
17
|
// \0\d+.\x7F标记Token:
|
|
@@ -354,6 +354,14 @@ class Token extends element_1.AstElement {
|
|
|
354
354
|
return index_1.default.normalizeTitle(title, defaultNs, this.#include, this.#config, opt);
|
|
355
355
|
}
|
|
356
356
|
/** @private */
|
|
357
|
+
inTableAttrs() {
|
|
358
|
+
return this.closest('table-attrs,ext')?.type === 'table-attrs' && (this.closest('table-attrs,arg,magic-word,template')?.type === 'table-attrs' ? 'error' : 'warning');
|
|
359
|
+
}
|
|
360
|
+
/** @private */
|
|
361
|
+
inHtmlAttrs() {
|
|
362
|
+
return this.closest('html-attrs,ext')?.type === 'html-attrs' ? 'error' : this.inTableAttrs();
|
|
363
|
+
}
|
|
364
|
+
/** @private */
|
|
357
365
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
358
366
|
let errors = super.lint(start, re);
|
|
359
367
|
if (this.type === 'root') {
|
|
@@ -89,10 +89,16 @@ let GalleryImageToken = (() => {
|
|
|
89
89
|
const imagemap = this.type === 'imagemap-image';
|
|
90
90
|
return this.normalizeTitle(this.firstChild.toString(), imagemap ? 0 : 6, { halfParsed: true, temporary, decode: !imagemap });
|
|
91
91
|
}
|
|
92
|
+
/** 判定无效的图片 */
|
|
93
|
+
#lint() {
|
|
94
|
+
const { ns, } = this.getAttribute('title');
|
|
95
|
+
// eslint-disable-next-line @stylistic/semi
|
|
96
|
+
return ns !== 6;
|
|
97
|
+
}
|
|
92
98
|
/** @private */
|
|
93
99
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
94
|
-
const errors = super.lint(start, re)
|
|
95
|
-
if (
|
|
100
|
+
const errors = super.lint(start, re);
|
|
101
|
+
if (this.#lint()) {
|
|
96
102
|
const e = (0, lint_1.generateForSelf)(this, { start }, 'invalid-gallery', 'invalid gallery image');
|
|
97
103
|
e.suggestions = [{ desc: 'prefix', range: [start, start], text: 'File:' }];
|
|
98
104
|
errors.push(e);
|
package/dist/src/magicLink.js
CHANGED
|
@@ -53,19 +53,27 @@ class MagicLinkToken extends index_2.Token {
|
|
|
53
53
|
super(url, config, accum, {});
|
|
54
54
|
this.#type = type;
|
|
55
55
|
}
|
|
56
|
-
/**
|
|
57
|
-
lint(
|
|
58
|
-
|
|
59
|
-
if (type === 'magic-link') {
|
|
56
|
+
/** 判定无效的ISBN */
|
|
57
|
+
#lint() {
|
|
58
|
+
if (this.type === 'magic-link') {
|
|
60
59
|
const { link } = this;
|
|
61
60
|
if (link.startsWith('ISBN')) {
|
|
62
61
|
// eslint-disable-next-line unicorn/no-useless-spread, @typescript-eslint/no-misused-spread
|
|
63
62
|
const digits = [...link.slice(5)].map(s => s === 'X' ? 10 : Number(s));
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
return digits.length === 10
|
|
64
|
+
? digits.reduce((sum, d, i) => sum + d * (10 - i), 0) % 11 !== 0
|
|
65
|
+
: digits.length === 13 && (digits[12] === 10
|
|
66
|
+
|| digits.reduce((sum, d, i) => sum + d * (i % 2 ? 3 : 1), 0) % 10 !== 0);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
/** @private */
|
|
72
|
+
lint(start = this.getAbsoluteIndex(), re) {
|
|
73
|
+
const errors = super.lint(start, re), rect = new rect_1.BoundingRect(this, start), { type, childNodes } = this;
|
|
74
|
+
if (type === 'magic-link') {
|
|
75
|
+
if (this.#lint()) {
|
|
76
|
+
errors.push((0, lint_1.generateForSelf)(this, rect, 'invalid-isbn', 'invalid ISBN'));
|
|
69
77
|
}
|
|
70
78
|
return errors;
|
|
71
79
|
}
|
|
@@ -99,7 +107,7 @@ class MagicLinkToken extends index_2.Token {
|
|
|
99
107
|
.getUrl(articlePath);
|
|
100
108
|
}
|
|
101
109
|
link = link.startsWith('RFC')
|
|
102
|
-
? `https://
|
|
110
|
+
? `https://datatracker.ietf.org/doc/html/rfc${link.slice(4)}`
|
|
103
111
|
: `https://pubmed.ncbi.nlm.nih.gov/${link.slice(5)}`;
|
|
104
112
|
}
|
|
105
113
|
else if (link.startsWith('//')) {
|
|
@@ -7,6 +7,7 @@ import type { AttributesToken, ExtToken } from '../../internal';
|
|
|
7
7
|
* 扩展标签内的纯文字Token
|
|
8
8
|
*/
|
|
9
9
|
export declare abstract class NowikiToken extends NowikiBaseToken {
|
|
10
|
+
#private;
|
|
10
11
|
readonly name: string;
|
|
11
12
|
abstract get nextSibling(): undefined;
|
|
12
13
|
abstract get previousSibling(): AttributesToken | undefined;
|
package/dist/src/nowiki/index.js
CHANGED
|
@@ -19,10 +19,15 @@ class NowikiToken extends base_1.NowikiBaseToken {
|
|
|
19
19
|
get type() {
|
|
20
20
|
return 'ext-inner';
|
|
21
21
|
}
|
|
22
|
+
/** 扩展标签内的无效内容 */
|
|
23
|
+
#lint() {
|
|
24
|
+
const { name, firstChild: { data } } = this;
|
|
25
|
+
return voidExt.has(name) && Boolean(data);
|
|
26
|
+
}
|
|
22
27
|
/** @private */
|
|
23
28
|
lint(start = this.getAbsoluteIndex()) {
|
|
24
|
-
const { name
|
|
25
|
-
if (
|
|
29
|
+
const { name } = this;
|
|
30
|
+
if (this.#lint()) {
|
|
26
31
|
const e = (0, lint_1.generateForSelf)(this, { start }, 'void-ext', index_1.default.msg('nothing should be in <$1>', name));
|
|
27
32
|
e.fix = { range: [start, e.endIndex], text: '', desc: 'empty' };
|
|
28
33
|
return [e];
|
package/dist/src/table/trBase.js
CHANGED
|
@@ -4,34 +4,6 @@ exports.TrBaseToken = void 0;
|
|
|
4
4
|
const lint_1 = require("../../util/lint");
|
|
5
5
|
const base_1 = require("./base");
|
|
6
6
|
const td_1 = require("./td");
|
|
7
|
-
const tableTags = new Set(['tr', 'td', 'th', 'caption']), tableTemplates = new Set(['Template:!!', 'Template:!-']);
|
|
8
|
-
/**
|
|
9
|
-
* Check if the content is fostered
|
|
10
|
-
* @param token
|
|
11
|
-
*/
|
|
12
|
-
const isFostered = (token) => {
|
|
13
|
-
const first = token.childNodes.find(child => child.text().trim());
|
|
14
|
-
if (!first
|
|
15
|
-
|| first.type === 'text' && first.data.trim().startsWith('!')
|
|
16
|
-
|| first.type === 'magic-word' && first.name === '!'
|
|
17
|
-
|| first.type === 'template' && tableTemplates.has(first.name)
|
|
18
|
-
|| first.is('html') && tableTags.has(first.name)) {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
else if (first.is('arg')) {
|
|
22
|
-
return first.length > 1 && isFostered(first.childNodes[1]);
|
|
23
|
-
}
|
|
24
|
-
else if (first.is('magic-word')) {
|
|
25
|
-
try {
|
|
26
|
-
const severity = first.getPossibleValues().map(isFostered);
|
|
27
|
-
return severity.includes('error')
|
|
28
|
-
? 'error'
|
|
29
|
-
: severity.includes('warning') && 'warning';
|
|
30
|
-
}
|
|
31
|
-
catch { }
|
|
32
|
-
}
|
|
33
|
-
return first.type === 'template' || first.type === 'magic-word' && first.name === 'invoke' ? 'warning' : 'error';
|
|
34
|
-
};
|
|
35
7
|
/**
|
|
36
8
|
* table row or table
|
|
37
9
|
*
|
|
@@ -44,7 +16,7 @@ class TrBaseToken extends base_1.TableBaseToken {
|
|
|
44
16
|
if (!inter) {
|
|
45
17
|
return errors;
|
|
46
18
|
}
|
|
47
|
-
const severity = isFostered(inter);
|
|
19
|
+
const severity = (0, lint_1.isFostered)(inter);
|
|
48
20
|
if (!severity) {
|
|
49
21
|
return errors;
|
|
50
22
|
}
|
package/dist/src/tagPair/ext.js
CHANGED
|
@@ -185,8 +185,11 @@ let ExtToken = (() => {
|
|
|
185
185
|
/** @private */
|
|
186
186
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
187
187
|
const errors = super.lint(start, re), rect = new rect_1.BoundingRect(this, start);
|
|
188
|
-
if (this.name !== 'nowiki'
|
|
189
|
-
|
|
188
|
+
if (this.name !== 'nowiki') {
|
|
189
|
+
const s = this.inHtmlAttrs();
|
|
190
|
+
if (s) {
|
|
191
|
+
errors.push((0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'extension tag in HTML tag attributes', s));
|
|
192
|
+
}
|
|
190
193
|
}
|
|
191
194
|
if (this.name === 'ref' && this.closest('heading-title')) {
|
|
192
195
|
errors.push((0, lint_1.generateForSelf)(this, rect, 'var-anchor', 'variable anchor in a section header'));
|
package/dist/util/lint.js
CHANGED
|
@@ -3,10 +3,39 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.provideValues = exports.cache = exports.generateForSelf = exports.generateForChild = exports.getEndPos = void 0;
|
|
6
|
+
exports.provideValues = exports.cache = exports.generateForSelf = exports.generateForChild = exports.getEndPos = exports.isFostered = void 0;
|
|
7
7
|
const debug_1 = require("./debug");
|
|
8
8
|
const rect_1 = require("../lib/rect");
|
|
9
9
|
const index_1 = __importDefault(require("../index"));
|
|
10
|
+
const tableTags = new Set(['tr', 'td', 'th', 'caption']), tableTemplates = new Set(['Template:!!', 'Template:!-']);
|
|
11
|
+
/**
|
|
12
|
+
* Check if the content is fostered
|
|
13
|
+
* @param token
|
|
14
|
+
*/
|
|
15
|
+
const isFostered = (token) => {
|
|
16
|
+
const first = token.childNodes.find(child => child.text().trim());
|
|
17
|
+
if (!first
|
|
18
|
+
|| first.type === 'text' && first.data.trim().startsWith('!')
|
|
19
|
+
|| first.type === 'magic-word' && first.name === '!'
|
|
20
|
+
|| first.type === 'template' && tableTemplates.has(first.name)
|
|
21
|
+
|| first.is('html') && tableTags.has(first.name)) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
else if (first.is('arg')) {
|
|
25
|
+
return first.length > 1 && (0, exports.isFostered)(first.childNodes[1]);
|
|
26
|
+
}
|
|
27
|
+
else if (first.is('magic-word')) {
|
|
28
|
+
try {
|
|
29
|
+
const severity = first.getPossibleValues().map(exports.isFostered);
|
|
30
|
+
return severity.includes('error')
|
|
31
|
+
? 'error'
|
|
32
|
+
: severity.includes('warning') && 'warning';
|
|
33
|
+
}
|
|
34
|
+
catch { }
|
|
35
|
+
}
|
|
36
|
+
return first.type === 'template' || first.type === 'magic-word' && first.name === 'invoke' ? 'warning' : 'error';
|
|
37
|
+
};
|
|
38
|
+
exports.isFostered = isFostered;
|
|
10
39
|
/**
|
|
11
40
|
* 计算结束位置
|
|
12
41
|
* @param top 起始行
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wikilint",
|
|
3
|
-
"version": "2.21.
|
|
3
|
+
"version": "2.21.1",
|
|
4
4
|
"description": "A Node.js linter for MediaWiki markup",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mediawiki",
|
|
@@ -77,14 +77,13 @@
|
|
|
77
77
|
"entities": "^6.0.0",
|
|
78
78
|
"mathjax": "^3.2.2",
|
|
79
79
|
"minimatch": "^10.0.1",
|
|
80
|
-
"stylelint": "^16.
|
|
80
|
+
"stylelint": "^16.20.0",
|
|
81
81
|
"vscode-css-languageservice": "^6.3.4",
|
|
82
82
|
"vscode-html-languageservice": "^5.3.3",
|
|
83
83
|
"vscode-json-languageservice": "^5.4.4"
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
86
|
"@stylistic/eslint-plugin": "^3.1.0",
|
|
87
|
-
"@stylistic/stylelint-plugin": "^3.1.2",
|
|
88
87
|
"@types/color-name": "^2.0.0",
|
|
89
88
|
"@types/color-rgba": "^2.1.3",
|
|
90
89
|
"@types/mocha": "^10.0.10",
|
|
@@ -102,11 +101,10 @@
|
|
|
102
101
|
"eslint-plugin-promise": "^7.2.1",
|
|
103
102
|
"eslint-plugin-regexp": "^2.7.0",
|
|
104
103
|
"eslint-plugin-unicorn": "^56.0.1",
|
|
105
|
-
"http-server": "^14.1.1",
|
|
106
104
|
"mocha": "^11.1.0",
|
|
107
105
|
"nyc": "^17.1.0",
|
|
108
106
|
"typescript": "^5.8.2",
|
|
109
|
-
"v8r": "^
|
|
107
|
+
"v8r": "^5.0.0",
|
|
110
108
|
"vscode-languageserver-textdocument": "^1.0.12"
|
|
111
109
|
},
|
|
112
110
|
"engines": {
|