@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.
Files changed (67) hide show
  1. package/README.md +147 -87
  2. package/dist/bidi.d.ts +9 -8
  3. package/dist/bidi.js +38 -23
  4. package/dist/codemirror.d.ts +7 -0
  5. package/dist/codemirror.js +22 -9
  6. package/dist/color.d.ts +8 -5
  7. package/dist/color.js +5 -1
  8. package/dist/config.d.ts +1 -0
  9. package/dist/config.js +1 -0
  10. package/dist/constants.d.ts +3 -2
  11. package/dist/constants.js +3 -2
  12. package/dist/css.d.ts +5 -0
  13. package/dist/css.js +14 -6
  14. package/dist/escape.d.ts +22 -2
  15. package/dist/escape.js +44 -25
  16. package/dist/fold.d.ts +57 -5
  17. package/dist/fold.js +149 -58
  18. package/dist/hover.d.ts +16 -3
  19. package/dist/hover.js +84 -67
  20. package/dist/html.js +17 -12
  21. package/dist/indent.d.ts +7 -0
  22. package/dist/indent.js +7 -1
  23. package/dist/index.d.ts +54 -16
  24. package/dist/index.js +91 -38
  25. package/dist/inlay.d.ts +1 -1
  26. package/dist/inlay.js +26 -25
  27. package/dist/javascript.d.ts +10 -1
  28. package/dist/javascript.js +50 -2
  29. package/dist/keybindings.d.ts +1 -0
  30. package/dist/keybindings.js +1 -0
  31. package/dist/keymap.d.ts +11 -0
  32. package/dist/keymap.js +3 -4
  33. package/dist/linter.d.ts +31 -2
  34. package/dist/linter.js +10 -3
  35. package/dist/lintsource.d.ts +47 -3
  36. package/dist/lintsource.js +50 -11
  37. package/dist/lua.d.ts +0 -2
  38. package/dist/lua.js +27 -10
  39. package/dist/main.min.js +31 -29
  40. package/dist/matchBrackets.d.ts +16 -0
  41. package/dist/matchBrackets.js +16 -0
  42. package/dist/matchTag.d.ts +5 -2
  43. package/dist/matchTag.js +11 -7
  44. package/dist/mediawiki.d.ts +15 -2
  45. package/dist/mediawiki.js +59 -45
  46. package/dist/mw.min.js +33 -37
  47. package/dist/mwConfig.js +2 -2
  48. package/dist/openLinks.d.ts +12 -2
  49. package/dist/openLinks.js +64 -54
  50. package/dist/ref.d.ts +16 -2
  51. package/dist/ref.js +110 -95
  52. package/dist/signature.d.ts +7 -1
  53. package/dist/signature.js +53 -49
  54. package/dist/static.d.ts +4 -0
  55. package/dist/static.js +4 -0
  56. package/dist/statusBar.js +9 -8
  57. package/dist/theme.d.ts +1 -0
  58. package/dist/theme.js +8 -0
  59. package/dist/token.d.ts +29 -7
  60. package/dist/token.js +33 -18
  61. package/dist/util.d.ts +25 -2
  62. package/dist/util.js +47 -1
  63. package/dist/wiki.min.js +32 -36
  64. package/i18n/en.json +2 -2
  65. package/i18n/zh-hans.json +2 -2
  66. package/i18n/zh-hant.json +2 -2
  67. 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;
