@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/index.d.ts CHANGED
@@ -31,30 +31,64 @@ export declare const registerCodeFolding: () => void;
31
31
  export declare const registerColorPicker: () => void;
32
32
  /** Register all common extensions */
33
33
  export declare const registerCommonExtensions: () => void;
34
- /** Register MediaWiki language support */
35
- export declare const registerMediaWiki: () => void;
36
- /** Register the `openLinks` extension */
37
- export declare const registerOpenLinks: () => void;
38
- /** Register the `escape` extension */
39
- export declare const registerEscape: () => void;
40
- /** Register the `refHover` extension */
41
- export declare const registerRefHover: () => void;
42
- /** Register the `hover` extension */
43
- export declare const registerHover: () => void;
44
- /** Register the `signatureHelp` extension */
45
- export declare const registerSignatureHelp: () => void;
46
- /** Register the `inlayHints` extension */
47
- export declare const registerInlayHints: () => void;
34
+ /**
35
+ * Register MediaWiki language support
36
+ * @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
37
+ * @param templatedata whether to use [Extension:TemplateData](https://www.mediawiki.org/wiki/Extension:TemplateData)
38
+ * for template hover information; enabled by default
39
+ */
40
+ export declare const registerMediaWiki: (articlePath?: string, templatedata?: boolean) => void;
41
+ /**
42
+ * Register the `openLinks` extension
43
+ * @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
44
+ */
45
+ export declare const registerOpenLinks: (articlePath?: string) => void;
46
+ /**
47
+ * Register the `escape` extension
48
+ * @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
49
+ */
50
+ export declare const registerEscape: (articlePath?: string) => void;
51
+ /**
52
+ * Register the `refHover` extension
53
+ * @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
54
+ */
55
+ export declare const registerRefHover: (articlePath?: string) => void;
56
+ /**
57
+ * Register the `hover` extension
58
+ * @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
59
+ * @param templatedata whether to use [Extension:TemplateData](https://www.mediawiki.org/wiki/Extension:TemplateData)
60
+ * for template information; enabled by default
61
+ */
62
+ export declare const registerHover: (articlePath?: string, templatedata?: boolean) => void;
63
+ /**
64
+ * Register the `signatureHelp` extension
65
+ * @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
66
+ */
67
+ export declare const registerSignatureHelp: (articlePath?: string) => void;
68
+ /**
69
+ * Register the `inlayHints` extension
70
+ * @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
71
+ */
72
+ export declare const registerInlayHints: (articlePath?: string) => void;
73
+ /** Register the `bidiIsolates` extension */
74
+ export declare const registerBidiIsolates: () => void;
48
75
  /** Register the `colorPicker` extension for MediaWiki */
49
76
  export declare const registerColorPickerForMediaWiki: () => void;
50
77
  /** Register the `bracketMatching` extension for MediaWiki */
51
78
  export declare const registerBracketMatchingForMediaWiki: () => void;
52
79
  /** Register the `codeFolding` extension for MediaWiki */
53
80
  export declare const registerCodeFoldingForMediaWiki: () => void;
54
- /** Register MediaWiki core language support */
55
- export declare const registerMediaWikiCore: () => void;
81
+ /**
82
+ * Register MediaWiki core language support
83
+ * @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
84
+ * @param templatedata whether to use [Extension:TemplateData](https://www.mediawiki.org/wiki/Extension:TemplateData)
85
+ * for template parameter autocompletion
86
+ */
87
+ export declare const registerMediaWikiCore: (articlePath?: string, templatedata?: boolean) => void;
56
88
  /** Register mixed MediaWiki-HTML language support */
57
89
  export declare const registerHTML: () => void;
90
+ /** Register the `bracketMatching` extension for mixed MediaWiki-HTML */
91
+ export declare const registerBracketMatchingForHTML: () => void;
58
92
  /** Register the `closeBrackets` extension for mixed MediaWiki-HTML */
59
93
  export declare const registerCloseBracketsForHTML: () => void;
60
94
  /** Register the `colorPicker` extension for mixed MediaWiki-HTML */
@@ -87,6 +121,10 @@ export declare const registerCloseBracketsForVue: () => void;
87
121
  export declare const registerColorPickerForVue: () => void;
88
122
  /** Register Vue core language support */
89
123
  export declare const registerVueCore: () => void;
