Example: Linter
The @codemirror/lint package provides a way to display errors and warnings in your editor. If you give it a source function that, when given an editor, produces an array of problems, it will call this function when changes are made to the document, and display its result.
The library does not come with a collection of lint sources. Some language packages (such as @codemirror/lang-javascript) may include integration with lint libraries, but usually setting up a source is something you have to do yourself.
There's two ways to do this:
-
Find a linter that you can run in the browser, run it on the content, and translate its output into the expected format.
-
Write one from scratch, possibly using the syntax tree kept by the editor.
In this example, we'll do the latter.
Assume for a second that the boss has decided that regular expressions are the work of the devil (to be fair, he's not entirely wrong), and should be forbidden in the entire codebase. We want a linter that highlights any use of a regular expression in JavaScript code.
Conveniently, the JavaScript parser emits a specific node type for regular expression literals, so all we have to do is iterate over the parse tree and emit a warning for every node like that we find.
import {syntaxTree} from "@codemirror/language"
import {linter, Diagnostic} from "@codemirror/lint"
const regexpLinter = linter(view => {
let diagnostics: Diagnostic[] = []
syntaxTree(view.state).cursor().iterate(node => {
if (node.name == "RegExp") diagnostics.push({
from: node.from,
to: node.to,
severity: "warning",
message: "Regular expressions are FORBIDDEN",
actions: [{
name: "Remove",
apply(view, from, to) { view.dispatch({changes: {from, to}}) }
}]
})
})
return diagnostics
})
Diagnostics (the objects returned
by a lint source) must have from and to properties indicating the
range they apply to, a
severity field, and a
message.
This one also uses the optional
actions field to add an
“action” for the diagnostic. This adds a button to the diagnostic that
can be clicked to perform some effect, like automatically fixing the
problem (which this does in a very crude way) or providing further
context.
The result of a call to linter is
an extension that you can include in a (JavaScript) editor to get a
result like this (sandbox link):
The gutter only appears if you also include
lintGutter. You can press
Ctrl-Shift-m (Cmd-Shift-m on macOS) to show a list of diagnostics in a
panel below the editor.