@codemirror/lint 6.4.2 → 6.6.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 +18 -0
- package/dist/index.cjs +23 -15
- package/dist/index.d.cts +14 -5
- package/dist/index.d.ts +14 -5
- package/dist/index.js +23 -15
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
## 6.6.0 (2024-04-29)
|
|
2
|
+
|
|
3
|
+
### New features
|
|
4
|
+
|
|
5
|
+
The new `hideOn` configuration option can be used to control in what circumstances lint tooltips get hidden by state changes.
|
|
6
|
+
|
|
7
|
+
## 6.5.0 (2024-01-30)
|
|
8
|
+
|
|
9
|
+
### Bug fixes
|
|
10
|
+
|
|
11
|
+
Make lint mark decorations inclusive, so that they are applied even if the marked content is replaced by a widget decoration.
|
|
12
|
+
|
|
13
|
+
### New features
|
|
14
|
+
|
|
15
|
+
`linter` can now be called with null as source to only provide a configuration.
|
|
16
|
+
|
|
17
|
+
`markerFilter` and `tooltipFilter` function now get passed the current editor state.
|
|
18
|
+
|
|
1
19
|
## 6.4.2 (2023-09-14)
|
|
2
20
|
|
|
3
21
|
### 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));
|
|
@@ -49,8 +50,12 @@ function findDiagnostic(diagnostics, diagnostic = null, after = 0) {
|
|
|
49
50
|
return found;
|
|
50
51
|
}
|
|
51
52
|
function hideTooltip(tr, tooltip) {
|
|
53
|
+
let from = tooltip.pos, to = tooltip.end || from;
|
|
54
|
+
let result = tr.state.facet(lintConfig).hideOn(tr, from, to);
|
|
55
|
+
if (result != null)
|
|
56
|
+
return result;
|
|
52
57
|
let line = tr.startState.doc.lineAt(tooltip.pos);
|
|
53
|
-
return !!(tr.effects.some(e => e.is(setDiagnosticsEffect)) || tr.changes.touchesRange(line.from, line.to));
|
|
58
|
+
return !!(tr.effects.some(e => e.is(setDiagnosticsEffect)) || tr.changes.touchesRange(line.from, Math.max(line.to, to)));
|
|
54
59
|
}
|
|
55
60
|
function maybeEnableLint(state$1, effects) {
|
|
56
61
|
return state$1.field(lintState, false) ? effects : effects.concat(state.StateEffect.appendConfig.of(lintExtensions));
|
|
@@ -108,7 +113,7 @@ function diagnosticCount(state) {
|
|
|
108
113
|
let lint = state.field(lintState, false);
|
|
109
114
|
return lint ? lint.diagnostics.size : 0;
|
|
110
115
|
}
|
|
111
|
-
const activeMark = view.Decoration.mark({ class: "cm-lintRange cm-lintRange-active" });
|
|
116
|
+
const activeMark = view.Decoration.mark({ class: "cm-lintRange cm-lintRange-active", inclusive: true });
|
|
112
117
|
function lintTooltip(view, pos, side) {
|
|
113
118
|
let { diagnostics } = view.state.field(lintState);
|
|
114
119
|
let found = [], stackStart = 2e8, stackEnd = 0;
|
|
@@ -122,7 +127,7 @@ function lintTooltip(view, pos, side) {
|
|
|
122
127
|
});
|
|
123
128
|
let diagnosticFilter = view.state.facet(lintConfig).tooltipFilter;
|
|
124
129
|
if (diagnosticFilter)
|
|
125
|
-
found = diagnosticFilter(found);
|
|
130
|
+
found = diagnosticFilter(found, view.state);
|
|
126
131
|
if (!found.length)
|
|
127
132
|
return null;
|
|
128
133
|
return {
|
|
@@ -227,11 +232,12 @@ const lintPlugin = view.ViewPlugin.fromClass(class {
|
|
|
227
232
|
else {
|
|
228
233
|
this.set = false;
|
|
229
234
|
let { state } = this.view, { sources } = state.facet(lintConfig);
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
+
if (sources.length)
|
|
236
|
+
Promise.all(sources.map(source => Promise.resolve(source(this.view)))).then(annotations => {
|
|
237
|
+
let all = annotations.reduce((a, b) => a.concat(b));
|
|
238
|
+
if (this.view.state.doc == state.doc)
|
|
239
|
+
this.view.dispatch(setDiagnostics(this.view.state, all));
|
|
240
|
+
}, error => { view.logException(this.view.state, error); });
|
|
235
241
|
}
|
|
236
242
|
}
|
|
237
243
|
update(update) {
|
|
@@ -257,11 +263,12 @@ const lintPlugin = view.ViewPlugin.fromClass(class {
|
|
|
257
263
|
});
|
|
258
264
|
const lintConfig = state.Facet.define({
|
|
259
265
|
combine(input) {
|
|
260
|
-
return Object.assign({ sources: input.map(i => i.source) }, state.combineConfig(input.map(i => i.config), {
|
|
266
|
+
return Object.assign({ sources: input.map(i => i.source).filter(x => x != null) }, state.combineConfig(input.map(i => i.config), {
|
|
261
267
|
delay: 750,
|
|
262
268
|
markerFilter: null,
|
|
263
269
|
tooltipFilter: null,
|
|
264
|
-
needsRefresh: null
|
|
270
|
+
needsRefresh: null,
|
|
271
|
+
hideOn: () => null,
|
|
265
272
|
}, {
|
|
266
273
|
needsRefresh: (a, b) => !a ? b : !b ? a : u => a(u) || b(u)
|
|
267
274
|
}));
|
|
@@ -270,7 +277,8 @@ const lintConfig = state.Facet.define({
|
|
|
270
277
|
/**
|
|
271
278
|
Given a diagnostic source, this function returns an extension that
|
|
272
279
|
enables linting with that source. It will be called whenever the
|
|
273
|
-
editor is idle (after its content changed).
|
|
280
|
+
editor is idle (after its content changed). If `null` is given as
|
|
281
|
+
source, this only configures the lint extension.
|
|
274
282
|
*/
|
|
275
283
|
function linter(source, config = {}) {
|
|
276
284
|
return [
|
|
@@ -628,7 +636,7 @@ class LintGutterMarker extends view.GutterMarker {
|
|
|
628
636
|
let diagnostics = this.diagnostics;
|
|
629
637
|
let diagnosticsFilter = view.state.facet(lintGutterConfig).tooltipFilter;
|
|
630
638
|
if (diagnosticsFilter)
|
|
631
|
-
diagnostics = diagnosticsFilter(diagnostics);
|
|
639
|
+
diagnostics = diagnosticsFilter(diagnostics, view.state);
|
|
632
640
|
if (diagnostics.length)
|
|
633
641
|
elt.onmouseover = () => gutterMarkerMouseOver(view, elt, diagnostics);
|
|
634
642
|
return elt;
|
|
@@ -707,7 +715,7 @@ const lintGutterMarkers = state.StateField.define({
|
|
|
707
715
|
if (effect.is(setDiagnosticsEffect)) {
|
|
708
716
|
let diagnostics = effect.value;
|
|
709
717
|
if (diagnosticFilter)
|
|
710
|
-
diagnostics = diagnosticFilter(diagnostics || []);
|
|
718
|
+
diagnostics = diagnosticFilter(diagnostics || [], tr.state);
|
|
711
719
|
markers = markersForDiagnostics(tr.state.doc, diagnostics.slice(0));
|
|
712
720
|
}
|
|
713
721
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _codemirror_state from '@codemirror/state';
|
|
2
|
-
import { EditorState, TransactionSpec, Extension } from '@codemirror/state';
|
|
2
|
+
import { EditorState, TransactionSpec, Extension, Transaction } from '@codemirror/state';
|
|
3
3
|
import { EditorView, Command, KeyBinding, ViewUpdate } from '@codemirror/view';
|
|
4
4
|
|
|
5
5
|
type Severity = "hint" | "info" | "warning" | "error";
|
|
@@ -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
|
|
@@ -85,6 +85,14 @@ interface LintConfig {
|
|
|
85
85
|
tooltip will appear if the empty set is returned.
|
|
86
86
|
*/
|
|
87
87
|
tooltipFilter?: null | DiagnosticFilter;
|
|
88
|
+
/**
|
|
89
|
+
Can be used to control what kind of transactions cause lint
|
|
90
|
+
hover tooltips associated with the given document range to be
|
|
91
|
+
hidden. By default any transactions that changes the line
|
|
92
|
+
around the range will hide it. Returning null falls back to this
|
|
93
|
+
behavior.
|
|
94
|
+
*/
|
|
95
|
+
hideOn?: (tr: Transaction, from: number, to: number) => boolean | null;
|
|
88
96
|
}
|
|
89
97
|
interface LintGutterConfig {
|
|
90
98
|
/**
|
|
@@ -147,9 +155,10 @@ type LintSource = (view: EditorView) => readonly Diagnostic[] | Promise<readonly
|
|
|
147
155
|
/**
|
|
148
156
|
Given a diagnostic source, this function returns an extension that
|
|
149
157
|
enables linting with that source. It will be called whenever the
|
|
150
|
-
editor is idle (after its content changed).
|
|
158
|
+
editor is idle (after its content changed). If `null` is given as
|
|
159
|
+
source, this only configures the lint extension.
|
|
151
160
|
*/
|
|
152
|
-
declare function linter(source: LintSource, config?: LintConfig): Extension;
|
|
161
|
+
declare function linter(source: LintSource | null, config?: LintConfig): Extension;
|
|
153
162
|
/**
|
|
154
163
|
Forces any linters [configured](https://codemirror.net/6/docs/ref/#lint.linter) to run when the
|
|
155
164
|
editor is idle to run right away.
|
|
@@ -170,4 +179,4 @@ arguments hold the diagnostic's current position.
|
|
|
170
179
|
*/
|
|
171
180
|
declare function forEachDiagnostic(state: EditorState, f: (d: Diagnostic, from: number, to: number) => void): void;
|
|
172
181
|
|
|
173
|
-
export { Action, Diagnostic, LintSource, closeLintPanel, diagnosticCount, forEachDiagnostic, forceLinting, lintGutter, lintKeymap, linter, nextDiagnostic, openLintPanel, previousDiagnostic, setDiagnostics, setDiagnosticsEffect };
|
|
182
|
+
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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _codemirror_state from '@codemirror/state';
|
|
2
|
-
import { EditorState, TransactionSpec, Extension } from '@codemirror/state';
|
|
2
|
+
import { EditorState, TransactionSpec, Extension, Transaction } from '@codemirror/state';
|
|
3
3
|
import { EditorView, Command, KeyBinding, ViewUpdate } from '@codemirror/view';
|
|
4
4
|
|
|
5
5
|
type Severity = "hint" | "info" | "warning" | "error";
|
|
@@ -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
|
|
@@ -85,6 +85,14 @@ interface LintConfig {
|
|
|
85
85
|
tooltip will appear if the empty set is returned.
|
|
86
86
|
*/
|
|
87
87
|
tooltipFilter?: null | DiagnosticFilter;
|
|
88
|
+
/**
|
|
89
|
+
Can be used to control what kind of transactions cause lint
|
|
90
|
+
hover tooltips associated with the given document range to be
|
|
91
|
+
hidden. By default any transactions that changes the line
|
|
92
|
+
around the range will hide it. Returning null falls back to this
|
|
93
|
+
behavior.
|
|
94
|
+
*/
|
|
95
|
+
hideOn?: (tr: Transaction, from: number, to: number) => boolean | null;
|
|
88
96
|
}
|
|
89
97
|
interface LintGutterConfig {
|
|
90
98
|
/**
|
|
@@ -147,9 +155,10 @@ type LintSource = (view: EditorView) => readonly Diagnostic[] | Promise<readonly
|
|
|
147
155
|
/**
|
|
148
156
|
Given a diagnostic source, this function returns an extension that
|
|
149
157
|
enables linting with that source. It will be called whenever the
|
|
150
|
-
editor is idle (after its content changed).
|
|
158
|
+
editor is idle (after its content changed). If `null` is given as
|
|
159
|
+
source, this only configures the lint extension.
|
|
151
160
|
*/
|
|
152
|
-
declare function linter(source: LintSource, config?: LintConfig): Extension;
|
|
161
|
+
declare function linter(source: LintSource | null, config?: LintConfig): Extension;
|
|
153
162
|
/**
|
|
154
163
|
Forces any linters [configured](https://codemirror.net/6/docs/ref/#lint.linter) to run when the
|
|
155
164
|
editor is idle to run right away.
|
|
@@ -170,4 +179,4 @@ arguments hold the diagnostic's current position.
|
|
|
170
179
|
*/
|
|
171
180
|
declare function forEachDiagnostic(state: EditorState, f: (d: Diagnostic, from: number, to: number) => void): void;
|
|
172
181
|
|
|
173
|
-
export { Action, Diagnostic, LintSource, closeLintPanel, diagnosticCount, forEachDiagnostic, forceLinting, lintGutter, lintKeymap, linter, nextDiagnostic, openLintPanel, previousDiagnostic, setDiagnostics, setDiagnosticsEffect };
|
|
182
|
+
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));
|
|
@@ -47,8 +48,12 @@ function findDiagnostic(diagnostics, diagnostic = null, after = 0) {
|
|
|
47
48
|
return found;
|
|
48
49
|
}
|
|
49
50
|
function hideTooltip(tr, tooltip) {
|
|
51
|
+
let from = tooltip.pos, to = tooltip.end || from;
|
|
52
|
+
let result = tr.state.facet(lintConfig).hideOn(tr, from, to);
|
|
53
|
+
if (result != null)
|
|
54
|
+
return result;
|
|
50
55
|
let line = tr.startState.doc.lineAt(tooltip.pos);
|
|
51
|
-
return !!(tr.effects.some(e => e.is(setDiagnosticsEffect)) || tr.changes.touchesRange(line.from, line.to));
|
|
56
|
+
return !!(tr.effects.some(e => e.is(setDiagnosticsEffect)) || tr.changes.touchesRange(line.from, Math.max(line.to, to)));
|
|
52
57
|
}
|
|
53
58
|
function maybeEnableLint(state, effects) {
|
|
54
59
|
return state.field(lintState, false) ? effects : effects.concat(StateEffect.appendConfig.of(lintExtensions));
|
|
@@ -106,7 +111,7 @@ function diagnosticCount(state) {
|
|
|
106
111
|
let lint = state.field(lintState, false);
|
|
107
112
|
return lint ? lint.diagnostics.size : 0;
|
|
108
113
|
}
|
|
109
|
-
const activeMark = /*@__PURE__*/Decoration.mark({ class: "cm-lintRange cm-lintRange-active" });
|
|
114
|
+
const activeMark = /*@__PURE__*/Decoration.mark({ class: "cm-lintRange cm-lintRange-active", inclusive: true });
|
|
110
115
|
function lintTooltip(view, pos, side) {
|
|
111
116
|
let { diagnostics } = view.state.field(lintState);
|
|
112
117
|
let found = [], stackStart = 2e8, stackEnd = 0;
|
|
@@ -120,7 +125,7 @@ function lintTooltip(view, pos, side) {
|
|
|
120
125
|
});
|
|
121
126
|
let diagnosticFilter = view.state.facet(lintConfig).tooltipFilter;
|
|
122
127
|
if (diagnosticFilter)
|
|
123
|
-
found = diagnosticFilter(found);
|
|
128
|
+
found = diagnosticFilter(found, view.state);
|
|
124
129
|
if (!found.length)
|
|
125
130
|
return null;
|
|
126
131
|
return {
|
|
@@ -225,11 +230,12 @@ const lintPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
225
230
|
else {
|
|
226
231
|
this.set = false;
|
|
227
232
|
let { state } = this.view, { sources } = state.facet(lintConfig);
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
+
if (sources.length)
|
|
234
|
+
Promise.all(sources.map(source => Promise.resolve(source(this.view)))).then(annotations => {
|
|
235
|
+
let all = annotations.reduce((a, b) => a.concat(b));
|
|
236
|
+
if (this.view.state.doc == state.doc)
|
|
237
|
+
this.view.dispatch(setDiagnostics(this.view.state, all));
|
|
238
|
+
}, error => { logException(this.view.state, error); });
|
|
233
239
|
}
|
|
234
240
|
}
|
|
235
241
|
update(update) {
|
|
@@ -255,11 +261,12 @@ const lintPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
255
261
|
});
|
|
256
262
|
const lintConfig = /*@__PURE__*/Facet.define({
|
|
257
263
|
combine(input) {
|
|
258
|
-
return Object.assign({ sources: input.map(i => i.source) }, combineConfig(input.map(i => i.config), {
|
|
264
|
+
return Object.assign({ sources: input.map(i => i.source).filter(x => x != null) }, combineConfig(input.map(i => i.config), {
|
|
259
265
|
delay: 750,
|
|
260
266
|
markerFilter: null,
|
|
261
267
|
tooltipFilter: null,
|
|
262
|
-
needsRefresh: null
|
|
268
|
+
needsRefresh: null,
|
|
269
|
+
hideOn: () => null,
|
|
263
270
|
}, {
|
|
264
271
|
needsRefresh: (a, b) => !a ? b : !b ? a : u => a(u) || b(u)
|
|
265
272
|
}));
|
|
@@ -268,7 +275,8 @@ const lintConfig = /*@__PURE__*/Facet.define({
|
|
|
268
275
|
/**
|
|
269
276
|
Given a diagnostic source, this function returns an extension that
|
|
270
277
|
enables linting with that source. It will be called whenever the
|
|
271
|
-
editor is idle (after its content changed).
|
|
278
|
+
editor is idle (after its content changed). If `null` is given as
|
|
279
|
+
source, this only configures the lint extension.
|
|
272
280
|
*/
|
|
273
281
|
function linter(source, config = {}) {
|
|
274
282
|
return [
|
|
@@ -626,7 +634,7 @@ class LintGutterMarker extends GutterMarker {
|
|
|
626
634
|
let diagnostics = this.diagnostics;
|
|
627
635
|
let diagnosticsFilter = view.state.facet(lintGutterConfig).tooltipFilter;
|
|
628
636
|
if (diagnosticsFilter)
|
|
629
|
-
diagnostics = diagnosticsFilter(diagnostics);
|
|
637
|
+
diagnostics = diagnosticsFilter(diagnostics, view.state);
|
|
630
638
|
if (diagnostics.length)
|
|
631
639
|
elt.onmouseover = () => gutterMarkerMouseOver(view, elt, diagnostics);
|
|
632
640
|
return elt;
|
|
@@ -705,7 +713,7 @@ const lintGutterMarkers = /*@__PURE__*/StateField.define({
|
|
|
705
713
|
if (effect.is(setDiagnosticsEffect)) {
|
|
706
714
|
let diagnostics = effect.value;
|
|
707
715
|
if (diagnosticFilter)
|
|
708
|
-
diagnostics = diagnosticFilter(diagnostics || []);
|
|
716
|
+
diagnostics = diagnosticFilter(diagnostics || [], tr.state);
|
|
709
717
|
markers = markersForDiagnostics(tr.state.doc, diagnostics.slice(0));
|
|
710
718
|
}
|
|
711
719
|
}
|