wikilint 2.18.0 → 2.18.2
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 +1 -1
- package/bin/config.js +4 -2
- package/config/.schema.json +14 -1
- package/config/default.json +460 -4
- package/config/enwiki.json +111 -0
- package/config/jawiki.json +954 -0
- package/config/llwiki.json +117 -0
- package/config/minimum.json +3 -0
- package/config/moegirl.json +104 -0
- package/config/zhwiki.json +109 -0
- package/data/signatures.json +141 -353
- package/dist/base.d.mts +10 -1
- package/dist/base.d.ts +10 -1
- package/dist/bin/config.js +67 -39
- package/dist/index.js +7 -5
- package/dist/lib/document.d.ts +6 -6
- package/dist/lib/document.js +43 -36
- package/dist/lib/lsp.d.ts +20 -3
- package/dist/lib/lsp.js +267 -103
- package/dist/src/attribute.js +10 -4
- package/dist/src/index.js +3 -2
- package/dist/src/nowiki/doubleUnderscore.d.ts +1 -0
- package/dist/src/nowiki/doubleUnderscore.js +2 -0
- package/dist/src/transclude.js +20 -9
- package/dist/util/diff.js +1 -1
- package/dist/util/lint.js +32 -1
- package/i18n/zh-hans.json +1 -0
- package/i18n/zh-hant.json +1 -0
- package/package.json +6 -3
package/dist/base.d.mts
CHANGED
|
@@ -5,6 +5,7 @@ export interface Config {
|
|
|
5
5
|
readonly namespaces: Record<string, string>;
|
|
6
6
|
readonly nsid: Record<string, number>;
|
|
7
7
|
readonly variable: string[];
|
|
8
|
+
readonly functionHook: string[];
|
|
8
9
|
readonly parserFunction: [Record<string, string>, Record<string, string> | string[], string[], string[]];
|
|
9
10
|
readonly doubleUnderscore: [string[], string[], Record<string, string>?, Record<string, string>?];
|
|
10
11
|
readonly protocol: string;
|
|
@@ -239,6 +240,13 @@ export interface LanguageService {
|
|
|
239
240
|
* @param text source Wikitext / 源代码
|
|
240
241
|
*/
|
|
241
242
|
provideDocumentSymbols(text: string): Promise<DocumentSymbol[]>;
|
|
243
|
+
/**
|
|
244
|
+
* Set the target Wikipedia
|
|
245
|
+
*
|
|
246
|
+
* 设置目标维基百科
|
|
247
|
+
* @param wiki Wikipedia URL / 维基百科网址
|
|
248
|
+
*/
|
|
249
|
+
setTargetWikipedia(wiki: string): Promise<void>;
|
|
242
250
|
}
|
|
243
251
|
export interface Parser {
|
|
244
252
|
config: Config | string;
|
|
@@ -247,8 +255,9 @@ export interface Parser {
|
|
|
247
255
|
* Get the current parser configuration
|
|
248
256
|
*
|
|
249
257
|
* 获取当前的解析设置
|
|
258
|
+
* @param config unprocessed parser configuration / 未处理的解析设置
|
|
250
259
|
*/
|
|
251
|
-
getConfig(): Config;
|
|
260
|
+
getConfig(config?: Config): Config;
|
|
252
261
|
/**
|
|
253
262
|
* Parse wikitext
|
|
254
263
|
*
|
package/dist/base.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export interface Config {
|
|
|
5
5
|
readonly namespaces: Record<string, string>;
|
|
6
6
|
readonly nsid: Record<string, number>;
|
|
7
7
|
readonly variable: string[];
|
|
8
|
+
readonly functionHook: string[];
|
|
8
9
|
readonly parserFunction: [Record<string, string>, Record<string, string> | string[], string[], string[]];
|
|
9
10
|
readonly doubleUnderscore: [string[], string[], Record<string, string>?, Record<string, string>?];
|
|
10
11
|
readonly protocol: string;
|
|
@@ -239,6 +240,13 @@ export interface LanguageService {
|
|
|
239
240
|
* @param text source Wikitext / 源代码
|
|
240
241
|
*/
|
|
241
242
|
provideDocumentSymbols(text: string): Promise<DocumentSymbol[]>;
|
|
243
|
+
/**
|
|
244
|
+
* Set the target Wikipedia
|
|
245
|
+
*
|
|
246
|
+
* 设置目标维基百科
|
|
247
|
+
* @param wiki Wikipedia URL / 维基百科网址
|
|
248
|
+
*/
|
|
249
|
+
setTargetWikipedia(wiki: string): Promise<void>;
|
|
242
250
|
}
|
|
243
251
|
export interface Parser {
|
|
244
252
|
config: Config | string;
|
|
@@ -247,8 +255,9 @@ export interface Parser {
|
|
|
247
255
|
* Get the current parser configuration
|
|
248
256
|
*
|
|
249
257
|
* 获取当前的解析设置
|
|
258
|
+
* @param config unprocessed parser configuration / 未处理的解析设置
|
|
250
259
|
*/
|
|
251
|
-
getConfig(): Config;
|
|
260
|
+
getConfig(config?: Config): Config;
|
|
252
261
|
/**
|
|
253
262
|
* Parse wikitext
|
|
254
263
|
*
|
package/dist/bin/config.js
CHANGED
|
@@ -8,34 +8,6 @@ const path_1 = __importDefault(require("path"));
|
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
9
|
const assert_1 = __importDefault(require("assert"));
|
|
10
10
|
const cm_1 = require("@bhsd/common/dist/cm");
|
|
11
|
-
const { argv } = process, [, , site, , force, old] = argv;
|
|
12
|
-
let [, , , url] = argv;
|
|
13
|
-
if (!site || !url) {
|
|
14
|
-
console.error('Usage: npx getParserConfig <site> <script path> [force]');
|
|
15
|
-
process.exit(1);
|
|
16
|
-
}
|
|
17
|
-
else if (/(?:\.php|\/)$/u.test(url)) {
|
|
18
|
-
url = url.slice(0, url.lastIndexOf('/'));
|
|
19
|
-
}
|
|
20
|
-
let mwConfig;
|
|
21
|
-
const mw = {
|
|
22
|
-
loader: {
|
|
23
|
-
/** @ignore */
|
|
24
|
-
impl(callback) {
|
|
25
|
-
Object.entries(callback()[1].files).find(([k]) => k.endsWith('.data.js'))[1]();
|
|
26
|
-
},
|
|
27
|
-
/** @ignore */
|
|
28
|
-
implement(_, callback) {
|
|
29
|
-
callback();
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
config: {
|
|
33
|
-
/** @ignore */
|
|
34
|
-
set({ extCodeMirrorConfig }) {
|
|
35
|
-
mwConfig = extCodeMirrorConfig;
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
11
|
/**
|
|
40
12
|
* Converts an array to an object.
|
|
41
13
|
* @param config parser configuration
|
|
@@ -65,14 +37,66 @@ const filterGadget = (id) => {
|
|
|
65
37
|
const n = Number(id);
|
|
66
38
|
return n < 2300 || n > 2303; // Gadget, Gadget talk, Gadget definition, Gadget definition talk
|
|
67
39
|
};
|
|
68
|
-
|
|
69
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Execute the data script.
|
|
42
|
+
* @param obj MediaWiki module implementation
|
|
43
|
+
*/
|
|
44
|
+
const execute = (obj) => {
|
|
45
|
+
Object.entries(obj.files).find(([k]) => k.endsWith('.data.js'))[1]();
|
|
46
|
+
};
|
|
47
|
+
const mw = {
|
|
48
|
+
loader: {
|
|
49
|
+
done: false,
|
|
50
|
+
/** @ignore */
|
|
51
|
+
impl(callback) {
|
|
52
|
+
execute(callback()[1]);
|
|
53
|
+
},
|
|
54
|
+
/** @ignore */
|
|
55
|
+
implement(name, callback) {
|
|
56
|
+
if (typeof callback === 'object') {
|
|
57
|
+
execute(callback);
|
|
58
|
+
}
|
|
59
|
+
else if (!this.done) {
|
|
60
|
+
callback();
|
|
61
|
+
}
|
|
62
|
+
if (name.startsWith('ext.CodeMirror.data')) {
|
|
63
|
+
this.done = true;
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
/** @ignore */
|
|
67
|
+
state() {
|
|
68
|
+
//
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
config: {
|
|
72
|
+
/** @ignore */
|
|
73
|
+
set({ extCodeMirrorConfig }) {
|
|
74
|
+
mwConfig = extCodeMirrorConfig;
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
let mwConfig;
|
|
79
|
+
/**
|
|
80
|
+
* Get the parser configuration for a Wikimedia Foundation project.
|
|
81
|
+
* @param site site nickname
|
|
82
|
+
* @param url script path
|
|
83
|
+
* @param force whether to overwrite the existing configuration
|
|
84
|
+
*/
|
|
85
|
+
exports.default = async (site, url, force) => {
|
|
86
|
+
if (!site || !url) {
|
|
87
|
+
console.error('Usage: npx getParserConfig <site> <script path> [force]');
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
else if (/(?:\.php|\/)$/u.test(url)) {
|
|
91
|
+
url = url.slice(0, url.lastIndexOf('/'));
|
|
92
|
+
}
|
|
93
|
+
const m = await (await fetch(`${url}/load.php?modules=ext.CodeMirror.data|ext.CodeMirror`)).text(), params = {
|
|
70
94
|
action: 'query',
|
|
71
95
|
meta: 'siteinfo',
|
|
72
|
-
siprop:
|
|
96
|
+
siprop: 'general|magicwords|functionhooks|namespaces|namespacealiases',
|
|
73
97
|
format: 'json',
|
|
74
98
|
formatversion: '2',
|
|
75
|
-
}, { query: { general: { variants }, magicwords, namespaces, namespacealiases, variables } } = await (await fetch(`${url}/api.php?${new URLSearchParams(params).toString()}`)).json();
|
|
99
|
+
}, { query: { general: { articlepath, variants }, magicwords, namespaces, namespacealiases, functionhooks, }, } = await (await fetch(`${url}/api.php?${new URLSearchParams(params).toString()}`)).json(), { query: { variables } } = await (await fetch(`${url}/api.php?${new URLSearchParams({ ...params, siprop: 'variables' }).toString()}`)).json();
|
|
76
100
|
eval(m); // eslint-disable-line no-eval
|
|
77
101
|
const dir = path_1.default.join('..', '..', 'config'), ns = Object.entries(namespaces).filter(([id]) => filterGadget(id))
|
|
78
102
|
.flatMap(([id, { name, canonical = '' }]) => [
|
|
@@ -87,8 +111,8 @@ const filterGadget = (id) => {
|
|
|
87
111
|
...ns.map(([id, canonical]) => [canonical.toLowerCase(), Number(id)]),
|
|
88
112
|
...namespacealiases.filter(({ id }) => filterGadget(id)).map(({ id, alias }) => [alias.toLowerCase(), id]),
|
|
89
113
|
]),
|
|
90
|
-
|
|
91
|
-
articlePath:
|
|
114
|
+
functionHook: [...functionhooks.map(s => s.toLowerCase()), 'msgnw'],
|
|
115
|
+
articlePath: articlepath,
|
|
92
116
|
};
|
|
93
117
|
config.doubleUnderscore[0] = [];
|
|
94
118
|
config.doubleUnderscore[1] = [];
|
|
@@ -102,11 +126,15 @@ const filterGadget = (id) => {
|
|
|
102
126
|
}
|
|
103
127
|
config.parserFunction[2] = getAliases(magicwords, new Set(['msg', 'raw']));
|
|
104
128
|
config.parserFunction[3] = getAliases(magicwords, new Set(['subst', 'safesubst']));
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
assert_1.default.deepStrictEqual(arrToObj(require(file)), arrToObj(config));
|
|
129
|
+
if (!config.variable) { // eslint-disable-line @typescript-eslint/no-unnecessary-condition
|
|
130
|
+
Object.assign(config, { variable: [...new Set([...variables, '='])] });
|
|
108
131
|
}
|
|
109
|
-
|
|
132
|
+
const file = path_1.default.join(__dirname, dir, `${site}.json`);
|
|
133
|
+
if (force || !fs_1.default.existsSync(file)) {
|
|
110
134
|
fs_1.default.writeFileSync(file, `${JSON.stringify(config, null, '\t')}\n`);
|
|
111
135
|
}
|
|
112
|
-
|
|
136
|
+
else {
|
|
137
|
+
assert_1.default.deepStrictEqual(arrToObj(require(file)), arrToObj(config));
|
|
138
|
+
}
|
|
139
|
+
return config;
|
|
140
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -26,25 +26,27 @@ const Parser = {
|
|
|
26
26
|
i18n: undefined,
|
|
27
27
|
rules: base_1.rules,
|
|
28
28
|
/** @implements */
|
|
29
|
-
getConfig() {
|
|
29
|
+
getConfig(config) {
|
|
30
30
|
/* NOT FOR BROWSER ONLY */
|
|
31
|
-
if (typeof this.config === 'string') {
|
|
31
|
+
if (!config && typeof this.config === 'string') {
|
|
32
32
|
this.config = rootRequire(this.config, 'config');
|
|
33
33
|
/* istanbul ignore if */
|
|
34
|
-
if (this.config.doubleUnderscore.length < 3
|
|
34
|
+
if (this.config.doubleUnderscore.length < 3
|
|
35
|
+
|| Array.isArray(this.config.parserFunction[1])
|
|
36
|
+
|| !('functionHook' in this.config)) {
|
|
35
37
|
(0, diff_1.error)(`The schema (${path_1.default.resolve(__dirname, '..', 'config', '.schema.json')}) of parser configuration is updated.`);
|
|
36
38
|
}
|
|
37
39
|
return this.getConfig();
|
|
38
40
|
}
|
|
39
41
|
/* NOT FOR BROWSER ONLY END */
|
|
40
|
-
const { doubleUnderscore } =
|
|
42
|
+
const parserConfig = config ?? this.config, { doubleUnderscore } = parserConfig;
|
|
41
43
|
for (let i = 0; i < 2; i++) {
|
|
42
44
|
if (doubleUnderscore.length > i + 2 && doubleUnderscore[i].length === 0) {
|
|
43
45
|
doubleUnderscore[i] = Object.keys(doubleUnderscore[i + 2]);
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
return {
|
|
47
|
-
...
|
|
49
|
+
...parserConfig,
|
|
48
50
|
excludes: [],
|
|
49
51
|
};
|
|
50
52
|
},
|
package/dist/lib/document.d.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type { Position } from 'vscode-languageserver-types';
|
|
2
2
|
import type { TextDocument } from 'vscode-languageserver-textdocument';
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
5
|
-
import type { PublicApi } from 'stylelint';
|
|
3
|
+
import type { JSONDocument } from 'vscode-json-languageservice';
|
|
4
|
+
import type { Stylesheet } from 'vscode-css-languageservice';
|
|
6
5
|
import type { Token } from '../internal';
|
|
7
6
|
export declare const jsonTags: string[];
|
|
8
|
-
declare
|
|
9
|
-
declare const
|
|
10
|
-
export
|
|
7
|
+
export declare const jsonLSP: import("vscode-json-languageservice").LanguageService | undefined;
|
|
8
|
+
export declare const cssLSP: import("vscode-css-languageservice").LanguageService | undefined;
|
|
9
|
+
export declare const stylelint: Promise<import("stylelint").PublicApi | undefined>;
|
|
11
10
|
/** embedded document */
|
|
12
11
|
declare class EmbeddedDocument implements TextDocument {
|
|
13
12
|
#private;
|
|
@@ -52,3 +51,4 @@ export declare class EmbeddedCSSDocument extends EmbeddedDocument {
|
|
|
52
51
|
constructor(root: Token, token: Token);
|
|
53
52
|
getContent(): string;
|
|
54
53
|
}
|
|
54
|
+
export {};
|
package/dist/lib/document.js
CHANGED
|
@@ -7,39 +7,47 @@ exports.EmbeddedCSSDocument = exports.EmbeddedJSONDocument = exports.stylelint =
|
|
|
7
7
|
const path_1 = __importDefault(require("path"));
|
|
8
8
|
const common_1 = require("@bhsd/common");
|
|
9
9
|
exports.jsonTags = ['templatedata', 'mapframe', 'maplink'];
|
|
10
|
-
|
|
11
|
-
try {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
10
|
+
exports.jsonLSP = (() => {
|
|
11
|
+
try {
|
|
12
|
+
const lsp = require('vscode-json-languageservice')
|
|
13
|
+
.getLanguageService({
|
|
14
|
+
/** @implements */
|
|
15
|
+
async schemaRequestService(uri) {
|
|
16
|
+
return (await fetch(uri)).text();
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
lsp.configure({
|
|
20
|
+
schemas: exports.jsonTags.map((tag) => {
|
|
21
|
+
const uri = path_1.default.join('..', '..', 'data', 'ext', tag);
|
|
22
|
+
try {
|
|
23
|
+
const schema = require(uri);
|
|
24
|
+
return {
|
|
25
|
+
uri,
|
|
26
|
+
fileMatch: [tag],
|
|
27
|
+
schema,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}).filter(Boolean),
|
|
34
|
+
});
|
|
35
|
+
return lsp;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
})();
|
|
41
|
+
exports.cssLSP = (() => {
|
|
42
|
+
try {
|
|
43
|
+
return require('vscode-css-languageservice')
|
|
44
|
+
.getCSSLanguageService();
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
})();
|
|
50
|
+
exports.stylelint = (async () => {
|
|
43
51
|
try {
|
|
44
52
|
return (await import('stylelint')).default;
|
|
45
53
|
}
|
|
@@ -47,7 +55,6 @@ const stylelint = (async () => {
|
|
|
47
55
|
return undefined;
|
|
48
56
|
}
|
|
49
57
|
})();
|
|
50
|
-
exports.stylelint = stylelint;
|
|
51
58
|
/** embedded document */
|
|
52
59
|
class EmbeddedDocument {
|
|
53
60
|
uri = '';
|
|
@@ -100,7 +107,7 @@ class EmbeddedJSONDocument extends EmbeddedDocument {
|
|
|
100
107
|
constructor(root, token) {
|
|
101
108
|
super('json', root, token);
|
|
102
109
|
this.uri = token.name;
|
|
103
|
-
this.jsonDoc = jsonLSP.parseJSONDocument(this);
|
|
110
|
+
this.jsonDoc = exports.jsonLSP.parseJSONDocument(this);
|
|
104
111
|
}
|
|
105
112
|
}
|
|
106
113
|
exports.EmbeddedJSONDocument = EmbeddedJSONDocument;
|
|
@@ -113,7 +120,7 @@ class EmbeddedCSSDocument extends EmbeddedDocument {
|
|
|
113
120
|
constructor(root, token) {
|
|
114
121
|
const { type, tag } = token.parentNode;
|
|
115
122
|
super('css', root, token, `${type === 'ext-attr' ? 'div' : tag}{`, '}');
|
|
116
|
-
this.styleSheet = cssLSP.parseStylesheet(this);
|
|
123
|
+
this.styleSheet = exports.cssLSP.parseStylesheet(this);
|
|
117
124
|
}
|
|
118
125
|
getContent() {
|
|
119
126
|
return (0, common_1.sanitizeInlineStyle)(super.getContent());
|
package/dist/lib/lsp.d.ts
CHANGED
|
@@ -1,18 +1,27 @@
|
|
|
1
1
|
import Parser from '../index';
|
|
2
2
|
import type { Range, Position, ColorInformation, ColorPresentation, FoldingRange, DocumentLink, Location, WorkspaceEdit, Diagnostic as DiagnosticBase, TextEdit, Hover, SignatureHelp, InlayHint, CodeAction, DocumentSymbol } from 'vscode-languageserver-types';
|
|
3
|
-
import type { LanguageService as LanguageServiceBase, CompletionItem, SignatureData } from '../base';
|
|
4
|
-
import type { AttributeToken } from '../internal';
|
|
3
|
+
import type { Config, LanguageService as LanguageServiceBase, CompletionItem, SignatureData } from '../base';
|
|
4
|
+
import type { Token, AttributeToken } from '../internal';
|
|
5
5
|
export interface QuickFixData extends TextEdit {
|
|
6
6
|
title: string;
|
|
7
7
|
fix: boolean;
|
|
8
8
|
}
|
|
9
9
|
export declare const tasks: WeakMap<object, Parser.LanguageService>;
|
|
10
|
+
/**
|
|
11
|
+
* Check if a token is a plain attribute.
|
|
12
|
+
* @param token
|
|
13
|
+
* @param token.type
|
|
14
|
+
* @param token.parentNode
|
|
15
|
+
* @param token.length
|
|
16
|
+
* @param token.firstChild
|
|
17
|
+
* @param style whether it is a style attribute
|
|
18
|
+
*/
|
|
19
|
+
export declare const isAttr: ({ type, parentNode, length, firstChild }: Token, style?: boolean) => boolean | undefined;
|
|
10
20
|
/** VSCode-style language service */
|
|
11
21
|
export declare class LanguageService implements LanguageServiceBase {
|
|
12
22
|
#private;
|
|
13
23
|
include: boolean;
|
|
14
24
|
lilypond: string;
|
|
15
|
-
lilypondData: string[];
|
|
16
25
|
/** @param uri 任务标识 */
|
|
17
26
|
constructor(uri: object);
|
|
18
27
|
/** @implements */
|
|
@@ -133,4 +142,12 @@ export declare class LanguageService implements LanguageServiceBase {
|
|
|
133
142
|
* @param text source Wikitext / 源代码
|
|
134
143
|
*/
|
|
135
144
|
provideDocumentSymbols(text: string): Promise<DocumentSymbol[]>;
|
|
145
|
+
/**
|
|
146
|
+
* Set the target Wikipedia
|
|
147
|
+
*
|
|
148
|
+
* 设置目标维基百科
|
|
149
|
+
* @param wiki Wikipedia URL / 维基百科网址
|
|
150
|
+
* @throws `RangeError` 不是有效的维基百科网址
|
|
151
|
+
*/
|
|
152
|
+
setTargetWikipedia(wiki: string): Promise<void>;
|
|
136
153
|
}
|