@bhsd/codemirror-mediawiki 3.10.2 → 3.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/codemirror.d.ts +3 -1
- package/dist/codemirror.js +8 -1
- package/dist/hover.js +1 -1
- package/dist/html.d.ts +2 -1
- package/dist/html.js +3 -2
- package/dist/javascript-globals.d.ts +1 -0
- package/dist/javascript-globals.js +68 -0
- package/dist/javascript.d.ts +4 -2
- package/dist/javascript.js +46 -22
- package/dist/lintsource.d.ts +2 -1
- package/dist/lintsource.js +24 -2
- package/dist/main.min.js +42 -37
- package/dist/matchTag.js +1 -1
- package/dist/mediawiki.js +2 -2
- package/dist/mw.min.js +45 -40
- package/dist/mwConfig.js +14 -82
- package/dist/openLinks.js +1 -1
- package/dist/ref.js +1 -1
- package/dist/signature.d.ts +4 -1
- package/dist/signature.js +34 -9
- package/dist/token.d.ts +1 -0
- package/dist/util.d.ts +7 -2
- package/dist/util.js +28 -5
- package/dist/vue.d.ts +2 -1
- package/dist/vue.js +3 -2
- package/dist/wiki.min.js +44 -40
- package/i18n/en.json +1 -1
- package/i18n/zh-hans.json +1 -1
- package/i18n/zh-hant.json +1 -1
- package/package.json +17 -20
package/dist/mwConfig.js
CHANGED
|
@@ -1,84 +1,16 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
var cleanAliases = (aliases) => {
|
|
12
|
-
for (const key in aliases) {
|
|
13
|
-
if (/^[^##].*:$/u.test(key)) {
|
|
14
|
-
delete aliases[key];
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
var getConfig = (magicWords, rule, flip) => {
|
|
19
|
-
const words = magicWords.filter(rule);
|
|
20
|
-
return Object.fromEntries(
|
|
21
|
-
(flip === void 0 ? words : words.filter(({ "case-sensitive": i }) => i !== flip)).flatMap(({ aliases, name: n, "case-sensitive": i }) => aliases.map((alias) => ({
|
|
22
|
-
alias: (i ? alias : alias.toLowerCase()).replace(/:$/u, ""),
|
|
23
|
-
name: n
|
|
24
|
-
}))).map(({ alias, name: n }) => [alias, n])
|
|
25
|
-
);
|
|
26
|
-
};
|
|
27
|
-
var getParserConfig = (minConfig, mwConfig) => {
|
|
28
|
-
const {
|
|
29
|
-
tags,
|
|
30
|
-
doubleUnderscore,
|
|
31
|
-
urlProtocols,
|
|
32
|
-
functionSynonyms,
|
|
33
|
-
variableIDs,
|
|
34
|
-
functionHooks,
|
|
35
|
-
redirection
|
|
36
|
-
} = mwConfig, [insensitive, sensitive] = functionSynonyms, behaviorSwitch = doubleUnderscore.map(
|
|
37
|
-
(obj, i) => Object.entries(obj).map(([k, v]) => [
|
|
38
|
-
isUnderscore(k) ? k.slice(2, -2) : k,
|
|
39
|
-
i && typeof v === "string" ? v.toUpperCase() : v
|
|
40
|
-
])
|
|
41
|
-
);
|
|
42
|
-
cleanAliases(insensitive);
|
|
43
|
-
cleanAliases(sensitive);
|
|
44
|
-
for (const [k, v] of Object.entries(insensitive)) {
|
|
45
|
-
if (k in sensitive) {
|
|
46
|
-
delete insensitive[k];
|
|
47
|
-
} else {
|
|
48
|
-
insensitive[k] = v.toLowerCase();
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return {
|
|
52
|
-
...minConfig,
|
|
53
|
-
ext: Object.keys(tags),
|
|
54
|
-
parserFunction: [{ ...insensitive }, { ...sensitive, "=": "=" }, [], []],
|
|
55
|
-
doubleUnderscore: [
|
|
56
|
-
...behaviorSwitch.map(
|
|
57
|
-
(entries) => entries.filter(([k]) => isUnderscore(k)).map(([k]) => k)
|
|
58
|
-
),
|
|
59
|
-
...behaviorSwitch.map(Object.fromEntries)
|
|
60
|
-
],
|
|
61
|
-
protocol: urlProtocols.replace(/\|\\?\/\\?\/$|\\(?=[:/])/gu, ""),
|
|
62
|
-
...variableIDs && { variable: [.../* @__PURE__ */ new Set([...variableIDs, "="])] },
|
|
63
|
-
...functionHooks && { functionHook: [.../* @__PURE__ */ new Set([...functionHooks.map((s) => s.toLowerCase()), "msgnw"])] },
|
|
64
|
-
...redirection && { redirection: redirection.map((s) => s.toLowerCase()) }
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
var getVariants = (variants) => {
|
|
68
|
-
var _a;
|
|
69
|
-
return (_a = variants == null ? void 0 : variants.map(({ code }) => code)) != null ? _a : [];
|
|
70
|
-
};
|
|
71
|
-
var getKeywords = (magicwords, web) => ({
|
|
72
|
-
img: Object.fromEntries(
|
|
73
|
-
magicwords.filter(({ name: n }) => n.startsWith("img_") && n !== "img_lossy").flatMap(({ name: n, aliases }) => {
|
|
74
|
-
const k = web ? n : n.slice(4).replace(/_/gu, "-");
|
|
75
|
-
return (n === "img_alt" ? aliases.filter((alias) => alias.includes("$1")) : aliases).map((alias) => [alias, k]);
|
|
76
|
-
})
|
|
77
|
-
),
|
|
78
|
-
redirection: magicwords.find(({ name: n }) => n === "redirect").aliases.map((s) => s.toLowerCase())
|
|
79
|
-
});
|
|
1
|
+
// mw/config.ts
|
|
2
|
+
import { CDN, setObject, getObject } from "@bhsd/browser";
|
|
3
|
+
import {
|
|
4
|
+
cleanAliases,
|
|
5
|
+
getParserConfig as getParserConfigBase,
|
|
6
|
+
getConfig,
|
|
7
|
+
getVariants,
|
|
8
|
+
getKeywords,
|
|
9
|
+
otherParserFunctions
|
|
10
|
+
} from "@bhsd/cm-util";
|
|
80
11
|
|
|
81
12
|
// src/static.ts
|
|
13
|
+
import { isUnderscore } from "@bhsd/cm-util";
|
|
82
14
|
var getStaticMwConfig = ({
|
|
83
15
|
variable,
|
|
84
16
|
parserFunction: [p0, p1, ...p2],
|
|
@@ -199,14 +131,14 @@ var getMwConfig = async (modes) => {
|
|
|
199
131
|
setObject("InPageEditMwConfig", ALL_SETTINGS_CACHE);
|
|
200
132
|
return { ...config, nsid };
|
|
201
133
|
};
|
|
202
|
-
var
|
|
134
|
+
var getParserConfig = (minConfig, mwConfig) => {
|
|
203
135
|
let config = getObject("wikilintConfig");
|
|
204
136
|
if (config) {
|
|
205
137
|
return config;
|
|
206
138
|
}
|
|
207
139
|
const { nsid, variants, functionSynonyms, img } = mwConfig, [insensitive] = functionSynonyms;
|
|
208
140
|
config = {
|
|
209
|
-
...
|
|
141
|
+
...getParserConfigBase(minConfig, mwConfig),
|
|
210
142
|
namespaces: mw.config.get("wgFormattedNamespaces"),
|
|
211
143
|
nsid,
|
|
212
144
|
variants,
|
|
@@ -228,5 +160,5 @@ var getParserConfig2 = (minConfig, mwConfig) => {
|
|
|
228
160
|
};
|
|
229
161
|
export {
|
|
230
162
|
getMwConfig,
|
|
231
|
-
|
|
163
|
+
getParserConfig
|
|
232
164
|
};
|
package/dist/openLinks.js
CHANGED
|
@@ -48,7 +48,7 @@ export const mouseEventListener = (e, view, isbnParser, titleParser) => {
|
|
|
48
48
|
if (node.name.includes(tokens.linkToSection)) {
|
|
49
49
|
node = node.prevSibling;
|
|
50
50
|
}
|
|
51
|
-
else if (!hasTag(new Set(node.name.split('_')), tags)) {
|
|
51
|
+
else if (node.to === position && !hasTag(new Set(node.name.split('_')), tags)) {
|
|
52
52
|
node = tree.resolve(position, 1);
|
|
53
53
|
}
|
|
54
54
|
const { name, from, to } = node;
|
package/dist/ref.js
CHANGED
|
@@ -72,7 +72,7 @@ export default (articlePath) => (cm) => {
|
|
|
72
72
|
return [
|
|
73
73
|
hoverTooltip(async (view, pos, side) => {
|
|
74
74
|
const { state } = view, node = ensureSyntaxTree(state, pos)?.resolve(pos, side);
|
|
75
|
-
if (node
|
|
75
|
+
if (node?.name.includes('-exttag-')) {
|
|
76
76
|
const tag = getTag(state, node);
|
|
77
77
|
if (tag && needHover(state, tag)) {
|
|
78
78
|
const { doc } = state, ref = await getLSP(view, false, toConfigGetter(cm.getWikiConfig, articlePath), base.CDN)?.provideDefinition(doc.toString(), indexToPos(doc, tag.first.to));
|
package/dist/signature.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { Extension } from '@codemirror/state';
|
|
2
|
-
import type { SignatureHelp } from 'vscode-languageserver-types';
|
|
2
|
+
import type { SignatureHelp as SignatureHelpBase, SignatureInformation } from 'vscode-languageserver-types';
|
|
3
3
|
import type { CodeMirror6 } from './codemirror';
|
|
4
|
+
interface SignatureHelp extends Omit<SignatureHelpBase, 'signatures'> {
|
|
5
|
+
signatures: SignatureInformation[] | string[];
|
|
6
|
+
}
|
|
4
7
|
/**
|
|
5
8
|
* @ignore
|
|
6
9
|
* @test
|
package/dist/signature.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { EditorView, showTooltip } from '@codemirror/view';
|
|
2
2
|
import { StateField, StateEffect } from '@codemirror/state';
|
|
3
|
+
import { syntaxTree } from '@codemirror/language';
|
|
3
4
|
import { getLSP } from '@bhsd/browser';
|
|
4
5
|
import { base } from './constants.js';
|
|
5
|
-
import { createTooltipView, indexToPos, escHTML, toConfigGetter, } from './util.js';
|
|
6
|
+
import { createTooltipView, indexToPos, escHTML, toConfigGetter, findTemplateName, isTemplate, } from './util.js';
|
|
6
7
|
const stateEffect = StateEffect.define(), field = StateField.define({
|
|
7
8
|
create() {
|
|
8
9
|
return undefined;
|
|
@@ -24,8 +25,12 @@ const stateEffect = StateEffect.define(), field = StateField.define({
|
|
|
24
25
|
* @ignore
|
|
25
26
|
* @test
|
|
26
27
|
*/
|
|
27
|
-
export const getSignatureHelp = ({ signatures, activeParameter: active }) => signatures.map(
|
|
28
|
-
|
|
28
|
+
export const getSignatureHelp = ({ signatures, activeParameter: active }) => signatures.map(signature => {
|
|
29
|
+
if (typeof signature === 'string') {
|
|
30
|
+
const safeLabel = escHTML(signature), pipe = safeLabel.indexOf('|'), equal = safeLabel.indexOf('=', pipe);
|
|
31
|
+
return `${safeLabel.slice(0, pipe)}|<b>${safeLabel.slice(pipe + 1, equal)}</b>${safeLabel.slice(equal)}`;
|
|
32
|
+
}
|
|
33
|
+
const { label, parameters, activeParameter = active } = signature, safeLabel = escHTML(label);
|
|
29
34
|
if (activeParameter < 0 || activeParameter >= parameters.length) {
|
|
30
35
|
return safeLabel;
|
|
31
36
|
}
|
|
@@ -46,22 +51,42 @@ export default (articlePath) => (cm) => {
|
|
|
46
51
|
return;
|
|
47
52
|
}
|
|
48
53
|
(async () => {
|
|
54
|
+
let signatureHelp = await getLSP(view, false, toConfigGetter(cm.getWikiConfig, articlePath), base.CDN)?.provideSignatureHelp(text, indexToPos(doc, cursor));
|
|
55
|
+
if (!signatureHelp && typeof cm.langConfig?.templateSignature === 'function') {
|
|
56
|
+
const tree = syntaxTree(state);
|
|
57
|
+
let node = tree.resolve(cursor, -1);
|
|
58
|
+
if (node.to === cursor && !isTemplate(node)) {
|
|
59
|
+
node = tree.resolve(cursor, 1);
|
|
60
|
+
}
|
|
61
|
+
if (isTemplate(node)) {
|
|
62
|
+
const [templateName, parameterName] = findTemplateName(state, node), tooltip = cm.langConfig.templateSignature(templateName, parameterName);
|
|
63
|
+
if (tooltip) {
|
|
64
|
+
signatureHelp = { signatures: [tooltip] };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
49
68
|
view.dispatch({
|
|
50
|
-
effects: stateEffect.of({
|
|
51
|
-
text,
|
|
52
|
-
cursor,
|
|
53
|
-
signatureHelp: await getLSP(view, false, toConfigGetter(cm.getWikiConfig, articlePath), base.CDN)?.provideSignatureHelp(text, indexToPos(doc, cursor)),
|
|
54
|
-
}),
|
|
69
|
+
effects: stateEffect.of({ text, cursor, signatureHelp }),
|
|
55
70
|
});
|
|
56
71
|
})();
|
|
57
72
|
}
|
|
58
73
|
}),
|
|
74
|
+
EditorView.domEventHandlers({
|
|
75
|
+
keydown({ key }, view) {
|
|
76
|
+
if (key === 'Escape') {
|
|
77
|
+
const { doc, selection: { main: { head } } } = view.state;
|
|
78
|
+
view.dispatch({
|
|
79
|
+
effects: stateEffect.of({ text: doc.toString(), cursor: head }),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
}),
|
|
59
84
|
showTooltip.from(field, (value) => {
|
|
60
85
|
if (!value) {
|
|
61
86
|
return null;
|
|
62
87
|
}
|
|
63
88
|
const { cursor, signatureHelp } = value;
|
|
64
|
-
return signatureHelp
|
|
89
|
+
return signatureHelp?.signatures.length
|
|
65
90
|
? {
|
|
66
91
|
pos: cursor,
|
|
67
92
|
above: true,
|
package/dist/token.d.ts
CHANGED
|
@@ -70,6 +70,7 @@ export interface MwConfig extends MwConfigBase {
|
|
|
70
70
|
linkSuggest?: ApiSuggest<string>;
|
|
71
71
|
paramSuggest?: ApiSuggest;
|
|
72
72
|
titleParser?: (state: EditorState, node: SyntaxNode) => string | undefined;
|
|
73
|
+
templateSignature?: (templateName: string | null, parameterName: string) => string | undefined;
|
|
73
74
|
}
|
|
74
75
|
declare class MediaWikiData {
|
|
75
76
|
/** 已解析的节点 */
|
package/dist/util.d.ts
CHANGED
|
@@ -45,12 +45,17 @@ export declare const sliceDoc: (state: EditorState, node: SyntaxNode | Selection
|
|
|
45
45
|
*/
|
|
46
46
|
export declare const braceStackUpdate: (state: EditorState, node: SyntaxNode) => [number, number];
|
|
47
47
|
/**
|
|
48
|
-
*
|
|
48
|
+
* Check if the node is a template parameter value
|
|
49
|
+
* @param node 语法树节点
|
|
50
|
+
*/
|
|
51
|
+
export declare const isTemplate: (node: SyntaxNode) => boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Find the current template name and parameter name
|
|
49
54
|
* @param state
|
|
50
55
|
* @param node 语法树节点
|
|
51
56
|
* @test
|
|
52
57
|
*/
|
|
53
|
-
export declare const findTemplateName: (state: EditorState, node: SyntaxNode) => string | null;
|
|
58
|
+
export declare const findTemplateName: (state: EditorState, node: SyntaxNode) => [string | null, string];
|
|
54
59
|
/**
|
|
55
60
|
* 判断节点是否包含指定类型
|
|
56
61
|
* @param types 节点类型
|
package/dist/util.js
CHANGED
|
@@ -57,17 +57,26 @@ export const braceStackUpdate = (state, node) => {
|
|
|
57
57
|
return [brackets.split('{{').length - 1, 1 - brackets.split('}}').length];
|
|
58
58
|
};
|
|
59
59
|
/**
|
|
60
|
-
*
|
|
60
|
+
* Check if the node is a template parameter value
|
|
61
|
+
* @param node 语法树节点
|
|
62
|
+
*/
|
|
63
|
+
export const isTemplate = (node) => node.name.split('_').includes(tokens.template);
|
|
64
|
+
/**
|
|
65
|
+
* Find the current template name and parameter name
|
|
61
66
|
* @param state
|
|
62
67
|
* @param node 语法树节点
|
|
63
68
|
* @test
|
|
64
69
|
*/
|
|
65
70
|
export const findTemplateName = (state, node) => {
|
|
66
71
|
let stack = -1, { prevSibling } = node,
|
|
67
|
-
/** 可包含`_`、`:`等 */ page = '';
|
|
72
|
+
/** 可包含`_`、`:`等 */ page = '', parameter = '', need = isTemplate(node);
|
|
68
73
|
while (prevSibling) {
|
|
69
74
|
const { name } = prevSibling;
|
|
70
75
|
if (name.includes(tokens.templateBracket)) {
|
|
76
|
+
if (need && parameter) {
|
|
77
|
+
need = false;
|
|
78
|
+
parameter = '';
|
|
79
|
+
}
|
|
71
80
|
const [lbrace, rbrace] = braceStackUpdate(state, prevSibling);
|
|
72
81
|
stack += lbrace;
|
|
73
82
|
if (stack >= 0) {
|
|
@@ -75,8 +84,22 @@ export const findTemplateName = (state, node) => {
|
|
|
75
84
|
}
|
|
76
85
|
stack += rbrace;
|
|
77
86
|
}
|
|
78
|
-
else if (stack === -1
|
|
79
|
-
|
|
87
|
+
else if (stack === -1) {
|
|
88
|
+
if (name.includes(tokens.templateName)) {
|
|
89
|
+
page = sliceDoc(state, prevSibling) + page;
|
|
90
|
+
}
|
|
91
|
+
else if (need) {
|
|
92
|
+
if (name.includes(tokens.templateDelimiter)) {
|
|
93
|
+
need = false;
|
|
94
|
+
}
|
|
95
|
+
else if (name.includes(tokens.templateArgumentName)) {
|
|
96
|
+
parameter = sliceDoc(state, prevSibling) + parameter;
|
|
97
|
+
}
|
|
98
|
+
else if (parameter && !name.includes(tokens.comment)) {
|
|
99
|
+
need = false;
|
|
100
|
+
parameter = '';
|
|
101
|
+
}
|
|
102
|
+
}
|
|
80
103
|
}
|
|
81
104
|
else if (page && !name.includes(tokens.comment)) {
|
|
82
105
|
prevSibling = null;
|
|
@@ -84,7 +107,7 @@ export const findTemplateName = (state, node) => {
|
|
|
84
107
|
}
|
|
85
108
|
({ prevSibling } = prevSibling);
|
|
86
109
|
}
|
|
87
|
-
return prevSibling && page;
|
|
110
|
+
return [prevSibling && page, parameter];
|
|
88
111
|
};
|
|
89
112
|
/**
|
|
90
113
|
* 判断节点是否包含指定类型
|
package/dist/vue.d.ts
CHANGED
package/dist/vue.js
CHANGED
|
@@ -3,12 +3,13 @@ import { htmlLanguage, htmlCompletionSource } from '@codemirror/lang-html';
|
|
|
3
3
|
import { javascript } from '@codemirror/lang-javascript';
|
|
4
4
|
import { LanguageSupport } from '@codemirror/language';
|
|
5
5
|
import { cssCompletion } from './css.js';
|
|
6
|
-
import { jsCompletion } from './javascript.js';
|
|
7
|
-
export default () => vue({
|
|
6
|
+
import { jsCompletion, markGlobalsPlugin } from './javascript.js';
|
|
7
|
+
export default (_, cm) => vue({
|
|
8
8
|
base: new LanguageSupport(htmlLanguage, [
|
|
9
9
|
htmlLanguage.data.of({ autocomplete: htmlCompletionSource }),
|
|
10
10
|
javascript().support,
|
|
11
11
|
jsCompletion,
|
|
12
12
|
cssCompletion(),
|
|
13
|
+
markGlobalsPlugin(cm),
|
|
13
14
|
]),
|
|
14
15
|
});
|