@bhsd/codemirror-mediawiki 2.1.15 → 2.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.
package/src/codemirror.ts CHANGED
@@ -1,4 +1,4 @@
1
- import {Compartment, EditorState} from '@codemirror/state';
1
+ import {Compartment, EditorState, EditorSelection} from '@codemirror/state';
2
2
  import {
3
3
  EditorView,
4
4
  lineNumbers,
@@ -24,8 +24,8 @@ import {linter, lintGutter, openLintPanel, closeLintPanel, lintKeymap} from '@co
24
24
  import {closeBrackets} from '@codemirror/autocomplete';
25
25
  import {mediawiki, html} from './mediawiki';
26
26
  import * as plugins from './plugins';
27
- import type {ViewPlugin} from '@codemirror/view';
28
- import type {Extension, Text} from '@codemirror/state';
27
+ import type {ViewPlugin, KeyBinding} from '@codemirror/view';
28
+ import type {Extension, Text, StateEffect} from '@codemirror/state';
29
29
  import type {Diagnostic} from '@codemirror/lint';
30
30
  import type {Highlighter} from '@lezer/highlight';
31
31
  import type {Linter} from 'eslint';
@@ -61,7 +61,8 @@ const avail: Record<string, [(config?: any) => Extension, Record<string, unknown
61
61
  {},
62
62
  ],
63
63
  };
64
- const CDN = 'https://testingcf.jsdelivr.net';
64
+
65
+ export const CDN = 'https://testingcf.jsdelivr.net';
65
66
 
66
67
  /**
67
68
  * 使用传统方法加载脚本
@@ -96,6 +97,7 @@ export class CodeMirror6 {
96
97
  readonly #linter = new Compartment();
97
98
  readonly #extensions = new Compartment();
98
99
  readonly #indent = new Compartment();
100
+ readonly #extraKeys = new Compartment();
99
101
  #lang;
100
102
  #visible = false;
101
103
  #preferred = new Set<string>();
@@ -130,6 +132,7 @@ export class CodeMirror6 {
130
132
  this.#linter.of([]),
131
133
  this.#extensions.of([]),
132
134
  this.#indent.of(indentUnit.of('\t')),
135
+ this.#extraKeys.of([]),
133
136
  syntaxHighlighting(defaultHighlightStyle as Highlighter),
134
137
  EditorView.contentAttributes.of({
135
138
  accesskey: textarea.accessKey,
@@ -168,6 +171,14 @@ export class CodeMirror6 {
168
171
  this.toggle(true);
169
172
  }
170
173
 
174
+ /**
175
+ * 修改扩展
176
+ * @param effects 扩展变动
177
+ */
178
+ #effects(effects: StateEffect<unknown> | StateEffect<unknown>[]): void {
179
+ this.#view.dispatch({effects});
180
+ }
181
+
171
182
  /** 刷新编辑器高度 */
172
183
  #refresh(): void {
173
184
  const {offsetHeight} = this.#textarea;
@@ -203,12 +214,10 @@ export class CodeMirror6 {
203
214
  * @param config 语言设置
204
215
  */
205
216
  setLanguage(lang = 'plain', config?: unknown): void {
206
- this.#view.dispatch({
207
- effects: [
208
- this.#language.reconfigure(languages[lang]!(config)),
209
- this.#linter.reconfigure(linters[lang] || []),
210
- ],
211
- });
217
+ this.#effects([
218
+ this.#language.reconfigure(languages[lang]!(config)),
219
+ this.#linter.reconfigure(linters[lang] || []),
220
+ ]);
212
221
  this.#lang = lang;
213
222
  this.#toggleLintPanel(Boolean(linters[lang]));
214
223
  }
@@ -229,9 +238,7 @@ export class CodeMirror6 {
229
238
  } else {
230
239
  delete linters[this.#lang];
231
240
  }
232
- this.#view.dispatch({
233
- effects: [this.#linter.reconfigure(linterExtension)],
234
- });
241
+ this.#effects(this.#linter.reconfigure(linterExtension));
235
242
  this.#toggleLintPanel(Boolean(lintSource));
236
243
  }
237
244
 
@@ -261,14 +268,12 @@ export class CodeMirror6 {
261
268
  }
262
269
  }
263
270
  }
264
- this.#view.dispatch({
265
- effects: [
266
- this.#extensions.reconfigure([...this.#preferred].map(name => {
267
- const [extension, configs] = avail[name]!;
268
- return extension(configs[this.#lang]);
269
- })),
270
- ],
271
- });
271
+ this.#effects(
272
+ this.#extensions.reconfigure([...this.#preferred].map(name => {
273
+ const [extension, configs] = avail[name]!;
274
+ return extension(configs[this.#lang]);
275
+ })),
276
+ );
272
277
  }
273
278
 
274
279
  /**
@@ -276,16 +281,14 @@ export class CodeMirror6 {
276
281
  * @param indent 缩进字符串
277
282
  */
278
283
  setIndent(indent: string): void {
279
- this.#view.dispatch({
280
- effects: [this.#indent.reconfigure(indentUnit.of(indent))],
281
- });
284
+ this.#effects(this.#indent.reconfigure(indentUnit.of(indent)));
282
285
  }
283
286
 
284
287
  /** 获取默认linter */
285
288
  async getLinter(opt?: Record<string, unknown>): Promise<LintSource | undefined> {
286
289
  switch (this.#lang) {
287
290
  case 'mediawiki': {
288
- const REPO = 'npm/wikiparser-node@1.4.1-b',
291
+ const REPO = 'npm/wikiparser-node@1.4.3-b',
289
292
  DIR = `${REPO}/extensions/dist`,
290
293
  src = `combine/${DIR}/base.min.js,${DIR}/lint.min.js`,
291
294
  lang = opt?.['i18n'];
@@ -471,4 +474,28 @@ export class CodeMirror6 {
471
474
  }
472
475
  this.#visible = show;
473
476
  }
477
+
478
+ /**
479
+ * 添加额外快捷键
480
+ * @param keys 快捷键
481
+ */
482
+ extraKeys(keys: KeyBinding[]): void {
483
+ this.#effects(this.#extraKeys.reconfigure(keymap.of(keys)));
484
+ }
485
+
486
+ /**
487
+ * 替换选中内容
488
+ * @param view EditorView
489
+ * @param func 替换函数
490
+ */
491
+ static replaceSelections(view: EditorView, func: (str: string) => string): void {
492
+ const {state} = view;
493
+ view.dispatch(state.update(state.changeByRange(({from, to}) => {
494
+ const insert = func(state.sliceDoc(from, to));
495
+ return {
496
+ range: EditorSelection.cursor(from + insert.length),
497
+ changes: {from, to, insert},
498
+ };
499
+ })));
500
+ }
474
501
  }