@bhsd/codemirror-mediawiki 3.9.1 → 3.10.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 +71 -11
- package/dist/bidi.d.ts +4 -8
- package/dist/bidi.js +33 -23
- package/dist/codemirror.js +15 -9
- package/dist/color.d.ts +1 -1
- package/dist/color.js +1 -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.js +9 -6
- package/dist/escape.d.ts +1 -1
- package/dist/escape.js +4 -3
- package/dist/fold.d.ts +2 -2
- package/dist/fold.js +113 -40
- package/dist/hover.d.ts +2 -2
- package/dist/hover.js +74 -62
- 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.js +45 -2
- package/dist/linter.d.ts +15 -2
- package/dist/linter.js +2 -2
- package/dist/lintsource.d.ts +15 -3
- package/dist/lintsource.js +13 -7
- package/dist/lua.d.ts +0 -2
- package/dist/lua.js +32 -26
- package/dist/main.min.js +31 -29
- package/dist/matchTag.js +4 -3
- package/dist/mediawiki.d.ts +4 -2
- package/dist/mediawiki.js +56 -44
- package/dist/mw.min.js +33 -37
- package/dist/mwConfig.js +2 -2
- package/dist/openLinks.d.ts +4 -2
- package/dist/openLinks.js +56 -54
- package/dist/ref.d.ts +1 -1
- package/dist/ref.js +92 -93
- package/dist/signature.d.ts +1 -1
- package/dist/signature.js +50 -49
- package/dist/statusBar.js +31 -9
- package/dist/theme.js +10 -23
- package/dist/token.d.ts +20 -6
- package/dist/token.js +26 -17
- package/dist/util.d.ts +17 -2
- package/dist/util.js +39 -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 +14 -12
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,8 @@ 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
|
-
declare const
|
|
5
|
+
declare type ISBNParser = (link: string) => string;
|
|
6
|
+
export declare const getISBNParser: (articlePath?: string) => ISBNParser | undefined;
|
|
7
|
+
export declare const mouseEventListener: (e: MouseEvent, view: EditorView, isbnParser?: ISBNParser, titleParser?: MwConfig["titleParser"]) => string | undefined;
|
|
8
|
+
declare const _default: (articlePath?: string) => ({ langConfig }: CodeMirror6) => Extension;
|
|
7
9
|
export default _default;
|
package/dist/openLinks.js
CHANGED
|
@@ -3,42 +3,27 @@ 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
|
-
export const
|
|
17
|
+
export const getISBNParser = (articlePath) => articlePath
|
|
18
|
+
? (link) => {
|
|
19
|
+
const page = `Special:Booksources/${link.slice(4).replace(/[\p{Zs}\t-]/gu, '')
|
|
20
|
+
.replace(/x$/u, 'X')}`;
|
|
21
|
+
return articlePath.includes('$1')
|
|
22
|
+
? articlePath.replace('$1', page)
|
|
23
|
+
: articlePath + (articlePath.endsWith('/') ? '' : '/') + page;
|
|
24
|
+
}
|
|
25
|
+
: undefined;
|
|
26
|
+
export const mouseEventListener = (e, view, isbnParser, titleParser) => {
|
|
42
27
|
if (!e[modKey]
|
|
43
28
|
|| !(e.target instanceof Element && getComputedStyle(e.target).textDecorationLine === 'underline')) {
|
|
44
29
|
return undefined;
|
|
@@ -62,8 +47,8 @@ export const mouseEventListener = (e, view, langConfig) => {
|
|
|
62
47
|
if (name.includes('-extlink-protocol')) {
|
|
63
48
|
return wrapURL(state.sliceDoc(from, node.nextSibling.to));
|
|
64
49
|
}
|
|
65
|
-
else if (name.includes(tokens.pageName) && typeof
|
|
66
|
-
return
|
|
50
|
+
else if (name.includes(tokens.pageName) && typeof titleParser === 'function') {
|
|
51
|
+
return titleParser(state, node);
|
|
67
52
|
}
|
|
68
53
|
else if (/-extlink(?:_|$)/u.test(name)) {
|
|
69
54
|
return wrapURL(state.sliceDoc(node.prevSibling.from, to));
|
|
@@ -76,30 +61,47 @@ export const mouseEventListener = (e, view, langConfig) => {
|
|
|
76
61
|
else if (link.startsWith('PMID')) {
|
|
77
62
|
return `https://pubmed.ncbi.nlm.nih.gov/${link.slice(4).trim()}`;
|
|
78
63
|
}
|
|
79
|
-
|
|
80
|
-
return langConfig.isbnParser(link);
|
|
81
|
-
}
|
|
64
|
+
return isbnParser?.(link);
|
|
82
65
|
}
|
|
83
66
|
return undefined;
|
|
84
67
|
};
|
|
85
|
-
export default ({ langConfig }) =>
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
68
|
+
export default (articlePath) => ({ langConfig }) => {
|
|
69
|
+
const isbnParser = getISBNParser(articlePath || langConfig?.articlePath);
|
|
70
|
+
return [
|
|
71
|
+
EditorView.domEventHandlers({
|
|
72
|
+
mousedown(e, view) {
|
|
73
|
+
if (e.button !== 0) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
const url = mouseEventListener(e, view, isbnParser, langConfig?.titleParser);
|
|
77
|
+
if (url) {
|
|
78
|
+
open(url, '_blank', 'noreferrer');
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
89
81
|
return undefined;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
82
|
+
},
|
|
83
|
+
keydown(e, view) {
|
|
84
|
+
if (e.key === key) {
|
|
85
|
+
toggleOpenLinks(view, true);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
keyup(e, view) {
|
|
89
|
+
if (e.key === key) {
|
|
90
|
+
toggleOpenLinks(view);
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
mousemove(e, view) {
|
|
94
|
+
toggleOpenLinks(view, e[modKey]);
|
|
95
|
+
},
|
|
96
|
+
}),
|
|
97
|
+
EditorView.theme({
|
|
98
|
+
[[
|
|
99
|
+
...links,
|
|
100
|
+
...langConfig?.titleParser ? wikiLinks : [],
|
|
101
|
+
]
|
|
102
|
+
.map(type => `.cm-mw-${type}`).join()]: {
|
|
103
|
+
cursor: 'var(--codemirror-cursor)',
|
|
104
|
+
},
|
|
105
|
+
}),
|
|
106
|
+
];
|
|
107
|
+
};
|
package/dist/ref.d.ts
CHANGED
package/dist/ref.js
CHANGED
|
@@ -6,109 +6,108 @@ 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
|
-
export default (cm) =>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const { name, selfClosing, first, last, to } = tag;
|
|
28
|
-
if (name === 'ref' && selfClosing) {
|
|
29
|
-
let prevSibling = last, nextSibling = null;
|
|
30
|
-
while (prevSibling && prevSibling.from > first.to) {
|
|
31
|
-
const key = getName(state, prevSibling);
|
|
32
|
-
if (prevSibling.name.split('_').includes(tokens.extTagAttribute)
|
|
33
|
-
&& /(?:^|\s)name(?:$|[\s=])/iu.test(key)) {
|
|
34
|
-
if (/(?:^|\s)name\s*=/iu.test(key)) {
|
|
35
|
-
({ nextSibling } = prevSibling);
|
|
36
|
-
}
|
|
37
|
-
break;
|
|
38
|
-
}
|
|
39
|
-
({ prevSibling } = prevSibling);
|
|
16
|
+
const getName = (state, node) => sliceDoc(state, node).trim();
|
|
17
|
+
export default (articlePath) => (cm) => {
|
|
18
|
+
return [
|
|
19
|
+
hoverTooltip(async (view, pos, side) => {
|
|
20
|
+
const { state } = view, node = ensureSyntaxTree(state, pos)?.resolve(pos, side);
|
|
21
|
+
if (node && /-exttag-(?!bracket)/u.test(node.name)) {
|
|
22
|
+
const tag = getTag(state, node);
|
|
23
|
+
if (!tag) {
|
|
24
|
+
return null;
|
|
40
25
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
26
|
+
const { name, selfClosing, first, last, to } = tag;
|
|
27
|
+
if (name === 'ref' && selfClosing) {
|
|
28
|
+
let prevSibling = last, nextSibling = null;
|
|
29
|
+
while (prevSibling && prevSibling.from > first.to) {
|
|
30
|
+
const key = getName(state, prevSibling);
|
|
31
|
+
if (prevSibling.name.split('_').includes(tokens.extTagAttribute)
|
|
32
|
+
&& /(?:^|\s)name(?:$|[\s=])/iu.test(key)) {
|
|
33
|
+
if (/(?:^|\s)name\s*=/iu.test(key)) {
|
|
34
|
+
({ nextSibling } = prevSibling);
|
|
35
|
+
}
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
({ prevSibling } = prevSibling);
|
|
46
39
|
}
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
40
|
+
if (nextSibling?.name.includes(tokens.extTagAttributeValue)) {
|
|
41
|
+
let target = getName(state, nextSibling);
|
|
42
|
+
const quote = target.charAt(0);
|
|
43
|
+
if (quote === '"' || quote === "'") {
|
|
44
|
+
target = target.slice(1, target.slice(-1) === quote ? -1 : undefined).trim();
|
|
45
|
+
}
|
|
46
|
+
if (target) {
|
|
47
|
+
const { doc } = state, ref = await getLSP(view, false, toConfigGetter(cm.getWikiConfig, articlePath), base.CDN)?.provideDefinition(doc.toString(), indexToPos(doc, first.to));
|
|
48
|
+
return {
|
|
49
|
+
pos,
|
|
50
|
+
end: to,
|
|
51
|
+
above: true,
|
|
52
|
+
create() {
|
|
53
|
+
const dom = elt('div', { class: selector.slice(1) });
|
|
54
|
+
dom.style.font = getComputedStyle(view.contentDOM).font;
|
|
55
|
+
if (ref) {
|
|
56
|
+
const { range: { start, end } } = ref[0], anchor = posToIndex(doc, start), head = posToIndex(doc, end), text = state.sliceDoc(anchor, head);
|
|
57
|
+
let result = '';
|
|
58
|
+
highlightCode(text, state.facet(language).parser.parse(text), {
|
|
59
|
+
style(tags) {
|
|
60
|
+
return highlightingFor(state, tags);
|
|
61
|
+
},
|
|
62
|
+
}, (code, classes) => {
|
|
63
|
+
const escaped = escHTML(code);
|
|
64
|
+
result += classes
|
|
65
|
+
? `<span class="${classes}">${escaped}</span>`
|
|
66
|
+
: escaped;
|
|
67
|
+
}, () => {
|
|
68
|
+
result += '<br>';
|
|
69
|
+
});
|
|
70
|
+
dom.innerHTML = result;
|
|
71
|
+
dom.addEventListener('click', () => {
|
|
72
|
+
view.dispatch({
|
|
73
|
+
selection: { anchor, head },
|
|
74
|
+
scrollIntoView: true,
|
|
75
|
+
});
|
|
76
|
+
view.focus();
|
|
77
77
|
});
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
dom
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
};
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
dom.textContent = state.phrase('No definition found');
|
|
81
|
+
dom.classList.add(noDef.slice(1));
|
|
82
|
+
}
|
|
83
|
+
return { dom };
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
88
87
|
}
|
|
89
88
|
}
|
|
90
89
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
90
|
+
return null;
|
|
91
|
+
}),
|
|
92
|
+
EditorView.updateListener.of(({ view, docChanged }) => {
|
|
93
|
+
if (docChanged) {
|
|
94
|
+
const tree = trees.get(view);
|
|
95
|
+
if (tree) {
|
|
96
|
+
tree.docChanged = true;
|
|
97
|
+
}
|
|
99
98
|
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
},
|
|
113
|
-
|
|
114
|
-
|
|
99
|
+
}),
|
|
100
|
+
EditorView.theme({
|
|
101
|
+
[selector]: {
|
|
102
|
+
padding: '2px 5px',
|
|
103
|
+
width: 'max-content',
|
|
104
|
+
maxWidth: '60vw',
|
|
105
|
+
cursor: 'pointer',
|
|
106
|
+
whiteSpace: 'pre-wrap',
|
|
107
|
+
},
|
|
108
|
+
[noDef]: {
|
|
109
|
+
color: 'var(--cm-comment)',
|
|
110
|
+
},
|
|
111
|
+
}),
|
|
112
|
+
];
|
|
113
|
+
};
|
package/dist/signature.d.ts
CHANGED
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,53 @@ const stateEffect = StateEffect.define(), field = StateField.define({
|
|
|
20
20
|
return oldValue;
|
|
21
21
|
},
|
|
22
22
|
});
|
|
23
|
-
export default (cm) =>
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
23
|
+
export default (articlePath) => (cm) => {
|
|
24
|
+
return [
|
|
25
|
+
field,
|
|
26
|
+
EditorView.updateListener.of(({ view, state, docChanged, selectionSet }) => {
|
|
27
|
+
if (docChanged || selectionSet && state.field(field)?.signatureHelp?.signatures.length) {
|
|
28
|
+
const { doc, selection: { main } } = state, { head: cursor } = main, text = doc.toString();
|
|
29
|
+
if (!main.empty) {
|
|
30
|
+
view.dispatch({
|
|
31
|
+
effects: stateEffect.of({ text, cursor }),
|
|
32
|
+
});
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
(async () => {
|
|
36
|
+
view.dispatch({
|
|
37
|
+
effects: stateEffect.of({
|
|
38
|
+
text,
|
|
39
|
+
cursor,
|
|
40
|
+
signatureHelp: await getLSP(view, false, toConfigGetter(cm.getWikiConfig, articlePath), base.CDN)?.provideSignatureHelp(text, indexToPos(doc, cursor)),
|
|
41
|
+
}),
|
|
42
|
+
});
|
|
43
|
+
})();
|
|
33
44
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
];
|
|
45
|
+
}),
|
|
46
|
+
showTooltip.from(field, (value) => {
|
|
47
|
+
if (!value) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const { cursor, signatureHelp } = value;
|
|
51
|
+
if (!signatureHelp || signatureHelp.signatures.length === 0) {
|
|
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
|
+
];
|
|
72
|
+
};
|
package/dist/statusBar.js
CHANGED
|
@@ -3,8 +3,8 @@ 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,
|
|
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', workerCls = 'cm-status-worker-enabled', lineCls = 'cm-status-line';
|
|
6
|
+
import { panelSelector, diagnosticSelector, actionSelector, bgDark, } from './constants.js';
|
|
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');
|
|
10
10
|
if (severity === 'fix') {
|
|
@@ -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`]: {
|
|
@@ -233,4 +234,25 @@ export default (cm, fixer) => [
|
|
|
233
234
|
cursor: 'pointer',
|
|
234
235
|
},
|
|
235
236
|
}),
|
|
237
|
+
EditorView.baseTheme({
|
|
238
|
+
[`&light ${menuSelector}`]: {
|
|
239
|
+
backgroundColor: '#f5f5f5',
|
|
240
|
+
boxShadow: '0 2px 2px 0 rgb(0,0,0,.25)',
|
|
241
|
+
},
|
|
242
|
+
[`&light ${menuHover}`]: {
|
|
243
|
+
backgroundColor: '#e2f2ff',
|
|
244
|
+
},
|
|
245
|
+
[`&light ${messageSelector}`]: {
|
|
246
|
+
borderColor: '#c8ccd1',
|
|
247
|
+
},
|
|
248
|
+
[`&dark ${menuSelector}`]: {
|
|
249
|
+
backgroundColor: '#252a33',
|
|
250
|
+
},
|
|
251
|
+
[`&dark ${menuHover}`]: {
|
|
252
|
+
backgroundColor: bgDark,
|
|
253
|
+
},
|
|
254
|
+
[`&dark ${messageSelector}`]: {
|
|
255
|
+
borderColor: '#000',
|
|
256
|
+
},
|
|
257
|
+
}),
|
|
236
258
|
];
|