@codemirror/lint 0.20.1 → 0.20.2
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 +8 -0
- package/dist/index.cjs +37 -14
- package/dist/index.d.ts +33 -8
- package/dist/index.js +38 -15
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## 0.20.2 (2022-05-02)
|
|
2
|
+
|
|
3
|
+
### New features
|
|
4
|
+
|
|
5
|
+
The package now exports the `LintSource` function type.
|
|
6
|
+
|
|
7
|
+
The new `markerFilter` and `tooltipFilter` options to `linter` and `lintGutter` allow more control over which diagnostics are visible and which have tooltips.
|
|
8
|
+
|
|
1
9
|
## 0.20.1 (2022-04-22)
|
|
2
10
|
|
|
3
11
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -24,7 +24,12 @@ class LintState {
|
|
|
24
24
|
this.selected = selected;
|
|
25
25
|
}
|
|
26
26
|
static init(diagnostics, panel, state) {
|
|
27
|
-
|
|
27
|
+
// Filter the list of diagnostics for which to create markers
|
|
28
|
+
let markedDiagnostics = diagnostics;
|
|
29
|
+
let diagnosticFilter = state.facet(lintConfig).markerFilter;
|
|
30
|
+
if (diagnosticFilter)
|
|
31
|
+
markedDiagnostics = diagnosticFilter(markedDiagnostics);
|
|
32
|
+
let ranges = view.Decoration.set(markedDiagnostics.map((d) => {
|
|
28
33
|
// For zero-length ranges or ranges covering only a line break, create a widget
|
|
29
34
|
return d.from == d.to || (d.from == d.to - 1 && state.doc.lineAt(d.from).to == d.from)
|
|
30
35
|
? view.Decoration.widget({
|
|
@@ -130,6 +135,9 @@ function lintTooltip(view, pos, side) {
|
|
|
130
135
|
stackEnd = Math.max(to, stackEnd);
|
|
131
136
|
}
|
|
132
137
|
});
|
|
138
|
+
let diagnosticFilter = view.state.facet(lintConfig).tooltipFilter;
|
|
139
|
+
if (diagnosticFilter)
|
|
140
|
+
found = diagnosticFilter(found);
|
|
133
141
|
if (!found.length)
|
|
134
142
|
return null;
|
|
135
143
|
return {
|
|
@@ -197,7 +205,7 @@ const lintPlugin = view.ViewPlugin.fromClass(class {
|
|
|
197
205
|
this.view = view;
|
|
198
206
|
this.timeout = -1;
|
|
199
207
|
this.set = true;
|
|
200
|
-
let { delay } = view.state.facet(
|
|
208
|
+
let { delay } = view.state.facet(lintConfig);
|
|
201
209
|
this.lintTime = Date.now() + delay;
|
|
202
210
|
this.run = this.run.bind(this);
|
|
203
211
|
this.timeout = setTimeout(this.run, delay);
|
|
@@ -209,7 +217,7 @@ const lintPlugin = view.ViewPlugin.fromClass(class {
|
|
|
209
217
|
}
|
|
210
218
|
else {
|
|
211
219
|
this.set = false;
|
|
212
|
-
let { state } = this.view, { sources } = state.facet(
|
|
220
|
+
let { state } = this.view, { sources } = state.facet(lintConfig);
|
|
213
221
|
Promise.all(sources.map(source => Promise.resolve(source(this.view)))).then(annotations => {
|
|
214
222
|
let all = annotations.reduce((a, b) => a.concat(b));
|
|
215
223
|
if (this.view.state.doc == state.doc)
|
|
@@ -218,12 +226,12 @@ const lintPlugin = view.ViewPlugin.fromClass(class {
|
|
|
218
226
|
}
|
|
219
227
|
}
|
|
220
228
|
update(update) {
|
|
221
|
-
let
|
|
222
|
-
if (update.docChanged ||
|
|
223
|
-
this.lintTime = Date.now() +
|
|
229
|
+
let config = update.state.facet(lintConfig);
|
|
230
|
+
if (update.docChanged || config != update.startState.facet(lintConfig)) {
|
|
231
|
+
this.lintTime = Date.now() + config.delay;
|
|
224
232
|
if (!this.set) {
|
|
225
233
|
this.set = true;
|
|
226
|
-
this.timeout = setTimeout(this.run,
|
|
234
|
+
this.timeout = setTimeout(this.run, config.delay);
|
|
227
235
|
}
|
|
228
236
|
}
|
|
229
237
|
}
|
|
@@ -237,9 +245,13 @@ const lintPlugin = view.ViewPlugin.fromClass(class {
|
|
|
237
245
|
clearTimeout(this.timeout);
|
|
238
246
|
}
|
|
239
247
|
});
|
|
240
|
-
const
|
|
248
|
+
const lintConfig = state.Facet.define({
|
|
241
249
|
combine(input) {
|
|
242
|
-
return { sources: input.map(i => i.source),
|
|
250
|
+
return Object.assign({ sources: input.map(i => i.source) }, state.combineConfig(input.map(i => i.config), {
|
|
251
|
+
delay: 750,
|
|
252
|
+
markerFilter: null,
|
|
253
|
+
tooltipFilter: null
|
|
254
|
+
}));
|
|
243
255
|
},
|
|
244
256
|
enables: lintPlugin
|
|
245
257
|
});
|
|
@@ -249,8 +261,7 @@ enables linting with that source. It will be called whenever the
|
|
|
249
261
|
editor is idle (after its content changed).
|
|
250
262
|
*/
|
|
251
263
|
function linter(source, config = {}) {
|
|
252
|
-
|
|
253
|
-
return lintSource.of({ source, delay: (_a = config.delay) !== null && _a !== void 0 ? _a : 750 });
|
|
264
|
+
return lintConfig.of({ source, config });
|
|
254
265
|
}
|
|
255
266
|
/**
|
|
256
267
|
Forces any linters [configured](https://codemirror.net/6/docs/ref/#lint.linter) to run when the
|
|
@@ -588,7 +599,12 @@ class LintGutterMarker extends view.GutterMarker {
|
|
|
588
599
|
toDOM(view) {
|
|
589
600
|
let elt = document.createElement("div");
|
|
590
601
|
elt.className = "cm-lint-marker cm-lint-marker-" + this.severity;
|
|
591
|
-
|
|
602
|
+
let diagnostics = this.diagnostics;
|
|
603
|
+
let diagnosticsFilter = view.state.facet(lintGutterConfig).tooltipFilter;
|
|
604
|
+
if (diagnosticsFilter)
|
|
605
|
+
diagnostics = diagnosticsFilter(diagnostics);
|
|
606
|
+
if (diagnostics.length)
|
|
607
|
+
elt.onmouseover = () => gutterMarkerMouseOver(view, elt, diagnostics);
|
|
592
608
|
return elt;
|
|
593
609
|
}
|
|
594
610
|
}
|
|
@@ -660,10 +676,15 @@ const lintGutterMarkers = state.StateField.define({
|
|
|
660
676
|
},
|
|
661
677
|
update(markers, tr) {
|
|
662
678
|
markers = markers.map(tr.changes);
|
|
663
|
-
|
|
679
|
+
let diagnosticFilter = tr.state.facet(lintGutterConfig).markerFilter;
|
|
680
|
+
for (let effect of tr.effects) {
|
|
664
681
|
if (effect.is(setDiagnosticsEffect)) {
|
|
665
|
-
|
|
682
|
+
let diagnostics = effect.value;
|
|
683
|
+
if (diagnosticFilter)
|
|
684
|
+
diagnostics = diagnosticFilter(diagnostics || []);
|
|
685
|
+
markers = markersForDiagnostics(tr.state.doc, diagnostics.slice(0));
|
|
666
686
|
}
|
|
687
|
+
}
|
|
667
688
|
return markers;
|
|
668
689
|
}
|
|
669
690
|
});
|
|
@@ -702,6 +723,8 @@ const lintGutterConfig = state.Facet.define({
|
|
|
702
723
|
combine(configs) {
|
|
703
724
|
return state.combineConfig(configs, {
|
|
704
725
|
hoverTime: 300 /* Time */,
|
|
726
|
+
markerFilter: null,
|
|
727
|
+
tooltipFilter: null
|
|
705
728
|
});
|
|
706
729
|
}
|
|
707
730
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -51,11 +51,39 @@ interface Action {
|
|
|
51
51
|
*/
|
|
52
52
|
apply: (view: EditorView, from: number, to: number) => void;
|
|
53
53
|
}
|
|
54
|
+
declare type DiagnosticFilter = (diagnostics: readonly Diagnostic[]) => Diagnostic[];
|
|
55
|
+
interface LintConfig {
|
|
56
|
+
/**
|
|
57
|
+
Time to wait (in milliseconds) after a change before running
|
|
58
|
+
the linter. Defaults to 750ms.
|
|
59
|
+
*/
|
|
60
|
+
delay?: number;
|
|
61
|
+
/**
|
|
62
|
+
Optional filter to determine which diagnostics produce markers
|
|
63
|
+
in the content.
|
|
64
|
+
*/
|
|
65
|
+
markerFilter?: null | DiagnosticFilter;
|
|
66
|
+
/**
|
|
67
|
+
Filter applied to a set of diagnostics shown in a tooltip. No
|
|
68
|
+
tooltip will appear if the empty set is returned.
|
|
69
|
+
*/
|
|
70
|
+
tooltipFilter?: null | DiagnosticFilter;
|
|
71
|
+
}
|
|
54
72
|
interface LintGutterConfig {
|
|
55
73
|
/**
|
|
56
74
|
The delay before showing a tooltip when hovering over a lint gutter marker.
|
|
57
75
|
*/
|
|
58
76
|
hoverTime?: number;
|
|
77
|
+
/**
|
|
78
|
+
Optional filter determining which diagnostics show a marker in
|
|
79
|
+
the gutter.
|
|
80
|
+
*/
|
|
81
|
+
markerFilter?: null | DiagnosticFilter;
|
|
82
|
+
/**
|
|
83
|
+
Optional filter for diagnostics displayed in a tooltip, which
|
|
84
|
+
can also be used to prevent a tooltip appearing.
|
|
85
|
+
*/
|
|
86
|
+
tooltipFilter?: null | DiagnosticFilter;
|
|
59
87
|
}
|
|
60
88
|
/**
|
|
61
89
|
Returns a transaction spec which updates the current set of
|
|
@@ -91,19 +119,16 @@ A set of default key bindings for the lint functionality.
|
|
|
91
119
|
- F8: [`nextDiagnostic`](https://codemirror.net/6/docs/ref/#lint.nextDiagnostic)
|
|
92
120
|
*/
|
|
93
121
|
declare const lintKeymap: readonly KeyBinding[];
|
|
122
|
+
/**
|
|
123
|
+
The type of a function that produces diagnostics.
|
|
124
|
+
*/
|
|
94
125
|
declare type LintSource = (view: EditorView) => readonly Diagnostic[] | Promise<readonly Diagnostic[]>;
|
|
95
126
|
/**
|
|
96
127
|
Given a diagnostic source, this function returns an extension that
|
|
97
128
|
enables linting with that source. It will be called whenever the
|
|
98
129
|
editor is idle (after its content changed).
|
|
99
130
|
*/
|
|
100
|
-
declare function linter(source: LintSource, config?:
|
|
101
|
-
/**
|
|
102
|
-
Time to wait (in milliseconds) after a change before running
|
|
103
|
-
the linter. Defaults to 750ms.
|
|
104
|
-
*/
|
|
105
|
-
delay?: number;
|
|
106
|
-
}): Extension;
|
|
131
|
+
declare function linter(source: LintSource, config?: LintConfig): Extension;
|
|
107
132
|
/**
|
|
108
133
|
Forces any linters [configured](https://codemirror.net/6/docs/ref/#lint.linter) to run when the
|
|
109
134
|
editor is idle to run right away.
|
|
@@ -116,4 +141,4 @@ the diagnostics.
|
|
|
116
141
|
*/
|
|
117
142
|
declare function lintGutter(config?: LintGutterConfig): Extension;
|
|
118
143
|
|
|
119
|
-
export { Action, Diagnostic, closeLintPanel, diagnosticCount, forceLinting, lintGutter, lintKeymap, linter, nextDiagnostic, openLintPanel, setDiagnostics, setDiagnosticsEffect };
|
|
144
|
+
export { Action, Diagnostic, LintSource, closeLintPanel, diagnosticCount, forceLinting, lintGutter, lintKeymap, linter, nextDiagnostic, openLintPanel, setDiagnostics, setDiagnosticsEffect };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Decoration, showPanel, EditorView, ViewPlugin, hoverTooltip, logException, gutter, showTooltip, getPanel, WidgetType, GutterMarker } from '@codemirror/view';
|
|
2
|
-
import { StateEffect, StateField, Facet,
|
|
2
|
+
import { StateEffect, StateField, Facet, combineConfig, RangeSet } from '@codemirror/state';
|
|
3
3
|
import elt from 'crelt';
|
|
4
4
|
|
|
5
5
|
class SelectedDiagnostic {
|
|
@@ -16,7 +16,12 @@ class LintState {
|
|
|
16
16
|
this.selected = selected;
|
|
17
17
|
}
|
|
18
18
|
static init(diagnostics, panel, state) {
|
|
19
|
-
|
|
19
|
+
// Filter the list of diagnostics for which to create markers
|
|
20
|
+
let markedDiagnostics = diagnostics;
|
|
21
|
+
let diagnosticFilter = state.facet(lintConfig).markerFilter;
|
|
22
|
+
if (diagnosticFilter)
|
|
23
|
+
markedDiagnostics = diagnosticFilter(markedDiagnostics);
|
|
24
|
+
let ranges = Decoration.set(markedDiagnostics.map((d) => {
|
|
20
25
|
// For zero-length ranges or ranges covering only a line break, create a widget
|
|
21
26
|
return d.from == d.to || (d.from == d.to - 1 && state.doc.lineAt(d.from).to == d.from)
|
|
22
27
|
? Decoration.widget({
|
|
@@ -122,6 +127,9 @@ function lintTooltip(view, pos, side) {
|
|
|
122
127
|
stackEnd = Math.max(to, stackEnd);
|
|
123
128
|
}
|
|
124
129
|
});
|
|
130
|
+
let diagnosticFilter = view.state.facet(lintConfig).tooltipFilter;
|
|
131
|
+
if (diagnosticFilter)
|
|
132
|
+
found = diagnosticFilter(found);
|
|
125
133
|
if (!found.length)
|
|
126
134
|
return null;
|
|
127
135
|
return {
|
|
@@ -189,7 +197,7 @@ const lintPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
189
197
|
this.view = view;
|
|
190
198
|
this.timeout = -1;
|
|
191
199
|
this.set = true;
|
|
192
|
-
let { delay } = view.state.facet(
|
|
200
|
+
let { delay } = view.state.facet(lintConfig);
|
|
193
201
|
this.lintTime = Date.now() + delay;
|
|
194
202
|
this.run = this.run.bind(this);
|
|
195
203
|
this.timeout = setTimeout(this.run, delay);
|
|
@@ -201,7 +209,7 @@ const lintPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
201
209
|
}
|
|
202
210
|
else {
|
|
203
211
|
this.set = false;
|
|
204
|
-
let { state } = this.view, { sources } = state.facet(
|
|
212
|
+
let { state } = this.view, { sources } = state.facet(lintConfig);
|
|
205
213
|
Promise.all(sources.map(source => Promise.resolve(source(this.view)))).then(annotations => {
|
|
206
214
|
let all = annotations.reduce((a, b) => a.concat(b));
|
|
207
215
|
if (this.view.state.doc == state.doc)
|
|
@@ -210,12 +218,12 @@ const lintPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
210
218
|
}
|
|
211
219
|
}
|
|
212
220
|
update(update) {
|
|
213
|
-
let
|
|
214
|
-
if (update.docChanged ||
|
|
215
|
-
this.lintTime = Date.now() +
|
|
221
|
+
let config = update.state.facet(lintConfig);
|
|
222
|
+
if (update.docChanged || config != update.startState.facet(lintConfig)) {
|
|
223
|
+
this.lintTime = Date.now() + config.delay;
|
|
216
224
|
if (!this.set) {
|
|
217
225
|
this.set = true;
|
|
218
|
-
this.timeout = setTimeout(this.run,
|
|
226
|
+
this.timeout = setTimeout(this.run, config.delay);
|
|
219
227
|
}
|
|
220
228
|
}
|
|
221
229
|
}
|
|
@@ -229,9 +237,13 @@ const lintPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
229
237
|
clearTimeout(this.timeout);
|
|
230
238
|
}
|
|
231
239
|
});
|
|
232
|
-
const
|
|
240
|
+
const lintConfig = /*@__PURE__*/Facet.define({
|
|
233
241
|
combine(input) {
|
|
234
|
-
return { sources: input.map(i => i.source),
|
|
242
|
+
return Object.assign({ sources: input.map(i => i.source) }, combineConfig(input.map(i => i.config), {
|
|
243
|
+
delay: 750,
|
|
244
|
+
markerFilter: null,
|
|
245
|
+
tooltipFilter: null
|
|
246
|
+
}));
|
|
235
247
|
},
|
|
236
248
|
enables: lintPlugin
|
|
237
249
|
});
|
|
@@ -241,8 +253,7 @@ enables linting with that source. It will be called whenever the
|
|
|
241
253
|
editor is idle (after its content changed).
|
|
242
254
|
*/
|
|
243
255
|
function linter(source, config = {}) {
|
|
244
|
-
|
|
245
|
-
return lintSource.of({ source, delay: (_a = config.delay) !== null && _a !== void 0 ? _a : 750 });
|
|
256
|
+
return lintConfig.of({ source, config });
|
|
246
257
|
}
|
|
247
258
|
/**
|
|
248
259
|
Forces any linters [configured](https://codemirror.net/6/docs/ref/#lint.linter) to run when the
|
|
@@ -580,7 +591,12 @@ class LintGutterMarker extends GutterMarker {
|
|
|
580
591
|
toDOM(view) {
|
|
581
592
|
let elt = document.createElement("div");
|
|
582
593
|
elt.className = "cm-lint-marker cm-lint-marker-" + this.severity;
|
|
583
|
-
|
|
594
|
+
let diagnostics = this.diagnostics;
|
|
595
|
+
let diagnosticsFilter = view.state.facet(lintGutterConfig).tooltipFilter;
|
|
596
|
+
if (diagnosticsFilter)
|
|
597
|
+
diagnostics = diagnosticsFilter(diagnostics);
|
|
598
|
+
if (diagnostics.length)
|
|
599
|
+
elt.onmouseover = () => gutterMarkerMouseOver(view, elt, diagnostics);
|
|
584
600
|
return elt;
|
|
585
601
|
}
|
|
586
602
|
}
|
|
@@ -652,10 +668,15 @@ const lintGutterMarkers = /*@__PURE__*/StateField.define({
|
|
|
652
668
|
},
|
|
653
669
|
update(markers, tr) {
|
|
654
670
|
markers = markers.map(tr.changes);
|
|
655
|
-
|
|
671
|
+
let diagnosticFilter = tr.state.facet(lintGutterConfig).markerFilter;
|
|
672
|
+
for (let effect of tr.effects) {
|
|
656
673
|
if (effect.is(setDiagnosticsEffect)) {
|
|
657
|
-
|
|
674
|
+
let diagnostics = effect.value;
|
|
675
|
+
if (diagnosticFilter)
|
|
676
|
+
diagnostics = diagnosticFilter(diagnostics || []);
|
|
677
|
+
markers = markersForDiagnostics(tr.state.doc, diagnostics.slice(0));
|
|
658
678
|
}
|
|
679
|
+
}
|
|
659
680
|
return markers;
|
|
660
681
|
}
|
|
661
682
|
});
|
|
@@ -694,6 +715,8 @@ const lintGutterConfig = /*@__PURE__*/Facet.define({
|
|
|
694
715
|
combine(configs) {
|
|
695
716
|
return combineConfig(configs, {
|
|
696
717
|
hoverTime: 300 /* Time */,
|
|
718
|
+
markerFilter: null,
|
|
719
|
+
tooltipFilter: null
|
|
697
720
|
});
|
|
698
721
|
}
|
|
699
722
|
});
|