@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.
Files changed (51) hide show
  1. package/README.md +71 -11
  2. package/dist/bidi.d.ts +4 -8
  3. package/dist/bidi.js +33 -23
  4. package/dist/codemirror.js +15 -9
  5. package/dist/color.d.ts +1 -1
  6. package/dist/color.js +1 -1
  7. package/dist/config.d.ts +1 -0
  8. package/dist/config.js +1 -0
  9. package/dist/constants.d.ts +3 -2
  10. package/dist/constants.js +3 -2
  11. package/dist/css.js +9 -6
  12. package/dist/escape.d.ts +1 -1
  13. package/dist/escape.js +4 -3
  14. package/dist/fold.d.ts +2 -2
  15. package/dist/fold.js +113 -40
  16. package/dist/hover.d.ts +2 -2
  17. package/dist/hover.js +74 -62
  18. package/dist/index.d.ts +54 -16
  19. package/dist/index.js +91 -38
  20. package/dist/inlay.d.ts +1 -1
  21. package/dist/inlay.js +26 -25
  22. package/dist/javascript.js +45 -2
  23. package/dist/linter.d.ts +15 -2
  24. package/dist/linter.js +2 -2
  25. package/dist/lintsource.d.ts +15 -3
  26. package/dist/lintsource.js +13 -7
  27. package/dist/lua.d.ts +0 -2
  28. package/dist/lua.js +32 -26
  29. package/dist/main.min.js +31 -29
  30. package/dist/matchTag.js +4 -3
  31. package/dist/mediawiki.d.ts +4 -2
  32. package/dist/mediawiki.js +56 -44
  33. package/dist/mw.min.js +33 -37
  34. package/dist/mwConfig.js +2 -2
  35. package/dist/openLinks.d.ts +4 -2
  36. package/dist/openLinks.js +56 -54
  37. package/dist/ref.d.ts +1 -1
  38. package/dist/ref.js +92 -93
  39. package/dist/signature.d.ts +1 -1
  40. package/dist/signature.js +50 -49
  41. package/dist/statusBar.js +31 -9
  42. package/dist/theme.js +10 -23
  43. package/dist/token.d.ts +20 -6
  44. package/dist/token.js +26 -17
  45. package/dist/util.d.ts +17 -2
  46. package/dist/util.js +39 -1
  47. package/dist/wiki.min.js +32 -36
  48. package/i18n/en.json +2 -2
  49. package/i18n/zh-hans.json +2 -2
  50. package/i18n/zh-hant.json +2 -2
  51. package/package.json +14 -12
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,3 +1,46 @@
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
+ const markGlobals = (tree, visibleRanges, state) => {
8
+ const decorations = [];
9
+ for (const { from, to } of visibleRanges) {
10
+ tree.iterate({
11
+ from,
12
+ to,
13
+ enter({ type, from: f, to: t }) {
14
+ const name = state.sliceDoc(f, t);
15
+ if (type.is('VariableName') && name in builtin) {
16
+ const completions = localCompletionSource({ state, pos: t, explicit: true });
17
+ if (!completions?.options.some(({ label }) => label === name)) {
18
+ decorations.push(globals.range(f, t));
19
+ }
20
+ }
21
+ },
22
+ });
23
+ }
24
+ return Decoration.set(decorations);
25
+ };
26
+ export default () => [
27
+ js(),
28
+ jsCompletion,
29
+ ViewPlugin.fromClass(class {
30
+ constructor({ state, visibleRanges }) {
31
+ this.tree = syntaxTree(state);
32
+ this.decorations = markGlobals(this.tree, visibleRanges, state);
33
+ }
34
+ update({ docChanged, viewportChanged, state, view: { visibleRanges } }) {
35
+ const tree = syntaxTree(state);
36
+ if (docChanged || viewportChanged || tree !== this.tree) {
37
+ this.tree = tree;
38
+ this.decorations = markGlobals(tree, visibleRanges, state);
39
+ }
40
+ }
41
+ }, {
42
+ decorations(v) {
43
+ return v.decorations;
44
+ },
45
+ }),
46
+ ];
package/dist/linter.d.ts CHANGED
@@ -1,6 +1,6 @@
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
5
  export type Option = Record<string, unknown> | null | undefined;
