wikilint 2.28.1 → 2.29.0
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/data/ext/ThirdPartyNotices.txt +33 -0
- package/data/ext/mapframe.json +489 -2
- package/dist/base.d.mts +4 -2
- package/dist/base.d.ts +4 -2
- package/dist/base.js +1 -0
- package/dist/base.mjs +2 -1
- package/dist/bin/config.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +23 -2
- package/dist/lib/document.d.ts +23 -7
- package/dist/lib/document.js +7 -27
- package/dist/lib/element.js +1 -1
- package/dist/lib/lintConfig.js +2 -0
- package/dist/lib/lsp.d.ts +1 -12
- package/dist/lib/lsp.js +41 -75
- package/dist/lib/node.js +23 -20
- package/dist/lib/title.d.ts +3 -1
- package/dist/lib/title.js +37 -9
- package/dist/mixin/elementLike.js +14 -9
- package/dist/parser/commentAndExt.js +30 -26
- package/dist/parser/links.js +4 -3
- package/dist/parser/redirect.js +1 -1
- package/dist/parser/selector.js +6 -8
- package/dist/src/arg.js +2 -2
- package/dist/src/attribute.js +27 -0
- package/dist/src/attributes.js +1 -1
- package/dist/src/converter.js +6 -3
- package/dist/src/imageParameter.d.ts +3 -1
- package/dist/src/imageParameter.js +18 -3
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.js +21 -28
- package/dist/src/link/file.js +7 -7
- package/dist/src/link/galleryImage.js +1 -1
- package/dist/src/link/redirectTarget.js +1 -1
- package/dist/src/multiLine/gallery.js +2 -2
- package/dist/src/multiLine/imagemap.js +3 -4
- package/dist/src/multiLine/paramTag.js +2 -2
- package/dist/src/nowiki/index.js +59 -2
- package/dist/src/table/base.js +1 -2
- package/dist/src/table/index.js +1 -2
- package/dist/src/transclude.js +3 -3
- package/dist/util/constants.js +3 -1
- package/dist/util/debug.js +1 -1
- package/dist/util/search.js +16 -0
- package/dist/util/sharable.js +27 -3
- package/dist/util/sharable.mjs +28 -4
- package/i18n/en.json +2 -0
- package/i18n/zh-hans.json +2 -0
- package/i18n/zh-hant.json +2 -0
- package/package.json +5 -3
- package/data/ext/maplink.json +0 -4
|
@@ -14,16 +14,17 @@ const elementLike = (constructor) => {
|
|
|
14
14
|
this);
|
|
15
15
|
}
|
|
16
16
|
getElementBy(condition) {
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
const stack = [...this.childNodes].reverse();
|
|
18
|
+
while (stack.length > 0) {
|
|
19
|
+
const child = stack.pop(), { type, childNodes } = child;
|
|
20
|
+
if (type === 'text') {
|
|
19
21
|
continue;
|
|
20
22
|
}
|
|
21
23
|
else if (condition(child)) {
|
|
22
24
|
return child;
|
|
23
25
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return descendant;
|
|
26
|
+
for (let i = childNodes.length - 1; i >= 0; i--) {
|
|
27
|
+
stack.push(childNodes[i]);
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
return undefined;
|
|
@@ -31,15 +32,19 @@ const elementLike = (constructor) => {
|
|
|
31
32
|
querySelector(selector) {
|
|
32
33
|
return this.getElementBy(this.#getCondition(selector));
|
|
33
34
|
}
|
|
34
|
-
getElementsBy(condition
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
getElementsBy(condition) {
|
|
36
|
+
const stack = [...this.childNodes].reverse(), descendants = [];
|
|
37
|
+
while (stack.length > 0) {
|
|
38
|
+
const child = stack.pop(), { type, childNodes } = child;
|
|
39
|
+
if (type === 'text') {
|
|
37
40
|
continue;
|
|
38
41
|
}
|
|
39
42
|
else if (condition(child)) {
|
|
40
43
|
descendants.push(child);
|
|
41
44
|
}
|
|
42
|
-
|
|
45
|
+
for (let i = childNodes.length - 1; i >= 0; i--) {
|
|
46
|
+
stack.push(childNodes[i]);
|
|
47
|
+
}
|
|
43
48
|
}
|
|
44
49
|
return descendants;
|
|
45
50
|
}
|
|
@@ -9,9 +9,9 @@ const translate_1 = require("../src/tagPair/translate");
|
|
|
9
9
|
const include_1 = require("../src/tagPair/include");
|
|
10
10
|
const ext_1 = require("../src/tagPair/ext");
|
|
11
11
|
const comment_1 = require("../src/nowiki/comment");
|
|
12
|
-
const onlyincludeLeft = '<onlyinclude>', onlyincludeRight = '</onlyinclude>', { length } = onlyincludeLeft,
|
|
12
|
+
const onlyincludeLeft = '<onlyinclude>', onlyincludeRight = '</onlyinclude>', { length } = onlyincludeLeft, getExtRegex = [false, true].map(includeOnly => {
|
|
13
13
|
const noincludeRegex = includeOnly ? 'includeonly' : '(?:no|only)include', includeRegex = includeOnly ? 'noinclude' : 'includeonly';
|
|
14
|
-
return (0, common_1.
|
|
14
|
+
return (0, common_1.getRegex)(exts => new RegExp(String.raw `<!--[\s\S]*?(?:-->|$)|<${noincludeRegex}(?:\s[^>]*)?/?>|</${noincludeRegex}\s*>|<(${exts // eslint-disable-next-line unicorn/prefer-string-raw
|
|
15
15
|
})(\s[^>]*?)?(?:/>|>([\s\S]*?)</(${'\\1'}\s*)>)|<(${includeRegex})(\s[^>]*?)?(?:/>|>([\s\S]*?)(?:</(${includeRegex}\s*)>|$))`, 'giu'));
|
|
16
16
|
});
|
|
17
17
|
/**
|
|
@@ -76,29 +76,33 @@ const parseCommentAndExt = (wikitext, config, accum, includeOnly) => {
|
|
|
76
76
|
});
|
|
77
77
|
wikitext = (0, string_1.restore)(wikitext, stack);
|
|
78
78
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
79
|
+
const re = getExtRegex[includeOnly ? 1 : 0](newExt.join('|'));
|
|
80
|
+
re.lastIndex = 0;
|
|
81
|
+
return re.test(wikitext)
|
|
82
|
+
? wikitext.replace(re, (substr, name, attr, inner, closing, include, includeAttr, includeInner, includeClosing) => {
|
|
83
|
+
const l = accum.length;
|
|
84
|
+
let ch = 'n';
|
|
85
|
+
if (name) {
|
|
86
|
+
ch = 'e';
|
|
87
|
+
// @ts-expect-error abstract class
|
|
88
|
+
new ext_1.ExtToken(name, attr, inner, closing, newConfig, include, accum);
|
|
89
|
+
}
|
|
90
|
+
else if (substr.startsWith('<!--')) {
|
|
91
|
+
ch = 'c';
|
|
92
|
+
const closed = substr.endsWith('-->');
|
|
93
|
+
// @ts-expect-error abstract class
|
|
94
|
+
new comment_1.CommentToken((0, string_1.restore)(substr, accum, 1).slice(4, closed ? -3 : undefined), closed, config, accum);
|
|
95
|
+
}
|
|
96
|
+
else if (include) {
|
|
97
|
+
// @ts-expect-error abstract class
|
|
98
|
+
new include_1.IncludeToken(include, includeAttr && (0, string_1.restore)(includeAttr, accum, 1), includeInner && (0, string_1.restore)(includeInner, accum, 1), includeClosing, config, accum);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
// @ts-expect-error abstract class
|
|
102
|
+
new noinclude_1.NoincludeToken(substr, config, accum, true);
|
|
103
|
+
}
|
|
104
|
+
return `\0${l}${ch}\x7F`;
|
|
105
|
+
})
|
|
106
|
+
: wikitext;
|
|
103
107
|
};
|
|
104
108
|
exports.parseCommentAndExt = parseCommentAndExt;
|
package/dist/parser/links.js
CHANGED
|
@@ -17,9 +17,10 @@ const regexImg = /^((?:(?!\0\d+!\x7F)[^\n[\]{}|])+)(\||\0\d+!\x7F)([\s\S]*)$/u;
|
|
|
17
17
|
* @param wikitext
|
|
18
18
|
* @param config
|
|
19
19
|
* @param accum
|
|
20
|
+
* @param page 页面名称
|
|
20
21
|
* @param tidy 是否整理链接
|
|
21
22
|
*/
|
|
22
|
-
const parseLinks = (wikitext, config, accum, tidy) => {
|
|
23
|
+
const parseLinks = (wikitext, config, accum, page, tidy) => {
|
|
23
24
|
config.regexLinks ??= new RegExp(String.raw `^\s*(?:${config.protocol}|//)`, 'iu');
|
|
24
25
|
const regex = config.inExt
|
|
25
26
|
? /^((?:(?!\0\d+!\x7F)[^\n[\]{}|])+)(?:(\||\0\d+!\x7F)([\s\S]*?[^\]]))?\]\]([\s\S]*)$/u
|
|
@@ -53,7 +54,7 @@ const parseLinks = (wikitext, config, accum, tidy) => {
|
|
|
53
54
|
s += `[[${x}`;
|
|
54
55
|
continue;
|
|
55
56
|
}
|
|
56
|
-
const { ns, valid, } = index_1.default.normalizeTitle(trimmed, 0, false, config, { halfParsed: true, temporary: true, decode: true, selfLink: true });
|
|
57
|
+
const { ns, valid, } = index_1.default.normalizeTitle(trimmed, 0, false, config, { halfParsed: true, temporary: true, decode: true, selfLink: true, page });
|
|
57
58
|
if (!valid) {
|
|
58
59
|
s += `[[${x}`;
|
|
59
60
|
continue;
|
|
@@ -80,7 +81,7 @@ const parseLinks = (wikitext, config, accum, tidy) => {
|
|
|
80
81
|
break;
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
|
-
text = (0, exports.parseLinks)(text, config, accum, tidy);
|
|
84
|
+
text = (0, exports.parseLinks)(text, config, accum, page, tidy);
|
|
84
85
|
if (!found) {
|
|
85
86
|
s += `[[${link}${delimiter}${text}`;
|
|
86
87
|
continue;
|
package/dist/parser/redirect.js
CHANGED
|
@@ -16,7 +16,7 @@ const parseRedirect = (text, config, accum) => {
|
|
|
16
16
|
config.regexRedirect ??= new RegExp(String.raw `^(\s*)((?:${config.redirection.join('|')})\s*(?::\s*)?)\[\[([^\n|\]]+)(\|.*?)?\]\](\s*)`, 'iu');
|
|
17
17
|
const mt = config.regexRedirect.exec(text);
|
|
18
18
|
if (mt
|
|
19
|
-
&& index_1.default.normalizeTitle(mt[3], 0, false, config, { halfParsed: true, temporary: true, decode: true }).valid) {
|
|
19
|
+
&& index_1.default.normalizeTitle(mt[3], 0, false, config, { halfParsed: true, temporary: true, decode: true, page: '' }).valid) {
|
|
20
20
|
text = `\0${accum.length}o\x7F${text.slice(mt[0].length)}`;
|
|
21
21
|
// @ts-expect-error abstract class
|
|
22
22
|
new redirect_1.RedirectToken(...mt.slice(1), config, accum);
|
package/dist/parser/selector.js
CHANGED
|
@@ -4,15 +4,13 @@ exports.getCondition = void 0;
|
|
|
4
4
|
/**
|
|
5
5
|
* type和name选择器
|
|
6
6
|
* @param selector
|
|
7
|
-
* @param type
|
|
8
|
-
* @param name
|
|
9
7
|
*/
|
|
10
|
-
const basic = (selector
|
|
8
|
+
const basic = (selector) => {
|
|
11
9
|
if (selector.includes('#')) {
|
|
12
|
-
const i = selector.indexOf('#');
|
|
13
|
-
return (i === 0 ||
|
|
10
|
+
const i = selector.indexOf('#'), targetType = selector.slice(0, i), targetName = selector.slice(i + 1);
|
|
11
|
+
return (type, name) => (i === 0 || type === targetType) && name === targetName;
|
|
14
12
|
}
|
|
15
|
-
return
|
|
13
|
+
return selector ? (type) => type === selector : () => true;
|
|
16
14
|
};
|
|
17
15
|
/**
|
|
18
16
|
* 将选择器转化为类型谓词
|
|
@@ -21,7 +19,7 @@ const basic = (selector, type, name) => {
|
|
|
21
19
|
* @param has `:has()`伪选择器
|
|
22
20
|
*/
|
|
23
21
|
const getCondition = (selector, scope, has) => {
|
|
24
|
-
const parts = selector.split(',');
|
|
25
|
-
return (({ type, name }) => parts.some(
|
|
22
|
+
const parts = selector.split(',').map(str => basic(str.trim()));
|
|
23
|
+
return (({ type, name }) => parts.some(condition => condition(type, name)));
|
|
26
24
|
};
|
|
27
25
|
exports.getCondition = getCondition;
|
package/dist/src/arg.js
CHANGED
|
@@ -123,12 +123,12 @@ let ArgToken = (() => {
|
|
|
123
123
|
argDefault.setAttribute('aIndex', index);
|
|
124
124
|
const childErrors = argDefault.lint(index, re);
|
|
125
125
|
if (childErrors.length > 0) {
|
|
126
|
-
|
|
126
|
+
Array.prototype.push.apply(errors, childErrors);
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
const rules = ['no-ignored', 'no-arg'], { lintConfig } = index_1.default, { computeEditInfo } = lintConfig, rect = new rect_1.BoundingRect(this, start), s = rules.map(rule => lintConfig.getSeverity(rule, 'arg'));
|
|
130
130
|
if (s[0] && rest.length > 0) {
|
|
131
|
-
|
|
131
|
+
Array.prototype.push.apply(errors, rest.map(child => {
|
|
132
132
|
const e = (0, lint_1.generateForChild)(child, rect, rules[0], 'invisible-triple-braces', s[0]);
|
|
133
133
|
e.startIndex--;
|
|
134
134
|
e.startCol--;
|
package/dist/src/attribute.js
CHANGED
|
@@ -12,6 +12,8 @@ const rect_1 = require("../lib/rect");
|
|
|
12
12
|
const index_1 = __importDefault(require("../index"));
|
|
13
13
|
const index_2 = require("./index");
|
|
14
14
|
const atom_1 = require("./atom");
|
|
15
|
+
/* NOT FOR BROWSER ONLY */
|
|
16
|
+
const document_1 = require("../lib/document");
|
|
15
17
|
const insecureStyle = /expression|(?:accelerator|-o-link(?:-source)?|-o-replace)\s*:|(?:url|src|image(?:-set)?)\s*\(|attr\s*\([^)]+[\s,]url/u, evil = /(?:^|\s|\*\/)(?:javascript|vbscript)(?:\W|$)/iu, complexTypes = new Set(['ext', 'arg', 'magic-word', 'template']), urlAttrs = new Set([
|
|
16
18
|
'about',
|
|
17
19
|
'property',
|
|
@@ -64,6 +66,7 @@ class AttributeToken extends index_2.Token {
|
|
|
64
66
|
}
|
|
65
67
|
else if (tag === 'gallery' && key === 'caption'
|
|
66
68
|
|| tag === 'ref' && key === 'details'
|
|
69
|
+
|| (tag === 'mapframe' || tag === 'maplink') && key === 'text'
|
|
67
70
|
|| tag === 'choose' && (key === 'before' || key === 'after')) {
|
|
68
71
|
const newConfig = {
|
|
69
72
|
...config,
|
|
@@ -207,6 +210,30 @@ class AttributeToken extends index_2.Token {
|
|
|
207
210
|
if (s[1] && sharable_1.obsoleteAttrs[tag]?.has(name)) {
|
|
208
211
|
errors.push((0, lint_1.generateForChild)(firstChild, rect, rules[1], 'obsolete-attribute', s[1]));
|
|
209
212
|
}
|
|
213
|
+
/* NOT FOR BROWSER ONLY */
|
|
214
|
+
const rule = 'invalid-css', sError = lintConfig.getSeverity(rule), sWarn = lintConfig.getSeverity(rule, 'warn');
|
|
215
|
+
if (document_1.cssLSP
|
|
216
|
+
&& (sError || sWarn)
|
|
217
|
+
&& name === 'style'
|
|
218
|
+
&& lastChild.length === 1 && lastChild.firstChild.type === 'text') {
|
|
219
|
+
const root = this.getRootNode(), textDoc = new document_1.EmbeddedCSSDocument(root, lastChild);
|
|
220
|
+
Array.prototype.push.apply(errors, document_1.cssLSP.doValidation(textDoc, textDoc.styleSheet)
|
|
221
|
+
.filter(({ code, severity }) => code !== 'css-ruleorselectorexpected' && code !== 'emptyRules'
|
|
222
|
+
&& (severity === 1 ? sError : sWarn))
|
|
223
|
+
.map(({ range: { start: { line, character }, end }, message, severity, code }) => ({
|
|
224
|
+
code: code,
|
|
225
|
+
rule,
|
|
226
|
+
message,
|
|
227
|
+
severity: (severity === 1 ? sError : sWarn),
|
|
228
|
+
startLine: line,
|
|
229
|
+
startCol: character,
|
|
230
|
+
startIndex: root.indexFromPos(line, character),
|
|
231
|
+
endLine: end.line,
|
|
232
|
+
endCol: end.character,
|
|
233
|
+
endIndex: root.indexFromPos(end.line, end.character),
|
|
234
|
+
})));
|
|
235
|
+
}
|
|
236
|
+
/* NOT FOR BROWSER ONLY END */
|
|
210
237
|
return errors;
|
|
211
238
|
}
|
|
212
239
|
}
|
package/dist/src/attributes.js
CHANGED
|
@@ -176,7 +176,7 @@ class AttributesToken extends index_2.Token {
|
|
|
176
176
|
const value = attr.getValue();
|
|
177
177
|
return [attr, value === true ? '' : value];
|
|
178
178
|
});
|
|
179
|
-
|
|
179
|
+
Array.prototype.push.apply(errors, pairs.map(([attr, value], i) => {
|
|
180
180
|
const e = (0, lint_1.generateForChild)(attr, rect, rules[1], index_1.default.msg('duplicate-attribute', key), severity);
|
|
181
181
|
if (computeEditInfo || fix) {
|
|
182
182
|
const remove = (0, lint_1.fixByRemove)(e);
|
package/dist/src/converter.js
CHANGED
|
@@ -83,9 +83,12 @@ let ConverterToken = (() => {
|
|
|
83
83
|
new converterRule_1.ConverterRuleToken(rules.join(';'), false, config, accum));
|
|
84
84
|
}
|
|
85
85
|
else {
|
|
86
|
-
this.
|
|
87
|
-
|
|
88
|
-
.
|
|
86
|
+
this.safeAppend([
|
|
87
|
+
firstRuleToken,
|
|
88
|
+
...rules.slice(1)
|
|
89
|
+
// @ts-expect-error abstract class
|
|
90
|
+
.map((rule) => new converterRule_1.ConverterRuleToken(rule, true, config, accum)),
|
|
91
|
+
]);
|
|
89
92
|
}
|
|
90
93
|
}
|
|
91
94
|
/** @private */
|
|
@@ -2,7 +2,7 @@ import { Token } from './index';
|
|
|
2
2
|
import type { LintError, Config } from '../base';
|
|
3
3
|
import type { Title } from '../lib/title';
|
|
4
4
|
import type { AtomToken, FileToken } from '../internal';
|
|
5
|
-
export declare const galleryParams: Set<string>;
|
|
5
|
+
export declare const galleryParams: Set<string>, extensions: Set<string>;
|
|
6
6
|
/**
|
|
7
7
|
* image parameter
|
|
8
8
|
*
|
|
@@ -15,6 +15,8 @@ export declare abstract class ImageParameterToken extends Token {
|
|
|
15
15
|
abstract get nextSibling(): this | undefined;
|
|
16
16
|
abstract get previousSibling(): AtomToken | this | undefined;
|
|
17
17
|
get type(): 'image-parameter';
|
|
18
|
+
/** thumbnail / 缩略图 */
|
|
19
|
+
get thumb(): Title | undefined;
|
|
18
20
|
/** image link / 图片链接 */
|
|
19
21
|
get link(): string | Title | undefined;
|
|
20
22
|
/** @param str 图片参数 */
|
|
@@ -3,7 +3,7 @@ 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.ImageParameterToken = exports.galleryParams = void 0;
|
|
6
|
+
exports.ImageParameterToken = exports.extensions = exports.galleryParams = void 0;
|
|
7
7
|
const common_1 = require("@bhsd/common");
|
|
8
8
|
const string_1 = require("../util/string");
|
|
9
9
|
const lint_1 = require("../util/lint");
|
|
@@ -14,7 +14,7 @@ const index_2 = require("./index");
|
|
|
14
14
|
const getUrlLikeRegex = (0, common_1.getRegex)(protocol => new RegExp(String.raw `^(?:${protocol}|//|\0\d+m\x7F)`, 'iu'));
|
|
15
15
|
const getUrlRegex = (0, common_1.getRegex)(protocol => new RegExp(String.raw `^(?:(?:${protocol}|//)${string_1.extUrlCharFirst}|\0\d+m\x7F)${string_1.extUrlChar}$`, 'iu'));
|
|
16
16
|
const getSyntaxRegex = (0, common_1.getRegex)(syntax => new RegExp(String.raw `^(\s*(?!\s))${syntax.replace('$1', '(.*)')}${syntax.endsWith('$1') ? '(?=$|\n)' : ''}(\s*)$`, 'u'));
|
|
17
|
-
exports.galleryParams = new Set(['alt', 'link', 'lang', 'page', 'caption']);
|
|
17
|
+
exports.galleryParams = new Set(['alt', 'link', 'lang', 'page', 'caption']), exports.extensions = new Set(['tiff', 'tif', 'png', 'gif', 'jpg', 'jpeg', 'webp', 'xcf', 'pdf', 'svg', 'djvu']);
|
|
18
18
|
/**
|
|
19
19
|
* 获取网址
|
|
20
20
|
* @param link 外链
|
|
@@ -44,7 +44,7 @@ function validate(key, val, config, halfParsed, ext) {
|
|
|
44
44
|
else if (value.startsWith('[[') && value.endsWith(']]')) {
|
|
45
45
|
value = value.slice(2, -2);
|
|
46
46
|
}
|
|
47
|
-
const title = index_1.default.normalizeTitle(value, 0, false, config, { halfParsed, decode: true, selfLink: true });
|
|
47
|
+
const title = index_1.default.normalizeTitle(value, 0, false, config, { halfParsed, decode: true, selfLink: true, page: '' });
|
|
48
48
|
return title.valid && title;
|
|
49
49
|
}
|
|
50
50
|
case 'lang':
|
|
@@ -70,6 +70,12 @@ class ImageParameterToken extends index_2.Token {
|
|
|
70
70
|
get type() {
|
|
71
71
|
return 'image-parameter';
|
|
72
72
|
}
|
|
73
|
+
/** thumbnail / 缩略图 */
|
|
74
|
+
get thumb() {
|
|
75
|
+
LINT: return this.name === 'manualthumb' // eslint-disable-line no-unused-labels
|
|
76
|
+
? this.normalizeTitle(`File:${super.text().trim()}`, 6, { page: '' })
|
|
77
|
+
: undefined;
|
|
78
|
+
}
|
|
73
79
|
/** image link / 图片链接 */
|
|
74
80
|
get link() {
|
|
75
81
|
LINT: { // eslint-disable-line no-unused-labels
|
|
@@ -183,6 +189,15 @@ class ImageParameterToken extends index_2.Token {
|
|
|
183
189
|
}
|
|
184
190
|
}
|
|
185
191
|
}
|
|
192
|
+
else if (name === 'manualthumb') {
|
|
193
|
+
const rule = 'invalid-gallery', s = lintConfig.getSeverity(rule, 'thumb');
|
|
194
|
+
if (s && !this.querySelector('arg,magic-word,template')) {
|
|
195
|
+
const { valid, ns, extension, } = this.thumb;
|
|
196
|
+
if (!valid || ns !== 6 || !exports.extensions.has(extension)) {
|
|
197
|
+
errors.push((0, lint_1.generateForSelf)(this, { start }, rule, 'invalid-thumb', s));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
186
201
|
return errors;
|
|
187
202
|
}
|
|
188
203
|
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -17,6 +17,14 @@ export declare class Token extends AstElement {
|
|
|
17
17
|
#private;
|
|
18
18
|
get type(): TokenTypes;
|
|
19
19
|
set type(value: TokenTypes);
|
|
20
|
+
/**
|
|
21
|
+
* page name
|
|
22
|
+
*
|
|
23
|
+
* 页面名称
|
|
24
|
+
* @since v1.29.0
|
|
25
|
+
*/
|
|
26
|
+
get pageName(): string | undefined;
|
|
27
|
+
set pageName(value: string | undefined);
|
|
20
28
|
/** @class */
|
|
21
29
|
constructor(wikitext?: string, config?: Parser.Config, accum?: Token[], acceptable?: WikiParserAcceptable);
|
|
22
30
|
/**
|
package/dist/src/index.js
CHANGED
|
@@ -55,9 +55,6 @@ const debug_1 = require("../util/debug");
|
|
|
55
55
|
const index_1 = __importDefault(require("../index"));
|
|
56
56
|
const element_1 = require("../lib/element");
|
|
57
57
|
const text_1 = require("../lib/text");
|
|
58
|
-
/* NOT FOR BROWSER ONLY */
|
|
59
|
-
const document_1 = require("../lib/document");
|
|
60
|
-
const lsp_1 = require("../lib/lsp");
|
|
61
58
|
const lintSelectors = ['category', 'html-attr#id,ext-attr#id,table-attr#id'];
|
|
62
59
|
/**
|
|
63
60
|
* base class for all tokens
|
|
@@ -75,12 +72,31 @@ class Token extends element_1.AstElement {
|
|
|
75
72
|
#include;
|
|
76
73
|
#built = false;
|
|
77
74
|
#string;
|
|
75
|
+
#pageName;
|
|
78
76
|
get type() {
|
|
79
77
|
return this.#type;
|
|
80
78
|
}
|
|
81
79
|
set type(value) {
|
|
82
80
|
this.#type = value;
|
|
83
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* page name
|
|
84
|
+
*
|
|
85
|
+
* 页面名称
|
|
86
|
+
* @since v1.29.0
|
|
87
|
+
*/
|
|
88
|
+
get pageName() {
|
|
89
|
+
return this.getRootNode().#pageName;
|
|
90
|
+
}
|
|
91
|
+
set pageName(value) {
|
|
92
|
+
if (value) {
|
|
93
|
+
const title = this.normalizeTitle(value, 0, { temporary: true, page: '' });
|
|
94
|
+
this.#pageName = title.valid ? title.title : undefined;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
this.#pageName = value === '' ? '' : undefined;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
84
100
|
/** @class */
|
|
85
101
|
constructor(wikitext, config = index_1.default.getConfig(), accum = [], acceptable) {
|
|
86
102
|
super();
|
|
@@ -255,7 +271,7 @@ class Token extends element_1.AstElement {
|
|
|
255
271
|
*/
|
|
256
272
|
#parseLinks(tidy) {
|
|
257
273
|
const { parseLinks } = require('../parser/links');
|
|
258
|
-
this.setText(parseLinks(this.firstChild.toString(), this.#config, this.#accum, tidy));
|
|
274
|
+
this.setText(parseLinks(this.firstChild.toString(), this.#config, this.#accum, this.pageName, tidy));
|
|
259
275
|
}
|
|
260
276
|
/**
|
|
261
277
|
* 解析单引号
|
|
@@ -353,7 +369,7 @@ class Token extends element_1.AstElement {
|
|
|
353
369
|
}
|
|
354
370
|
/** @private */
|
|
355
371
|
normalizeTitle(title, defaultNs = 0, opt) {
|
|
356
|
-
return index_1.default.normalizeTitle(title, defaultNs, this
|
|
372
|
+
return index_1.default.normalizeTitle(title, defaultNs, this.getAttribute('include'), this.#config, { page: this.pageName, ...opt });
|
|
357
373
|
}
|
|
358
374
|
/** @private */
|
|
359
375
|
inTableAttrs() {
|
|
@@ -464,29 +480,6 @@ class Token extends element_1.AstElement {
|
|
|
464
480
|
delete e.suggestions;
|
|
465
481
|
}
|
|
466
482
|
}
|
|
467
|
-
/* NOT FOR BROWSER ONLY */
|
|
468
|
-
}
|
|
469
|
-
else if ((0, lsp_1.isAttr)(this, true)) {
|
|
470
|
-
const rule = 'invalid-css', s = lintConfig.getSeverity(rule), sWarn = lintConfig.getSeverity(rule, 'warn');
|
|
471
|
-
if (s || sWarn) {
|
|
472
|
-
const root = this.getRootNode(), textDoc = new document_1.EmbeddedCSSDocument(root, this);
|
|
473
|
-
errors.push(...document_1.cssLSP.doValidation(textDoc, textDoc.styleSheet)
|
|
474
|
-
.filter(({ code, severity }) => code !== 'css-ruleorselectorexpected' && code !== 'emptyRules'
|
|
475
|
-
&& (severity === 1 ? s : sWarn))
|
|
476
|
-
.map(({ range: { start: { line, character }, end }, message, severity, code }) => ({
|
|
477
|
-
code: code,
|
|
478
|
-
rule,
|
|
479
|
-
message,
|
|
480
|
-
severity: (severity === 1 ? s : sWarn),
|
|
481
|
-
startLine: line,
|
|
482
|
-
startCol: character,
|
|
483
|
-
startIndex: root.indexFromPos(line, character),
|
|
484
|
-
endLine: end.line,
|
|
485
|
-
endCol: end.character,
|
|
486
|
-
endIndex: root.indexFromPos(end.line, end.character),
|
|
487
|
-
})));
|
|
488
|
-
}
|
|
489
|
-
/* NOT FOR BROWSER ONLY END */
|
|
490
483
|
}
|
|
491
484
|
return errors;
|
|
492
485
|
}
|
package/dist/src/link/file.js
CHANGED
|
@@ -14,7 +14,7 @@ const frame = new Map([
|
|
|
14
14
|
['frameless', 'Frameless'],
|
|
15
15
|
['framed', 'Frame'],
|
|
16
16
|
['thumbnail', 'Thumb'],
|
|
17
|
-
]), argTypes = new Set(['arg']), transclusion = new Set(['template', 'magic-word']), horizAlign = new Set(['left', 'right', 'center', 'none']), vertAlign = new Set(['baseline', 'sub', 'super', 'top', 'text-top', 'middle', 'bottom', 'text-bottom'])
|
|
17
|
+
]), argTypes = new Set(['arg']), transclusion = new Set(['template', 'magic-word']), horizAlign = new Set(['left', 'right', 'center', 'none']), vertAlign = new Set(['baseline', 'sub', 'super', 'top', 'text-top', 'middle', 'bottom', 'text-bottom']);
|
|
18
18
|
/**
|
|
19
19
|
* a more sophisticated string-explode function
|
|
20
20
|
* @param str string to be exploded
|
|
@@ -82,7 +82,7 @@ class FileToken extends base_1.LinkBaseToken {
|
|
|
82
82
|
const errors = super.lint(start, re), args = filterArgs(this.getAllArgs(), argTypes), keys = [...new Set(args.map(({ name }) => name))], frameKeys = keys.filter(key => frame.has(key)), horizAlignKeys = keys.filter(key => horizAlign.has(key)), vertAlignKeys = keys.filter(key => vertAlign.has(key)), [fr] = frameKeys, unscaled = fr === 'framed' || fr === 'manualthumb', rect = new rect_1.BoundingRect(this, start), { lintConfig } = index_1.default, { computeEditInfo, fix } = lintConfig, { ns, extension, } = this.getAttribute('title'), { firstChild } = this;
|
|
83
83
|
let rule = 'nested-link', s = lintConfig.getSeverity(rule, 'file');
|
|
84
84
|
if (s
|
|
85
|
-
&& extensions.has(extension)
|
|
85
|
+
&& imageParameter_1.extensions.has(extension)
|
|
86
86
|
&& this.closest('ext-link-text')
|
|
87
87
|
&& this.getValue('link')?.trim() !== '') {
|
|
88
88
|
const e = (0, lint_1.generateForSelf)(this, rect, rule, 'link-in-extlink', s);
|
|
@@ -157,22 +157,22 @@ class FileToken extends base_1.LinkBaseToken {
|
|
|
157
157
|
];
|
|
158
158
|
}
|
|
159
159
|
if (relevantArgs.length > 1) {
|
|
160
|
-
let severity = !isCaption || !extension || extensions.has(extension);
|
|
160
|
+
let severity = !isCaption || !extension || imageParameter_1.extensions.has(extension);
|
|
161
161
|
if (isCaption && severity) {
|
|
162
162
|
const plainArgs = filterArgs(relevantArgs, transclusion);
|
|
163
163
|
severity = plainArgs.length > 1 && ((arg) => plainArgs.includes(arg));
|
|
164
164
|
}
|
|
165
|
-
|
|
165
|
+
Array.prototype.push.apply(errors, generate(relevantArgs, 'duplicate', key, severity));
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
if (frameKeys.length > 1) {
|
|
169
|
-
|
|
169
|
+
Array.prototype.push.apply(errors, generate(args.filter(({ name }) => frame.has(name)), 'conflicting', 'frame'));
|
|
170
170
|
}
|
|
171
171
|
if (horizAlignKeys.length > 1) {
|
|
172
|
-
|
|
172
|
+
Array.prototype.push.apply(errors, generate(args.filter(({ name }) => horizAlign.has(name)), 'conflicting', 'horizontal-alignment'));
|
|
173
173
|
}
|
|
174
174
|
if (vertAlignKeys.length > 1) {
|
|
175
|
-
|
|
175
|
+
Array.prototype.push.apply(errors, generate(args.filter(({ name }) => vertAlign.has(name)), 'conflicting', 'vertical-alignment'));
|
|
176
176
|
}
|
|
177
177
|
return errors;
|
|
178
178
|
}
|
|
@@ -91,7 +91,7 @@ let GalleryImageToken = (() => {
|
|
|
91
91
|
/** @private */
|
|
92
92
|
getTitle(temporary) {
|
|
93
93
|
const imagemap = this.type === 'imagemap-image';
|
|
94
|
-
return this.normalizeTitle(this.firstChild.toString(), imagemap ? 0 : 6, { halfParsed: true, temporary, decode: !imagemap });
|
|
94
|
+
return this.normalizeTitle(this.firstChild.toString(), imagemap ? 0 : 6, { halfParsed: true, temporary, decode: !imagemap, page: '' });
|
|
95
95
|
}
|
|
96
96
|
/** 判定无效的图片 */
|
|
97
97
|
#lint() {
|
|
@@ -31,7 +31,7 @@ class RedirectTargetToken extends base_1.LinkBaseToken {
|
|
|
31
31
|
}
|
|
32
32
|
/** @private */
|
|
33
33
|
getTitle() {
|
|
34
|
-
return this.normalizeTitle(this.firstChild.toString(), 0, { halfParsed: true, decode: true });
|
|
34
|
+
return this.normalizeTitle(this.firstChild.toString(), 0, { halfParsed: true, decode: true, page: '' });
|
|
35
35
|
}
|
|
36
36
|
/** @private */
|
|
37
37
|
lint(start = this.getAbsoluteIndex()) {
|
|
@@ -42,7 +42,7 @@ class GalleryToken extends index_2.MultiLineToken {
|
|
|
42
42
|
* @param file 文件名
|
|
43
43
|
*/
|
|
44
44
|
#checkFile(file) {
|
|
45
|
-
return this.normalizeTitle(file, 6, { halfParsed: true, temporary: true, decode: true }).valid;
|
|
45
|
+
return this.normalizeTitle(file, 6, { halfParsed: true, temporary: true, decode: true, page: '' }).valid;
|
|
46
46
|
}
|
|
47
47
|
/** @private */
|
|
48
48
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
@@ -83,7 +83,7 @@ class GalleryToken extends index_2.MultiLineToken {
|
|
|
83
83
|
else if (type !== 'noinclude' && type !== 'text') {
|
|
84
84
|
const childErrors = child.lint(start, re);
|
|
85
85
|
if (childErrors.length > 0) {
|
|
86
|
-
|
|
86
|
+
Array.prototype.push.apply(errors, childErrors);
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
start += length + 1;
|
|
@@ -35,7 +35,7 @@ class ImagemapToken extends index_2.MultiLineToken {
|
|
|
35
35
|
//
|
|
36
36
|
}
|
|
37
37
|
else if (first) {
|
|
38
|
-
const pipe = line.indexOf('|'), file = pipe === -1 ? line : line.slice(0, pipe), { valid, ns, } = this.normalizeTitle(file, 0, { halfParsed: true, temporary: true });
|
|
38
|
+
const pipe = line.indexOf('|'), file = pipe === -1 ? line : line.slice(0, pipe), { valid, ns, } = this.normalizeTitle(file, 0, { halfParsed: true, temporary: true, page: '' });
|
|
39
39
|
if (valid
|
|
40
40
|
&& ns === 6) {
|
|
41
41
|
// @ts-expect-error abstract class
|
|
@@ -56,8 +56,7 @@ class ImagemapToken extends index_2.MultiLineToken {
|
|
|
56
56
|
const i = line.indexOf('['), substr = line.slice(i), mtIn = /^\[\[([^|]+)(?:\|([^\]]*))?\]\][\w\s]*$/u
|
|
57
57
|
.exec(substr);
|
|
58
58
|
if (mtIn) {
|
|
59
|
-
if (this.normalizeTitle(mtIn[1], 0, { halfParsed: true, temporary: true, selfLink: true })
|
|
60
|
-
.valid) {
|
|
59
|
+
if (this.normalizeTitle(mtIn[1], 0, { halfParsed: true, temporary: true, selfLink: true, page: '' }).valid) {
|
|
61
60
|
// @ts-expect-error abstract class
|
|
62
61
|
super.insertAt(new imagemapLink_1.ImagemapLinkToken(line.slice(0, i), mtIn.slice(1), substr.slice(substr.indexOf(']]') + 2), config, accum));
|
|
63
62
|
continue;
|
|
@@ -85,7 +84,7 @@ class ImagemapToken extends index_2.MultiLineToken {
|
|
|
85
84
|
const errors = super.lint(start, re), rect = new rect_1.BoundingRect(this, start), { childNodes, image } = this, rule = 'invalid-imagemap', { lintConfig } = index_1.default, s = lintConfig.getSeverity(rule, image ? 'link' : 'image');
|
|
86
85
|
if (s) {
|
|
87
86
|
if (image) {
|
|
88
|
-
|
|
87
|
+
Array.prototype.push.apply(errors, childNodes.filter(child => {
|
|
89
88
|
const str = child.toString().trim();
|
|
90
89
|
return child.is('noinclude')
|
|
91
90
|
&& str && !str.startsWith('#');
|
|
@@ -19,7 +19,7 @@ class ParamTagToken extends index_2.MultiLineToken {
|
|
|
19
19
|
constructor(include, wikitext, config = index_1.default.getConfig(), accum = [], acceptable) {
|
|
20
20
|
super(undefined, config, accum, {});
|
|
21
21
|
if (wikitext) {
|
|
22
|
-
this.
|
|
22
|
+
this.safeAppend(wikitext.split('\n')
|
|
23
23
|
.map(line => acceptable ? line : (0, commentAndExt_1.parseCommentAndExt)(line, config, accum, include))
|
|
24
24
|
// @ts-expect-error abstract class
|
|
25
25
|
.map((line) => new paramLine_1.ParamLineToken(line, config, accum, {})));
|
|
@@ -54,7 +54,7 @@ class ParamTagToken extends index_2.MultiLineToken {
|
|
|
54
54
|
else {
|
|
55
55
|
const childErrors = child.lint(start, false);
|
|
56
56
|
if (childErrors.length > 0) {
|
|
57
|
-
|
|
57
|
+
Array.prototype.push.apply(errors, childErrors);
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
}
|