124
+ /** Register AbuseFilter language support */
125
+ export declare const registerAbuseFilter: () => void;
126
+ /** Register AbuseFilter core language support */
127
+ export declare const registerAbuseFilterCore: () => void;
90
128
  /**
91
129
  * Register a custom language support
92
130
  * @param name language name
package/dist/index.js CHANGED
@@ -4,13 +4,14 @@ import { highlightSelectionMatches } from '@codemirror/search';
4
4
  import { autocompletion, closeBrackets, acceptCompletion, completionKeymap, startCompletion, } from '@codemirror/autocomplete';
5
5
  import { json } from '@codemirror/lang-json';
6
6
  import { autoCloseTags } from '@codemirror/lang-html';
7
+ import { abusefilter, analyzer } from '@bhsd/lezer-abusefilter';
7
8
  import { getLSP } from '@bhsd/browser';
8
9
  import { colorPicker } from '@bhsd/codemirror-css-color-picker';
9
- import bidiIsolation from './bidi.js';
10
+ import bidiIsolates from './bidi.js';
10
11
  import { CodeMirror6, avail, languages, linterRegistry, destroyListeners, plain, optionalFunctions, themes, } from './codemirror.js';
11
12
  import mediawikiColorPicker from './color.js';
12
13
  import escapeKeymap from './escape.js';
13
- import codeFolding, { mediaWikiFold, foldHandler } from './fold.js';
14
+ import codeFolding, { mediawikiFold, foldHandler } from './fold.js';
14
15
  import magicWordHover from './hover.js';
15
16
  import { detectIndent } from './indent.js';
16
17
  import inlayHints from './inlay.js';
@@ -18,10 +19,10 @@ import formatKeymap from './keymap.js';
18
19
  import { getWikiLintSource, getJsLintSource, getCssLintSource, getJsonLintSource, getLuaLintSource, getVueLintSource, getHTMLLintSource, } from './lintsource.js';
19
20
  import bracketMatchingBase from './matchBrackets.js';
20
21
  import tagMatchingState from './matchTag.js';
21
- import { mediawikiBase } from './mediawiki.js';
22
+ import { mediawikiBase, } from './mediawiki.js';
22
23
  import openLinks from './openLinks.js';
23
24
  import refHover from './ref.js';
24
- import signatureHelp from './signature.js';
25
+ import signatureHelpBase from './signature.js';
25
26
  import { tagModes, getStaticMwConfig } from './static.js';
26
27
  import statusBar from './statusBar.js';
27
28
  import css from './css.js';
@@ -139,16 +140,21 @@ const registerLangExtension = (lang, name, ext) => {
139
140
  addon[1] ??= {};
140
141
  addon[1][lang] = ext;
141
142
  };
142
- /** Register MediaWiki language support */
143
- export const registerMediaWiki = () => {
143
+ /**
144
+ * Register MediaWiki language support
145
+ * @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
146
+ * @param templatedata whether to use [Extension:TemplateData](https://www.mediawiki.org/wiki/Extension:TemplateData)
147
+ * for template hover information; enabled by default
148
+ */
149
+ export const registerMediaWiki = (articlePath, templatedata) => {
144
150
  registerCommonExtensions();
145
- registerMediaWikiCore();
146
- registerOpenLinks();
147
- registerEscape();
148
- registerRefHover();
149
- registerHover();
150
- registerSignatureHelp();
151
- registerInlayHints();
151
+ registerMediaWikiCore(articlePath, templatedata);
152
+ registerOpenLinks(articlePath);
153
+ registerEscape(articlePath);
154
+ registerRefHover(articlePath);
155
+ registerHover(articlePath, templatedata);
156
+ registerSignatureHelp(articlePath);
157
+ registerInlayHints(articlePath);
152
158
  registerColorPickerForMediaWiki();
153
159
  registerBracketMatchingForMediaWiki();
154
160
  registerCodeFoldingForMediaWiki();
@@ -161,33 +167,57 @@ export const registerMediaWiki = () => {
161
167
  const registerExtensionForMediaWiki = (name, ext) => {
162
168
  avail[name] ??= mediawikiOnly(ext);
163
169
  };
164
- /** Register the `openLinks` extension */
165
- export const registerOpenLinks = () => {
166
- registerExtensionForMediaWiki('openLinks', openLinks);
170
+ /**
171
+ * Register the `openLinks` extension
172
+ * @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
173
+ */
174
+ export const registerOpenLinks = (articlePath) => {
175
+ registerExtensionForMediaWiki('openLinks', openLinks(articlePath));
176
+ };
177
+ /**
178
+ * Register the `escape` extension
179
+ * @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
180
+ */
181
+ export const registerEscape = (articlePath) => {
182
+ registerExtensionForMediaWiki('escape', escapeKeymap(articlePath));
167
183
  };
168
- /** Register the `escape` extension */
169
- export const registerEscape = () => {
170
- registerExtensionForMediaWiki('escape', escapeKeymap);
184
+ /**
185
+ * Register the `refHover` extension
186
+ * @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
187
+ */
188
+ export const registerRefHover = (articlePath) => {
189
+ registerExtensionForMediaWiki('refHover', refHover(articlePath));
171
190
  };
172
- /** Register the `refHover` extension */
173
- export const registerRefHover = () => {
174
- registerExtensionForMediaWiki('refHover', refHover);
191
+ /**
192
+ * Register the `hover` extension
193
+ * @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
194
+ * @param templatedata whether to use [Extension:TemplateData](https://www.mediawiki.org/wiki/Extension:TemplateData)
195
+ * for template information; enabled by default
196
+ */
197
+ export const registerHover = (articlePath, templatedata) => {
198
+ registerExtensionForMediaWiki('hover', magicWordHover(articlePath, templatedata));
175
199
  };
176
- /** Register the `hover` extension */
177
- export const registerHover = () => {
178
- registerExtensionForMediaWiki('hover', magicWordHover);
200
+ /**
201
+ * Register the `signatureHelp` extension
202
+ * @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
203
+ */
204
+ export const registerSignatureHelp = (articlePath) => {
205
+ registerExtensionForMediaWiki('signatureHelp', signatureHelpBase(articlePath));
179
206
  };
180
- /** Register the `signatureHelp` extension */
181
- export const registerSignatureHelp = () => {
182
- registerExtensionForMediaWiki('signatureHelp', signatureHelp);
207
+ /**
208
+ * Register the `inlayHints` extension
209
+ * @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
210
+ */
211
+ export const registerInlayHints = (articlePath) => {
212
+ registerExtensionForMediaWiki('inlayHints', inlayHints(articlePath));
183
213
  };
184
- /** Register the `inlayHints` extension */
185
- export const registerInlayHints = () => {
186
- registerExtensionForMediaWiki('inlayHints', inlayHints);
214
+ /** Register the `bidiIsolates` extension */
215
+ export const registerBidiIsolates = () => {
216
+ registerExtensionForMediaWiki('bidiIsolates', bidiIsolates);
187
217
  };
188
218
  /** Register the `colorPicker` extension for MediaWiki */
189
219
  export const registerColorPickerForMediaWiki = () => {
190
- registerLangExtension('mediawiki', 'colorPicker', mediawikiColorPicker());
220
+ registerLangExtension('mediawiki', 'colorPicker', mediawikiColorPicker);
191
221
  };
192
222
  /** Register the `bracketMatching` extension for MediaWiki */
193
223
  export const registerBracketMatchingForMediaWiki = () => {
@@ -198,7 +228,7 @@ export const registerBracketMatchingForMediaWiki = () => {
198
228
  };
199
229
  /** Register the `codeFolding` extension for MediaWiki */
200
230
  export const registerCodeFoldingForMediaWiki = () => {
201
- registerLangExtension('mediawiki', 'codeFolding', mediaWikiFold);
231
+ registerLangExtension('mediawiki', 'codeFolding', mediawikiFold);
202
232
  optionalFunctions.foldHandler = foldHandler;
203
233
  };
204
234
  /**
@@ -210,16 +240,20 @@ const registerLintSource = (lang, lintSource) => {
210
240
  linterRegistry[lang] = lintSource;
211
241
  optionalFunctions.statusBar = statusBar;
212
242
  };
213
- /** Register MediaWiki core language support */
214
- export const registerMediaWikiCore = () => {
243
+ /**
244
+ * Register MediaWiki core language support
245
+ * @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
246
+ * @param templatedata whether to use [Extension:TemplateData](https://www.mediawiki.org/wiki/Extension:TemplateData)
247
+ * for template parameter autocompletion
248
+ */
249
+ export const registerMediaWikiCore = (articlePath, templatedata) => {
215
250
  CodeMirror6.getMwConfig = (config) => getStaticMwConfig(config, tagModes);
216
251
  languages['mediawiki'] = (config) => [
217
- mediawikiBase(config),
252
+ mediawikiBase(config, templatedata),
218
253
  plain(),
219
- bidiIsolation,
220
254
  keymap.of(formatKeymap),
221
255
  ];
222
- registerLintSource('mediawiki', getWikiLintSource);
256
+ registerLintSource('mediawiki', getWikiLintSource(articlePath));
223
257
  destroyListeners.push(view => {
224
258
  if (typeof wikiparse === 'object' && wikiparse.LanguageService) {
225
259
  getLSP(view)?.destroy();
@@ -230,9 +264,17 @@ export const registerMediaWikiCore = () => {
230
264
  export const registerHTML = () => {
231
265
  registerCommonExtensions();
232
266
  registerHTMLCore();
267
+ registerBracketMatchingForHTML();
233
268
  registerCloseBracketsForHTML();
234
269
  registerColorPickerForHTML();
235
270
  };
271
+ /** Register the `bracketMatching` extension for mixed MediaWiki-HTML */
272
+ export const registerBracketMatchingForHTML = () => {
273
+ registerLangExtension('html', 'bracketMatching', [
274
+ {},
275
+ tagMatchingState,
276
+ ]);
277
+ };
236
278
  /** Register the `closeBrackets` extension for mixed MediaWiki-HTML */
237
279
  export const registerCloseBracketsForHTML = () => {
238
280
  registerLangExtension('html', 'closeBrackets', autoCloseTags);
@@ -317,6 +359,17 @@ export const registerVueCore = () => {
317
359
  registerLintSource('vue', getVueLintSource);
318
360
  optionalFunctions.detectIndent = detectIndent;
319
361
  };
362
+ /** Register AbuseFilter language support */
363
+ export const registerAbuseFilter = () => {
364
+ registerExtensions();
365
+ registerAbuseFilterCore();
366
+ };
367
+ /** Register AbuseFilter core language support */
368
+ export const registerAbuseFilterCore = () => {
369
+ languages['abusefilter'] = abusefilter;
370
+ registerLintSource('abusefilter', () => state => analyzer({ state }));
371
+ optionalFunctions.detectIndent = detectIndent;
372
+ };
320
373
  /**
321
374
  * Register a custom language support
322
375
  * @param name language name
package/dist/inlay.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import type { Extension } from '@codemirror/state';
2
2
  import type { CodeMirror6 } from './codemirror';
3
- declare const _default: (cm: CodeMirror6) => Extension;
3
+ declare const _default: (articlePath?: string) => (cm: CodeMirror6) => Extension;
4
4
  export default _default;
package/dist/inlay.js CHANGED
@@ -3,7 +3,7 @@ import { Decoration, EditorView, WidgetType, ViewPlugin } from '@codemirror/view
3
3
  import { getLSP } from '@bhsd/browser';
4
4
  import elt from 'crelt';
5
5
  import { base } from './constants.js';
6
- import { posToIndex, } from './util.js';
6
+ import { posToIndex, toConfigGetter, } from './util.js';
7
7
  const cls = 'cm-inlay-hint';
8
8
  class InlayHintWidget extends WidgetType {
9
9
  constructor(label) {
@@ -25,10 +25,9 @@ const stateEffect = StateEffect.define(), field = StateField.define({
25
25
  const { value: { text, inlayHints } } = effect;
26
26
  if (str === text) {
27
27
  return inlayHints
28
- ? Decoration.set(inlayHints.reverse()
29
- .map(({ position, label }) => [posToIndex(doc, position), label])
30
- .sort(([a], [b]) => a - b)
31
- .map(([index, label]) => Decoration.widget({ widget: new InlayHintWidget(label) }).range(index)))
28
+ ? Decoration.set(inlayHints.map(({ position, label }) => Decoration.widget({
29
+ widget: new InlayHintWidget(label),
30
+ }).range(posToIndex(doc, position))), true)
32
31
  : Decoration.none;
33
32
  }
34
33
  }
@@ -50,23 +49,25 @@ const update = async ({ view, docChanged }) => {
50
49
  });
51
50
  }
52
51
  };
53
- export default (cm) => [
54
- field,
55
- ViewPlugin.define(view => {
56
- const timer = setInterval(() => {
57
- if (getLSP(view, false, cm.getWikiConfig, base.CDN)) {
58
- clearInterval(timer);
59
- void update({ view, docChanged: true });
60
- }
61
- }, 100);
62
- return { update };
63
- }),
64
- EditorView.theme({
65
- [`.${cls}`]: {
66
- color: '#969696',
67
- fontStyle: 'italic',
68
- '-webkitUserSelect': 'none',
69
- userSelect: 'none',
70
- },
71
- }),
72
- ];
52
+ export default (articlePath) => (cm) => {
53
+ return [
54
+ field,
55
+ ViewPlugin.define(view => {
56
+ const timer = setInterval(() => {
57
+ if (getLSP(view, false, toConfigGetter(cm.getWikiConfig, articlePath), base.CDN)) {
58
+ clearInterval(timer);
59
+ void update({ view, docChanged: true });
60
+ }
61
+ }, 100);
62
+ return { update };
63
+ }),
64
+ EditorView.theme({
65
+ [`.${cls}`]: {
66
+ color: '#969696',
67
+ fontStyle: 'italic',
68
+ '-webkitUserSelect': 'none',
69
+ userSelect: 'none',
70
+ },
71
+ }),
72
+ ];
73
+ };
@@ -1,4 +1,13 @@
1
- import type { Extension } from '@codemirror/state';
1
+ import type { Extension, EditorState } from '@codemirror/state';
2
+ import type { DecorationSet } from '@codemirror/view';
3
+ import type { Tree } from '@lezer/common';
4
+ import type { DocRange } from './fold';
2
5
  export declare const jsCompletion: Extension;
6
+ /**
7
+ * 高亮显示全局变量
8
+ * @ignore
9
+ * @test
10
+ */
11
+ export declare const markGlobals: (tree: Tree, visibleRanges: readonly DocRange[], state: EditorState) => DecorationSet;
3
12
  declare const _default: () => Extension;
4
13
  export default _default;
@@ -1,3 +1,51 @@
1
- import { javascript as js, javascriptLanguage, scopeCompletionSource } from '@codemirror/lang-javascript';
1
+ import { javascript as js, javascriptLanguage, scopeCompletionSource, localCompletionSource, } from '@codemirror/lang-javascript';
2
+ import { ViewPlugin, Decoration } from '@codemirror/view';
3
+ import { syntaxTree } from '@codemirror/language';
4
+ import { builtin } from 'globals/globals.json';
2
5
  export const jsCompletion = javascriptLanguage.data.of({ autocomplete: scopeCompletionSource(globalThis) });
3
- export default () => [js(), jsCompletion];
6
+ const globals = Decoration.mark({ class: 'cm-globals' });
7
+ /**
8
+ * 高亮显示全局变量
9
+ * @ignore
10
+ * @test
11
+ */
12
+ export const markGlobals = (tree, visibleRanges, state) => {
13
+ const decorations = [];
14
+ for (const { from, to } of visibleRanges) {
15
+ tree.iterate({
16
+ from,
17
+ to,
18
+ enter({ type, from: f, to: t }) {
19
+ const name = state.sliceDoc(f, t);
20
+ if (type.is('VariableName') && name in builtin) {
21
+ const completions = localCompletionSource({ state, pos: t, explicit: true });
22
+ if (!completions?.options.some(({ label }) => label === name)) {
23
+ decorations.push(globals.range(f, t));
24
+ }
25
+ }
26
+ },
27
+ });
28
+ }
29
+ return Decoration.set(decorations);
30
+ };
31
+ export default () => [
32
+ js(),
33
+ jsCompletion,
34
+ ViewPlugin.fromClass(class {
35
+ constructor({ state, visibleRanges }) {
36
+ this.tree = syntaxTree(state);
37
+ this.decorations = markGlobals(this.tree, visibleRanges, state);
38
+ }
39
+ update({ docChanged, viewportChanged, state, view: { visibleRanges } }) {
40
+ const tree = syntaxTree(state);
41
+ if (docChanged || viewportChanged || tree !== this.tree) {
42
+ this.tree = tree;
43
+ this.decorations = markGlobals(tree, visibleRanges, state);
44
+ }
45
+ }
46
+ }, {
47
+ decorations(v) {
48
+ return v.decorations;
49
+ },
50
+ }),
51
+ ];
@@ -11,5 +11,6 @@ export declare const keybindings: KeymapConfig[];
11
11
  * @param text 跨行文本
12
12
  * @param pre 前缀
13
13
  * @param post 后缀
14
+ * @test
14
15
  */
15
16
  export declare const encapsulateLines: (text: string, pre: string, post: string) => string;
@@ -26,6 +26,7 @@ export const keybindings = [
26
26
  * @param text 跨行文本
27
27
  * @param pre 前缀
28
28
  * @param post 后缀
29
+ * @test
29
30
  */
30
31
  export const encapsulateLines = (text, pre, post) => {
31
32
  const lines = text.split('\n');
package/dist/keymap.d.ts CHANGED
@@ -1,3 +1,14 @@
1
1
  import type { KeyBinding } from '@codemirror/view';
2
+ import type { KeymapConfig } from './keybindings';
3
+ /**
4
+ * 生成keymap
5
+ * @param opt 快捷键设置
6
+ * @param opt.key 键名
7
+ * @param opt.pre 前缀
8
+ * @param opt.post 后缀
9
+ * @param opt.splitlines 是否分行
10
+ * @test
11
+ */
12
+ export declare const getKeymap: ({ key, pre, post, splitlines }: KeymapConfig) => KeyBinding;
2
13
  declare const _default: KeyBinding[];
3
14
  export default _default;
package/dist/keymap.js CHANGED
@@ -7,8 +7,9 @@ import { keybindings, encapsulateLines } from './keybindings.js';
7
7
  * @param opt.pre 前缀
8
8
  * @param opt.post 后缀
9
9
  * @param opt.splitlines 是否分行
10
+ * @test
10
11
  */
11
- const getKeymap = ({ key, pre = '', post = '', splitlines }) => ({
12
+ export const getKeymap = ({ key, pre = '', post = '', splitlines }) => ({
12
13
  key,
13
14
  run(view) {
14
15
  const { state } = view;
@@ -22,9 +23,7 @@ const getKeymap = ({ key, pre = '', post = '', splitlines }) => ({
22
23
  }
23
24
  const insert = pre + state.sliceDoc(from, to) + post, head = from + insert.length;
24
25
  return {
25
- range: from === to
26
- ? EditorSelection.range(from + pre.length, head - post.length)
27
- : EditorSelection.range(head, head),
26
+ range: EditorSelection.cursor(from === to ? from + pre.length : head),
28
27
  changes: { from, to, insert },
29
28
  };
30
29
  }));
package/dist/linter.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- import type { Diagnostic as DiagnosticBase, Range } from 'vscode-languageserver-types';
1
+ import type { Diagnostic as DiagnosticBase, Range, Position } from 'vscode-languageserver-types';
2
2
  import type { Linter } from 'eslint';
3
- import type { Warning } from 'stylelint';
3
+ import type { Warning } from 'stylelint/types/stylelint';
4
4
  import type { Diagnostic } from 'luacheck-browserify';
5
+ import type { AST } from 'wikiparser-node';
5
6
  export type Option = Record<string, unknown> | null | undefined;
6
7
  export type LiveOption = (runtime?: boolean) => Option | Promise<Option>;
7
8
  declare type asyncLinter<T, S = Record<string, unknown>> = ((text: string, config?: Option) => T) & {
@@ -20,27 +21,55 @@ declare interface MixedDiagnostic extends Omit<DiagnosticBase, 'range'> {
20
21
  }
21
22
  export declare const stylelintRepo = "npm/@bhsd/stylelint-browserify";
22
23
  export declare const eslintRepo = "npm/@bhsd/eslint-browserify", luacheckRepo = "npm/luacheck-browserify";
24
+ /**
25
+ * 计算位置
26
+ * @param range 范围
27
+ * @param lineOrOffset 行号或相对位置
28
+ * @param column 列号
29
+ * @test
30
+ */
31
+ export declare const offsetAt: (range: [number, number], lineOrOffset: number, column?: number) => number;
32
+ /**
33
+ * 获取伪CSS代码块的前缀
34
+ * @param token AST 节点
35
+ * @param token.type 节点类型
36
+ * @param token.tag 节点标签
37
+ * @param i 节点序号
38
+ * @test
39
+ */
40
+ export declare const getPrefix: ({ type, tag }: AST, i: number) => string;
41
+ /**
42
+ * 将偏移量转换为位置
43
+ * @param code 代码字符串
44
+ * @param index 偏移量
45
+ * @test
46
+ */
47
+ export declare const indexToPos: (code: string, index: number) => Position;
23
48
  /**
24
49
  * 获取 Wikitext LSP
25
50
  * @param opt 选项
26
51
  * @param opt.cdn jsDelivr CDN,不含库名
27
52
  * @param obj 对象
53
+ * @test
28
54
  */
29
55
  export declare const getWikiLinter: getAsyncLinter<Promise<MixedDiagnostic[]>, Option, object>;
30
56
  export declare const jsConfig: Option;
31
57
  /**
32
58
  * 获取 ESLint
33
59
  * @param cdn CDN 地址
60
+ * @test
34
61
  */
35
62
  export declare const getJsLinter: getAsyncLinter<Linter.LintMessage[], string>;
36
63
  /**
37
64
  * 获取 Stylelint
38
65
  * @param cdn CDN 地址
66
+ * @test
39
67
  */
40
68
  export declare const getCssLinter: getAsyncLinter<Promise<Warning[]>, string>;
41
69
  /**
42
70
  * 获取 Luacheck
43
71
  * @param cdn CDN 地址
72
+ * @test
44
73
  */
45
74
  export declare const getLuaLinter: getAsyncLinter<Promise<Diagnostic[]>, string>;
46
75
  export {};
package/dist/linter.js CHANGED
@@ -8,8 +8,9 @@ export const eslintRepo = 'npm/@bhsd/eslint-browserify', luacheckRepo = 'npm/lua
8
8
  * @param range 范围
9
9
  * @param lineOrOffset 行号或相对位置
10
10
  * @param column 列号
11
+ * @test
11
12
  */
12
- const offsetAt = (range, lineOrOffset, column) => {
13
+ export const offsetAt = (range, lineOrOffset, column) => {
13
14
  if (column === undefined) {
14
15
  return Math.min(range[1], range[0] + Math.max(0, lineOrOffset));
15
16
  }
@@ -24,14 +25,16 @@ const offsetAt = (range, lineOrOffset, column) => {
24
25
  * @param token.type 节点类型
25
26
  * @param token.tag 节点标签
26
27
  * @param i 节点序号
28
+ * @test
27
29
  */
28
- const getPrefix = ({ type, tag }, i) => `${type === 'ext-attr' ? 'div' : tag}#${i}{\n`;
30
+ export const getPrefix = ({ type, tag }, i) => `${type === 'ext-attr' ? 'div' : tag}#${i}{\n`;
29
31
  /**
30
32
  * 将偏移量转换为位置
31
33
  * @param code 代码字符串
32
34
  * @param index 偏移量
35
+ * @test
33
36
  */
34
- const indexToPos = (code, index) => {
37
+ export const indexToPos = (code, index) => {
35
38
  const lines = code.slice(0, index).split('\n');
36
39
  return { line: lines.length - 1, character: lines[lines.length - 1].length };
37
40
  };
@@ -45,6 +48,7 @@ const isStylelintConfig = (config) => Boolean(config && ('extends' in config ||
45
48
  * @param opt 选项
46
49
  * @param opt.cdn jsDelivr CDN,不含库名
47
50
  * @param obj 对象
51
+ * @test
48
52
  */
49
53
  export const getWikiLinter = async (opt, obj) => {
50
54
  const cdn = opt?.['cdn'];
@@ -120,6 +124,7 @@ export const jsConfig = /* #__PURE__ */ (() => ({
120
124
  /**
121
125
  * 获取 ESLint
122
126
  * @param cdn CDN 地址
127
+ * @test
123
128
  */
124
129
  export const getJsLinter = async (cdn = eslintRepo) => {
125
130
  await loadScript(cdn, 'eslint');
@@ -151,6 +156,7 @@ export const getJsLinter = async (cdn = eslintRepo) => {
151
156
  /**
152
157
  * 获取 Stylelint
153
158
  * @param cdn CDN 地址
159
+ * @test
154
160
  */
155
161
  export const getCssLinter = async (cdn = stylelintRepo) => {
156
162
  await loadScript(cdn, 'stylelint');
@@ -170,6 +176,7 @@ export const getCssLinter = async (cdn = stylelintRepo) => {
170
176
  /**
171
177
  * 获取 Luacheck
172
178
  * @param cdn CDN 地址
179
+ * @test
173
180
  */
174
181
  export const getLuaLinter = async (cdn = luacheckRepo) => {
175
182
  await loadScript(cdn, 'luacheck');