@bhsd/codemirror-mediawiki 3.10.2 → 3.11.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 CHANGED
@@ -929,7 +929,7 @@ Refresh linting immediately.
929
929
  *version added: 3.8.0*
930
930
 
931
931
  **type**: `string`
932
- By default, libraries such as [WikiParser-Node](https://www.npmjs.com/package/wikiparser-node) are loaded from `testingcf.jsdelivr.net`. You can change the [jsDelivr CDN](https://www.jsdelivr.com/network) by setting this property.
932
+ By default, libraries such as [WikiParser-Node](https://www.npmjs.com/package/wikiparser-node) are loaded from `fastly.jsdelivr.net`. You can change the [jsDelivr CDN](https://www.jsdelivr.com/network) by setting this property.
933
933
 
934
934
  ```js
935
935
  CodeMirror6.CDN = 'https://cdn.jsdelivr.net';
@@ -26,7 +26,7 @@ declare interface OptionalFunctions {
26
26
  foldHandler: typeof foldHandler;
27
27
  }
28
28
  export declare const plain: () => Extension;
29
- export declare const languages: Record<string, (config?: any) => Extension>;
29
+ export declare const languages: Record<string, (config?: any, cm?: CodeMirror6) => Extension>;
30
30
  export declare const avail: Record<string, Addon<any>>;
31
31
  export declare const linterRegistry: Record<string, LintSourceGetter>;
32
32
  export declare const menuRegistry: MenuItem[];
@@ -57,6 +57,8 @@ export declare class CodeMirror6 {
57
57
  get lang(): string;
58
58
  /** whether the editor view is visible */
59
59
  get visible(): boolean;
60
+ /** @private */
61
+ get lintSources(): LintSource[];
60
62
  /**
61
63
  * @param textarea textarea element
62
64
  * @param lang language
@@ -82,6 +82,7 @@ export class CodeMirror6 {
82
82
  #preferred = new Set();
83
83
  #indentStr = '\t';
84
84
  #nestedMWLanguage;
85
+ #lintSources = [];
85
86
  /** textarea element */
86
87
  get textarea() {
87
88
  return this.#textarea;
@@ -98,6 +99,10 @@ export class CodeMirror6 {
98
99
  get visible() {
99
100
  return this.#visible && this.textarea.isConnected;
100
101
  }
102
+ /** @private */
103
+ get lintSources() {
104
+ return this.#lintSources;
105
+ }
101
106
  /**
102
107
  * @param textarea textarea element
103
108
  * @param lang language
@@ -120,7 +125,7 @@ export class CodeMirror6 {
120
125
  if (isMW || this.#lang === 'html') {
121
126
  config ??= this.langConfig;
122
127
  }
123
- const lang = (languages[this.#lang] ?? plain)(config);
128
+ const lang = (languages[this.#lang] ?? plain)(config, this);
124
129
  this.#nestedMWLanguage = lang.nestedMWLanguage;
125
130
  if (isMW) {
126
131
  this.langConfig = config;
@@ -312,9 +317,11 @@ export class CodeMirror6 {
312
317
  ]
313
318
  : [];
314
319
  if (lintSource) {
320
+ this.#lintSources = lintSources;
315
321
  linters[this.#lang] = linterExtension;
316
322
  }
317
323
  else {
324
+ this.#lintSources.length = 0;
318
325
  delete linters[this.#lang];
319
326
  }
320
327
  if (this.#view) {
package/dist/hover.js CHANGED
@@ -37,7 +37,7 @@ export const getHoverFromApi = async (state, pos, side, paramSuggest, templateda
37
37
  }
38
38
  }
39
39
  else if (node?.name.includes(tokens.templateArgumentName)) {
40
- const name = findTemplateName(state, node);
40
+ const [name] = findTemplateName(state, node);
41
41
  if (name) {
42
42
  const result = await paramSuggest(name, templatedata), param = sliceDoc(state, node).trim().slice(0, -1).trim(), [, , info, section] = result.find(([keys]) => keys.includes(param)) ?? [];
43
43
  if (info || section && section !== 'Optional') {
package/dist/html.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { LanguageSupport } from '@codemirror/language';
2
2
  import type { MwConfig } from './token';
3
- declare const _default: (config: MwConfig) => LanguageSupport;
3
+ import type { CodeMirror6 } from './codemirror';
4
+ declare const _default: (config: MwConfig, cm?: CodeMirror6) => LanguageSupport;
4
5
  export default _default;
package/dist/html.js CHANGED
@@ -4,10 +4,10 @@ import { javascript, javascriptLanguage } from '@codemirror/lang-javascript';
4
4
  import { cssLanguage } from '@codemirror/lang-css';
5
5
  import { LanguageSupport } from '@codemirror/language';
6
6
  import { cssCompletion } from './css.js';
7
- import { jsCompletion } from './javascript.js';
7
+ import { jsCompletion, markGlobalsPlugin } from './javascript.js';
8
8
  import { mediawikiBase } from './mediawiki.js';
9
9
  import { getLightHighlightStyle } from './theme.js';
10
- export default (config) => {
10
+ export default (config, cm) => {
11
11
  const { language, support } = mediawikiBase(config),
12
12
  /** @test */
13
13
  lang = htmlLanguage.configure({
@@ -31,6 +31,7 @@ export default (config) => {
31
31
  cssCompletion(),
32
32
  support,
33
33
  getLightHighlightStyle(),
34
+ markGlobalsPlugin(cm),
34
35
  ]);
35
36
  Object.assign(langSupport, { nestedMWLanguage: language });
36
37
  return langSupport;
@@ -2,12 +2,14 @@ import type { Extension, EditorState } from '@codemirror/state';
2
2
  import type { DecorationSet } from '@codemirror/view';
3
3
  import type { Tree } from '@lezer/common';
4
4
  import type { DocRange } from './fold';
5
+ import type { CodeMirror6 } from './codemirror';
5
6
  export declare const jsCompletion: Extension;
6
7
  /**
7
8
  * 高亮显示全局变量
8
9
  * @ignore
9
10
  * @test
10
11
  */
11
- export declare const markGlobals: (tree: Tree, visibleRanges: readonly DocRange[], state: EditorState) => DecorationSet;
12
- declare const _default: () => Extension;
12
+ export declare const markGlobals: (tree: Tree, visibleRanges: readonly DocRange[], state: EditorState, cm?: CodeMirror6) => DecorationSet;
13
+ export declare const markGlobalsPlugin: (cm?: CodeMirror6) => Extension;
14
+ declare const _default: (_?: unknown, cm?: CodeMirror6) => Extension;
13
15
  export default _default;
@@ -1,23 +1,39 @@
1
1
  import { javascript as js, javascriptLanguage, scopeCompletionSource, localCompletionSource, } from '@codemirror/lang-javascript';
2
2
  import { ViewPlugin, Decoration } from '@codemirror/view';
3
3
  import { syntaxTree } from '@codemirror/language';
4
+ import { setDiagnosticsEffect } from '@codemirror/lint';
4
5
  import { builtin } from 'globals/globals.json';
5
6
  export const jsCompletion = javascriptLanguage.data.of({ autocomplete: scopeCompletionSource(globalThis) });
6
- const globals = Decoration.mark({ class: 'cm-globals' });
7
+ const globals = Decoration.mark({ class: 'cm-globals' }), builtinGlobals = new Set(Object.keys(builtin));
7
8
  /**
8
9
  * 高亮显示全局变量
9
10
  * @ignore
10
11
  * @test
11
12
  */
12
- export const markGlobals = (tree, visibleRanges, state) => {
13
+ export const markGlobals = (tree, visibleRanges, state, cm) => {
13
14
  const decorations = [];
15
+ let allGlobals = builtinGlobals;
16
+ if (cm?.lintSources.length && typeof eslint === 'object' && 'environments' in eslint) {
17
+ const env = cm.lintSources[0]?.config?.env;
18
+ if (env) {
19
+ allGlobals = new Set(builtinGlobals);
20
+ for (const key of Object.keys(env)) {
21
+ const obj = eslint.environments.get(key)?.globals;
22
+ if (obj) {
23
+ for (const k of Object.keys(obj)) {
24
+ allGlobals.add(k);
25
+ }
26
+ }
27
+ }
28
+ }
29
+ }
14
30
  for (const { from, to } of visibleRanges) {
15
31
  tree.iterate({
16
32
  from,
17
33
  to,
18
34
  enter({ type, from: f, to: t }) {
19
35
  const name = state.sliceDoc(f, t);
20
- if (type.is('VariableName') && name in builtin) {
36
+ if (type.is('VariableName') && javascriptLanguage.isActiveAt(state, f) && allGlobals.has(name)) {
21
37
  const completions = localCompletionSource({ state, pos: t, explicit: true });
22
38
  if (!completions?.options.some(({ label }) => label === name)) {
23
39
  decorations.push(globals.range(f, t));
@@ -28,24 +44,32 @@ export const markGlobals = (tree, visibleRanges, state) => {
28
44
  }
29
45
  return Decoration.set(decorations);
30
46
  };
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);
47
+ export const markGlobalsPlugin = (cm) => ViewPlugin.fromClass(class {
48
+ constructor({ state, visibleRanges }) {
49
+ this.tree = syntaxTree(state);
50
+ this.decorations = markGlobals(this.tree, visibleRanges, state, cm);
51
+ }
52
+ update({ docChanged, viewportChanged, state, view: { visibleRanges }, transactions }) {
53
+ const tree = syntaxTree(state);
54
+ let flag;
55
+ if (docChanged || viewportChanged || tree !== this.tree) {
56
+ this.tree = tree;
57
+ flag = true;
38
58
  }
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
- }
59
+ else {
60
+ flag = transactions.some(tr => tr.effects.some(e => e.is(setDiagnosticsEffect)));
61
+ }
62
+ if (flag) {
63
+ this.decorations = markGlobals(tree, visibleRanges, state, cm);
45
64
  }
46
- }, {
47
- decorations(v) {
48
- return v.decorations;
49
- },
50
- }),
65
+ }
66
+ }, {
67
+ decorations(v) {
68
+ return v.decorations;
69
+ },
70
+ });
71
+ export default (_, cm) => [
72
+ js(),
73
+ jsCompletion,
74
+ markGlobalsPlugin(cm),
51
75
  ];
@@ -4,7 +4,8 @@ import type { Language } from '@codemirror/language';
4
4
  import type { Diagnostic, Action } from '@codemirror/lint';
5
5
  import type { Option, LiveOption } from './linter';
6
6
  import type { DocRange } from './fold';
7
- export type LintSource = ((state: EditorState) => readonly Diagnostic[] | Promise<readonly Diagnostic[]>) & {
7
+ export type LintSource<T = unknown> = ((state: EditorState) => readonly Diagnostic[] | Promise<readonly Diagnostic[]>) & {
8
+ config?: T;
8
9
  fixer?: (doc: Text, rule?: string) => string | Promise<string>;
9
10
  };
10
11
  export type LintSources = LintSource | [LintSource, ...LintSource[]];
@@ -115,6 +115,11 @@ export const getJsLintSource = async (opt) => {
115
115
  const { CDN } = base, esLint = await getJsLinter(CDN && `${CDN}/${eslintRepo}`);
116
116
  const lintSource = async ({ doc }) => jsLintSource(esLint, doc.toString(), await getOpt(opt), doc);
117
117
  lintSource.fixer = (doc, rule) => esLint.fixer(doc.toString(), rule);
118
+ Object.defineProperty(lintSource, 'config', {
119
+ get() {
120
+ return esLint.config;
121
+ },
122
+ });
118
123
  return lintSource;
119
124
  };
120
125
  const cssLintSource = async (styleLint, code, opt, doc, f = 0, t) => {
@@ -153,6 +158,11 @@ export const getCssLintSource = async (opt) => {
153
158
  const { CDN } = base, styleLint = await getCssLinter(CDN && `${CDN}/${stylelintRepo}`);
154
159
  const lintSource = async ({ doc }) => cssLintSource(styleLint, doc.toString(), await getOpt(opt), doc);
155
160
  lintSource.fixer = async (doc, rule) => styleLint.fixer(doc.toString(), rule);
161
+ Object.defineProperty(lintSource, 'config', {
162
+ get() {
163
+ return styleLint.config;
164
+ },
165
+ });
156
166
  return lintSource;
157
167
  };
158
168
  /**
@@ -161,7 +171,7 @@ export const getCssLintSource = async (opt) => {
161
171
  */
162
172
  export const getVueLintSource = async (opt) => {
163
173
  const { CDN } = base, styleLint = await getCssLinter(CDN && `${CDN}/${stylelintRepo}`), esLint = await getJsLinter(CDN && `${CDN}/${eslintRepo}`);
164
- return async (state) => {
174
+ const lintSource = async (state) => {
165
175
  const { doc } = state, option = await getOpt(opt, true) ?? {}, js = option['js'], css = option['css'];
166
176
  return [
167
177
  ...(await Promise.all(cssLanguage.findRegions(state).map(async ({ from, to }) => {
@@ -180,6 +190,12 @@ export const getVueLintSource = async (opt) => {
180
190
  .flatMap(({ from, to }) => jsLintSource(esLint, state.sliceDoc(from, to), js, doc, from, to)),
181
191
  ];
182
192
  };
193
+ Object.defineProperty(lintSource, 'config', {
194
+ get() {
195
+ return esLint.config;
196
+ },
197
+ });
198
+ return lintSource;
183
199
  };
184
200
  /**
185
201
  * @implements
@@ -187,7 +203,7 @@ export const getVueLintSource = async (opt) => {
187
203
  */
188
204
  export const getHTMLLintSource = async (opt, view, language) => {
189
205
  const vueLintSource = await getVueLintSource(opt), wikiLint = await getWikiLinter({ include: false, ...await getOpt(opt), cdn: base.CDN }, view);
190
- return async (state) => {
206
+ const lintSource = async (state) => {
191
207
  const { doc } = state, option = await getOpt(opt, true) ?? {}, wiki = option['wiki'];
192
208
  return [
193
209
  ...await vueLintSource(state),
@@ -195,6 +211,12 @@ export const getHTMLLintSource = async (opt, view, language) => {
195
211
  .map(({ from, to }) => wikiLintSource(wikiLint, state.sliceDoc(from, to), wiki, doc, from, to)))).flat(),
196
212
  ];
197
213
  };
214
+ Object.defineProperty(lintSource, 'config', {
215
+ get() {
216
+ return vueLintSource.config;
217
+ },
218
+ });
219
+ return lintSource;
198
220
  };
199
221
  /**
200
222
  * @implements