@bhsd/codemirror-mediawiki 3.9.2 → 3.10.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 +147 -87
- package/dist/bidi.d.ts +9 -8
- package/dist/bidi.js +38 -23
- package/dist/codemirror.d.ts +7 -0
- package/dist/codemirror.js +22 -9
- package/dist/color.d.ts +8 -5
- package/dist/color.js +5 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +1 -0
- package/dist/constants.d.ts +3 -2
- package/dist/constants.js +3 -2
- package/dist/css.d.ts +5 -0
- package/dist/css.js +14 -6
- package/dist/escape.d.ts +22 -2
- package/dist/escape.js +44 -25
- package/dist/fold.d.ts +57 -5
- package/dist/fold.js +149 -58
- package/dist/hover.d.ts +16 -3
- package/dist/hover.js +84 -67
- package/dist/html.js +17 -12
- package/dist/indent.d.ts +7 -0
- package/dist/indent.js +7 -1
- package/dist/index.d.ts +54 -16
- package/dist/index.js +91 -38
- package/dist/inlay.d.ts +1 -1
- package/dist/inlay.js +26 -25
- package/dist/javascript.d.ts +10 -1
- package/dist/javascript.js +50 -2
- package/dist/keybindings.d.ts +1 -0
- package/dist/keybindings.js +1 -0
- package/dist/keymap.d.ts +11 -0
- package/dist/keymap.js +3 -4
- package/dist/linter.d.ts +31 -2
- package/dist/linter.js +10 -3
- package/dist/lintsource.d.ts +47 -3
- package/dist/lintsource.js +50 -11
- package/dist/lua.d.ts +0 -2
- package/dist/lua.js +27 -10
- package/dist/main.min.js +31 -29
- package/dist/matchBrackets.d.ts +16 -0
- package/dist/matchBrackets.js +16 -0
- package/dist/matchTag.d.ts +5 -2
- package/dist/matchTag.js +11 -7
- package/dist/mediawiki.d.ts +15 -2
- package/dist/mediawiki.js +59 -45
- package/dist/mw.min.js +33 -37
- package/dist/mwConfig.js +2 -2
- package/dist/openLinks.d.ts +12 -2
- package/dist/openLinks.js +64 -54
- package/dist/ref.d.ts +16 -2
- package/dist/ref.js +110 -95
- package/dist/signature.d.ts +7 -1
- package/dist/signature.js +53 -49
- package/dist/static.d.ts +4 -0
- package/dist/static.js +4 -0
- package/dist/statusBar.js +9 -8
- package/dist/theme.d.ts +1 -0
- package/dist/theme.js +8 -0
- package/dist/token.d.ts +29 -7
- package/dist/token.js +33 -18
- package/dist/util.d.ts +25 -2
- package/dist/util.js +47 -1
- package/dist/wiki.min.js +32 -36
- package/i18n/en.json +2 -2
- package/i18n/zh-hans.json +2 -2
- package/i18n/zh-hant.json +2 -2
- package/package.json +15 -13
package/dist/mwConfig.js
CHANGED
|
@@ -149,7 +149,7 @@ var getMwConfig = async (modes) => {
|
|
|
149
149
|
config = getStaticMwConfig(parserConfig, modes);
|
|
150
150
|
} else {
|
|
151
151
|
await mw.loader.using("mediawiki.api");
|
|
152
|
-
const { query: { general: { variants }, magicwords, extensiontags, functionhooks, variables } } = await new mw.Api().get({
|
|
152
|
+
const { query: { general: { variants, langconversion }, magicwords, extensiontags, functionhooks, variables } } = await new mw.Api().get({
|
|
153
153
|
meta: "siteinfo",
|
|
154
154
|
siprop: [
|
|
155
155
|
"general",
|
|
@@ -185,7 +185,7 @@ var getMwConfig = async (modes) => {
|
|
|
185
185
|
Object.assign(config, {
|
|
186
186
|
...getKeywords(magicwords, true),
|
|
187
187
|
tagModes: modes,
|
|
188
|
-
variants: getVariants(variants),
|
|
188
|
+
variants: langconversion ? getVariants(variants) : [],
|
|
189
189
|
urlProtocols: mw.config.get("wgUrlProtocols").replace(/\\:/gu, ":")
|
|
190
190
|
});
|
|
191
191
|
(_b = config.variableIDs) != null ? _b : config.variableIDs = variables;
|
package/dist/openLinks.d.ts
CHANGED
|
@@ -2,6 +2,16 @@ import { EditorView } from '@codemirror/view';
|
|
|
2
2
|
import type { Extension } from '@codemirror/state';
|
|
3
3
|
import type { CodeMirror6 } from './codemirror';
|
|
4
4
|
import type { MwConfig } from './token';
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
declare type ISBNParser = (link: string) => string;
|
|
6
|
+
/**
|
|
7
|
+
* @implements
|
|
8
|
+
* @test
|
|
9
|
+
*/
|
|
10
|
+
export declare const getISBNParser: (articlePath?: string) => ISBNParser | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* @ignore
|
|
13
|
+
* @test
|
|
14
|
+
*/
|
|
15
|
+
export declare const mouseEventListener: (e: MouseEvent, view: EditorView, isbnParser?: ISBNParser, titleParser?: MwConfig["titleParser"]) => string | undefined;
|
|
16
|
+
declare const _default: (articlePath?: string) => ({ langConfig }: CodeMirror6) => Extension;
|
|
7
17
|
export default _default;
|
package/dist/openLinks.js
CHANGED
|
@@ -3,42 +3,35 @@ import { ensureSyntaxTree } from '@codemirror/language';
|
|
|
3
3
|
import { tokens } from './config.js';
|
|
4
4
|
import { isMac } from './constants.js';
|
|
5
5
|
import { hasTag } from './util.js';
|
|
6
|
-
const
|
|
6
|
+
const tags = ['extLinkProtocol', 'extLink', 'freeExtLinkProtocol', 'freeExtLink', 'magicLink', 'pageName'], links = ['extlink-protocol', 'extlink', 'free-extlink-protocol', 'free-extlink', 'magic-link'], pagename = '.cm-mw-pagename', wikiLinks = [
|
|
7
7
|
'template-name',
|
|
8
8
|
'link-pagename',
|
|
9
9
|
`parserfunction${pagename}`,
|
|
10
10
|
`exttag-attribute-value${pagename}`,
|
|
11
11
|
`file-text${pagename}`,
|
|
12
|
-
];
|
|
13
|
-
const toggleOpenLinks = (toggle) => {
|
|
14
|
-
|
|
15
|
-
if (toggle) {
|
|
16
|
-
ele.style.setProperty('--codemirror-cursor', 'pointer');
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
ele.style.removeProperty('--codemirror-cursor');
|
|
20
|
-
}
|
|
21
|
-
}
|
|
12
|
+
], modKey = isMac ? 'metaKey' : 'ctrlKey', key = isMac ? 'Meta' : 'Control';
|
|
13
|
+
const toggleOpenLinks = ({ contentDOM }, toggle) => {
|
|
14
|
+
contentDOM.style[toggle ? 'setProperty' : 'removeProperty']('--codemirror-cursor', 'pointer');
|
|
22
15
|
};
|
|
23
|
-
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
|
24
|
-
globalThis.document?.addEventListener('keydown', e => {
|
|
25
|
-
if (e.key === key) {
|
|
26
|
-
toggleOpenLinks(true);
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
globalThis.document?.addEventListener('keyup', e => {
|
|
30
|
-
if (e.key === key) {
|
|
31
|
-
toggleOpenLinks();
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
globalThis.document?.addEventListener('visibilitychange', () => {
|
|
35
|
-
if (document.hidden) {
|
|
36
|
-
toggleOpenLinks();
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
/* eslint-enable @typescript-eslint/no-unnecessary-condition */
|
|
40
16
|
const wrapURL = (url) => url.startsWith('//') ? location.protocol + url : url;
|
|
41
|
-
|
|
17
|
+
/**
|
|
18
|
+
* @implements
|
|
19
|
+
* @test
|
|
20
|
+
*/
|
|
21
|
+
export const getISBNParser = (articlePath) => articlePath
|
|
22
|
+
? (link) => {
|
|
23
|
+
const page = `Special:Booksources/${link.slice(4).replace(/[\p{Zs}\t-]/gu, '')
|
|
24
|
+
.replace(/x$/u, 'X')}`;
|
|
25
|
+
return articlePath.includes('$1')
|
|
26
|
+
? articlePath.replace('$1', page)
|
|
27
|
+
: articlePath + (articlePath.endsWith('/') ? '' : '/') + page;
|
|
28
|
+
}
|
|
29
|
+
: undefined;
|
|
30
|
+
/**
|
|
31
|
+
* @ignore
|
|
32
|
+
* @test
|
|
33
|
+
*/
|
|
34
|
+
export const mouseEventListener = (e, view, isbnParser, titleParser) => {
|
|
42
35
|
if (!e[modKey]
|
|
43
36
|
|| !(e.target instanceof Element && getComputedStyle(e.target).textDecorationLine === 'underline')) {
|
|
44
37
|
return undefined;
|
|
@@ -62,8 +55,8 @@ export const mouseEventListener = (e, view, langConfig) => {
|
|
|
62
55
|
if (name.includes('-extlink-protocol')) {
|
|
63
56
|
return wrapURL(state.sliceDoc(from, node.nextSibling.to));
|
|
64
57
|
}
|
|
65
|
-
else if (name.includes(tokens.pageName) && typeof
|
|
66
|
-
return
|
|
58
|
+
else if (name.includes(tokens.pageName) && typeof titleParser === 'function') {
|
|
59
|
+
return titleParser(state, node);
|
|
67
60
|
}
|
|
68
61
|
else if (/-extlink(?:_|$)/u.test(name)) {
|
|
69
62
|
return wrapURL(state.sliceDoc(node.prevSibling.from, to));
|
|
@@ -76,30 +69,47 @@ export const mouseEventListener = (e, view, langConfig) => {
|
|
|
76
69
|
else if (link.startsWith('PMID')) {
|
|
77
70
|
return `https://pubmed.ncbi.nlm.nih.gov/${link.slice(4).trim()}`;
|
|
78
71
|
}
|
|
79
|
-
|
|
80
|
-
return langConfig.isbnParser(link);
|
|
81
|
-
}
|
|
72
|
+
return isbnParser?.(link);
|
|
82
73
|
}
|
|
83
74
|
return undefined;
|
|
84
75
|
};
|
|
85
|
-
export default ({ langConfig }) =>
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
76
|
+
export default (articlePath) => ({ langConfig }) => {
|
|
77
|
+
const isbnParser = getISBNParser(articlePath || langConfig?.articlePath);
|
|
78
|
+
return [
|
|
79
|
+
EditorView.domEventHandlers({
|
|
80
|
+
mousedown(e, view) {
|
|
81
|
+
if (e.button !== 0) {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
const url = mouseEventListener(e, view, isbnParser, langConfig?.titleParser);
|
|
85
|
+
if (url) {
|
|
86
|
+
open(url, '_blank', 'noreferrer');
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
89
|
return undefined;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
90
|
+
},
|
|
91
|
+
keydown(e, view) {
|
|
92
|
+
if (e.key === key) {
|
|
93
|
+
toggleOpenLinks(view, true);
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
keyup(e, view) {
|
|
97
|
+
if (e.key === key) {
|
|
98
|
+
toggleOpenLinks(view);
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
mousemove(e, view) {
|
|
102
|
+
toggleOpenLinks(view, e[modKey]);
|
|
103
|
+
},
|
|
104
|
+
}),
|
|
105
|
+
EditorView.theme({
|
|
106
|
+
[[
|
|
107
|
+
...links,
|
|
108
|
+
...langConfig?.titleParser ? wikiLinks : [],
|
|
109
|
+
]
|
|
110
|
+
.map(type => `.cm-mw-${type}`).join()]: {
|
|
111
|
+
cursor: 'var(--codemirror-cursor)',
|
|
112
|
+
},
|
|
113
|
+
}),
|
|
114
|
+
];
|
|
115
|
+
};
|
package/dist/ref.d.ts
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
|
-
import type { Extension } from '@codemirror/state';
|
|
1
|
+
import type { EditorState, Extension } from '@codemirror/state';
|
|
2
2
|
import type { CodeMirror6 } from './codemirror';
|
|
3
|
-
|
|
3
|
+
import type { Tag } from './matchTag';
|
|
4
|
+
/**
|
|
5
|
+
* 高亮<ref>内容
|
|
6
|
+
* @param state 编辑器EditorState
|
|
7
|
+
* @param text <ref>内容
|
|
8
|
+
* @test
|
|
9
|
+
*/
|
|
10
|
+
export declare const highlightRef: (state: EditorState, text: string) => string;
|
|
11
|
+
/**
|
|
12
|
+
* 判断是否需要显示悬停提示
|
|
13
|
+
* @ignore
|
|
14
|
+
* @test
|
|
15
|
+
*/
|
|
16
|
+
export declare const needHover: (state: EditorState, { name, selfClosing, first, last }: Tag) => boolean;
|
|
17
|
+
declare const _default: (articlePath?: string) => (cm: CodeMirror6) => Extension;
|
|
4
18
|
export default _default;
|
package/dist/ref.js
CHANGED
|
@@ -6,109 +6,124 @@ import elt from 'crelt';
|
|
|
6
6
|
import { base } from './constants.js';
|
|
7
7
|
import { tokens } from './config.js';
|
|
8
8
|
import { getTag } from './matchTag.js';
|
|
9
|
-
import { indexToPos, posToIndex, escHTML, } from './util.js';
|
|
9
|
+
import { sliceDoc, indexToPos, posToIndex, escHTML, toConfigGetter, } from './util.js';
|
|
10
10
|
const trees = new WeakMap(), selector = '.cm-tooltip-ref', noDef = '.cm-tooltip-no-def';
|
|
11
11
|
/**
|
|
12
12
|
* 获取节点内容
|
|
13
13
|
* @param state
|
|
14
14
|
* @param node 语法树节点
|
|
15
|
-
* @param node.from 起始位置
|
|
16
|
-
* @param node.to 结束位置
|
|
17
15
|
*/
|
|
18
|
-
const getName = (state,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const dom = elt('div', { class: selector.slice(1) });
|
|
56
|
-
dom.style.font = getComputedStyle(view.contentDOM).font;
|
|
57
|
-
if (ref) {
|
|
58
|
-
const { range: { start, end } } = ref[0], anchor = posToIndex(doc, start), head = posToIndex(doc, end), text = state.sliceDoc(anchor, head);
|
|
59
|
-
let result = '';
|
|
60
|
-
highlightCode(text, state.facet(language).parser.parse(text), {
|
|
61
|
-
style(tags) {
|
|
62
|
-
return highlightingFor(state, tags);
|
|
63
|
-
},
|
|
64
|
-
}, (code, classes) => {
|
|
65
|
-
const escaped = escHTML(code);
|
|
66
|
-
result += classes
|
|
67
|
-
? `<span class="${classes}">${escaped}</span>`
|
|
68
|
-
: escaped;
|
|
69
|
-
}, () => {
|
|
70
|
-
result += '<br>';
|
|
71
|
-
});
|
|
72
|
-
dom.innerHTML = result;
|
|
73
|
-
dom.addEventListener('click', () => {
|
|
74
|
-
view.dispatch({
|
|
75
|
-
selection: { anchor, head },
|
|
76
|
-
scrollIntoView: true,
|
|
77
|
-
});
|
|
78
|
-
view.focus();
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
dom.textContent = state.phrase('No definition found');
|
|
83
|
-
dom.classList.add(noDef.slice(1));
|
|
84
|
-
}
|
|
85
|
-
return { dom };
|
|
86
|
-
},
|
|
87
|
-
};
|
|
88
|
-
}
|
|
16
|
+
const getName = (state, node) => sliceDoc(state, node).trim();
|
|
17
|
+
/**
|
|
18
|
+
* 高亮<ref>内容
|
|
19
|
+
* @param state 编辑器EditorState
|
|
20
|
+
* @param text <ref>内容
|
|
21
|
+
* @test
|
|
22
|
+
*/
|
|
23
|
+
export const highlightRef = (state, text) => {
|
|
24
|
+
let result = '';
|
|
25
|
+
highlightCode(text, state.facet(language).parser.parse(text), {
|
|
26
|
+
style(tags) {
|
|
27
|
+
return highlightingFor(state, tags);
|
|
28
|
+
},
|
|
29
|
+
}, (code, classes) => {
|
|
30
|
+
const escaped = escHTML(code);
|
|
31
|
+
result += classes
|
|
32
|
+
? `<span class="${classes}">${escaped}</span>`
|
|
33
|
+
: escaped;
|
|
34
|
+
}, () => {
|
|
35
|
+
result += '<br>';
|
|
36
|
+
});
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* 判断是否需要显示悬停提示
|
|
41
|
+
* @ignore
|
|
42
|
+
* @test
|
|
43
|
+
*/
|
|
44
|
+
export const needHover = (state, { name, selfClosing, first, last }) => {
|
|
45
|
+
if (name === 'ref' && selfClosing) {
|
|
46
|
+
let prevSibling = last, nextSibling = null;
|
|
47
|
+
while (prevSibling && prevSibling.from > first.to) {
|
|
48
|
+
const key = getName(state, prevSibling);
|
|
49
|
+
if (prevSibling.name.split('_').includes(tokens.extTagAttribute)
|
|
50
|
+
&& /(?:^|\s)name(?:$|[\s=])/iu.test(key)) {
|
|
51
|
+
if (/(?:^|\s)name\s*=/iu.test(key)) {
|
|
52
|
+
({ nextSibling } = prevSibling);
|
|
89
53
|
}
|
|
54
|
+
break;
|
|
90
55
|
}
|
|
56
|
+
({ prevSibling } = prevSibling);
|
|
91
57
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
58
|
+
if (nextSibling?.name.includes(tokens.extTagAttributeValue)) {
|
|
59
|
+
let target = getName(state, nextSibling);
|
|
60
|
+
const quote = target.charAt(0);
|
|
61
|
+
if (quote === '"' || quote === "'") {
|
|
62
|
+
target = target.slice(1, target.slice(-1) === quote ? -1 : undefined).trim();
|
|
63
|
+
}
|
|
64
|
+
if (target) {
|
|
65
|
+
return true;
|
|
99
66
|
}
|
|
100
67
|
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
68
|
+
}
|
|
69
|
+
return false;
|
|
70
|
+
};
|
|
71
|
+
export default (articlePath) => (cm) => {
|
|
72
|
+
return [
|
|
73
|
+
hoverTooltip(async (view, pos, side) => {
|
|
74
|
+
const { state } = view, node = ensureSyntaxTree(state, pos)?.resolve(pos, side);
|
|
75
|
+
if (node && node.name.includes('-exttag-')) {
|
|
76
|
+
const tag = getTag(state, node);
|
|
77
|
+
if (tag && needHover(state, tag)) {
|
|
78
|
+
const { doc } = state, ref = await getLSP(view, false, toConfigGetter(cm.getWikiConfig, articlePath), base.CDN)?.provideDefinition(doc.toString(), indexToPos(doc, tag.first.to));
|
|
79
|
+
return {
|
|
80
|
+
pos,
|
|
81
|
+
end: tag.to,
|
|
82
|
+
above: true,
|
|
83
|
+
create() {
|
|
84
|
+
const dom = elt('div', { class: selector.slice(1) });
|
|
85
|
+
dom.style.font = getComputedStyle(view.contentDOM).font;
|
|
86
|
+
if (ref) {
|
|
87
|
+
const { range: { start, end } } = ref[0], anchor = posToIndex(doc, start), head = posToIndex(doc, end);
|
|
88
|
+
dom.innerHTML = highlightRef(state, state.sliceDoc(anchor, head));
|
|
89
|
+
dom.addEventListener('click', () => {
|
|
90
|
+
view.dispatch({
|
|
91
|
+
selection: { anchor, head },
|
|
92
|
+
scrollIntoView: true,
|
|
93
|
+
});
|
|
94
|
+
view.focus();
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
dom.textContent = state.phrase('No definition found');
|
|
99
|
+
dom.classList.add(noDef.slice(1));
|
|
100
|
+
}
|
|
101
|
+
return { dom };
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}),
|
|
108
|
+
EditorView.updateListener.of(({ view, docChanged }) => {
|
|
109
|
+
if (docChanged) {
|
|
110
|
+
const tree = trees.get(view);
|
|
111
|
+
if (tree) {
|
|
112
|
+
tree.docChanged = true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}),
|
|
116
|
+
EditorView.theme({
|
|
117
|
+
[selector]: {
|
|
118
|
+
padding: '2px 5px',
|
|
119
|
+
width: 'max-content',
|
|
120
|
+
maxWidth: '60vw',
|
|
121
|
+
cursor: 'pointer',
|
|
122
|
+
whiteSpace: 'pre-wrap',
|
|
123
|
+
},
|
|
124
|
+
[noDef]: {
|
|
125
|
+
color: 'var(--cm-comment)',
|
|
126
|
+
},
|
|
127
|
+
}),
|
|
128
|
+
];
|
|
129
|
+
};
|
package/dist/signature.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { Extension } from '@codemirror/state';
|
|
2
|
+
import type { SignatureHelp } from 'vscode-languageserver-types';
|
|
2
3
|
import type { CodeMirror6 } from './codemirror';
|
|
3
|
-
|
|
4
|
+
/**
|
|
5
|
+
* @ignore
|
|
6
|
+
* @test
|
|
7
|
+
*/
|
|
8
|
+
export declare const getSignatureHelp: ({ signatures, activeParameter: active }: SignatureHelp) => string;
|
|
9
|
+
declare const _default: (articlePath?: string) => (cm: CodeMirror6) => Extension;
|
|
4
10
|
export default _default;
|
package/dist/signature.js
CHANGED
|
@@ -2,7 +2,7 @@ import { EditorView, showTooltip } from '@codemirror/view';
|
|
|
2
2
|
import { StateField, StateEffect } from '@codemirror/state';
|
|
3
3
|
import { getLSP } from '@bhsd/browser';
|
|
4
4
|
import { base } from './constants.js';
|
|
5
|
-
import { createTooltipView, indexToPos, escHTML, } from './util.js';
|
|
5
|
+
import { createTooltipView, indexToPos, escHTML, toConfigGetter, } from './util.js';
|
|
6
6
|
const stateEffect = StateEffect.define(), field = StateField.define({
|
|
7
7
|
create() {
|
|
8
8
|
return undefined;
|
|
@@ -20,52 +20,56 @@ const stateEffect = StateEffect.define(), field = StateField.define({
|
|
|
20
20
|
return oldValue;
|
|
21
21
|
},
|
|
22
22
|
});
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
23
|
+
/**
|
|
24
|
+
* @ignore
|
|
25
|
+
* @test
|
|
26
|
+
*/
|
|
27
|
+
export const getSignatureHelp = ({ signatures, activeParameter: active }) => signatures.map(({ label, parameters, activeParameter = active }) => {
|
|
28
|
+
const safeLabel = escHTML(label);
|
|
29
|
+
if (activeParameter < 0 || activeParameter >= parameters.length) {
|
|
30
|
+
return safeLabel;
|
|
31
|
+
}
|
|
32
|
+
const colon = safeLabel.indexOf(':'), parts = safeLabel.slice(colon + 1, -2).split('|');
|
|
33
|
+
parts[activeParameter] = `<b>${parts[activeParameter]}</b>`;
|
|
34
|
+
return `${safeLabel.slice(0, colon)}:${parts.join('|')}}}`;
|
|
35
|
+
}).join('<br>');
|
|
36
|
+
export default (articlePath) => (cm) => {
|
|
37
|
+
return [
|
|
38
|
+
field,
|
|
39
|
+
EditorView.updateListener.of(({ view, state, docChanged, selectionSet }) => {
|
|
40
|
+
if (docChanged || selectionSet && state.field(field)?.signatureHelp?.signatures.length) {
|
|
41
|
+
const { doc, selection: { main } } = state, { head: cursor } = main, text = doc.toString();
|
|
42
|
+
if (!main.empty) {
|
|
43
|
+
view.dispatch({
|
|
44
|
+
effects: stateEffect.of({ text, cursor }),
|
|
45
|
+
});
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
(async () => {
|
|
49
|
+
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
|
+
}),
|
|
55
|
+
});
|
|
56
|
+
})();
|
|
33
57
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
const { signatures, activeParameter: active } = signatureHelp;
|
|
55
|
-
return {
|
|
56
|
-
pos: cursor,
|
|
57
|
-
above: true,
|
|
58
|
-
create(view) {
|
|
59
|
-
return createTooltipView(view, signatures.map(({ label, parameters, activeParameter = active }) => {
|
|
60
|
-
const safeLabel = escHTML(label);
|
|
61
|
-
if (activeParameter < 0 || activeParameter >= parameters.length) {
|
|
62
|
-
return safeLabel;
|
|
63
|
-
}
|
|
64
|
-
const colon = safeLabel.indexOf(':'), parts = safeLabel.slice(colon + 1, -2).split('|');
|
|
65
|
-
parts[activeParameter] = `<b>${parts[activeParameter]}</b>`;
|
|
66
|
-
return `${safeLabel.slice(0, colon)}:${parts.join('|')}}}`;
|
|
67
|
-
}).join('<br>'));
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
}),
|
|
71
|
-
];
|
|
58
|
+
}),
|
|
59
|
+
showTooltip.from(field, (value) => {
|
|
60
|
+
if (!value) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const { cursor, signatureHelp } = value;
|
|
64
|
+
return signatureHelp && signatureHelp.signatures.length > 0
|
|
65
|
+
? {
|
|
66
|
+
pos: cursor,
|
|
67
|
+
above: true,
|
|
68
|
+
create(view) {
|
|
69
|
+
return createTooltipView(view, getSignatureHelp(signatureHelp));
|
|
70
|
+
},
|
|
71
|
+
}
|
|
72
|
+
: null;
|
|
73
|
+
}),
|
|
74
|
+
];
|
|
75
|
+
};
|
package/dist/static.d.ts
CHANGED
|
@@ -22,4 +22,8 @@ export declare const tagModes: {
|
|
|
22
22
|
combooption: string;
|
|
23
23
|
inputbox: string;
|
|
24
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
* @ignore
|
|
27
|
+
* @test
|
|
28
|
+
*/
|
|
25
29
|
export declare const getStaticMwConfig: ({ variable, parserFunction: [p0, p1, ...p2], protocol, nsid, functionHook, variants, redirection, ext, doubleUnderscore: [d0, d1, d2, d3], img, }: ConfigData, modes: Record<string, string>) => MwConfig;
|
package/dist/static.js
CHANGED
|
@@ -21,6 +21,10 @@ export const tagModes = {
|
|
|
21
21
|
combooption: 'mediawiki',
|
|
22
22
|
inputbox: 'text/inputbox',
|
|
23
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* @ignore
|
|
26
|
+
* @test
|
|
27
|
+
*/
|
|
24
28
|
export const getStaticMwConfig = ({ variable, parserFunction: [p0, p1, ...p2], protocol, nsid, functionHook, variants, redirection, ext, doubleUnderscore: [d0, d1, d2, d3], img, }, modes) => ({
|
|
25
29
|
tags: Object.fromEntries(ext.map(s => [s, true])),
|
|
26
30
|
tagModes: modes,
|
package/dist/statusBar.js
CHANGED
|
@@ -3,7 +3,7 @@ import { nextDiagnostic, setDiagnosticsEffect } from '@codemirror/lint';
|
|
|
3
3
|
import { gotoLine } from '@codemirror/search';
|
|
4
4
|
import elt from 'crelt';
|
|
5
5
|
import { menuRegistry } from './codemirror.js';
|
|
6
|
-
import { panelSelector, diagnosticSelector, actionSelector, bgDark } from './constants.js';
|
|
6
|
+
import { panelSelector, diagnosticSelector, actionSelector, bgDark, } from './constants.js';
|
|
7
7
|
const statusSelector = '.cm-panel-status', workerSelector = '.cm-status-worker', errorSelector = '.cm-status-error', warningSelector = '.cm-status-warning', enabledSelector = '.cm-status-fix-enabled', disabledSelector = '.cm-status-fix-disabled', menuSelector = '.cm-status-fix-menu', menuHover = `${menuSelector}>div:hover`, messageSelector = '.cm-status-message', workerCls = 'cm-status-worker-enabled', lineCls = 'cm-status-line';
|
|
8
8
|
function getLintMarker(view, severity, menu) {
|
|
9
9
|
const marker = elt('div', { class: `cm-status-${severity}` }), icon = elt('div');
|
|
@@ -43,13 +43,13 @@ const toggleClass = (classList, enabled) => {
|
|
|
43
43
|
classList.toggle(disabledSelector.slice(1), !enabled);
|
|
44
44
|
};
|
|
45
45
|
const getDiagnostics = (all, main) => all.filter(({ from, to }) => from <= main.to && to >= main.from);
|
|
46
|
-
const updateDiagnosticMessage = (
|
|
46
|
+
const updateDiagnosticMessage = (view, allDiagnostics, main, msg) => {
|
|
47
47
|
const diagnostics = getDiagnostics(allDiagnostics, main);
|
|
48
48
|
if (diagnostics.length === 0) {
|
|
49
49
|
msg.textContent = '';
|
|
50
50
|
}
|
|
51
51
|
else {
|
|
52
|
-
const diagnostic = diagnostics.find(({ from, to }) => from <= main.head && to >= main.head) ?? diagnostics[0]
|
|
52
|
+
const diagnostic = diagnostics.find(({ from, to }) => from <= main.head && to >= main.head) ?? diagnostics[0];
|
|
53
53
|
if (diagnostic.renderMessage) {
|
|
54
54
|
msg.replaceChildren(diagnostic.renderMessage(view));
|
|
55
55
|
}
|
|
@@ -94,7 +94,8 @@ const updateMenu = (cm, allDiagnostics, main, classList, optionAll, menu, fixer)
|
|
|
94
94
|
};
|
|
95
95
|
export default (cm, fixer) => [
|
|
96
96
|
showPanel.of(view => {
|
|
97
|
-
let diagnostics = []
|
|
97
|
+
let diagnostics = [];
|
|
98
|
+
let menu;
|
|
98
99
|
if (!view.state.readOnly && (fixer || menuRegistry.length > 0)) {
|
|
99
100
|
menu = elt('div', { class: menuSelector.slice(1), tabIndex: -1 });
|
|
100
101
|
if (fixer) {
|
|
@@ -118,7 +119,7 @@ export default (cm, fixer) => [
|
|
|
118
119
|
});
|
|
119
120
|
view.dom.append(menu);
|
|
120
121
|
}
|
|
121
|
-
const error = getLintMarker(view, 'error'), warning = getLintMarker(view, 'warning'), fix = getLintMarker(view, 'fix', menu), optionAll = elt('div', 'Fix all auto-fixable problems'), worker = elt('div', { class: workerSelector.slice(1) }, error, warning, fix), message = elt('div', { class: messageSelector.slice(1) }), position = elt('div', { class: lineCls }, '0:0'), dom = elt('div', { class: `${panelSelector.slice(1)} ${statusSelector.slice(1)}` }, worker, message, position)
|
|
122
|
+
const error = getLintMarker(view, 'error'), warning = getLintMarker(view, 'warning'), fix = getLintMarker(view, 'fix', menu), { classList } = fix.firstChild, optionAll = elt('div', 'Fix all auto-fixable problems'), worker = elt('div', { class: workerSelector.slice(1) }, error, warning, fix), message = elt('div', { class: messageSelector.slice(1) }), position = elt('div', { class: lineCls }, '0:0'), dom = elt('div', { class: `${panelSelector.slice(1)} ${statusSelector.slice(1)}` }, worker, message, position);
|
|
122
123
|
position.addEventListener('click', () => {
|
|
123
124
|
gotoLine(view);
|
|
124
125
|
});
|
|
@@ -132,13 +133,13 @@ export default (cm, fixer) => [
|
|
|
132
133
|
worker.classList.toggle(workerCls, diagnostics.length > 0);
|
|
133
134
|
updateDiagnosticsCount(diagnostics, 'error', error);
|
|
134
135
|
updateDiagnosticsCount(diagnostics, 'warning', warning);
|
|
135
|
-
updateDiagnosticMessage(
|
|
136
|
+
updateDiagnosticMessage(view, diagnostics, main, message);
|
|
136
137
|
updateMenu(cm, diagnostics, main, classList, optionAll, menu, fixer);
|
|
137
138
|
}
|
|
138
139
|
}
|
|
139
140
|
}
|
|
140
141
|
if (docChanged || selectionSet) {
|
|
141
|
-
updateDiagnosticMessage(
|
|
142
|
+
updateDiagnosticMessage(view, diagnostics, main, message);
|
|
142
143
|
updateMenu(cm, diagnostics, main, classList, optionAll, menu, fixer);
|
|
143
144
|
const { number, from } = doc.lineAt(main.head);
|
|
144
145
|
position.textContent = `${number}:${main.head - from}`;
|
|
@@ -174,7 +175,7 @@ export default (cm, fixer) => [
|
|
|
174
175
|
[`${errorSelector},${warningSelector}`]: {
|
|
175
176
|
paddingRight: '8px',
|
|
176
177
|
},
|
|
177
|
-
[`.${workerCls} ${errorSelector}
|
|
178
|
+
[`.${workerCls} ${errorSelector}, .${workerCls} ${warningSelector}`]: {
|
|
178
179
|
cursor: 'pointer',
|
|
179
180
|
},
|
|
180
181
|
[`${workerSelector}>*>div`]: {
|