Skip to content

Commit 36fbd46

Browse files
authored
feat: support common languages in codemirror (#159)
This add syntax highlighting, not LSPs. Styling looks horrible but that's for another PR. ![image.png](https://app.graphite.com/user-attachments/assets/3cb1be6a-c45e-4db7-9ea6-fa40ab4da164.png)
1 parent c405c9c commit 36fbd46

File tree

5 files changed

+576
-2
lines changed

5 files changed

+576
-2
lines changed

apps/array/package.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,27 @@
6868
},
6969
"dependencies": {
7070
"@ai-sdk/openai": "^2.0.52",
71+
"@codemirror/lang-angular": "^0.1.4",
72+
"@codemirror/lang-cpp": "^6.0.3",
73+
"@codemirror/lang-css": "^6.3.1",
74+
"@codemirror/lang-go": "^6.0.1",
75+
"@codemirror/lang-html": "^6.4.11",
76+
"@codemirror/lang-java": "^6.0.2",
77+
"@codemirror/lang-javascript": "^6.2.4",
78+
"@codemirror/lang-jinja": "^6.0.0",
79+
"@codemirror/lang-json": "^6.0.2",
80+
"@codemirror/lang-liquid": "^6.3.0",
81+
"@codemirror/lang-markdown": "^6.5.0",
82+
"@codemirror/lang-php": "^6.0.2",
83+
"@codemirror/lang-python": "^6.2.1",
84+
"@codemirror/lang-rust": "^6.0.2",
85+
"@codemirror/lang-sass": "^6.0.2",
86+
"@codemirror/lang-sql": "^6.10.0",
87+
"@codemirror/lang-vue": "^0.1.3",
88+
"@codemirror/lang-wast": "^6.0.2",
89+
"@codemirror/lang-xml": "^6.1.0",
90+
"@codemirror/lang-yaml": "^6.1.2",
91+
"@codemirror/language": "^6.11.3",
7192
"@codemirror/state": "^6.5.2",
7293
"@codemirror/view": "^6.38.8",
7394
"@dnd-kit/react": "^0.1.21",

apps/array/src/renderer/features/code-editor/components/CodeEditorPanel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export function CodeEditorPanel({
7373

7474
return (
7575
<Box height="100%" style={{ overflow: "hidden" }}>
76-
<CodeMirrorEditor content={fileContent} readOnly />
76+
<CodeMirrorEditor content={fileContent} filePath={filePath} readOnly />
7777
</Box>
7878
);
7979
}

apps/array/src/renderer/features/code-editor/components/CodeMirrorEditor.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import {
2+
defaultHighlightStyle,
3+
syntaxHighlighting,
4+
} from "@codemirror/language";
15
import type { Extension } from "@codemirror/state";
26
import { EditorState } from "@codemirror/state";
37
import {
@@ -6,14 +10,17 @@ import {
610
lineNumbers,
711
} from "@codemirror/view";
812
import { useEffect, useRef } from "react";
13+
import { getLanguageExtension } from "../utils/languages";
914

1015
interface CodeMirrorEditorProps {
1116
content: string;
17+
filePath?: string;
1218
readOnly?: boolean;
1319
}
1420

1521
export function CodeMirrorEditor({
1622
content,
23+
filePath,
1724
readOnly = false,
1825
}: CodeMirrorEditorProps) {
1926
const editorRef = useRef<HTMLDivElement>(null);
@@ -24,10 +31,14 @@ export function CodeMirrorEditor({
2431
return;
2532
}
2633

34+
const languageExtension = filePath ? getLanguageExtension(filePath) : null;
35+
2736
const extensions: Extension[] = [
2837
lineNumbers(),
2938
highlightActiveLineGutter(),
39+
syntaxHighlighting(defaultHighlightStyle),
3040
EditorView.editable.of(!readOnly),
41+
...(languageExtension ? [languageExtension] : []),
3142
EditorView.theme({
3243
"&": {
3344
height: "100%",
@@ -69,7 +80,7 @@ export function CodeMirrorEditor({
6980
viewRef.current?.destroy();
7081
viewRef.current = null;
7182
};
72-
}, [content, readOnly]);
83+
}, [content, filePath, readOnly]);
7384

7485
return <div ref={editorRef} style={{ height: "100%", width: "100%" }} />;
7586
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { angular } from "@codemirror/lang-angular";
2+
import { cpp } from "@codemirror/lang-cpp";
3+
import { css } from "@codemirror/lang-css";
4+
import { go } from "@codemirror/lang-go";
5+
import { html } from "@codemirror/lang-html";
6+
import { java } from "@codemirror/lang-java";
7+
import { javascript } from "@codemirror/lang-javascript";
8+
import { jinja } from "@codemirror/lang-jinja";
9+
import { json } from "@codemirror/lang-json";
10+
import { liquid } from "@codemirror/lang-liquid";
11+
import { markdown } from "@codemirror/lang-markdown";
12+
import { php } from "@codemirror/lang-php";
13+
import { python } from "@codemirror/lang-python";
14+
import { rust } from "@codemirror/lang-rust";
15+
import { sass } from "@codemirror/lang-sass";
16+
import { sql } from "@codemirror/lang-sql";
17+
import { vue } from "@codemirror/lang-vue";
18+
import { wast } from "@codemirror/lang-wast";
19+
import { xml } from "@codemirror/lang-xml";
20+
import { yaml } from "@codemirror/lang-yaml";
21+
import type { Extension } from "@codemirror/state";
22+
23+
type LanguageExtension = () => Extension;
24+
25+
const LANGUAGE_MAP: Record<string, LanguageExtension> = {
26+
// JavaScript/TypeScript
27+
js: () => javascript({ jsx: true }),
28+
jsx: () => javascript({ jsx: true }),
29+
mjs: () => javascript(),
30+
ts: () => javascript({ jsx: true, typescript: true }),
31+
tsx: () => javascript({ jsx: true, typescript: true }),
32+
33+
// Web
34+
html: html,
35+
htm: html,
36+
css: css,
37+
scss: () => sass({ indented: false }),
38+
sass: () => sass({ indented: true }),
39+
vue: vue,
40+
component: angular,
41+
42+
// Data formats
43+
json: json,
44+
xml: xml,
45+
svg: xml,
46+
yaml: yaml,
47+
yml: yaml,
48+
49+
// Programming languages
50+
py: python,
51+
rs: rust,
52+
go: go,
53+
java: java,
54+
cpp: cpp,
55+
c: cpp,
56+
h: cpp,
57+
hpp: cpp,
58+
php: php,
59+
sql: sql,
60+
wast: wast,
61+
wat: wast,
62+
63+
// Templates
64+
jinja: jinja,
65+
jinja2: jinja,
66+
j2: jinja,
67+
liquid: liquid,
68+
69+
// Docs
70+
md: markdown,
71+
markdown: markdown,
72+
};
73+
74+
export function getLanguageExtension(filePath: string): Extension | null {
75+
const ext = filePath.split(".").pop()?.toLowerCase();
76+
if (!ext) return null;
77+
78+
const factory = LANGUAGE_MAP[ext];
79+
return factory ? factory() : null;
80+
}

0 commit comments

Comments
 (0)