@bhsd/codemirror-mediawiki 3.11.4 → 3.11.5

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,6 +1,6 @@
1
1
  import { EditorView } from '@codemirror/view';
2
- import type { KeyBinding } from '@codemirror/view';
3
- import type { Extension } from '@codemirror/state';
2
+ import type { ViewPlugin, KeyBinding, DecorationSet } from '@codemirror/view';
3
+ import type { Extension, StateField } from '@codemirror/state';
4
4
  import type { SyntaxNode } from '@lezer/common';
5
5
  import type { ConfigGetter } from '@bhsd/browser';
6
6
  import type { ConfigData } from 'wikiparser-node';
@@ -20,6 +20,18 @@ declare interface MenuItem {
20
20
  isActionable(this: void, cm: CodeMirror6): boolean;
21
21
  getItems(this: void, cm: CodeMirror6): HTMLElement[];
22
22
  }
23
+ declare type LintExtension = [
24
+ unknown,
25
+ ViewPlugin<{
26
+ set: boolean;
27
+ force(): void;
28
+ }>,
29
+ [
30
+ StateField<{
31
+ diagnostics: DecorationSet;
32
+ }>
33
+ ]
34
+ ];
23
35
  declare interface OptionalFunctions {
24
36
  statusBar: typeof statusBar;
25
37
  detectIndent: typeof detectIndent;
@@ -82,6 +94,8 @@ export declare class CodeMirror6 {
82
94
  * @param lintSource function for syntax checking
83
95
  */
84
96
  lint(lintSource?: LintSources): void;
97
+ /** @private */
98
+ getLintExtension(): LintExtension | undefined;
85
99
  /** Update syntax checking immediately */
86
100
  update(): void;
87
101
  /**
@@ -3,10 +3,11 @@ import { EditorSelection, Compartment, EditorState, SelectionRange, } from '@cod
3
3
  import { syntaxHighlighting, defaultHighlightStyle, indentOnInput, indentUnit, ensureSyntaxTree, syntaxTree, } from '@codemirror/language';
4
4
  import { defaultKeymap, historyKeymap, history, redo, indentWithTab, insertNewlineKeepIndent, deleteCharBackwardStrict, } from '@codemirror/commands';
5
5
  import { searchKeymap } from '@codemirror/search';
6
- import { linter, lintGutter, nextDiagnostic } from '@codemirror/lint';
6
+ import { linter, lintGutter } from '@codemirror/lint';
7
7
  import elt from 'crelt';
8
8
  import { base, panelSelector, panelsSelector, diagnosticSelector, noDetectionLangs } from './constants.js';
9
9
  import { light } from './theme.js';
10
+ import { nextDiagnostic } from './lint.js';
10
11
  export const plain = () => [
11
12
  EditorView.contentAttributes.of({ spellcheck: 'true' }),
12
13
  keymap.of([
@@ -277,7 +278,7 @@ export class CodeMirror6 {
277
278
  */
278
279
  lint(lintSource) {
279
280
  const lintSources = typeof lintSource === 'function' ? [lintSource] : lintSource;
280
- const linterExtension = (cm) => lintSources
281
+ const linterExtension = (cm) => lintSources?.length
281
282
  ? [
282
283
  ...lintSources.map(source => linter(async ({ state }) => {
283
284
  const diagnostics = (await source(state)).map((diagnostic) => ({
@@ -301,7 +302,7 @@ export class CodeMirror6 {
301
302
  return diagnostics;
302
303
  })),
303
304
  lintGutter(),
304
- keymap.of([{ key: 'F8', run: nextDiagnostic }]),
305
+ keymap.of([{ key: 'F8', run: () => nextDiagnostic(this) }]),
305
306
  optionalFunctions.statusBar(cm, lintSources[0].fixer),
306
307
  ]
307
308
  : [];
@@ -318,15 +319,17 @@ export class CodeMirror6 {
318
319
  this.#minHeight(Boolean(lintSource));
319
320
  }
320
321
  }
322
+ /** @private */
323
+ getLintExtension() {
324
+ return this.#view && this.#linter.get(this.#view.state)[0];
325
+ }
321
326
  /** Update syntax checking immediately */
322
327
  update() {
323
- if (this.#view) {
324
- const [extension] = this.#linter.get(this.#view.state);
325
- if (extension) {
326
- const plugin = this.#view.plugin(extension[1]);
327
- plugin.set = true;
328
- plugin.force();
329
- }
328
+ const extension = this.getLintExtension();
329
+ if (extension) {
330
+ const plugin = this.#view.plugin(extension[1]);
331
+ plugin.set = true;
332
+ plugin.force();
330
333
  }
331
334
  }
332
335
  /**
@@ -435,7 +438,7 @@ export class CodeMirror6 {
435
438
  this.#textarea.style.display = '';
436
439
  this.#textarea.setSelectionRange(from, to, head === to ? 'forward' : 'backward');
437
440
  if (hasFocus) {
438
- this.#textarea.focus();
441
+ this.#textarea.focus({ preventScroll: true });
439
442
  }
440
443
  requestAnimationFrame(() => {
441
444
  this.#textarea.scrollTop = scrollTop;
package/dist/lint.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import type { CodeMirror6 } from './codemirror';
2
+ /**
3
+ * 选中下一个诊断的范围
4
+ * @param cm CodeMirror6 实例
5
+ */
6
+ export declare const nextDiagnostic: (cm: CodeMirror6) => boolean;
package/dist/lint.js ADDED
@@ -0,0 +1,28 @@
1
+ const findDiagnostic = (deco, head, anchor = head) => {
2
+ let found;
3
+ deco.between(head, Infinity, (_, __, { spec: { diagnostics } }) => {
4
+ const next = diagnostics.sort((a, b) => a.from - b.from || a.to - b.to)
5
+ .find(({ from, to }) => from > head || from === head && to > anchor);
6
+ if (next) {
7
+ found = next;
8
+ return false;
9
+ }
10
+ return undefined;
11
+ });
12
+ return found;
13
+ };
14
+ /**
15
+ * 选中下一个诊断的范围
16
+ * @param cm CodeMirror6 实例
17
+ */
18
+ export const nextDiagnostic = (cm) => {
19
+ const view = cm.view, { state } = view, { diagnostics } = state.field(cm.getLintExtension()[2][0]), { from, to } = state.selection.main, next = findDiagnostic(diagnostics, from, to) ?? findDiagnostic(diagnostics, 0);
20
+ if (!next || next.from === from && next.to === to) {
21
+ return false;
22
+ }
23
+ view.dispatch({
24
+ selection: { anchor: next.from, head: next.to },
25
+ scrollIntoView: true,
26
+ });
27
+ return true;
28
+ };