6
6
  export type LiveOption = (runtime?: boolean) => Option | Promise<Option>;
@@ -20,6 +20,19 @@ declare interface MixedDiagnostic extends Omit<DiagnosticBase, 'range'> {
20
20
  }
21
21
  export declare const stylelintRepo = "npm/@bhsd/stylelint-browserify";
22
22
  export declare const eslintRepo = "npm/@bhsd/eslint-browserify", luacheckRepo = "npm/luacheck-browserify";
23
+ /**
24
+ * 计算位置
25
+ * @param range 范围
26
+ * @param lineOrOffset 行号或相对位置
27
+ * @param column 列号
28
+ */
29
+ export declare const offsetAt: (range: [number, number], lineOrOffset: number, column?: number) => number;
30
+ /**
31
+ * 将偏移量转换为位置
32
+ * @param code 代码字符串
33
+ * @param index 偏移量
34
+ */
35
+ export declare const indexToPos: (code: string, index: number) => Position;
23
36
  /**
24
37
  * 获取 Wikitext LSP
25
38
  * @param opt 选项
package/dist/linter.js CHANGED
@@ -9,7 +9,7 @@ export const eslintRepo = 'npm/@bhsd/eslint-browserify', luacheckRepo = 'npm/lua
9
9
  * @param lineOrOffset 行号或相对位置
10
10
  * @param column 列号
11
11
  */
