@codemirror/lint 6.4.2 → 6.5.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/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## 6.5.0 (2024-01-30)
2
+
3
+ ### Bug fixes
4
+
5
+ Make lint mark decorations inclusive, so that they are applied even if the marked content is replaced by a widget decoration.
6
+
7
+ ### New features
8
+
9
+ `linter` can now be called with null as source to only provide a configuration.
10
+
11
+ `markerFilter` and `tooltipFilter` function now get passed the current editor state.
12
+
1
13
  ## 6.4.2 (2023-09-14)
2
14
 
3
15
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -22,7 +22,7 @@ class LintState {
22
22
  let markedDiagnostics = diagnostics;
23
23
  let diagnosticFilter = state.facet(lintConfig).markerFilter;
24
24
  if (diagnosticFilter)
25
- markedDiagnostics = diagnosticFilter(markedDiagnostics);
25
+ markedDiagnostics = diagnosticFilter(markedDiagnostics, state);
26
26
  let ranges = view.Decoration.set(markedDiagnostics.map((d) => {
27
27
  // For zero-length ranges or ranges covering only a line break, create a widget
28
28
  return d.from == d.to || (d.from == d.to - 1 && state.doc.lineAt(d.from).to == d.from)
@@ -32,7 +32,8 @@ class LintState {
32
32
  }).range(d.from)
33
33
  : view.Decoration.mark({
34
34
  attributes: { class: "cm-lintRange cm-lintRange-" + d.severity + (d.markClass ? " " + d.markClass : "") },
35
- diagnostic: d
35
+ diagnostic: d,
36
+ inclusive: true
36
37
  }).range(d.from, d.to);
37
38
  }), true);
38
39
  return new LintState(ranges, panel, findDiagnostic(ranges));
@@ -108,7 +109,7 @@ function diagnosticCount(state) {
108
109
  let lint = state.field(lintState, false);
109
110
  return lint ? lint.diagnostics.size : 0;
110
111
  }
111
- const activeMark = view.Decoration.mark({ class: "cm-lintRange cm-lintRange-active" });
112
+ const activeMark = view.Decoration.mark({ class: "cm-lintRange cm-lintRange-active", inclusive: true });
112
113
  function lintTooltip(view, pos, side) {
113
114
  let { diagnostics } = view.state.field(lintState);
114
115
  let found = [], stackStart = 2e8, stackEnd = 0;
@@ -122,7 +123,7 @@ function lintTooltip(view, pos, side) {
122
123
  });
123
124
  let diagnosticFilter = view.state.facet(lintConfig).tooltipFilter;
124
125
  if (diagnosticFilter)
125
- found = diagnosticFilter(found);
126
+ found = diagnosticFilter(found, view.state);
126
127
  if (!found.length)
127
128
  return null;
