@bhsd/codemirror-mediawiki 3.0.3 → 3.2.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.
@@ -1,37 +1,34 @@
1
1
  import { EditorView } from '@codemirror/view';
2
2
  import type { KeyBinding } from '@codemirror/view';
3
3
  import type { Extension } from '@codemirror/state';
4
- import type { LanguageSupport } from '@codemirror/language';
5
4
  import type { SyntaxNode } from '@lezer/common';
6
5
  import type { ConfigData } from 'wikiparser-node';
7
6
  import type { MwConfig } from './token';
8
- import type { DocRange } from './fold';
7
+ import type { DocRange, foldHandler } from './fold';
9
8
  import type { Option, LiveOption } from './linter';
10
9
  import type { LintSource, LintSourceGetter } from './lintsource';
11
- export type { MwConfig };
12
- export type Addon<T> = [(config?: T, cm?: CodeMirror6) => Extension, Record<string, T>?];
10
+ import type { detectIndent } from './indent';
11
+ import type statusBar from './statusBar';
12
+ export type AddonMain<T> = (config?: T, cm?: CodeMirror6) => Extension;
13
+ export type Addon<T> = [AddonMain<T>, Record<string, T>?];
13
14
  export type Dialect = 'sanitized-css' | undefined;
14
- /** Register MediaWiki language support */
15
- export declare const registerMediaWiki: () => void;
16
- /** Register mixed MediaWiki-HTML language support */
17
- export declare const registerHTML: () => void;
18
- /** Register JavaScript language support */
19
- export declare const registerJavaScript: () => void;
20
- /** Register CSS language support */
21
- export declare const registerCSS: () => void;
22
- /** Register JSON language support */
23
- export declare const registerJSON: () => void;
24
- /** Register Lua language support */
25
- export declare const registerLua: () => void;
26
- /** Register Vue language support */
27
- export declare const registerVue: () => void;
28
- /**
29
- * Register a custom language support
30
- * @param name language name
31
- * @param lang language support
32
- * @param lintSource optional linter
33
- */
34
- export declare const registerLanguage: (name: string, lang: (config?: unknown) => LanguageSupport, lintSource?: LintSourceGetter) => void;
15
+ export interface MenuItem {
16
+ name: string;
17
+ isActionable(this: void, cm: CodeMirror6): boolean;
18
+ getItems(this: void, cm: CodeMirror6): HTMLDivElement[];
19
+ }
20
+ declare interface OptionalFunctions {
21
+ statusBar: typeof statusBar;
22
+ detectIndent: typeof detectIndent;
23
+ foldHandler: typeof foldHandler;
24
+ }
25
+ export declare const plain: () => Extension;
26
+ export declare const languages: Record<string, (config?: any) => Extension>;
27
+ export declare const avail: Record<string, Addon<any>>;
28
+ export declare const linterRegistry: Record<string, LintSourceGetter>;
29
+ export declare const menuRegistry: MenuItem[];
30
+ export declare const destroyListeners: ((view: EditorView) => void)[];
31
+ export declare const optionalFunctions: OptionalFunctions;
35
32
  /** CodeMirror 6 editor */
