wikilint 2.40.0 → 2.42.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/README.md +2 -2
- package/config/.schema.json +5 -0
- package/config/default.json +1 -1
- package/config/enwiki.json +3 -2
- package/config/jawiki.json +6 -5
- package/config/llwiki.json +2 -1
- package/config/minimum.json +1 -1
- package/config/moegirl.json +2 -1
- package/config/zhwiki.json +3 -2
- package/dist/base.d.mts +3 -3
- package/dist/base.d.ts +3 -3
- package/dist/bin/cli.js +1 -1
- package/dist/bin/config.js +11 -10
- package/dist/lib/element.d.ts +0 -7
- package/dist/lib/element.js +0 -18
- package/dist/lib/lintConfig.js +30 -23
- package/dist/lib/lsp.d.ts +2 -0
- package/dist/lib/lsp.js +8 -20
- package/dist/lib/node.d.ts +2 -0
- package/dist/lib/node.js +0 -7
- package/dist/lib/text.js +2 -3
- package/dist/map.d.ts +65 -0
- package/dist/map.js +2 -0
- package/dist/mixin/attributesParent.d.ts +1 -1
- package/dist/mixin/elementLike.d.ts +12 -0
- package/dist/mixin/elementLike.js +32 -19
- package/dist/src/attribute.d.ts +1 -1
- package/dist/src/attribute.js +7 -7
- package/dist/src/attributes.d.ts +1 -1
- package/dist/src/attributes.js +8 -14
- package/dist/src/index.js +3 -4
- package/dist/src/magicLink.js +1 -1
- package/dist/src/nowiki/doubleUnderscore.js +1 -1
- package/dist/src/nowiki/quote.js +1 -3
- package/dist/src/table/td.d.ts +1 -1
- package/dist/src/table/td.js +1 -1
- package/dist/src/tagPair/ext.js +4 -1
- package/dist/util/debug.js +5 -7
- package/dist/util/sharable.js +2 -0
- package/dist/util/sharable.mjs +3 -1
- package/package.json +13 -13
package/README.md
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/wikilint)
|
|
6
6
|
[](https://github.com/bhsd-harry/wikiparser-node/actions/workflows/codeql.yml)
|
|
7
7
|
[](https://github.com/bhsd-harry/wikiparser-node/actions/workflows/node.js.yml)
|
|
8
|
-
[](https://www.npmjs.com/package/wikilint)
|
|
9
|
+

|
|
10
10
|
|
|
11
11
|
This is a minimal version of [WikiParser-Node](https://www.npmjs.com/package/wikiparser-node). The [Wikitext LSP](https://www.npmjs.com/package/wikitext-lsp) and the [WikiParser Language Server](https://marketplace.visualstudio.com/items?itemName=Bhsd.vscode-extension-wikiparser) VS Code extension is written based on this package.
|
|
12
12
|
|
package/config/.schema.json
CHANGED
|
@@ -242,6 +242,11 @@
|
|
|
242
242
|
"description": "base URL of internal links",
|
|
243
243
|
"type": "string",
|
|
244
244
|
"pattern": "\\$1"
|
|
245
|
+
},
|
|
246
|
+
"server": {
|
|
247
|
+
"description": "base URL of the server",
|
|
248
|
+
"type": "string",
|
|
249
|
+
"pattern": "^(?:https?:)?//"
|
|
245
250
|
}
|
|
246
251
|
},
|
|
247
252
|
"required": [
|
package/config/default.json
CHANGED
|
@@ -1465,7 +1465,7 @@
|
|
|
1465
1465
|
"EXPECTUNUSEDTEMPLATE": "EXPECTUNUSEDTEMPLATE"
|
|
1466
1466
|
}
|
|
1467
1467
|
],
|
|
1468
|
-
"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:|wikipedia://|worldwind://|xmpp
|
|
1468
|
+
"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:|wikipedia://|worldwind://|xmpp:|commonsfinder://",
|
|
1469
1469
|
"interwiki": [],
|
|
1470
1470
|
"img": {
|
|
1471
1471
|
"thumbnail": "thumbnail",
|
package/config/enwiki.json
CHANGED
|
@@ -591,7 +591,7 @@
|
|
|
591
591
|
"EXPECTED_UNCONNECTED_PAGE": "EXPECTEDUNCONNECTEDPAGE"
|
|
592
592
|
}
|
|
593
593
|
],
|
|
594
|
-
"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:|wikipedia://|worldwind://|xmpp
|
|
594
|
+
"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:|wikipedia://|worldwind://|xmpp:|commonsfinder://",
|
|
595
595
|
"interwiki": [],
|
|
596
596
|
"img": {
|
|
597
597
|
"alt=$1": "alt",
|
|
@@ -632,5 +632,6 @@
|
|
|
632
632
|
"#redirect"
|
|
633
633
|
],
|
|
634
634
|
"variants": [],
|
|
635
|
-
"articlePath": "/wiki/$1"
|
|
635
|
+
"articlePath": "/wiki/$1",
|
|
636
|
+
"server": "//en.wikipedia.org"
|
|
636
637
|
}
|
package/config/jawiki.json
CHANGED
|
@@ -899,7 +899,7 @@
|
|
|
899
899
|
"EXPECTED_UNCONNECTED_PAGE": "EXPECTEDUNCONNECTEDPAGE"
|
|
900
900
|
}
|
|
901
901
|
],
|
|
902
|
-
"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:|wikipedia://|worldwind://|xmpp
|
|
902
|
+
"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:|wikipedia://|worldwind://|xmpp:|commonsfinder://",
|
|
903
903
|
"interwiki": [],
|
|
904
904
|
"img": {
|
|
905
905
|
"代替文=$1": "alt",
|
|
@@ -915,12 +915,14 @@
|
|
|
915
915
|
"中央": "center",
|
|
916
916
|
"center": "center",
|
|
917
917
|
"centre": "center",
|
|
918
|
+
"class=$1": "class",
|
|
918
919
|
"フレーム": "framed",
|
|
919
920
|
"frame": "framed",
|
|
920
921
|
"framed": "framed",
|
|
921
922
|
"enframed": "framed",
|
|
922
923
|
"フレームなし": "frameless",
|
|
923
924
|
"frameless": "frameless",
|
|
925
|
+
"lang=$1": "lang",
|
|
924
926
|
"左": "left",
|
|
925
927
|
"left": "left",
|
|
926
928
|
"リンク=$1": "link",
|
|
@@ -959,9 +961,7 @@
|
|
|
959
961
|
"upright=$1": "upright",
|
|
960
962
|
"upright $1": "upright",
|
|
961
963
|
"$1ピクセル": "width",
|
|
962
|
-
"$1px": "width"
|
|
963
|
-
"class=$1": "class",
|
|
964
|
-
"lang=$1": "lang"
|
|
964
|
+
"$1px": "width"
|
|
965
965
|
},
|
|
966
966
|
"redirection": [
|
|
967
967
|
"#転送",
|
|
@@ -971,5 +971,6 @@
|
|
|
971
971
|
"#redirect"
|
|
972
972
|
],
|
|
973
973
|
"variants": [],
|
|
974
|
-
"articlePath": "/wiki/$1"
|
|
974
|
+
"articlePath": "/wiki/$1",
|
|
975
|
+
"server": "//ja.wikipedia.org"
|
|
975
976
|
}
|
package/config/llwiki.json
CHANGED
package/config/minimum.json
CHANGED
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
{},
|
|
126
126
|
{}
|
|
127
127
|
],
|
|
128
|
-
"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:|wikipedia://|worldwind://|xmpp
|
|
128
|
+
"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:|wikipedia://|worldwind://|xmpp:|commonsfinder://",
|
|
129
129
|
"interwiki": [],
|
|
130
130
|
"img": {},
|
|
131
131
|
"redirection": [
|
package/config/moegirl.json
CHANGED
package/config/zhwiki.json
CHANGED
|
@@ -961,7 +961,7 @@
|
|
|
961
961
|
"EXPECTED_UNCONNECTED_PAGE": "EXPECTEDUNCONNECTEDPAGE"
|
|
962
962
|
}
|
|
963
963
|
],
|
|
964
|
-
"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:|wikipedia://|worldwind://|xmpp
|
|
964
|
+
"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:|wikipedia://|worldwind://|xmpp:|commonsfinder://",
|
|
965
965
|
"interwiki": [],
|
|
966
966
|
"img": {
|
|
967
967
|
"alt=$1": "alt",
|
|
@@ -1060,5 +1060,6 @@
|
|
|
1060
1060
|
"zh-sg",
|
|
1061
1061
|
"zh-tw"
|
|
1062
1062
|
],
|
|
1063
|
-
"articlePath": "/wiki/$1"
|
|
1063
|
+
"articlePath": "/wiki/$1",
|
|
1064
|
+
"server": "//zh.wikipedia.org"
|
|
1064
1065
|
}
|
package/dist/base.d.mts
CHANGED
|
@@ -9,7 +9,6 @@ export interface Config {
|
|
|
9
9
|
readonly parserFunction: [Record<string, string>, Record<string, string>, string[], string[]];
|
|
10
10
|
readonly doubleUnderscore: [string[], string[], Record<string, string>, Record<string, string>];
|
|
11
11
|
readonly protocol: string;
|
|
12
|
-
readonly interwiki: string[];
|
|
13
12
|
readonly img: Record<string, string>;
|
|
14
13
|
readonly redirection: string[];
|
|
15
14
|
readonly variants: string[];
|
|
@@ -267,8 +266,9 @@ export interface LanguageService {
|
|
|
267
266
|
[Symbol.dispose](): void;
|
|
268
267
|
}
|
|
269
268
|
export type SeverityLevel = 0 | 1 | 2 | false | 'off' | 'warning' | 'error';
|
|
270
|
-
export type
|
|
271
|
-
export type
|
|
269
|
+
export type FullLintConfigValue = [SeverityLevel, Record<string, SeverityLevel>?];
|
|
270
|
+
export type LintConfigValue = SeverityLevel | FullLintConfigValue | Record<string, SeverityLevel>;
|
|
271
|
+
export type LintRuleConfig<T = LintConfigValue> = Partial<Record<LintError.Rule, T>>;
|
|
272
272
|
export interface FullLintConfig {
|
|
273
273
|
rules: LintRuleConfig;
|
|
274
274
|
configurationComment?: string;
|
package/dist/base.d.ts
CHANGED
|
@@ -9,7 +9,6 @@ export interface Config {
|
|
|
9
9
|
readonly parserFunction: [Record<string, string>, Record<string, string>, string[], string[]];
|
|
10
10
|
readonly doubleUnderscore: [string[], string[], Record<string, string>, Record<string, string>];
|
|
11
11
|
readonly protocol: string;
|
|
12
|
-
readonly interwiki: string[];
|
|
13
12
|
readonly img: Record<string, string>;
|
|
14
13
|
readonly redirection: string[];
|
|
15
14
|
readonly variants: string[];
|
|
@@ -267,8 +266,9 @@ export interface LanguageService {
|
|
|
267
266
|
[Symbol.dispose](): void;
|
|
268
267
|
}
|
|
269
268
|
export type SeverityLevel = 0 | 1 | 2 | false | 'off' | 'warning' | 'error';
|
|
270
|
-
export type
|
|
271
|
-
export type
|
|
269
|
+
export type FullLintConfigValue = [SeverityLevel, Record<string, SeverityLevel>?];
|
|
270
|
+
export type LintConfigValue = SeverityLevel | FullLintConfigValue | Record<string, SeverityLevel>;
|
|
271
|
+
export type LintRuleConfig<T = LintConfigValue> = Partial<Record<LintError.Rule, T>>;
|
|
272
272
|
export interface FullLintConfig {
|
|
273
273
|
rules: LintRuleConfig;
|
|
274
274
|
configurationComment?: string;
|
package/dist/bin/cli.js
CHANGED
|
@@ -148,7 +148,7 @@ const plural = (n, word) => `${n} ${word}${n === 1 ? '' : 's'}`;
|
|
|
148
148
|
*/
|
|
149
149
|
const styleText = (format, text) => {
|
|
150
150
|
if (!colors) {
|
|
151
|
-
format = (Array.isArray(format) ? format : [format]).filter(f => !colorSet.has(f));
|
|
151
|
+
format = (Array.isArray(format) ? format : [format]).filter((f) => !colorSet.has(f));
|
|
152
152
|
}
|
|
153
153
|
return util_1.default.styleText(format, text);
|
|
154
154
|
};
|
package/dist/bin/config.js
CHANGED
|
@@ -40,7 +40,7 @@ const filterGadget = (id) => {
|
|
|
40
40
|
const n = Number(id);
|
|
41
41
|
return n < 2300 || n > 2303; // Gadget, Gadget talk, Gadget definition, Gadget definition talk
|
|
42
42
|
};
|
|
43
|
-
const pkg = "wikilint", version = "2.
|
|
43
|
+
const pkg = "wikilint", version = "2.42.0";
|
|
44
44
|
/**
|
|
45
45
|
* Get the parser configuration for a Wikimedia Foundation project.
|
|
46
46
|
* @param site site nickname
|
|
@@ -78,13 +78,7 @@ exports.default = async (site, url, user, force, internal) => {
|
|
|
78
78
|
'User-Agent': `${pkg}/${version} (https://www.npmjs.com/package/${pkg}; ${user}) Node.js/${process.version}`,
|
|
79
79
|
},
|
|
80
80
|
}
|
|
81
|
-
: undefined, m = await (await fetch(`${url}/load.php?modules=ext.CodeMirror.data|ext.CodeMirror`, headers)).text(),
|
|
82
|
-
action: 'query',
|
|
83
|
-
meta: 'siteinfo',
|
|
84
|
-
siprop: 'general|magicwords|functionhooks|namespaces|namespacealiases',
|
|
85
|
-
format: 'json',
|
|
86
|
-
formatversion: '2',
|
|
87
|
-
}, { general: { articlepath, variants, langconversion }, magicwords, namespaces, namespacealiases, functionhooks, } = (await (await fetch(`${url}/api.php?${new URLSearchParams(params).toString()}`, headers)).json()).query, tempFile = path_1.default.join(__dirname, 'mw.js');
|
|
81
|
+
: undefined, m = await (await fetch(`${url}/load.php?modules=ext.CodeMirror.data|ext.CodeMirror`, headers)).text(), tempFile = path_1.default.join(__dirname, 'mw.js');
|
|
88
82
|
fs_1.default.writeFileSync(tempFile, m);
|
|
89
83
|
const { stdout, stderr } = (0, child_process_1.spawnSync)(process.execPath, [
|
|
90
84
|
'-r',
|
|
@@ -108,13 +102,19 @@ exports.default = async (site, url, user, force, internal) => {
|
|
|
108
102
|
catch {
|
|
109
103
|
throw new RangeError('Extension:CodeMirror is not installed!');
|
|
110
104
|
}
|
|
111
|
-
const
|
|
105
|
+
const params = {
|
|
106
|
+
action: 'query',
|
|
107
|
+
meta: 'siteinfo',
|
|
108
|
+
siprop: `general|magicwords|namespaces|namespacealiases${mwConfig.functionHooks ? '' : '|functionhooks'}`,
|
|
109
|
+
format: 'json',
|
|
110
|
+
formatversion: '2',
|
|
111
|
+
}, { general: { articlepath, server, variants, langconversion }, magicwords, namespaces, namespacealiases, functionhooks, } = (await (await fetch(`${url}/api.php?${new URLSearchParams(params).toString()}`, headers)).json()).query, ns = Object.entries(namespaces).filter(([id]) => filterGadget(id))
|
|
112
112
|
.flatMap(([id, { name, canonical = '' }]) => [
|
|
113
113
|
[id, name],
|
|
114
114
|
...name === canonical ? [] : [[id, canonical]],
|
|
115
115
|
]), config = {
|
|
116
116
|
...(0, cm_util_1.getParserConfig)(require(path_1.default.join(dir, 'minimum.json')), mwConfig),
|
|
117
|
-
|
|
117
|
+
...!(mwConfig.imageKeywords && mwConfig.redirection) && (0, cm_util_1.getKeywords)(magicwords),
|
|
118
118
|
variants: langconversion ? (0, cm_util_1.getVariants)(variants) : [],
|
|
119
119
|
namespaces: Object.fromEntries(ns),
|
|
120
120
|
nsid: Object.fromEntries([
|
|
@@ -122,6 +122,7 @@ exports.default = async (site, url, user, force, internal) => {
|
|
|
122
122
|
...namespacealiases.filter(({ id }) => filterGadget(id)).map(({ id, alias }) => [alias.toLowerCase(), id]),
|
|
123
123
|
]),
|
|
124
124
|
articlePath: articlepath,
|
|
125
|
+
server,
|
|
125
126
|
}, { doubleUnderscore, parserFunction, variable } = config;
|
|
126
127
|
doubleUnderscore[0] = [];
|
|
127
128
|
doubleUnderscore[1] = [];
|
package/dist/lib/element.d.ts
CHANGED
|
@@ -33,13 +33,6 @@ export declare abstract class AstElement extends AstNode {
|
|
|
33
33
|
* @param i position to be inserted at / 插入位置
|
|
34
34
|
*/
|
|
35
35
|
insertAt<T extends AstNodes>(node: T, i?: number): T;
|
|
36
|
-
/**
|
|
37
|
-
* Get the closest ancestor node that matches the selector
|
|
38
|
-
*
|
|
39
|
-
* 最近的符合选择器的祖先节点
|
|
40
|
-
* @param selector selector / 选择器
|
|
41
|
-
*/
|
|
42
|
-
closest<T = Token>(selector: string): T | undefined;
|
|
43
36
|
/**
|
|
44
37
|
* Insert a batch of child nodes at the end
|
|
45
38
|
*
|
package/dist/lib/element.js
CHANGED
|
@@ -37,7 +37,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
37
37
|
exports.AstElement = void 0;
|
|
38
38
|
const string_1 = require("../util/string");
|
|
39
39
|
const debug_1 = require("../util/debug");
|
|
40
|
-
const selector_1 = require("../util/selector");
|
|
41
40
|
const node_1 = require("./node");
|
|
42
41
|
const elementLike_1 = require("../mixin/elementLike");
|
|
43
42
|
/**
|
|
@@ -88,23 +87,6 @@ let AstElement = (() => {
|
|
|
88
87
|
(0, debug_1.setChildNodes)(this, i, 0, [node]);
|
|
89
88
|
return node;
|
|
90
89
|
}
|
|
91
|
-
/**
|
|
92
|
-
* Get the closest ancestor node that matches the selector
|
|
93
|
-
*
|
|
94
|
-
* 最近的符合选择器的祖先节点
|
|
95
|
-
* @param selector selector / 选择器
|
|
96
|
-
*/
|
|
97
|
-
closest(selector) {
|
|
98
|
-
const condition = (0, selector_1.getCondition)(selector, this);
|
|
99
|
-
let { parentNode } = this;
|
|
100
|
-
while (parentNode) {
|
|
101
|
-
if (condition(parentNode)) {
|
|
102
|
-
return parentNode;
|
|
103
|
-
}
|
|
104
|
-
({ parentNode } = parentNode);
|
|
105
|
-
}
|
|
106
|
-
return undefined;
|
|
107
|
-
}
|
|
108
90
|
/** @private */
|
|
109
91
|
isInside(type) {
|
|
110
92
|
return this.closest(`${type},ext`)?.type === type;
|
package/dist/lib/lintConfig.js
CHANGED
|
@@ -12,8 +12,8 @@ const dict = new Map([
|
|
|
12
12
|
['error', 'error'],
|
|
13
13
|
]);
|
|
14
14
|
const defaultLintRuleConfig = {
|
|
15
|
-
'arg-in-ext': 1,
|
|
16
|
-
'blank-alt': 1,
|
|
15
|
+
'arg-in-ext': [1],
|
|
16
|
+
'blank-alt': [1],
|
|
17
17
|
'bold-header': [
|
|
18
18
|
1,
|
|
19
19
|
{
|
|
@@ -47,7 +47,7 @@ const defaultLintRuleConfig = {
|
|
|
47
47
|
// value: 2,
|
|
48
48
|
},
|
|
49
49
|
],
|
|
50
|
-
'insecure-style': 2,
|
|
50
|
+
'insecure-style': [2],
|
|
51
51
|
'invalid-gallery': [
|
|
52
52
|
2,
|
|
53
53
|
{
|
|
@@ -72,14 +72,14 @@ const defaultLintRuleConfig = {
|
|
|
72
72
|
// name: 2,
|
|
73
73
|
},
|
|
74
74
|
],
|
|
75
|
-
'invalid-isbn': 2,
|
|
75
|
+
'invalid-isbn': [2],
|
|
76
76
|
'invalid-json': [
|
|
77
77
|
2,
|
|
78
78
|
{
|
|
79
79
|
duplicate: 1,
|
|
80
80
|
},
|
|
81
81
|
],
|
|
82
|
-
'invalid-url': 1,
|
|
82
|
+
'invalid-url': [1],
|
|
83
83
|
'lonely-apos': [
|
|
84
84
|
1,
|
|
85
85
|
{
|
|
@@ -110,7 +110,7 @@ const defaultLintRuleConfig = {
|
|
|
110
110
|
// ref: 2,
|
|
111
111
|
},
|
|
112
112
|
],
|
|
113
|
-
'no-arg': 1,
|
|
113
|
+
'no-arg': [1],
|
|
114
114
|
'no-duplicate': [
|
|
115
115
|
2,
|
|
116
116
|
{
|
|
@@ -144,8 +144,8 @@ const defaultLintRuleConfig = {
|
|
|
144
144
|
// references: 2,
|
|
145
145
|
},
|
|
146
146
|
],
|
|
147
|
-
'obsolete-attr': 1,
|
|
148
|
-
'obsolete-tag': 1,
|
|
147
|
+
'obsolete-attr': [1],
|
|
148
|
+
'obsolete-tag': [1],
|
|
149
149
|
'parsing-order': [
|
|
150
150
|
2,
|
|
151
151
|
{
|
|
@@ -182,7 +182,7 @@ const defaultLintRuleConfig = {
|
|
|
182
182
|
// redirect: 2,
|
|
183
183
|
},
|
|
184
184
|
],
|
|
185
|
-
'table-layout': 1,
|
|
185
|
+
'table-layout': [1],
|
|
186
186
|
'tag-like': [
|
|
187
187
|
2,
|
|
188
188
|
{
|
|
@@ -190,17 +190,17 @@ const defaultLintRuleConfig = {
|
|
|
190
190
|
invalid: 1,
|
|
191
191
|
},
|
|
192
192
|
],
|
|
193
|
-
'unbalanced-header': 2,
|
|
193
|
+
'unbalanced-header': [2],
|
|
194
194
|
'unclosed-comment': [
|
|
195
195
|
1,
|
|
196
196
|
{
|
|
197
197
|
// include: 1,
|
|
198
198
|
},
|
|
199
199
|
],
|
|
200
|
-
'unclosed-quote': 1,
|
|
201
|
-
'unclosed-table': 2,
|
|
202
|
-
unescaped: 2,
|
|
203
|
-
'unknown-page': 1,
|
|
200
|
+
'unclosed-quote': [1],
|
|
201
|
+
'unclosed-table': [2],
|
|
202
|
+
unescaped: [2],
|
|
203
|
+
'unknown-page': [1],
|
|
204
204
|
'unmatched-tag': [
|
|
205
205
|
1,
|
|
206
206
|
{
|
|
@@ -247,7 +247,7 @@ const defaultLintRuleConfig = {
|
|
|
247
247
|
warn: 1,
|
|
248
248
|
},
|
|
249
249
|
],
|
|
250
|
-
'invalid-math': 2,
|
|
250
|
+
'invalid-math': [2],
|
|
251
251
|
};
|
|
252
252
|
const defaultLintConfig = {
|
|
253
253
|
configurationComment: 'lint',
|
|
@@ -264,8 +264,9 @@ const validateSeverity = (severity) => dict.has(severity);
|
|
|
264
264
|
* 验证设置值是否符合规范
|
|
265
265
|
* @param value 设置值
|
|
266
266
|
*/
|
|
267
|
-
const validateConfigValue = (value) => validateSeverity(value)
|
|
268
|
-
|
|
267
|
+
const validateConfigValue = (value) => validateSeverity(value) || (Array.isArray(value)
|
|
268
|
+
? validateSeverity(value[0]) && (value.length === 1 || typeof value[1] === 'object')
|
|
269
|
+
: typeof value === 'object');
|
|
269
270
|
/**
|
|
270
271
|
* 设置语法检查规则
|
|
271
272
|
* @param obj 语法检查设置对象
|
|
@@ -282,7 +283,16 @@ const set = (obj, key, value) => {
|
|
|
282
283
|
return false;
|
|
283
284
|
}
|
|
284
285
|
if (validateConfigValue(value)) {
|
|
285
|
-
|
|
286
|
+
if (Array.isArray(value)) {
|
|
287
|
+
obj[key] = value;
|
|
288
|
+
}
|
|
289
|
+
else if (typeof value === 'object') {
|
|
290
|
+
const [base, options = {}] = defaultLintRuleConfig[key];
|
|
291
|
+
obj[key] = [base, { ...clone(options), ...value }];
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
obj[key] = [value];
|
|
295
|
+
}
|
|
286
296
|
return true;
|
|
287
297
|
}
|
|
288
298
|
/* c8 ignore next */
|
|
@@ -305,11 +315,8 @@ class LintRuleConfiguration {
|
|
|
305
315
|
}
|
|
306
316
|
/** @implements */
|
|
307
317
|
getSeverity(rule, key) {
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
return dict.get(value);
|
|
311
|
-
}
|
|
312
|
-
return key ? dict.get(value[1]?.[key]) ?? dict.get(value[0]) : dict.get(value[0]);
|
|
318
|
+
const [base, options] = this[rule], severity = dict.get(base);
|
|
319
|
+
return key ? dict.get(options?.[key]) ?? severity : severity;
|
|
313
320
|
}
|
|
314
321
|
}
|
|
315
322
|
/** 语法检查设置 */
|
package/dist/lib/lsp.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Token } from '../src/index';
|
|
|
3
3
|
import type { Range, Position, ColorInformation, ColorPresentation, FoldingRange, DocumentLink, Location, WorkspaceEdit, Diagnostic as DiagnosticBase, TextEdit, Hover, SignatureHelp, InlayHint, CodeAction, DocumentSymbol } from 'vscode-languageserver-types';
|
|
4
4
|
import type { Config, LanguageService as LanguageServiceBase, CompletionItem, SignatureData } from '../base';
|
|
5
5
|
import type { AttributeToken } from '../internal';
|
|
6
|
+
import type { TokenTypeMap, SelectedTokenTypes } from '../map';
|
|
6
7
|
export interface QuickFixData extends TextEdit {
|
|
7
8
|
title: string;
|
|
8
9
|
fix: boolean;
|
|
@@ -128,6 +129,7 @@ export declare class LanguageService implements LanguageServiceBase {
|
|
|
128
129
|
* @since v1.16.3
|
|
129
130
|
*/
|
|
130
131
|
provideInlayHints(text: string): Promise<InlayHint[]>;
|
|
132
|
+
querySelectorAll<T = Token>(selector: string): T[];
|
|
131
133
|
/**
|
|
132
134
|
* Provide refactoring actions
|
|
133
135
|
*
|
package/dist/lib/lsp.js
CHANGED
|
@@ -157,15 +157,6 @@ const getRefName = (token) => getRefAttr(token, refTags, nameAttrs);
|
|
|
157
157
|
* @param token `group` attribute token
|
|
158
158
|
*/
|
|
159
159
|
const getRefGroup = (token) => getRefAttr(token, referencesTags, groupAttrs);
|
|
160
|
-
/**
|
|
161
|
-
* Get the attribute of a `<ref>` tag.
|
|
162
|
-
* @param token extension token
|
|
163
|
-
* @param target attribute name
|
|
164
|
-
*/
|
|
165
|
-
const getRefTagAttr = (token, target) => {
|
|
166
|
-
const attr = token?.getAttr(target);
|
|
167
|
-
return attr !== true && attr || false;
|
|
168
|
-
};
|
|
169
160
|
/**
|
|
170
161
|
* Get the effective name of a token.
|
|
171
162
|
* @param token
|
|
@@ -673,8 +664,7 @@ class LanguageService {
|
|
|
673
664
|
}),
|
|
674
665
|
...match.startsWith('#')
|
|
675
666
|
? []
|
|
676
|
-
: getCompletion(root.querySelectorAll('template').filter(token => token !== cur)
|
|
677
|
-
.map(token => {
|
|
667
|
+
: getCompletion(root.querySelectorAll('template').filter(token => token !== cur).map(token => {
|
|
678
668
|
const { name } = token;
|
|
679
669
|
if (colon) {
|
|
680
670
|
return name;
|
|
@@ -1164,8 +1154,7 @@ class LanguageService {
|
|
|
1164
1154
|
* @param position position / 位置
|
|
1165
1155
|
*/
|
|
1166
1156
|
async provideReferences(text, position) {
|
|
1167
|
-
const root = await this.#queue(text), { offsetNode, offset } = caretPositionFromWord(root, this.#text, position), element = offsetNode.type === 'text' ? offsetNode.parentNode : offsetNode, node = offset === 0
|
|
1168
|
-
&& (element.is('ext-attr-dirty') || element.is('html-attr-dirty'))
|
|
1157
|
+
const root = await this.#queue(text), { offsetNode, offset } = caretPositionFromWord(root, this.#text, position), element = offsetNode.type === 'text' ? offsetNode.parentNode : offsetNode, node = offset === 0 && (element.is('ext-attr-dirty') || element.is('html-attr-dirty'))
|
|
1169
1158
|
? element.parentNode.parentNode
|
|
1170
1159
|
: element, { type } = node, refName = getRefName(node), refGroup = getRefGroup(node);
|
|
1171
1160
|
if (!refName && !refGroup && !referenceTypes.has(type)) {
|
|
@@ -1192,13 +1181,13 @@ class LanguageService {
|
|
|
1192
1181
|
}
|
|
1193
1182
|
const ext = node.is('ext') && node.name === 'ref'
|
|
1194
1183
|
? node
|
|
1195
|
-
: node.closest('ext#ref'), refName =
|
|
1184
|
+
: node.closest('ext#ref'), refName = ext?.getAttr('name');
|
|
1196
1185
|
if (!refName) {
|
|
1197
1186
|
return undefined;
|
|
1198
1187
|
}
|
|
1199
|
-
const refGroup =
|
|
1200
|
-
&&
|
|
1201
|
-
&&
|
|
1188
|
+
const refGroup = ext.getAttr('group'), refs = root.querySelectorAll('ext#ref').filter(token => token.innerText
|
|
1189
|
+
&& token.getAttr('name') === refName
|
|
1190
|
+
&& token.getAttr('group') === refGroup).reverse().map(({ lastChild }) => ({
|
|
1202
1191
|
range: createNodeRange(lastChild),
|
|
1203
1192
|
}));
|
|
1204
1193
|
return refs.length === 0 ? undefined : refs;
|
|
@@ -1235,7 +1224,7 @@ class LanguageService {
|
|
|
1235
1224
|
if (!node) {
|
|
1236
1225
|
return undefined;
|
|
1237
1226
|
}
|
|
1238
|
-
const { type } = node, refName = getRefName(node), refNameGroup = refName &&
|
|
1227
|
+
const { type } = node, refName = getRefName(node), refNameGroup = refName && node.parentNode.parentNode.getAttr('group'), refGroup = getRefGroup(node), name = getName(node), refs = root.querySelectorAll(type).filter(token => {
|
|
1239
1228
|
const { type: t } = token.parentNode;
|
|
1240
1229
|
if (type === 'link-target' && t !== 'link' && t !== 'redirect-target') {
|
|
1241
1230
|
return false;
|
|
@@ -1243,7 +1232,7 @@ class LanguageService {
|
|
|
1243
1232
|
return type === 'attr-value'
|
|
1244
1233
|
? getRefGroup(token) === refGroup
|
|
1245
1234
|
|| getRefName(token) === refName
|
|
1246
|
-
&&
|
|
1235
|
+
&& token.parentNode.parentNode.getAttr('group') === refNameGroup
|
|
1247
1236
|
: getName(token) === name;
|
|
1248
1237
|
});
|
|
1249
1238
|
return refs.length === 0
|
|
@@ -1443,7 +1432,6 @@ class LanguageService {
|
|
|
1443
1432
|
}
|
|
1444
1433
|
return hints;
|
|
1445
1434
|
}
|
|
1446
|
-
/** @private */
|
|
1447
1435
|
querySelectorAll(selector) {
|
|
1448
1436
|
return this.#done.querySelectorAll(selector);
|
|
1449
1437
|
}
|
package/dist/lib/node.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AstNode as AstNodeBase, TokenTypes, LintError } from '../base';
|
|
2
2
|
import type { NodeLike } from '../mixin/nodeLike';
|
|
3
3
|
import type { AstText, Token } from '../internal';
|
|
4
|
+
import type { TokenTypeMap, SelectedTokenTypes } from '../map';
|
|
4
5
|
export type AstNodes = AstText | Token;
|
|
5
6
|
export interface Dimension {
|
|
6
7
|
readonly height: number;
|
|
@@ -93,6 +94,7 @@ export declare abstract class AstNode implements AstNodeBase {
|
|
|
93
94
|
* @param type token type / 节点类型
|
|
94
95
|
* @since v1.10.0
|
|
95
96
|
*/
|
|
97
|
+
is<K extends SelectedTokenTypes>(type: K): this is TokenTypeMap[K];
|
|
96
98
|
is<T extends Token>(type: TokenTypes): this is T;
|
|
97
99
|
/**
|
|
98
100
|
* Get the text and the start/end positions of all lines
|
package/dist/lib/node.js
CHANGED
|
@@ -238,13 +238,6 @@ let AstNode = (() => {
|
|
|
238
238
|
...this.getRootNode().posFromIndex(this.getAbsoluteIndex()),
|
|
239
239
|
};
|
|
240
240
|
}
|
|
241
|
-
/**
|
|
242
|
-
* Whether to be of a certain type
|
|
243
|
-
*
|
|
244
|
-
* 是否是某种类型的节点
|
|
245
|
-
* @param type token type / 节点类型
|
|
246
|
-
* @since v1.10.0
|
|
247
|
-
*/
|
|
248
241
|
is(type) {
|
|
249
242
|
return this.type === type;
|
|
250
243
|
}
|
package/dist/lib/text.js
CHANGED
|
@@ -104,7 +104,7 @@ class AstText extends node_1.AstNode {
|
|
|
104
104
|
return [];
|
|
105
105
|
}
|
|
106
106
|
errorRegex.lastIndex = 0;
|
|
107
|
-
const errors = [], nextType = nextSibling?.type, nextName = nextSibling?.name, previousType = previousSibling?.type, root = this.getRootNode(), rootStr = root.toString(), { ext, html, variants } = root.getAttribute('config'), { top, left } = root.posFromIndex(start), { lintConfig } = index_1.default, tagLike = lintConfig.rules['tag-like'], specified =
|
|
107
|
+
const errors = [], nextType = nextSibling?.type, nextName = nextSibling?.name, previousType = previousSibling?.type, root = this.getRootNode(), rootStr = root.toString(), { ext, html, variants } = root.getAttribute('config'), { top, left } = root.posFromIndex(start), { lintConfig } = index_1.default, tagLike = lintConfig.rules['tag-like'], specified = tagLike[1]
|
|
108
108
|
? new Set(Object.keys(tagLike[1]).filter(tag => tag !== 'invalid' && tag !== 'disallowed'))
|
|
109
109
|
: new Set(), tags = new Set([
|
|
110
110
|
'onlyinclude',
|
|
@@ -144,8 +144,7 @@ class AstText extends node_1.AstNode {
|
|
|
144
144
|
// Rule & Severity
|
|
145
145
|
let startIndex = start + index, endIndex = startIndex + length, rule, severity, endLine, endCol;
|
|
146
146
|
const nextChar = rootStr[endIndex], previousChar = rootStr[startIndex - 1], leftBracket = lbrace || lbrack, lConverter = error === '{' && previousChar === '-' && variants.length > 0, rConverter = error === '}' && nextChar === '-' && variants.length > 0, brokenExtLink = lbrack && nextType === 'free-ext-link' && !data.slice(index + 1).trim()
|
|
147
|
-
|| rbrack && previousType === 'free-ext-link'
|
|
148
|
-
&& !data.slice(0, index).includes(']');
|
|
147
|
+
|| rbrack && previousType === 'free-ext-link' && index === 0;
|
|
149
148
|
if (magicLink) {
|
|
150
149
|
rule = 'lonely-http';
|
|
151
150
|
error = error.toUpperCase();
|
package/dist/map.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { RedirectToken, RedirectTargetToken, OnlyincludeToken, IncludeToken, CommentToken, ExtToken, AttributesToken, AttributeToken, AtomToken, ArgToken, TranscludeToken, SyntaxToken, ParameterToken, HeadingToken, HtmlToken, TableToken, TrToken, TdToken, DoubleUnderscoreToken, HrToken, LinkToken, CategoryToken, FileToken, ImageParameterToken, QuoteToken, ExtLinkToken, MagicLinkToken, ListToken, DdToken, ConverterToken, ConverterFlagsToken, ConverterRuleToken, TranslateToken, TvarToken, HiddenToken, GalleryImageToken, ParamLineToken, ImagemapLinkToken } from './internal';
|
|
2
|
+
export interface TokenTypeMap {
|
|
3
|
+
redirect: RedirectToken;
|
|
4
|
+
'redirect-syntax': SyntaxToken;
|
|
5
|
+
'redirect-target': RedirectTargetToken;
|
|
6
|
+
translate: TranslateToken;
|
|
7
|
+
'translate-attr': SyntaxToken;
|
|
8
|
+
tvar: TvarToken;
|
|
9
|
+
'tvar-name': SyntaxToken;
|
|
10
|
+
onlyinclude: OnlyincludeToken;
|
|
11
|
+
include: IncludeToken;
|
|
12
|
+
comment: CommentToken;
|
|
13
|
+
ext: ExtToken;
|
|
14
|
+
'ext-attrs': AttributesToken;
|
|
15
|
+
'ext-attr-dirty': AtomToken;
|
|
16
|
+
'ext-attr': AttributeToken;
|
|
17
|
+
'attr-key': AtomToken;
|
|
18
|
+
arg: ArgToken;
|
|
19
|
+
'arg-name': AtomToken;
|
|
20
|
+
hidden: HiddenToken;
|
|
21
|
+
'magic-word': TranscludeToken;
|
|
22
|
+
'magic-word-name': SyntaxToken;
|
|
23
|
+
'invoke-function': AtomToken;
|
|
24
|
+
'invoke-module': AtomToken;
|
|
25
|
+
template: TranscludeToken;
|
|
26
|
+
'template-name': AtomToken;
|
|
27
|
+
parameter: ParameterToken;
|
|
28
|
+
heading: HeadingToken;
|
|
29
|
+
'heading-trail': SyntaxToken;
|
|
30
|
+
html: HtmlToken;
|
|
31
|
+
'html-attrs': AttributesToken;
|
|
32
|
+
'html-attr-dirty': AtomToken;
|
|
33
|
+
'html-attr': AttributeToken;
|
|
34
|
+
table: TableToken;
|
|
35
|
+
tr: TrToken;
|
|
36
|
+
td: TdToken;
|
|
37
|
+
'table-syntax': SyntaxToken;
|
|
38
|
+
'table-attrs': AttributesToken;
|
|
39
|
+
'table-attr-dirty': AtomToken;
|
|
40
|
+
'table-attr': AttributeToken;
|
|
41
|
+
hr: HrToken;
|
|
42
|
+
'double-underscore': DoubleUnderscoreToken;
|
|
43
|
+
link: LinkToken;
|
|
44
|
+
'link-target': AtomToken;
|
|
45
|
+
category: CategoryToken;
|
|
46
|
+
file: FileToken;
|
|
47
|
+
'gallery-image': GalleryImageToken;
|
|
48
|
+
'imagemap-image': GalleryImageToken;
|
|
49
|
+
'image-parameter': ImageParameterToken;
|
|
50
|
+
quote: QuoteToken;
|
|
51
|
+
'ext-link': ExtLinkToken;
|
|
52
|
+
'ext-link-url': MagicLinkToken;
|
|
53
|
+
'free-ext-link': MagicLinkToken;
|
|
54
|
+
'magic-link': MagicLinkToken;
|
|
55
|
+
list: ListToken;
|
|
56
|
+
dd: DdToken;
|
|
57
|
+
converter: ConverterToken;
|
|
58
|
+
'converter-flags': ConverterFlagsToken;
|
|
59
|
+
'converter-flag': AtomToken;
|
|
60
|
+
'converter-rule': ConverterRuleToken;
|
|
61
|
+
'converter-rule-variant': AtomToken;
|
|
62
|
+
'param-line': ParamLineToken;
|
|
63
|
+
'imagemap-link': ImagemapLinkToken;
|
|
64
|
+
}
|
|
65
|
+
export type SelectedTokenTypes = keyof TokenTypeMap;
|
package/dist/map.js
ADDED
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
import type { AstNodes, Token } from '../internal';
|
|
2
|
+
import type { TokenTypeMap, SelectedTokenTypes } from '../map';
|
|
2
3
|
declare type ElementConstructor = abstract new (...args: any[]) => {
|
|
4
|
+
readonly parentNode: Token | undefined;
|
|
3
5
|
readonly childNodes: readonly AstNodes[];
|
|
4
6
|
};
|
|
5
7
|
export interface ElementLike {
|
|
8
|
+
/**
|
|
9
|
+
* Get the closest ancestor node that matches the selector
|
|
10
|
+
*
|
|
11
|
+
* 最近的符合选择器的祖先节点
|
|
12
|
+
* @param selector selector / 选择器
|
|
13
|
+
*/
|
|
14
|
+
closest<K extends SelectedTokenTypes>(selector: K): TokenTypeMap[K] | undefined;
|
|
15
|
+
closest<T = Token>(selector: string): T | undefined;
|
|
6
16
|
/**
|
|
7
17
|
* Get the first descendant that matches the selector
|
|
8
18
|
*
|
|
9
19
|
* 符合选择器的第一个后代节点
|
|
10
20
|
* @param selector selector / 选择器
|
|
11
21
|
*/
|
|
22
|
+
querySelector<K extends SelectedTokenTypes>(selector: K): TokenTypeMap[K] | undefined;
|
|
12
23
|
querySelector<T = Token>(selector: string): T | undefined;
|
|
13
24
|
/**
|
|
14
25
|
* Get all descendants that match the selector
|
|
@@ -16,6 +27,7 @@ export interface ElementLike {
|
|
|
16
27
|
* 符合选择器的所有后代节点
|
|
17
28
|
* @param selector selector / 选择器
|
|
18
29
|
*/
|
|
30
|
+
querySelectorAll<K extends SelectedTokenTypes>(selector: K): TokenTypeMap[K][];
|
|
19
31
|
querySelectorAll<T = Token>(selector: string): T[];
|
|
20
32
|
/**
|
|
21
33
|
* Escape `=` and `|`
|
|
@@ -5,12 +5,23 @@ const debug_1 = require("../util/debug");
|
|
|
5
5
|
const selector_1 = require("../util/selector");
|
|
6
6
|
/** @ignore */
|
|
7
7
|
const elementLike = (constructor) => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
class ElementLike extends constructor {
|
|
9
|
+
#getCondition(selector) {
|
|
10
|
+
return (0, selector_1.getCondition)(selector, this);
|
|
11
|
+
}
|
|
12
|
+
closest(selector) {
|
|
13
|
+
const condition = this.#getCondition(selector);
|
|
14
|
+
let { parentNode } = this;
|
|
15
|
+
while (parentNode) {
|
|
16
|
+
if (condition(parentNode)) {
|
|
17
|
+
return parentNode;
|
|
18
|
+
}
|
|
19
|
+
({ parentNode } = parentNode);
|
|
12
20
|
}
|
|
13
|
-
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
getElementBy(condition) {
|
|
24
|
+
LINT: {
|
|
14
25
|
const stack = [...this.childNodes].reverse();
|
|
15
26
|
while (stack.length > 0) {
|
|
16
27
|
const child = stack.pop(), { type, childNodes } = child;
|
|
@@ -26,10 +37,12 @@ const elementLike = (constructor) => {
|
|
|
26
37
|
}
|
|
27
38
|
return undefined;
|
|
28
39
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
40
|
+
}
|
|
41
|
+
querySelector(selector) {
|
|
42
|
+
LINT: return this.getElementBy(this.#getCondition(selector));
|
|
43
|
+
}
|
|
44
|
+
getElementsBy(condition) {
|
|
45
|
+
LINT: {
|
|
33
46
|
const stack = [...this.childNodes].reverse(), descendants = [];
|
|
34
47
|
while (stack.length > 0) {
|
|
35
48
|
const child = stack.pop(), { type, childNodes } = child;
|
|
@@ -45,19 +58,19 @@ const elementLike = (constructor) => {
|
|
|
45
58
|
}
|
|
46
59
|
return descendants;
|
|
47
60
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
61
|
+
}
|
|
62
|
+
querySelectorAll(selector) {
|
|
63
|
+
LINT: return this.getElementsBy(this.#getCondition(selector));
|
|
64
|
+
}
|
|
65
|
+
escape() {
|
|
66
|
+
LSP: {
|
|
67
|
+
for (const child of this.childNodes) {
|
|
68
|
+
child.escape();
|
|
56
69
|
}
|
|
57
70
|
}
|
|
58
71
|
}
|
|
59
|
-
(0, debug_1.mixin)(ElementLike, constructor);
|
|
60
|
-
return ElementLike;
|
|
61
72
|
}
|
|
73
|
+
(0, debug_1.mixin)(ElementLike, constructor);
|
|
74
|
+
return ElementLike;
|
|
62
75
|
};
|
|
63
76
|
exports.elementLike = elementLike;
|
package/dist/src/attribute.d.ts
CHANGED
package/dist/src/attribute.js
CHANGED
|
@@ -151,14 +151,14 @@ class AttributeToken extends index_2.Token {
|
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
|
-
else if (name === 'style' &&
|
|
154
|
+
else if (name === 'style' && insecureStyle.test(value)) {
|
|
155
155
|
LINT: {
|
|
156
156
|
rule = 'insecure-style';
|
|
157
157
|
const s = lintConfig.getSeverity(rule);
|
|
158
158
|
return s && (0, lint_1.generateForChild)(lastChild, rect, rule, 'insecure-style', s);
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
|
-
else if (name === 'tabindex' &&
|
|
161
|
+
else if (name === 'tabindex' && value !== '0') {
|
|
162
162
|
LINT: {
|
|
163
163
|
const s = lintConfig.getSeverity(rule, 'tabindex');
|
|
164
164
|
if (s) {
|
|
@@ -173,18 +173,18 @@ class AttributeToken extends index_2.Token {
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
|
-
else if (
|
|
176
|
+
else if ((/^xmlns:[\w:.-]+$/u.test(name) || urlAttrs.has(name)) && evil.test(value)
|
|
177
177
|
|| simple
|
|
178
|
-
&& (name === 'href' || tag === 'img' && name === 'src')
|
|
178
|
+
&& (name === 'href' || type === 'ext-attr' && tag === 'img' && name === 'src')
|
|
179
179
|
&& !new RegExp(String.raw `^(?:${this.getAttribute('config').protocol}|//)\S+$`, 'iu')
|
|
180
|
-
.test(value))
|
|
180
|
+
.test(value)) {
|
|
181
181
|
LINT: {
|
|
182
182
|
const s = lintConfig.getSeverity(rule, 'value');
|
|
183
183
|
return s && (0, lint_1.generateForChild)(lastChild, rect, rule, 'illegal-attribute-value', s);
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
else if (simple && type !== 'ext-attr') {
|
|
187
|
-
const data = (0, lint_1.provideValues)(tag, name), v =
|
|
187
|
+
const data = (0, lint_1.provideValues)(tag, name), v = value.toLowerCase();
|
|
188
188
|
if (data.length > 0 && data.every(n => n !== v)) {
|
|
189
189
|
LINT: {
|
|
190
190
|
const s = lintConfig.getSeverity(rule, 'value');
|
|
@@ -249,7 +249,7 @@ class AttributeToken extends index_2.Token {
|
|
|
249
249
|
* 获取属性值
|
|
250
250
|
*/
|
|
251
251
|
getValue() {
|
|
252
|
-
return this.#equal ? this.lastChild.text().
|
|
252
|
+
return this.#equal ? this.lastChild.text().replace(/[\t\r\n ]+/gu, ' ').trim() : '';
|
|
253
253
|
}
|
|
254
254
|
/** @private */
|
|
255
255
|
escape() {
|
package/dist/src/attributes.d.ts
CHANGED
package/dist/src/attributes.js
CHANGED
|
@@ -146,7 +146,7 @@ class AttributesToken extends index_2.Token {
|
|
|
146
146
|
/** @private */
|
|
147
147
|
lint(start = this.getAbsoluteIndex(), re) {
|
|
148
148
|
LINT: {
|
|
149
|
-
const errors = super.lint(start, re), { parentNode, childNodes, type, name: tag } = this, attrs = new Map(), duplicated = new Set(), rect = new rect_1.BoundingRect(this, start), rules = ['no-ignored', '
|
|
149
|
+
const errors = super.lint(start, re), { parentNode, childNodes, type, name: tag } = this, attrs = new Map(), duplicated = new Set(), rect = new rect_1.BoundingRect(this, start), rules = ['no-ignored', 'required-attr', 'no-duplicate'], { lintConfig } = index_1.default, { computeEditInfo, fix } = lintConfig, s = ['closingTag', 'invalidAttributes', 'nonWordAttributes']
|
|
150
150
|
.map(k => lintConfig.getSeverity(rules[0], k));
|
|
151
151
|
if (s[0] && this.#lint()) {
|
|
152
152
|
const e = (0, lint_1.generateForSelf)(this, rect, rules[0], 'attributes-of-closing-tag', s[0]);
|
|
@@ -182,28 +182,22 @@ class AttributesToken extends index_2.Token {
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
if (type === 'ext-attrs' && required.has(tag)) {
|
|
185
|
-
const severity = lintConfig.getSeverity(rules[
|
|
185
|
+
const severity = lintConfig.getSeverity(rules[1], tag);
|
|
186
186
|
if (severity) {
|
|
187
187
|
for (const key of required.get(tag)) {
|
|
188
|
-
const keys = typeof key === 'string' ? [key] : key
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
});
|
|
192
|
-
if (missing) {
|
|
193
|
-
errors.push((0, lint_1.generateForSelf)(this, rect, rules[2], index_1.default.msg('required-attribute', keys.join('/')), severity));
|
|
188
|
+
const keys = typeof key === 'string' ? [key] : key;
|
|
189
|
+
if (!keys.some(k => this.getAttr(k))) {
|
|
190
|
+
errors.push((0, lint_1.generateForSelf)(this, rect, rules[1], index_1.default.msg('required-attribute', keys.join('/')), severity));
|
|
194
191
|
}
|
|
195
192
|
}
|
|
196
193
|
}
|
|
197
194
|
}
|
|
198
|
-
const severity = lintConfig.getSeverity(rules[
|
|
195
|
+
const severity = lintConfig.getSeverity(rules[2], 'attribute');
|
|
199
196
|
if (severity && duplicated.size > 0) {
|
|
200
197
|
for (const key of duplicated) {
|
|
201
|
-
const pairs = attrs.get(key).map(attr =>
|
|
202
|
-
const value = attr.getValue();
|
|
203
|
-
return [attr, value === true ? '' : value];
|
|
204
|
-
});
|
|
198
|
+
const pairs = attrs.get(key).map(attr => [attr, attr.getValue()]);
|
|
205
199
|
Array.prototype.push.apply(errors, pairs.map(([attr, value], i) => {
|
|
206
|
-
const e = (0, lint_1.generateForChild)(attr, rect, rules[
|
|
200
|
+
const e = (0, lint_1.generateForChild)(attr, rect, rules[2], index_1.default.msg('duplicate-attribute', key), severity);
|
|
207
201
|
if (computeEditInfo || fix) {
|
|
208
202
|
const remove = (0, lint_1.fixByRemove)(e);
|
|
209
203
|
if (!value || pairs.slice(0, i).some(([, v]) => v === value)) {
|
package/dist/src/index.js
CHANGED
|
@@ -372,9 +372,8 @@ class Token extends element_1.AstElement {
|
|
|
372
372
|
}
|
|
373
373
|
/** @private */
|
|
374
374
|
inTableAttrs() {
|
|
375
|
-
return this.isInside('table-attrs')
|
|
376
|
-
? 2
|
|
377
|
-
: 1);
|
|
375
|
+
return this.isInside('table-attrs')
|
|
376
|
+
&& (this.closest('table-attrs,arg,parameter')?.is('table-attrs') ? 2 : 1);
|
|
378
377
|
}
|
|
379
378
|
/** @private */
|
|
380
379
|
inHtmlAttrs() {
|
|
@@ -395,7 +394,7 @@ class Token extends element_1.AstElement {
|
|
|
395
394
|
}
|
|
396
395
|
else {
|
|
397
396
|
const value = cat.getValue();
|
|
398
|
-
if (value
|
|
397
|
+
if (value) {
|
|
399
398
|
key = `#${value}`;
|
|
400
399
|
}
|
|
401
400
|
}
|
package/dist/src/magicLink.js
CHANGED
|
@@ -142,7 +142,7 @@ class MagicLinkToken extends index_2.Token {
|
|
|
142
142
|
.getUrl(articlePath)
|
|
143
143
|
: new URL(link.startsWith('RFC')
|
|
144
144
|
? `https://datatracker.ietf.org/doc/html/rfc${link.slice(4)}`
|
|
145
|
-
: `https://
|
|
145
|
+
: `https://www.ncbi.nlm.nih.gov/pubmed/${link.slice(5)}?dopt=Abstract`);
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
}
|
|
@@ -44,7 +44,7 @@ const base_1 = require("./base");
|
|
|
44
44
|
* 状态开关
|
|
45
45
|
*/
|
|
46
46
|
let DoubleUnderscoreToken = (() => {
|
|
47
|
-
let _classDecorators = [(0, hidden_1.hiddenToken)(), (0, padded_1.padded)('__')];
|
|
47
|
+
let _classDecorators = [(0, hidden_1.hiddenToken)(true, false), (0, padded_1.padded)('__')];
|
|
48
48
|
let _classDescriptor;
|
|
49
49
|
let _classExtraInitializers = [];
|
|
50
50
|
let _classThis;
|
package/dist/src/nowiki/quote.js
CHANGED
|
@@ -46,9 +46,7 @@ class QuoteToken extends base_1.NowikiBaseToken {
|
|
|
46
46
|
/** @private */
|
|
47
47
|
text() {
|
|
48
48
|
const { parentNode, innerText } = this;
|
|
49
|
-
return parentNode?.is('image-parameter') && parentNode.name !== 'caption'
|
|
50
|
-
? ''
|
|
51
|
-
: innerText;
|
|
49
|
+
return parentNode?.is('image-parameter') && parentNode.name !== 'caption' ? '' : innerText;
|
|
52
50
|
}
|
|
53
51
|
/** @private */
|
|
54
52
|
lint(start = this.getAbsoluteIndex()) {
|
package/dist/src/table/td.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export interface TdSpanAttrs {
|
|
|
7
7
|
rowspan?: number;
|
|
8
8
|
colspan?: number;
|
|
9
9
|
}
|
|
10
|
-
declare type TdAttrGetter<T extends string> = T extends keyof TdSpanAttrs ? number : string |
|
|
10
|
+
declare type TdAttrGetter<T extends string> = T extends keyof TdSpanAttrs ? number : string | undefined;
|
|
11
11
|
/**
|
|
12
12
|
* `<td>`, `<th>` or `<caption>`
|
|
13
13
|
*
|
package/dist/src/table/td.js
CHANGED
|
@@ -184,7 +184,7 @@ let TdToken = (() => {
|
|
|
184
184
|
getAttr(key) {
|
|
185
185
|
LINT: {
|
|
186
186
|
const value = super.getAttr(key);
|
|
187
|
-
return (key === 'rowspan' || key === 'colspan' ? parseInt(value) || 1 : value);
|
|
187
|
+
return (key === 'rowspan' || key === 'colspan' ? parseInt(value || '') || 1 : value);
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
/** @private */
|
package/dist/src/tagPair/ext.js
CHANGED
|
@@ -94,6 +94,7 @@ let ExtToken = (() => {
|
|
|
94
94
|
innerToken = new PreToken(inner, newConfig, accum);
|
|
95
95
|
break;
|
|
96
96
|
}
|
|
97
|
+
newConfig.excludes.push('list');
|
|
97
98
|
// fall through
|
|
98
99
|
case 'indicator':
|
|
99
100
|
case 'poem':
|
|
@@ -116,7 +117,9 @@ let ExtToken = (() => {
|
|
|
116
117
|
case 'tab':
|
|
117
118
|
newConfig.ext = newConfig.ext.filter(e => e !== 'tabs');
|
|
118
119
|
break;
|
|
119
|
-
|
|
120
|
+
case 'ref':
|
|
121
|
+
newConfig.ext = newConfig.ext.filter(e => e !== 'references');
|
|
122
|
+
// no default
|
|
120
123
|
}
|
|
121
124
|
innerToken = new index_2.Token(inner, newConfig, accum);
|
|
122
125
|
break;
|
package/dist/util/debug.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.mixin = exports.emptyArray = exports.getMagicWordInfo = exports.setChildNodes = exports.isLink = exports.isRowEnd = exports.
|
|
3
|
+
exports.mixin = exports.emptyArray = exports.getMagicWordInfo = exports.setChildNodes = exports.isLink = exports.isRowEnd = exports.Shadow = void 0;
|
|
4
|
+
exports.isToken = isToken;
|
|
4
5
|
exports.Shadow = {
|
|
5
6
|
running: false,
|
|
6
7
|
/** @private */
|
|
@@ -33,12 +34,9 @@ exports.Shadow = {
|
|
|
33
34
|
},
|
|
34
35
|
rev: 0,
|
|
35
36
|
};
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
*/
|
|
40
|
-
const isToken = (type) => (node) => node.type === type;
|
|
41
|
-
exports.isToken = isToken;
|
|
37
|
+
function isToken(type) {
|
|
38
|
+
return (node) => node.type === type;
|
|
39
|
+
}
|
|
42
40
|
/**
|
|
43
41
|
* 是否是行尾
|
|
44
42
|
* @param token 节点
|
package/dist/util/sharable.js
CHANGED
|
@@ -88,6 +88,8 @@ exports.htmlAttrs = (() => ({
|
|
|
88
88
|
categorytree: blockAttrs,
|
|
89
89
|
combooption: blockAttrs,
|
|
90
90
|
img: new Set(['alt', 'src', 'width', 'height', 'loading', 'srcset']),
|
|
91
|
+
/* NOT FOR BROWSER ONLY */
|
|
92
|
+
a: new Set(['href', 'rel', 'rev']),
|
|
91
93
|
}))();
|
|
92
94
|
exports.extAttrs = (() => ({
|
|
93
95
|
pre: new Set(['format']),
|
package/dist/util/sharable.mjs
CHANGED
|
@@ -85,7 +85,9 @@ const htmlAttrs = /* @__PURE__ */ (() => ({
|
|
|
85
85
|
poem: blockAttrs,
|
|
86
86
|
categorytree: blockAttrs,
|
|
87
87
|
combooption: blockAttrs,
|
|
88
|
-
img: /* @__PURE__ */ new Set(["alt", "src", "width", "height", "loading", "srcset"])
|
|
88
|
+
img: /* @__PURE__ */ new Set(["alt", "src", "width", "height", "loading", "srcset"]),
|
|
89
|
+
/* NOT FOR BROWSER ONLY */
|
|
90
|
+
a: /* @__PURE__ */ new Set(["href", "rel", "rev"])
|
|
89
91
|
}))();
|
|
90
92
|
const extAttrs = /* @__PURE__ */ (() => ({
|
|
91
93
|
pre: /* @__PURE__ */ new Set(["format"]),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wikilint",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.42.0",
|
|
4
4
|
"description": "A Node.js linter for MediaWiki markup",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mediawiki",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"/errors/README",
|
|
19
19
|
"/config/",
|
|
20
20
|
"!/config/mediawikiwiki.json",
|
|
21
|
-
"!/config/
|
|
21
|
+
"!/config/github.json",
|
|
22
22
|
"/data/",
|
|
23
23
|
"/i18n/",
|
|
24
24
|
"/coverage/badge.svg",
|
|
@@ -74,9 +74,9 @@
|
|
|
74
74
|
]
|
|
75
75
|
},
|
|
76
76
|
"dependencies": {
|
|
77
|
-
"@bhsd/cm-util": "^
|
|
77
|
+
"@bhsd/cm-util": "^2.0.1",
|
|
78
78
|
"@bhsd/common": "^2.2.1",
|
|
79
|
-
"@bhsd/stylelint-util": "^1.0.
|
|
79
|
+
"@bhsd/stylelint-util": "^1.0.3",
|
|
80
80
|
"binary-search": "^1.3.6",
|
|
81
81
|
"vscode-languageserver-types": "^3.17.5"
|
|
82
82
|
},
|
|
@@ -84,29 +84,29 @@
|
|
|
84
84
|
"color-name": "~2.0.2",
|
|
85
85
|
"entities": "^8.0.0",
|
|
86
86
|
"mathoid-texvcjs": "^0.6.0",
|
|
87
|
-
"stylelint": "^17.
|
|
87
|
+
"stylelint": "^17.12.0",
|
|
88
88
|
"vscode-css-languageservice": "^6.3.10",
|
|
89
89
|
"vscode-html-languageservice": "^5.6.2",
|
|
90
90
|
"vscode-json-languageservice": "^5.7.2"
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|
|
93
|
-
"@bhsd/code-standard": "^2.
|
|
94
|
-
"@bhsd/nodejs": "^1.0.
|
|
95
|
-
"@bhsd/test-util": "^1.
|
|
93
|
+
"@bhsd/code-standard": "^2.5.1",
|
|
94
|
+
"@bhsd/nodejs": "^1.0.1",
|
|
95
|
+
"@bhsd/test-util": "^1.3.1",
|
|
96
96
|
"@types/color-name": "^2.0.0",
|
|
97
97
|
"@types/color-rgba": "^2.1.3",
|
|
98
98
|
"@types/mocha": "^10.0.10",
|
|
99
|
-
"@types/node": "^
|
|
100
|
-
"@typescript-eslint/parser": "^8.59.
|
|
99
|
+
"@types/node": "^25.9.0",
|
|
100
|
+
"@typescript-eslint/parser": "^8.59.4",
|
|
101
101
|
"c8": "^11.0.0",
|
|
102
102
|
"color-rgba": "^3.0.0",
|
|
103
103
|
"diff2html-cli": "^5.2.15",
|
|
104
104
|
"esbuild": "^0.28.0",
|
|
105
|
-
"eslint": "^10.
|
|
105
|
+
"eslint": "^10.4.1",
|
|
106
106
|
"markdownlint-cli2": "^0.22.1",
|
|
107
|
-
"mocha": "^11.7.
|
|
107
|
+
"mocha": "^11.7.6",
|
|
108
108
|
"typescript": "^6.0.3",
|
|
109
|
-
"v8r": "^6.
|
|
109
|
+
"v8r": "^6.1.0",
|
|
110
110
|
"vscode-languageserver-textdocument": "^1.0.12"
|
|
111
111
|
},
|
|
112
112
|
"engines": {
|