12
- const offsetAt = (range, lineOrOffset, column) => {
12
+ export const offsetAt = (range, lineOrOffset, column) => {
13
13
  if (column === undefined) {
14
14
  return Math.min(range[1], range[0] + Math.max(0, lineOrOffset));
15
15
  }
@@ -31,7 +31,7 @@ const getPrefix = ({ type, tag }, i) => `${type === 'ext-attr' ? 'div' : tag}#${
31
31
  * @param code 代码字符串
32
32
  * @param index 偏移量
33
33
  */
34
- const indexToPos = (code, index) => {
34
+ export const indexToPos = (code, index) => {
35
35
  const lines = code.slice(0, index).split('\n');
36
36
  return { line: lines.length - 1, character: lines[lines.length - 1].length };
37
37
  };
@@ -3,10 +3,10 @@ import type { Text, EditorState } from '@codemirror/state';
3
3
  import type { Language } from '@codemirror/language';
4
4
  import type { Diagnostic, Action } from '@codemirror/lint';
5
5
  import type { Option, LiveOption } from './linter';
6
- export type LintSource = ((state: EditorState) => Diagnostic[] | Promise<Diagnostic[]>) & {
6
+ export type LintSource = ((state: EditorState) => readonly Diagnostic[] | Promise<readonly Diagnostic[]>) & {
7
7
  fixer?: (doc: Text, rule?: string) => string | Promise<string>;
8
8
  };
9
- export type LintSources = LintSource | [LintSource] | [LintSource, LintSource];
9
+ export type LintSources = LintSource | [LintSource, ...LintSource[]];
10
10
  export type LintSourceGetter = (opt?: Option | LiveOption, view?: EditorView, nestedMWLanguage?: Language) => LintSource | Promise<LintSource>;
11
11
  export interface ExtendedAction extends Action {
12
12
  tooltip: string | undefined;
@@ -17,7 +17,19 @@ export interface ExtendedAction extends Action {
17
17
  * @param runtime 是否为运行时选项
18
18
  */
19
19
  export declare const getOpt: (opt: Option | LiveOption, runtime?: boolean) => Option | Promise<Option>;
20
- export declare const getWikiLintSource: LintSourceGetter;
20
+ /**
21
+ * 获取指定行列的位置
22
+ * @param doc 文档
23
+ * @param line 行号
24
+ * @param column 列号
25
+ * @param from 子语言起始位置
26
+ */
27
+ export declare const pos: (doc: Text, line: number, column: number, from?: number) => number;
28
+ export declare const getRange: (doc: Text, line: number, column: number, endLine?: number, endColumn?: number, f?: number, t?: number) => {
29
+ from: number;
30
+ to: number;
31
+ };
32
+ export declare const getWikiLintSource: (articlePath?: string) => LintSourceGetter;
21
33
  export declare const getJsLintSource: LintSourceGetter;
22
34
  export declare const getCssLintSource: LintSourceGetter;
23
35
  export declare const getVueLintSource: LintSourceGetter;
@@ -3,7 +3,7 @@ import { cssLanguage } from '@codemirror/lang-css';
3
3
  import { javascriptLanguage } from '@codemirror/lang-javascript';
4
4
  import { sanitizeInlineStyle, lintJSON } from '@bhsd/common';
5
5
  import { getWikiLinter, getJsLinter, getCssLinter, getLuaLinter, stylelintRepo, eslintRepo, luacheckRepo, } from './linter.js';
6
- import { posToIndex, } from './util.js';
6
+ import { posToIndex, toConfigGetter, } from './util.js';
7
7
  import { base } from './constants.js';
8
8
  /**
9
9
  * 获取Linter选项
@@ -18,7 +18,7 @@ export const getOpt = (opt, runtime) => typeof opt === 'function' ? opt(runtime)
18
18
  * @param column 列号
19
19
  * @param from 子语言起始位置
20
20
  */
21
- const pos = (doc, line, column, from = 0) => {
21
+ export const pos = (doc, line, column, from = 0) => {
22
22
  if (from === 0) {
23
23
  return posToIndex(doc, { line: line - 1, character: column - 1 });
24
24
  }
@@ -28,7 +28,7 @@ const pos = (doc, line, column, from = 0) => {
28
28
  character: (line === 1 ? from - lineDesc.from : 0) + column - 1,
29
29
  });
30
30
  };
31
- const getRange = (doc, line, column, endLine, endColumn, f = 0, t = Infinity) => {
31
+ export const getRange = (doc, line, column, endLine, endColumn, f = 0, t = Infinity) => {
32
32
  const start = pos(doc, line, column, f);
33
33
  return {
34
34
  from: start,
@@ -56,9 +56,15 @@ const wikiLintSource = async (wikiLint, text, opt, doc, f = 0, t) => (await wiki
56
56
  ? getRange(doc, r.start.line + 1, r.start.character + 1, r.end.line + 1, r.end.character + 1, f, t)
57
57
  : { from: from + f, to: (to ?? from) + f },
58
58
  }));
59
- export const getWikiLintSource = async (opt, v) => {
60
- const wikiLint = await getWikiLinter({ ...await getOpt(opt), cdn: base.CDN }, v);
61
- const lintSource = async ({ doc }) => wikiLintSource(wikiLint, doc.toString(), await getOpt(opt, true), doc);
59
+ export const getWikiLintSource = (articlePath) => async (opt, v) => {
60
+ const options = { ...await getOpt(opt), cdn: base.CDN };
61
+ if (articlePath) {
62
+ options.getConfig = toConfigGetter(options.getConfig, articlePath);
63
+ }
64
+ const wikiLint = await getWikiLinter(options, v);
65
+ const lintSource = async ({ doc }) => {
66
+ return wikiLintSource(wikiLint, doc.toString(), await getOpt(opt, true), doc);
67
+ };
62
68
  if (wikiLint.fixer) {
63
69
  lintSource.fixer = (_, rule) => wikiLint.fixer('', rule);
64
70
  }
@@ -166,7 +172,7 @@ export const getHTMLLintSource = async (opt, view, language) => {
166
172
  };
167
173
  };
168
174
  export const getJsonLintSource = () => ({ doc }) => lintJSON(doc.toString())
169
- .map(({ message, position, severity }) => ({ message, severity, from: position, to: position }));
175
+ .map(({ message, from, to = from, severity }) => ({ message, severity, from, to }));
170
176
  export const getLuaLintSource = async () => {
171
177
  const { CDN } = base, luaLint = await getLuaLinter(CDN && `${CDN}/${luacheckRepo}`);
172
178
  return async ({ doc }) => (await luaLint(doc.toString()))
package/dist/lua.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { lua } from '@codemirror/legacy-modes/mode/lua';
2
1
  import { LanguageSupport } from '@codemirror/language';
3
2
  declare const _default: () => LanguageSupport;
4
3
  export default _default;
5
- export { lua };
package/dist/lua.js CHANGED
@@ -1,8 +1,9 @@
1
1
  /* eslint-disable no-template-curly-in-string */
2
2
  import { lua } from '@codemirror/legacy-modes/mode/lua';
3
- import { syntaxTree, LanguageSupport, StreamLanguage, foldService } from '@codemirror/language';
3
+ import { syntaxTree, LanguageSupport, StreamLanguage, foldService, HighlightStyle, syntaxHighlighting, } from '@codemirror/language';
4
4
  import { snippetCompletion } from '@codemirror/autocomplete';
5
- import { leadingSpaces } from './util.js';
5
+ import { tags } from '@lezer/highlight';
6
+ import { leadingSpaces, sliceDoc } from './util.js';
6
7
  const map = {
7
8
  1: 'constant',
8
9
  2: 'function',
@@ -84,7 +85,9 @@ const map = {
84
85
  addWarning: 2,
85
86
  allToString: 2,
86
87
  clone: 2,
88
+ getContentLanguage: 2,
87
89
  getCurrentFrame: 2,
90
+ getLanguage: 2,
88
91
  incrementExpensiveFunctionCount: 2,
89
92
  isSubsting: 2,
90
93
  loadData: 2,
@@ -300,8 +303,8 @@ const map = {
300
303
  detail: 'in loop',
301
304
  type: 'keyword',
302
305
  }),
303
- ], types = new Set(['variableName', 'variableName.standard', 'keyword']);
304
- lua.languageData['autocomplete'] = (context => {
306
+ ], types = new Set(['variableName', 'variableName.standard', 'keyword']), lang = StreamLanguage.define(lua);
307
+ const source = context => {
305
308
  const { state, pos } = context, node = syntaxTree(state).resolveInner(pos, -1);
306
309
  if (!types.has(node.name)) {
307
310
  return null;
@@ -396,7 +399,7 @@ lua.languageData['autocomplete'] = (context => {
396
399
  return {
397
400
  from,
398
401
  options: prevSibling?.name !== 'keyword'
399
- || builtin.includes(state.sliceDoc(prevSibling.from, prevSibling.to))
402
+ || builtin.includes(sliceDoc(state, prevSibling))
400
403
  ? [...binary, ...blocks]
401
404
  : [...builtins, ...constants, ...tables, ...unary, ...blocks],
402
405
  validFor,
@@ -404,26 +407,29 @@ lua.languageData['autocomplete'] = (context => {
404
407
  }
405
408
  }
406
409
  return null;
407
- });
408
- const support = foldService.of(({ doc, tabSize }, start, from) => {
409
- const { text, number } = doc.lineAt(start);
410
- if (!text.trim()) {
411
- return null;
412
- }
413
- const getIndent = (line) => leadingSpaces(line).replace(/\t/gu, ' '.repeat(tabSize)).length;
414
- const indent = getIndent(text);
415
- let j = number, empty = true;
416
- for (; j < doc.lines; j++) {
417
- const { text: next } = doc.line(j + 1);
418
- if (next.trim()) {
419
- const nextIndent = getIndent(next);
420
- if (indent >= nextIndent) {
421
- break;
410
+ };
411
+ const support = [
412
+ syntaxHighlighting(HighlightStyle.define([{ tag: tags.standard(tags.variableName), class: 'cm-globals' }])),
413
+ lang.data.of({ autocomplete: source }),
414
+ foldService.of(({ doc, tabSize }, start, from) => {
415
+ const { text, number } = doc.lineAt(start);
416
+ if (!text.trim()) {
417
+ return null;
418
+ }
419
+ const getIndent = (line) => leadingSpaces(line).replace(/\t/gu, ' '.repeat(tabSize)).length;
420
+ const indent = getIndent(text);
421
+ let j = number, empty = true;
422
+ for (; j < doc.lines; j++) {
423
+ const { text: next } = doc.line(j + 1);
424
+ if (next.trim()) {
425
+ const nextIndent = getIndent(next);
426
+ if (indent >= nextIndent) {
427
+ break;
428
+ }
429
+ empty = false;
422
430
  }
423
- empty = false;
424
431
  }
425
- }
426
- return empty || j === number ? null : { from, to: doc.line(j).to };
427
- });
428
- export default () => new LanguageSupport(StreamLanguage.define(lua), support);
429
- export { lua };
432
+ return empty || j === number ? null : { from, to: doc.line(j).to };
433
+ }),
434
+ ];
435
+ export default () => new LanguageSupport(lang, support);