@codemirror/lint 6.8.5 → 6.9.1
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 +16 -0
- package/dist/index.cjs +52 -14
- package/dist/index.d.cts +9 -2
- package/dist/index.d.ts +9 -2
- package/dist/index.js +52 -14
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
## 6.9.1 (2025-10-23)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Properly display diagnostics that just cover multiple newlines as widgets.
|
|
6
|
+
|
|
7
|
+
## 6.9.0 (2025-10-02)
|
|
8
|
+
|
|
9
|
+
### Bug fixes
|
|
10
|
+
|
|
11
|
+
Multiple configurations to `linter` will now be merged without raising an error.
|
|
12
|
+
|
|
13
|
+
### New features
|
|
14
|
+
|
|
15
|
+
The new `markClass` option to actions makes it possible to style action buttons.
|
|
16
|
+
|
|
1
17
|
## 6.8.5 (2025-03-26)
|
|
2
18
|
|
|
3
19
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -24,6 +24,7 @@ class LintState {
|
|
|
24
24
|
diagnostics = diagnosticFilter(diagnostics, state$1);
|
|
25
25
|
let sorted = diagnostics.slice().sort((a, b) => a.from - b.from || a.to - b.to);
|
|
26
26
|
let deco = new state.RangeSetBuilder(), active = [], pos = 0;
|
|
27
|
+
let scan = state$1.doc.iter(), scanPos = 0;
|
|
27
28
|
for (let i = 0;;) {
|
|
28
29
|
let next = i == sorted.length ? null : sorted[i];
|
|
29
30
|
if (!next && !active.length)
|
|
@@ -51,8 +52,30 @@ class LintState {
|
|
|
51
52
|
break;
|
|
52
53
|
}
|
|
53
54
|
}
|
|
55
|
+
let widget = false;
|
|
56
|
+
if (active.some(d => d.from == from && d.to == to)) {
|
|
57
|
+
widget = from == to;
|
|
58
|
+
if (!widget && to - from < 10) {
|
|
59
|
+
let behind = from - (scanPos + scan.value.length);
|
|
60
|
+
if (behind > 0) {
|
|
61
|
+
scan.next(behind);
|
|
62
|
+
scanPos = from;
|
|
63
|
+
}
|
|
64
|
+
for (let check = from;;) {
|
|
65
|
+
if (check >= to) {
|
|
66
|
+
widget = true;
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
if (!scan.lineBreak && scanPos + scan.value.length > check)
|
|
70
|
+
break;
|
|
71
|
+
check = scanPos + scan.value.length;
|
|
72
|
+
scanPos += scan.value.length;
|
|
73
|
+
scan.next();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
54
77
|
let sev = maxSeverity(active);
|
|
55
|
-
if (
|
|
78
|
+
if (widget) {
|
|
56
79
|
deco.add(from, from, view.Decoration.widget({
|
|
57
80
|
widget: new DiagnosticWidget(sev),
|
|
58
81
|
diagnostics: active.slice()
|
|
@@ -319,22 +342,36 @@ function batchResults(promises, sink, error) {
|
|
|
319
342
|
}
|
|
320
343
|
const lintConfig = state.Facet.define({
|
|
321
344
|
combine(input) {
|
|
322
|
-
return
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
345
|
+
return {
|
|
346
|
+
sources: input.map(i => i.source).filter(x => x != null),
|
|
347
|
+
...state.combineConfig(input.map(i => i.config), {
|
|
348
|
+
delay: 750,
|
|
349
|
+
markerFilter: null,
|
|
350
|
+
tooltipFilter: null,
|
|
351
|
+
needsRefresh: null,
|
|
352
|
+
hideOn: () => null,
|
|
353
|
+
}, {
|
|
354
|
+
delay: Math.max,
|
|
355
|
+
markerFilter: combineFilter,
|
|
356
|
+
tooltipFilter: combineFilter,
|
|
357
|
+
needsRefresh: (a, b) => !a ? b : !b ? a : u => a(u) || b(u),
|
|
358
|
+
hideOn: (a, b) => !a ? b : !b ? a : (t, x, y) => a(t, x, y) || b(t, x, y),
|
|
359
|
+
autoPanel: (a, b) => a || b
|
|
360
|
+
})
|
|
361
|
+
};
|
|
331
362
|
}
|
|
332
363
|
});
|
|
364
|
+
function combineFilter(a, b) {
|
|
365
|
+
return !a ? b : !b ? a : (d, s) => b(a(d, s), s);
|
|
366
|
+
}
|
|
333
367
|
/**
|
|
334
368
|
Given a diagnostic source, this function returns an extension that
|
|
335
369
|
enables linting with that source. It will be called whenever the
|
|
336
|
-
editor is idle (after its content changed).
|
|
337
|
-
|
|
370
|
+
editor is idle (after its content changed).
|
|
371
|
+
|
|
372
|
+
Note that settings given here will apply to all linters active in
|
|
373
|
+
the editor. If `null` is given as source, this only configures the
|
|
374
|
+
lint extension.
|
|
338
375
|
*/
|
|
339
376
|
function linter(source, config = {}) {
|
|
340
377
|
return [
|
|
@@ -384,9 +421,10 @@ function renderDiagnostic(view, diagnostic, inPanel) {
|
|
|
384
421
|
let nameElt = keyIndex < 0 ? name : [name.slice(0, keyIndex),
|
|
385
422
|
elt("u", name.slice(keyIndex, keyIndex + 1)),
|
|
386
423
|
name.slice(keyIndex + 1)];
|
|
424
|
+
let markClass = action.markClass ? " " + action.markClass : "";
|
|
387
425
|
return elt("button", {
|
|
388
426
|
type: "button",
|
|
389
|
-
class: "cm-diagnosticAction",
|
|
427
|
+
class: "cm-diagnosticAction" + markClass,
|
|
390
428
|
onclick: click,
|
|
391
429
|
onmousedown: click,
|
|
392
430
|
"aria-label": ` Action: ${name}${keyIndex < 0 ? "" : ` (access key "${keys[i]})"`}.`
|
|
@@ -809,7 +847,7 @@ const lintGutterTooltip = state.StateField.define({
|
|
|
809
847
|
create() { return null; },
|
|
810
848
|
update(tooltip, tr) {
|
|
811
849
|
if (tooltip && tr.docChanged)
|
|
812
|
-
tooltip = hideTooltip(tr, tooltip) ? null :
|
|
850
|
+
tooltip = hideTooltip(tr, tooltip) ? null : { ...tooltip, pos: tr.changes.mapPos(tooltip.pos) };
|
|
813
851
|
return tr.effects.reduce((t, e) => e.is(setLintGutterTooltip) ? e.value : t, tooltip);
|
|
814
852
|
},
|
|
815
853
|
provide: field => view.showTooltip.from(field)
|
package/dist/index.d.cts
CHANGED
|
@@ -56,6 +56,10 @@ interface Action {
|
|
|
56
56
|
*/
|
|
57
57
|
name: string;
|
|
58
58
|
/**
|
|
59
|
+
When given, add an extra CSS class to the action button.
|
|
60
|
+
*/
|
|
61
|
+
markClass?: string;
|
|
62
|
+
/**
|
|
59
63
|
The function to call when the user activates this action. Is
|
|
60
64
|
given the diagnostic's _current_ position, which may have
|
|
61
65
|
changed since the creation of the diagnostic, due to editing.
|
|
@@ -161,8 +165,11 @@ type LintSource = (view: EditorView) => readonly Diagnostic[] | Promise<readonly
|
|
|
161
165
|
/**
|
|
162
166
|
Given a diagnostic source, this function returns an extension that
|
|
163
167
|
enables linting with that source. It will be called whenever the
|
|
164
|
-
editor is idle (after its content changed).
|
|
165
|
-
|
|
168
|
+
editor is idle (after its content changed).
|
|
169
|
+
|
|
170
|
+
Note that settings given here will apply to all linters active in
|
|
171
|
+
the editor. If `null` is given as source, this only configures the
|
|
172
|
+
lint extension.
|
|
166
173
|
*/
|
|
167
174
|
declare function linter(source: LintSource | null, config?: LintConfig): Extension;
|
|
168
175
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -56,6 +56,10 @@ interface Action {
|
|
|
56
56
|
*/
|
|
57
57
|
name: string;
|
|
58
58
|
/**
|
|
59
|
+
When given, add an extra CSS class to the action button.
|
|
60
|
+
*/
|
|
61
|
+
markClass?: string;
|
|
62
|
+
/**
|
|
59
63
|
The function to call when the user activates this action. Is
|
|
60
64
|
given the diagnostic's _current_ position, which may have
|
|
61
65
|
changed since the creation of the diagnostic, due to editing.
|
|
@@ -161,8 +165,11 @@ type LintSource = (view: EditorView) => readonly Diagnostic[] | Promise<readonly
|
|
|
161
165
|
/**
|
|
162
166
|
Given a diagnostic source, this function returns an extension that
|
|
163
167
|
enables linting with that source. It will be called whenever the
|
|
164
|
-
editor is idle (after its content changed).
|
|
165
|
-
|
|
168
|
+
editor is idle (after its content changed).
|
|
169
|
+
|
|
170
|
+
Note that settings given here will apply to all linters active in
|
|
171
|
+
the editor. If `null` is given as source, this only configures the
|
|
172
|
+
lint extension.
|
|
166
173
|
*/
|
|
167
174
|
declare function linter(source: LintSource | null, config?: LintConfig): Extension;
|
|
168
175
|
/**
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,7 @@ class LintState {
|
|
|
22
22
|
diagnostics = diagnosticFilter(diagnostics, state);
|
|
23
23
|
let sorted = diagnostics.slice().sort((a, b) => a.from - b.from || a.to - b.to);
|
|
24
24
|
let deco = new RangeSetBuilder(), active = [], pos = 0;
|
|
25
|
+
let scan = state.doc.iter(), scanPos = 0;
|
|
25
26
|
for (let i = 0;;) {
|
|
26
27
|
let next = i == sorted.length ? null : sorted[i];
|
|
27
28
|
if (!next && !active.length)
|
|
@@ -49,8 +50,30 @@ class LintState {
|
|
|
49
50
|
break;
|
|
50
51
|
}
|
|
51
52
|
}
|
|
53
|
+
let widget = false;
|
|
54
|
+
if (active.some(d => d.from == from && d.to == to)) {
|
|
55
|
+
widget = from == to;
|
|
56
|
+
if (!widget && to - from < 10) {
|
|
57
|
+
let behind = from - (scanPos + scan.value.length);
|
|
58
|
+
if (behind > 0) {
|
|
59
|
+
scan.next(behind);
|
|
60
|
+
scanPos = from;
|
|
61
|
+
}
|
|
62
|
+
for (let check = from;;) {
|
|
63
|
+
if (check >= to) {
|
|
64
|
+
widget = true;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
if (!scan.lineBreak && scanPos + scan.value.length > check)
|
|
68
|
+
break;
|
|
69
|
+
check = scanPos + scan.value.length;
|
|
70
|
+
scanPos += scan.value.length;
|
|
71
|
+
scan.next();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
52
75
|
let sev = maxSeverity(active);
|
|
53
|
-
if (
|
|
76
|
+
if (widget) {
|
|
54
77
|
deco.add(from, from, Decoration.widget({
|
|
55
78
|
widget: new DiagnosticWidget(sev),
|
|
56
79
|
diagnostics: active.slice()
|
|
@@ -317,22 +340,36 @@ function batchResults(promises, sink, error) {
|
|
|
317
340
|
}
|
|
318
341
|
const lintConfig = /*@__PURE__*/Facet.define({
|
|
319
342
|
combine(input) {
|
|
320
|
-
return
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
343
|
+
return {
|
|
344
|
+
sources: input.map(i => i.source).filter(x => x != null),
|
|
345
|
+
...combineConfig(input.map(i => i.config), {
|
|
346
|
+
delay: 750,
|
|
347
|
+
markerFilter: null,
|
|
348
|
+
tooltipFilter: null,
|
|
349
|
+
needsRefresh: null,
|
|
350
|
+
hideOn: () => null,
|
|
351
|
+
}, {
|
|
352
|
+
delay: Math.max,
|
|
353
|
+
markerFilter: combineFilter,
|
|
354
|
+
tooltipFilter: combineFilter,
|
|
355
|
+
needsRefresh: (a, b) => !a ? b : !b ? a : u => a(u) || b(u),
|
|
356
|
+
hideOn: (a, b) => !a ? b : !b ? a : (t, x, y) => a(t, x, y) || b(t, x, y),
|
|
357
|
+
autoPanel: (a, b) => a || b
|
|
358
|
+
})
|
|
359
|
+
};
|
|
329
360
|
}
|
|
330
361
|
});
|
|
362
|
+
function combineFilter(a, b) {
|
|
363
|
+
return !a ? b : !b ? a : (d, s) => b(a(d, s), s);
|
|
364
|
+
}
|
|
331
365
|
/**
|
|
332
366
|
Given a diagnostic source, this function returns an extension that
|
|
333
367
|
enables linting with that source. It will be called whenever the
|
|
334
|
-
editor is idle (after its content changed).
|
|
335
|
-
|
|
368
|
+
editor is idle (after its content changed).
|
|
369
|
+
|
|
370
|
+
Note that settings given here will apply to all linters active in
|
|
371
|
+
the editor. If `null` is given as source, this only configures the
|
|
372
|
+
lint extension.
|
|
336
373
|
*/
|
|
337
374
|
function linter(source, config = {}) {
|
|
338
375
|
return [
|
|
@@ -382,9 +419,10 @@ function renderDiagnostic(view, diagnostic, inPanel) {
|
|
|
382
419
|
let nameElt = keyIndex < 0 ? name : [name.slice(0, keyIndex),
|
|
383
420
|
elt("u", name.slice(keyIndex, keyIndex + 1)),
|
|
384
421
|
name.slice(keyIndex + 1)];
|
|
422
|
+
let markClass = action.markClass ? " " + action.markClass : "";
|
|
385
423
|
return elt("button", {
|
|
386
424
|
type: "button",
|
|
387
|
-
class: "cm-diagnosticAction",
|
|
425
|
+
class: "cm-diagnosticAction" + markClass,
|
|
388
426
|
onclick: click,
|
|
389
427
|
onmousedown: click,
|
|
390
428
|
"aria-label": ` Action: ${name}${keyIndex < 0 ? "" : ` (access key "${keys[i]})"`}.`
|
|
@@ -807,7 +845,7 @@ const lintGutterTooltip = /*@__PURE__*/StateField.define({
|
|
|
807
845
|
create() { return null; },
|
|
808
846
|
update(tooltip, tr) {
|
|
809
847
|
if (tooltip && tr.docChanged)
|
|
810
|
-
tooltip = hideTooltip(tr, tooltip) ? null :
|
|
848
|
+
tooltip = hideTooltip(tr, tooltip) ? null : { ...tooltip, pos: tr.changes.mapPos(tooltip.pos) };
|
|
811
849
|
return tr.effects.reduce((t, e) => e.is(setLintGutterTooltip) ? e.value : t, tooltip);
|
|
812
850
|
},
|
|
813
851
|
provide: field => showTooltip.from(field)
|