128
129
  return {
@@ -227,11 +228,12 @@ const lintPlugin = view.ViewPlugin.fromClass(class {
227
228
  else {
228
229
  this.set = false;
229
230
  let { state } = this.view, { sources } = state.facet(lintConfig);
230
- Promise.all(sources.map(source => Promise.resolve(source(this.view)))).then(annotations => {
231
- let all = annotations.reduce((a, b) => a.concat(b));
232
- if (this.view.state.doc == state.doc)
233
- this.view.dispatch(setDiagnostics(this.view.state, all));
234
- }, error => { view.logException(this.view.state, error); });
231
+ if (sources.length)
232
+ Promise.all(sources.map(source => Promise.resolve(source(this.view)))).then(annotations => {
233
+ let all = annotations.reduce((a, b) => a.concat(b));
234
+ if (this.view.state.doc == state.doc)
235
+ this.view.dispatch(setDiagnostics(this.view.state, all));
236
+ }, error => { view.logException(this.view.state, error); });
235
237
  }
236
238
  }
237
239
  update(update) {
@@ -257,7 +259,7 @@ const lintPlugin = view.ViewPlugin.fromClass(class {
257
259
  });
258
260
  const lintConfig = state.Facet.define({
259
261
  combine(input) {
260
- return Object.assign({ sources: input.map(i => i.source) }, state.combineConfig(input.map(i => i.config), {
262
+ return Object.assign({ sources: input.map(i => i.source).filter(x => x != null) }, state.combineConfig(input.map(i => i.config), {
261
263
  delay: 750,
262
264
  markerFilter: null,
263
265
  tooltipFilter: null,
@@ -270,7 +272,8 @@ const lintConfig = state.Facet.define({
270
272
  /**
271
273
  Given a diagnostic source, this function returns an extension that
272
274
  enables linting with that source. It will be called whenever the
273
- editor is idle (after its content changed).
275
+ editor is idle (after its content changed). If `null` is given as
276
+ source, this only configures the lint extension.
274
277
  */
275
278
  function linter(source, config = {}) {
276
279
  return [
@@ -628,7 +631,7 @@ class LintGutterMarker extends view.GutterMarker {
628
631
  let diagnostics = this.diagnostics;
629
632
  let diagnosticsFilter = view.state.facet(lintGutterConfig).tooltipFilter;
630
633
  if (diagnosticsFilter)
631
- diagnostics = diagnosticsFilter(diagnostics);
634
+ diagnostics = diagnosticsFilter(diagnostics, view.state);
632
635
  if (diagnostics.length)
633
636
  elt.onmouseover = () => gutterMarkerMouseOver(view, elt, diagnostics);
634
637
  return elt;
@@ -707,7 +710,7 @@ const lintGutterMarkers = state.StateField.define({
707
710
  if (effect.is(setDiagnosticsEffect)) {
708
711
  let diagnostics = effect.value;
709
712
  if (diagnosticFilter)
710
- diagnostics = diagnosticFilter(diagnostics || []);
713
+ diagnostics = diagnosticFilter(diagnostics || [], tr.state);
711
714
  markers = markersForDiagnostics(tr.state.doc, diagnostics.slice(0));
712
715
  }
713
716
  }
package/dist/index.d.cts CHANGED
@@ -62,7 +62,7 @@ interface Action {
62
62
  */
63
63
  apply: (view: EditorView, from: number, to: number) => void;
64
64
  }
65
- type DiagnosticFilter = (diagnostics: readonly Diagnostic[]) => Diagnostic[];
65
+ type DiagnosticFilter = (diagnostics: readonly Diagnostic[], state: EditorState) => Diagnostic[];
66
66
  interface LintConfig {
67
67
  /**
68
68
  Time to wait (in milliseconds) after a change before running
@@ -147,9 +147,10 @@ type LintSource = (view: EditorView) => readonly Diagnostic[] | Promise<readonly
147
147
  /**
148
148
  Given a diagnostic source, this function returns an extension that
149
149
  enables linting with that source. It will be called whenever the
150
- editor is idle (after its content changed).
150
+ editor is idle (after its content changed). If `null` is given as
151
+ source, this only configures the lint extension.
151
152
  */
152
- declare function linter(source: LintSource, config?: LintConfig): Extension;
153
+ declare function linter(source: LintSource | null, config?: LintConfig): Extension;
153
154
  /**
154
155
  Forces any linters [configured](https://codemirror.net/6/docs/ref/#lint.linter) to run when the
155
156
  editor is idle to run right away.
@@ -170,4 +171,4 @@ arguments hold the diagnostic's current position.
170
171
  */
171
172
  declare function forEachDiagnostic(state: EditorState, f: (d: Diagnostic, from: number, to: number) => void): void;
172
173
 
173
- export { Action, Diagnostic, LintSource, closeLintPanel, diagnosticCount, forEachDiagnostic, forceLinting, lintGutter, lintKeymap, linter, nextDiagnostic, openLintPanel, previousDiagnostic, setDiagnostics, setDiagnosticsEffect };
174
+ export { type Action, type Diagnostic, type LintSource, closeLintPanel, diagnosticCount, forEachDiagnostic, forceLinting, lintGutter, lintKeymap, linter, nextDiagnostic, openLintPanel, previousDiagnostic, setDiagnostics, setDiagnosticsEffect };
package/dist/index.d.ts CHANGED
@@ -62,7 +62,7 @@ interface Action {
62
62
  */
63
63
  apply: (view: EditorView, from: number, to: number) => void;
64
64
  }
65
- type DiagnosticFilter = (diagnostics: readonly Diagnostic[]) => Diagnostic[];
65
+ type DiagnosticFilter = (diagnostics: readonly Diagnostic[], state: EditorState) => Diagnostic[];
66
66
  interface LintConfig {
67
67
  /**
68
68
  Time to wait (in milliseconds) after a change before running
@@ -147,9 +147,10 @@ type LintSource = (view: EditorView) => readonly Diagnostic[] | Promise<readonly
147
147
  /**
148
148
  Given a diagnostic source, this function returns an extension that
149
149
  enables linting with that source. It will be called whenever the
150
- editor is idle (after its content changed).
150
+ editor is idle (after its content changed). If `null` is given as
151
+ source, this only configures the lint extension.
151
152
  */
152
- declare function linter(source: LintSource, config?: LintConfig): Extension;
153
+ declare function linter(source: LintSource | null, config?: LintConfig): Extension;
153
154
  /**
154
155
  Forces any linters [configured](https://codemirror.net/6/docs/ref/#lint.linter) to run when the
155
156
  editor is idle to run right away.
@@ -170,4 +171,4 @@ arguments hold the diagnostic's current position.
170
171
  */
171
172
  declare function forEachDiagnostic(state: EditorState, f: (d: Diagnostic, from: number, to: number) => void): void;
172
173
 
173
- export { Action, Diagnostic, LintSource, closeLintPanel, diagnosticCount, forEachDiagnostic, forceLinting, lintGutter, lintKeymap, linter, nextDiagnostic, openLintPanel, previousDiagnostic, setDiagnostics, setDiagnosticsEffect };
174
+ export { type Action, type Diagnostic, type LintSource, closeLintPanel, diagnosticCount, forEachDiagnostic, forceLinting, lintGutter, lintKeymap, linter, nextDiagnostic, openLintPanel, previousDiagnostic, setDiagnostics, setDiagnosticsEffect };
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ class LintState {
20
20
  let markedDiagnostics = diagnostics;
21
21
  let diagnosticFilter = state.facet(lintConfig).markerFilter;
22
22
  if (diagnosticFilter)
23
- markedDiagnostics = diagnosticFilter(markedDiagnostics);
23
+ markedDiagnostics = diagnosticFilter(markedDiagnostics, state);
24
24
  let ranges = Decoration.set(markedDiagnostics.map((d) => {
25
25
  // For zero-length ranges or ranges covering only a line break, create a widget
26
26
  return d.from == d.to || (d.from == d.to - 1 && state.doc.lineAt(d.from).to == d.from)
@@ -30,7 +30,8 @@ class LintState {
30
30
  }).range(d.from)
31
31
  : Decoration.mark({
32
32
  attributes: { class: "cm-lintRange cm-lintRange-" + d.severity + (d.markClass ? " " + d.markClass : "") },
33
- diagnostic: d
33
+ diagnostic: d,
34
+ inclusive: true
34
35
  }).range(d.from, d.to);
35
36
  }), true);
36
37
  return new LintState(ranges, panel, findDiagnostic(ranges));
@@ -106,7 +107,7 @@ function diagnosticCount(state) {
106
107
  let lint = state.field(lintState, false);
107
108
  return lint ? lint.diagnostics.size : 0;
108
109
  }
109
- const activeMark = /*@__PURE__*/Decoration.mark({ class: "cm-lintRange cm-lintRange-active" });
110
+ const activeMark = /*@__PURE__*/Decoration.mark({ class: "cm-lintRange cm-lintRange-active", inclusive: true });
110
111
  function lintTooltip(view, pos, side) {
111
112
  let { diagnostics } = view.state.field(lintState);
112
113
  let found = [], stackStart = 2e8, stackEnd = 0;
@@ -120,7 +121,7 @@ function lintTooltip(view, pos, side) {
120
121
  });
121
122
  let diagnosticFilter = view.state.facet(lintConfig).tooltipFilter;
122
123
  if (diagnosticFilter)
123
- found = diagnosticFilter(found);
124
+ found = diagnosticFilter(found, view.state);
124
125
  if (!found.length)
125
126
  return null;
126
127
  return {
@@ -225,11 +226,12 @@ const lintPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
225
226
  else {
226
227
  this.set = false;
227
228
  let { state } = this.view, { sources } = state.facet(lintConfig);
228
- Promise.all(sources.map(source => Promise.resolve(source(this.view)))).then(annotations => {
229
- let all = annotations.reduce((a, b) => a.concat(b));
230
- if (this.view.state.doc == state.doc)
231
- this.view.dispatch(setDiagnostics(this.view.state, all));
232
- }, error => { logException(this.view.state, error); });
229
+ if (sources.length)
230
+ Promise.all(sources.map(source => Promise.resolve(source(this.view)))).then(annotations => {
231
+ let all = annotations.reduce((a, b) => a.concat(b));
232
+ if (this.view.state.doc == state.doc)
233
+ this.view.dispatch(setDiagnostics(this.view.state, all));
234
+ }, error => { logException(this.view.state, error); });
233
235
  }
234
236
  }
235
237
  update(update) {
@@ -255,7 +257,7 @@ const lintPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
255
257
  });
256
258
  const lintConfig = /*@__PURE__*/Facet.define({
257
259
  combine(input) {
258
- return Object.assign({ sources: input.map(i => i.source) }, combineConfig(input.map(i => i.config), {
260
+ return Object.assign({ sources: input.map(i => i.source).filter(x => x != null) }, combineConfig(input.map(i => i.config), {
259
261
  delay: 750,
260
262
  markerFilter: null,
261
263
  tooltipFilter: null,
@@ -268,7 +270,8 @@ const lintConfig = /*@__PURE__*/Facet.define({
268
270
  /**
269
271
  Given a diagnostic source, this function returns an extension that
270
272
  enables linting with that source. It will be called whenever the
271
- editor is idle (after its content changed).
273
+ editor is idle (after its content changed). If `null` is given as
274
+ source, this only configures the lint extension.
272
275
  */
273
276
  function linter(source, config = {}) {
274
277
  return [
@@ -626,7 +629,7 @@ class LintGutterMarker extends GutterMarker {
626
629
  let diagnostics = this.diagnostics;
627
630
  let diagnosticsFilter = view.state.facet(lintGutterConfig).tooltipFilter;
628
631
  if (diagnosticsFilter)
629
- diagnostics = diagnosticsFilter(diagnostics);
632
+ diagnostics = diagnosticsFilter(diagnostics, view.state);
630
633
  if (diagnostics.length)
631
634
  elt.onmouseover = () => gutterMarkerMouseOver(view, elt, diagnostics);
632
635
  return elt;
@@ -705,7 +708,7 @@ const lintGutterMarkers = /*@__PURE__*/StateField.define({
705
708
  if (effect.is(setDiagnosticsEffect)) {
706
709
  let diagnostics = effect.value;
707
710
  if (diagnosticFilter)
708
- diagnostics = diagnosticFilter(diagnostics || []);
711
+ diagnostics = diagnosticFilter(diagnostics || [], tr.state);
709
712
  markers = markersForDiagnostics(tr.state.doc, diagnostics.slice(0));
710
713
  }
711
714
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/lint",
3
- "version": "6.4.2",
3
+ "version": "6.5.0",
4
4
  "description": "Linting support for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",