Skip to content

Commit 09ecc22

Browse files
committed
Expose a basic linter configs in the code editor component
1 parent 759ad2b commit 09ecc22

File tree

2 files changed

+36
-20
lines changed

2 files changed

+36
-20
lines changed

apps/webapp/app/components/code/JSONEditor.tsx

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { json as jsonLang } from "@codemirror/lang-json";
2-
import type { ViewUpdate } from "@codemirror/view";
1+
import { json as jsonLang, jsonParseLinter } from "@codemirror/lang-json";
2+
import type { EditorView, ViewUpdate } from "@codemirror/view";
33
import { CheckIcon, ClipboardIcon, TrashIcon } from "@heroicons/react/20/solid";
44
import type { ReactCodeMirrorProps, UseCodeMirror } from "@uiw/react-codemirror";
55
import { useCodeMirror } from "@uiw/react-codemirror";
@@ -8,6 +8,7 @@ import { cn } from "~/utils/cn";
88
import { Button } from "../primitives/Buttons";
99
import { getEditorSetup } from "./codeMirrorSetup";
1010
import { darkTheme } from "./codeMirrorTheme";
11+
import { linter, lintGutter, type Diagnostic } from "@codemirror/lint";
1112

1213
export interface JSONEditorProps extends Omit<ReactCodeMirrorProps, "onBlur"> {
1314
defaultValue?: string;
@@ -18,18 +19,35 @@ export interface JSONEditorProps extends Omit<ReactCodeMirrorProps, "onBlur"> {
1819
onBlur?: (code: string) => void;
1920
showCopyButton?: boolean;
2021
showClearButton?: boolean;
22+
linterEnabled?: boolean;
23+
allowEmpty?: boolean;
2124
}
2225

2326
const languages = {
2427
json: jsonLang,
2528
};
2629

30+
function emptyAwareJsonLinter() {
31+
return (view: EditorView): Diagnostic[] => {
32+
const content = view.state.doc.toString().trim();
33+
34+
// return no errors if content is empty
35+
if (!content) {
36+
return [];
37+
}
38+
39+
return jsonParseLinter()(view);
40+
};
41+
}
42+
2743
type JSONEditorDefaultProps = Partial<JSONEditorProps>;
2844

2945
const defaultProps: JSONEditorDefaultProps = {
3046
language: "json",
3147
readOnly: true,
3248
basicSetup: false,
49+
linterEnabled: true,
50+
allowEmpty: true,
3351
};
3452

3553
export function JSONEditor(opts: JSONEditorProps) {
@@ -44,6 +62,8 @@ export function JSONEditor(opts: JSONEditorProps) {
4462
autoFocus,
4563
showCopyButton = true,
4664
showClearButton = true,
65+
linterEnabled,
66+
allowEmpty,
4767
} = {
4868
...defaultProps,
4969
...opts,
@@ -56,6 +76,19 @@ export function JSONEditor(opts: JSONEditorProps) {
5676

5777
extensions.push(languageExtension());
5878

79+
if (linterEnabled) {
80+
extensions.push(lintGutter());
81+
82+
switch (language) {
83+
case "json": {
84+
extensions.push(allowEmpty ? linter(emptyAwareJsonLinter()) : linter(jsonParseLinter()));
85+
break;
86+
}
87+
default:
88+
language satisfies never;
89+
}
90+
}
91+
5992
const editor = useRef<HTMLDivElement>(null);
6093
const settings: Omit<UseCodeMirror, "onBlur"> = {
6194
...opts,

apps/webapp/app/components/code/codeMirrorSetup.ts

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,25 @@
11
import { closeBrackets } from "@codemirror/autocomplete";
22
import { indentWithTab } from "@codemirror/commands";
3-
import { jsonParseLinter } from "@codemirror/lang-json";
43
import { bracketMatching } from "@codemirror/language";
5-
import { type Diagnostic, linter, lintGutter, lintKeymap } from "@codemirror/lint";
4+
import { lintKeymap } from "@codemirror/lint";
65
import { highlightSelectionMatches } from "@codemirror/search";
76
import { Prec, type Extension } from "@codemirror/state";
87
import {
98
drawSelection,
109
dropCursor,
11-
type EditorView,
1210
highlightActiveLine,
1311
highlightActiveLineGutter,
1412
highlightSpecialChars,
1513
keymap,
1614
lineNumbers,
1715
} from "@codemirror/view";
1816

19-
function emptyAwareJsonLinter() {
20-
return (view: EditorView): Diagnostic[] => {
21-
const content = view.state.doc.toString().trim();
22-
23-
// return no errors if content is empty
24-
if (!content) {
25-
return [];
26-
}
27-
28-
return jsonParseLinter()(view);
29-
};
30-
}
31-
3217
export function getEditorSetup(showLineNumbers = true, showHighlights = true): Array<Extension> {
3318
const options = [
3419
drawSelection(),
3520
dropCursor(),
3621
bracketMatching(),
3722
closeBrackets(),
38-
lintGutter(),
39-
linter(emptyAwareJsonLinter()),
4023
Prec.highest(
4124
keymap.of([
4225
{

0 commit comments

Comments
 (0)