36
33
  export declare class CodeMirror6 {
37
34
  #private;
@@ -72,6 +69,11 @@ export declare class CodeMirror6 {
72
69
  lint(lintSource?: LintSource): void;
73
70
  /** Update syntax checking immediately */
74
71
  update(): void;
72
+ /**
73
+ * Check if the editor enables a specific extension
74
+ * @param name extension name
75
+ */
76
+ hasPreference(name: string): boolean;
75
77
  /**
76
78
  * Add extensions
77
79
  * @param names extension names
@@ -139,5 +141,6 @@ export declare class CodeMirror6 {
139
141
  * to a CodeMirror-MediaWiki configuration
140
142
  * @param config WikiParser-Node configuration
141
143
  */
142
- static getMwConfig(config: ConfigData): MwConfig;
144
+ abstract static getMwConfig(config: ConfigData): MwConfig;
143
145
  }
146
+ export {};
@@ -1,173 +1,31 @@
1
- import { EditorView, lineNumbers, keymap, highlightSpecialChars, highlightActiveLine, highlightActiveLineGutter, highlightWhitespace, highlightTrailingWhitespace, drawSelection, scrollPastEnd, rectangularSelection, crosshairCursor, } from '@codemirror/view';
1
+ import { EditorView, lineNumbers, keymap, highlightActiveLineGutter, } from '@codemirror/view';
2
2
  import { Compartment, EditorState, EditorSelection, SelectionRange } from '@codemirror/state';
3
3
  import { syntaxHighlighting, defaultHighlightStyle, indentOnInput, indentUnit, ensureSyntaxTree, } from '@codemirror/language';
4
4
  import { defaultKeymap, historyKeymap, history, redo, indentWithTab } from '@codemirror/commands';
5
- import { searchKeymap, highlightSelectionMatches } from '@codemirror/search';
5
+ import { searchKeymap } from '@codemirror/search';
6
6
  import { linter, lintGutter, lintKeymap } from '@codemirror/lint';
7
- import { closeBrackets, autocompletion, acceptCompletion, completionKeymap, startCompletion, } from '@codemirror/autocomplete';
8
- import { json } from '@codemirror/lang-json';
9
- import { autoCloseTags } from '@codemirror/lang-html';
10
- import { css as cssParser } from '@codemirror/legacy-modes/mode/css';
11
- import { getLSP } from '@bhsd/browser';
12
- import { colorPicker as cssColorPicker, colorPickerTheme, makeColorPicker } from '@bhsd/codemirror-css-color-picker';
13
- import colorPicker, { discoverColors } from './color';
14
- import { mediawiki, html, FullMediaWiki } from './mediawiki';
15
- import escapeKeymap from './escape';
16
- import codeFolding, { foldHandler, mediaWikiFold } from './fold';
17
- import tagMatchingState from './matchTag';
18
- import refHover from './ref';
19
- import magicWordHover from './hover';
20
- import signatureHelp from './signature';
21
- import inlayHints from './inlay';
22
- import { getWikiLintSource, getJsLintSource, getCssLintSource, getJsonLintSource, getLuaLintSource, getVueLintSource, } from './lintsource';
23
- import openLinks from './openLinks';
24
- import { tagModes, getStaticMwConfig } from './static';
25
- import bidiIsolation from './bidi';
26
- import toolKeymap from './keymap';
27
- import statusBar from './statusBar';
28
- import { detectIndent } from './indent';
29
- import bracketMatching from './matchBrackets';
30
- import javascript from './javascript';
31
- import css from './css';
32
- import lua from './lua';
33
- import vue from './vue';
34
- const plain = () => EditorView.contentAttributes.of({ spellcheck: 'true' });
7
+ export const plain = () => EditorView.contentAttributes.of({ spellcheck: 'true' });
35
8
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
- const languages = { plain };
37
- function mediawikiOnly(ext) {
38
- return typeof ext === 'function'
39
- ? [(enable, cm) => enable ? ext(cm) : [], { mediawiki: true }]
40
- : [(e = []) => e, { mediawiki: ext }];
41
- }
9
+ export const languages = { plain };
42
10
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
- const avail = {
44
- highlightSpecialChars: [highlightSpecialChars],
45
- highlightActiveLine: [highlightActiveLine],
46
- highlightWhitespace: [highlightWhitespace],
47
- highlightTrailingWhitespace: [highlightTrailingWhitespace],
48
- highlightSelectionMatches: [highlightSelectionMatches],
49
- bracketMatching: [
50
- ([config, e = []] = []) => [
51
- bracketMatching(config),
52
- e,
53
- ],
54
- ],
55
- closeBrackets: [(e = []) => [closeBrackets(), e]],
56
- scrollPastEnd: [scrollPastEnd],
57
- allowMultipleSelections: [
58
- () => [
59
- EditorState.allowMultipleSelections.of(true),
60
- drawSelection(),
61
- rectangularSelection(),
62
- crosshairCursor(),
63
- ],
64
- ],
65
- autocompletion: [
66
- () => [
67
- autocompletion({ defaultKeymap: false }),
68
- keymap.of([
69
- ...completionKeymap.filter(({ run }) => run !== startCompletion),
70
- { key: 'Shift-Enter', run: startCompletion },
71
- { key: 'Tab', run: acceptCompletion },
72
- ]),
73
- ],
74
- ],
75
- codeFolding,
76
- colorPicker,
11
+ export const avail = {};
12
+ export const linterRegistry = {};
13
+ export const menuRegistry = [];
14
+ export const destroyListeners = [];
15
+ export const optionalFunctions = {
16
+ statusBar() {
17
+ return [];
18
+ },
19
+ detectIndent(_, indent) {
20
+ return indent;
21
+ },
22
+ foldHandler() {
23
+ return () => { };
24
+ },
77
25
  };
78
- const linterRegistry = {};
79
- const destroyListeners = [];
80
26
  const editExtensions = new Set(['closeBrackets', 'autocompletion', 'signatureHelp']);
81
27
  const linters = {};
82
28
  const phrases = {};
83
- /**
84
- * 注册特定语言的扩展
85
- * @param lang 语言
86
- * @param name 扩展名
87
- * @param ext 扩展
88
- */
89
- const registerLangExtension = (lang, name, ext) => {
90
- const addon = avail[name];
91
- addon[1] ??= {};
92
- addon[1][lang] = ext;
93
- };
94
- /** Register MediaWiki language support */
95
- export const registerMediaWiki = () => {
96
- languages['mediawiki'] = (config) => [
97
- mediawiki(config),
98
- plain(),
99
- bidiIsolation,
100
- toolKeymap,
101
- ];
102
- registerLangExtension('mediawiki', 'colorPicker', [
103
- [makeColorPicker({ discoverColors }), colorPickerTheme],
104
- { marginLeft: '0.6ch' },
105
- ]);
106
- registerLangExtension('mediawiki', 'bracketMatching', [
107
- { brackets: '()[]{}()【】[]{}' },
108
- tagMatchingState,
109
- ]);
110
- registerLangExtension('mediawiki', 'codeFolding', mediaWikiFold);
111
- Object.assign(avail, {
112
- openLinks: mediawikiOnly(openLinks),
113
- escape: mediawikiOnly(keymap.of(escapeKeymap)),
114
- refHover: mediawikiOnly(refHover),
115
- hover: mediawikiOnly(magicWordHover),
116
- signatureHelp: mediawikiOnly(signatureHelp),
117
- inlayHints: mediawikiOnly(inlayHints),
118
- });
119
- linterRegistry['mediawiki'] = getWikiLintSource;
120
- destroyListeners.push(view => getLSP(view)?.destroy());
121
- };
122
- /** Register mixed MediaWiki-HTML language support */
123
- export const registerHTML = () => {
124
- Object.assign(FullMediaWiki.prototype, {
125
- css() {
126
- return cssParser;
127
- },
128
- });
129
- languages['html'] = html;
130
- };
131
- /** Register JavaScript language support */
132
- export const registerJavaScript = () => {
133
- languages['javascript'] = javascript;
134
- linterRegistry['javascript'] = getJsLintSource;
135
- };
136
- /** Register CSS language support */
137
- export const registerCSS = () => {
138
- languages['css'] = css;
139
- registerLangExtension('css', 'colorPicker', [cssColorPicker]);
140
- linterRegistry['css'] = getCssLintSource;
141
- };
142
- /** Register JSON language support */
143
- export const registerJSON = () => {
144
- languages['json'] = json;
145
- linterRegistry['json'] = getJsonLintSource;
146
- };
147
- /** Register Lua language support */
148
- export const registerLua = () => {
149
- languages['lua'] = lua;
150
- linterRegistry['lua'] = getLuaLintSource;
151
- };
152
- /** Register Vue language support */
153
- export const registerVue = () => {
154
- languages['vue'] = vue;
155
- registerLangExtension('vue', 'closeBrackets', autoCloseTags);
156
- registerLangExtension('vue', 'colorPicker', [cssColorPicker]);
157
- linterRegistry['vue'] = getVueLintSource;
158
- };
159
- /**
160
- * Register a custom language support
161
- * @param name language name
162
- * @param lang language support
163
- * @param lintSource optional linter
164
- */
165
- export const registerLanguage = (name, lang, lintSource) => {
166
- languages[name] = lang;
167
- if (lintSource) {
168
- linterRegistry[name] = lintSource;
169
- }
170
- };
171
29
  /** CodeMirror 6 editor */
172
30
  export class CodeMirror6 {
173
31
  #textarea;
@@ -184,6 +42,7 @@ export class CodeMirror6 {
184
42
  #visible = false;
185
43
  #preferred = new Set();
186
44
  #indentStr = '\t';
45
+ #nestedMWLanguage;
187
46
  /** textarea element */
188
47
  get textarea() {
189
48
  return this.#textarea;
@@ -213,6 +72,15 @@ export class CodeMirror6 {
213
72
  this.initialize(config);
214
73
  }
215
74
  }
75
+ /**
76
+ * 获取语言扩展
77
+ * @param config 语言设置
78
+ */
79
+ #getLanguage(config) {
80
+ const lang = (languages[this.#lang] ?? plain)(config);
81
+ this.#nestedMWLanguage = lang.nestedMWLanguage;
82
+ return lang;
83
+ }
216
84
  /**
217
85
  * Initialize the editor
218
86
  * @param config language configuration
@@ -220,7 +88,7 @@ export class CodeMirror6 {
220
88
  initialize(config) {
221
89
  let timer;
222
90
  const { textarea, lang } = this, { value, dir: d, accessKey, tabIndex, lang: l, readOnly } = textarea, extensions = [
223
- this.#language.of(languages[lang](config)),
91
+ this.#language.of(this.#getLanguage(config)),
224
92
  this.#linter.of(linters[lang] ?? []),
225
93
  this.#extensions.of([]),
226
94
  this.#dir.of(EditorView.editorAttributes.of({ dir: d })),
@@ -277,7 +145,7 @@ export class CodeMirror6 {
277
145
  : [
278
146
  history(),
279
147
  indentOnInput(),
280
- this.#indent.of(indentUnit.of(detectIndent(value, this.#indentStr, lang))),
148
+ this.#indent.of(indentUnit.of(optionalFunctions.detectIndent(value, this.#indentStr, lang))),
281
149
  keymap.of([
282
150
  ...historyKeymap,
283
151
  indentWithTab,
@@ -296,7 +164,7 @@ export class CodeMirror6 {
296
164
  this.#view.scrollDOM.style.fontSize = fontSize;
297
165
  this.#view.scrollDOM.style.lineHeight = lineHeight;
298
166
  this.toggle(true);
299
- this.#view.dom.addEventListener('click', foldHandler(this.#view));
167
+ this.#view.dom.addEventListener('click', optionalFunctions.foldHandler(this.#view));
300
168
  this.prefer({});
301
169
  }
302
170
  /**
@@ -326,7 +194,7 @@ export class CodeMirror6 {
326
194
  async setLanguage(lang = 'plain', config) {
327
195
  this.#lang = lang;
328
196
  if (this.#view) {
329
- const ext = (languages[lang] ?? plain)(config);
197
+ const ext = this.#getLanguage(config);
330
198
  this.#effects([
331
199
  this.#language.reconfigure(ext),
332
200
  this.#linter.reconfigure(linters[lang] ?? []),
@@ -353,7 +221,7 @@ export class CodeMirror6 {
353
221
  }),
354
222
  lintGutter(),
355
223
  keymap.of(lintKeymap),
356
- statusBar(lintSource.fixer),
224
+ optionalFunctions.statusBar(this, lintSource.fixer),
357
225
  ]
358
226
  : [];
359
227
  if (lintSource) {
@@ -378,6 +246,13 @@ export class CodeMirror6 {
378
246
  }
379
247
  }
380
248
  }
249
+ /**
250
+ * Check if the editor enables a specific extension
251
+ * @param name extension name
252
+ */
253
+ hasPreference(name) {
254
+ return this.#preferred.has(name);
255
+ }
381
256
  /**
382
257
  * Add extensions
383
258
  * @param names extension names
@@ -410,7 +285,7 @@ export class CodeMirror6 {
410
285
  */
411
286
  setIndent(indent) {
412
287
  if (this.#view) {
413
- this.#effects(this.#indent.reconfigure(indentUnit.of(detectIndent(this.#view.state.doc, indent, this.#lang))));
288
+ this.#effects(this.#indent.reconfigure(indentUnit.of(optionalFunctions.detectIndent(this.#view.state.doc, indent, this.#lang))));
414
289
  }
415
290
  else {
416
291
  this.#indentStr = indent;
@@ -430,7 +305,7 @@ export class CodeMirror6 {
430
305
  * @param opt linter options
431
306
  */
432
307
  async getLinter(opt) {
433
- return linterRegistry[this.#lang]?.(opt, this.#view);
308
+ return linterRegistry[this.#lang]?.(opt, this.#view, this.#nestedMWLanguage);
434
309
  }
435
310
  /**
436
311
  * Set content
@@ -558,12 +433,4 @@ export class CodeMirror6 {
558
433
  };
559
434
  }));
560
435
  }
561
- /**
562
- * Convert a [WikiParser-Node](https://npmjs.com/package/wikiparser-node) configuration
563
- * to a CodeMirror-MediaWiki configuration
564
- * @param config WikiParser-Node configuration
565
- */
566
- static getMwConfig(config) {
567
- return getStaticMwConfig(config, tagModes);
568
- }
569
436
  }
package/dist/color.d.ts CHANGED
@@ -3,5 +3,5 @@ import type { Tree } from '@lezer/common';
3
3
  import type { StyleSpec } from 'style-mod';
4
4
  import type { WidgetOptions } from '@bhsd/codemirror-css-color-picker';
5
5
  export declare const discoverColors: (_: Tree, from: number, to: number, type: string, doc: Text) => WidgetOptions[] | null;
6
- declare const _default: [([e, style]?: [Extension?, StyleSpec?]) => Extension];
6
+ declare const _default: ([e, style]?: [Extension?, StyleSpec?]) => Extension;
7
7
  export default _default;
package/dist/color.js CHANGED
@@ -27,19 +27,17 @@ export const discoverColors = (_, from, to, type, doc) => {
27
27
  };
28
28
  }).filter(Boolean);
29
29
  };
30
- export default [
31
- ([e, style] = []) => e
32
- ? [
33
- e,
34
- EditorView.theme({
35
- [`.${wrapperClassName}`]: {
36
- outline: 'none',
37
- ...style,
38
- },
39
- [`.${wrapperClassName} input[type="color"]`]: {
40
- outline: '1px solid #eee',
41
- },
42
- }),
43
- ]
44
- : [],
45
- ];
30
+ export default (([e, style] = []) => e
31
+ ? [
32
+ e,
33
+ EditorView.theme({
34
+ [`.${wrapperClassName}`]: {
35
+ outline: 'none',
36
+ ...style,
37
+ },
38
+ [`.${wrapperClassName} input[type="color"]`]: {
39
+ outline: '1px solid #eee',
40
+ },
41
+ }),
42
+ ]
43
+ : []);
package/dist/css.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import { LanguageSupport } from '@codemirror/language';
2
+ import type { Extension } from '@codemirror/state';
2
3
  import type { Dialect } from './codemirror';
4
+ export declare const cssCompletion: (dialect?: Dialect) => Extension;
3
5
  declare const _default: (dialect: Dialect) => LanguageSupport;
4
6
  export default _default;
package/dist/css.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { cssLanguage, cssCompletionSource } from '@codemirror/lang-css';
2
2
  import { LanguageSupport, syntaxTree } from '@codemirror/language';
3
- export default (dialect) => new LanguageSupport(cssLanguage, cssLanguage.data.of({
3
+ export const cssCompletion = (dialect) => cssLanguage.data.of({
4
4
  autocomplete(context) {
5
5
  const { state, pos } = context, node = syntaxTree(state).resolveInner(pos, -1), result = cssCompletionSource(context);
6
6
  if (result) {
@@ -27,4 +27,5 @@ export default (dialect) => new LanguageSupport(cssLanguage, cssLanguage.data.of
27
27
  }
28
28
  return result;
29
29
  },
30
- }));
30
+ });
31
+ export default (dialect) => new LanguageSupport(cssLanguage, cssCompletion(dialect));