@@ -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
- export declare const mouseEventListener: (e: MouseEvent, view: EditorView, langConfig: MwConfig | undefined) => string | undefined;
6
- declare const _default: ({ langConfig }: CodeMirror6) => Extension;
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 modKey = isMac ? 'metaKey' : 'ctrlKey', key = isMac ? 'Meta' : 'Control', tags = ['extLinkProtocol', 'extLink', 'freeExtLinkProtocol', 'freeExtLink', 'magicLink', 'pageName'], links = ['extlink-protocol', 'extlink', 'free-extlink-protocol', 'free-extlink', 'magic-link'], pagename = '.cm-mw-pagename', wikiLinks = [
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
- for (const ele of document.querySelectorAll('.cm-content')) {
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 mouseEventListener = (e, view, langConfig) => {
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 langConfig?.titleParser === 'function') {
66
- return langConfig.titleParser(state, node);
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
- else if (typeof langConfig?.isbnParser === 'function') {
80
- return langConfig.isbnParser(link);
81
- }
72
+ return isbnParser?.(link);
82
73
  }
83
74
  return undefined;
84
75
  };
85
- export default ({ langConfig }) => [
86
- EditorView.domEventHandlers({
87
- mousedown(e, view) {
88
- if (e.button !== 0) {
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
- const url = mouseEventListener(e, view, langConfig);
92
- if (url) {
93
- open(url, '_blank', 'noopener noreferrer');
94
- return true;
95
- }
96
- return undefined;
97
- },
98
- }),
99
- EditorView.theme({
100
- [[...links, ...langConfig?.titleParser ? wikiLinks : []]
101
- .map(type => `.cm-mw-${type}`).join()]: {
102
- cursor: 'var(--codemirror-cursor)',
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
- declare const _default: (cm: CodeMirror6) => Extension;
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, { from, to }) => state.sliceDoc(from, to).trim();
19
- export default (cm) => [
20
- hoverTooltip(async (view, pos, side) => {
21
- const { state } = view, node = ensureSyntaxTree(state, pos)?.resolve(pos, side);
22
- if (node && /-exttag-(?!bracket)/u.test(node.name)) {
23
- const tag = getTag(state, node);
24
- if (!tag) {
25
- return null;
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);
40
- }
41
- if (nextSibling?.name.includes(tokens.extTagAttributeValue)) {
42
- let target = getName(state, nextSibling);
43
- const quote = target.charAt(0);
44
- if (quote === '"' || quote === "'") {
45
- target = target.slice(1, target.slice(-1) === quote ? -1 : undefined).trim();
46
- }
47
- if (target) {
48
- const { doc } = state, ref = await getLSP(view, false, cm.getWikiConfig, base.CDN)
49
- ?.provideDefinition(doc.toString(), indexToPos(doc, first.to));
50
- return {
51
- pos,
52
- end: to,
53
- above: true,
54
- create() {
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
- return null;
93
- }),
94
- EditorView.updateListener.of(({ view, docChanged }) => {
95
- if (docChanged) {
96
- const tree = trees.get(view);
97
- if (tree) {
98
- tree.docChanged = true;
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
- EditorView.theme({
103
- [selector]: {
104
- padding: '2px 5px',
105
- width: 'max-content',
106
- maxWidth: '60vw',
107
- cursor: 'pointer',
108
- whiteSpace: 'pre-wrap',
109
- },
110
- [noDef]: {
111
- color: 'var(--cm-comment)',
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
+ };
@@ -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
- declare const _default: (cm: CodeMirror6) => Extension;
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
- export default (cm) => [
24
- field,
25
- EditorView.updateListener.of(({ view, state, docChanged, selectionSet }) => {
26
- if (docChanged || selectionSet && state.field(field)?.signatureHelp?.signatures.length) {
27
- const { doc, selection: { main } } = state, { head: cursor } = main, text = doc.toString();
28
- if (!main.empty) {
29
- view.dispatch({
30
- effects: stateEffect.of({ text, cursor }),
31
- });
32
- return;
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
- (async () => {
35
- view.dispatch({
36
- effects: stateEffect.of({
37
- text,
38
- cursor,
39
- signatureHelp: await getLSP(view, false, cm.getWikiConfig, base.CDN)
40
- ?.provideSignatureHelp(text, indexToPos(doc, cursor)),
41
- }),
42
- });
43
- })();
44
- }
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
- ];
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 = (cm, allDiagnostics, main, msg) => {
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], view = cm.view;
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 = [], menu;
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), { classList } = fix.firstChild;
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(cm, diagnostics, main, message);
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(cm, diagnostics, main, message);
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},.${workerCls} ${warningSelector}`]: {
178
+ [`.${workerCls} ${errorSelector}, .${workerCls} ${warningSelector}`]: {
178
179
  cursor: 'pointer',
179
180
  },
180
181
  [`${workerSelector}>*>div`]: {