Skip to content

Commit 6335d16

Browse files
committed
Move to CodeMirror editor
1 parent 30653db commit 6335d16

File tree

6 files changed

+578
-66
lines changed

6 files changed

+578
-66
lines changed

blocks/pomsky-viewer/Editor.tsx

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { Box } from "@primer/react";
2+
import "./index.css";
3+
4+
import { indentWithTab } from "@codemirror/commands";
5+
import { javascript } from "@codemirror/lang-javascript";
6+
import { EditorState } from "@codemirror/state";
7+
import { EditorView, keymap } from "@codemirror/view";
8+
import { basicSetup } from "codemirror";
9+
10+
let savedState: EditorState;
11+
12+
export default (function (props: {
13+
text: string;
14+
onChange: (text: string) => void;
15+
}) {
16+
let editor: EditorView;
17+
18+
return (
19+
<Box
20+
className="content"
21+
ref={(element) => {
22+
editor?.destroy();
23+
editor ??= new EditorView({
24+
doc: props.text,
25+
state: savedState,
26+
extensions: [
27+
basicSetup,
28+
keymap.of([
29+
// @ts-ignore
30+
indentWithTab,
31+
]),
32+
javascript({ typescript: true }),
33+
EditorView.updateListener.of((update) => {
34+
if (update.changes.empty) return;
35+
savedState = update.state;
36+
props.onChange(update.state.doc.toString());
37+
}),
38+
],
39+
parent: element!,
40+
});
41+
}}
42+
></Box>
43+
);
44+
});

blocks/pomsky-viewer/Show.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default function Show(props: {
2+
when: boolean | any;
3+
children?: null | string | JSX.Element | JSX.Element[];
4+
}) {
5+
return <>{props.when ? props.children : null}</>;
6+
}

blocks/pomsky-viewer/index.css

+13-9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
*:before,
33
*:after {
44
box-sizing: border-box;
5+
overflow: hidden;
56
}
67

78
html,
@@ -10,24 +11,27 @@ body,
1011
height: 100%;
1112
}
1213

13-
.content {
14-
height: 100%;
14+
.pomsky-viewer {
15+
display: grid;
16+
grid-template-rows: 48px calc(100% - 48px);
1517
width: 100%;
16-
padding: 2px;
18+
height: 100%;
1719
}
1820

19-
textarea {
20-
resize: none;
21-
border: none;
22-
outline: none;
21+
.header {
22+
display: flex;
23+
flex-direction: row;
24+
height: 48px;
2325
}
2426

25-
button {
26-
height: 32px;
27+
.content {
28+
overflow: auto;
29+
scrollbar-width: 0;
2730
}
2831

2932
pre {
3033
margin: 0;
34+
padding: 2px;
3135
word-break: break-all;
3236
white-space: pre-wrap;
3337
}

blocks/pomsky-viewer/index.tsx

+54-57
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,26 @@ import {
55
Box,
66
Button,
77
ButtonGroup,
8+
Flash,
89
} from "@primer/react";
910
import "./index.css";
1011

1112
import initPomsky, { PomskyResult, compile } from "pomsky-wasm";
1213
import { memo, useEffect, useState } from "react";
1314
import pomskyWASM from "./pomsky-wasm.json";
1415

16+
import Editor from "./Editor";
17+
import Show from "./Show";
18+
19+
function findRowColContext(str: string, start: number) {
20+
const previousLines = str.slice(0, start).split("\n");
21+
const row = previousLines.length;
22+
const column = (previousLines[previousLines.length - 1] ?? "").length + 1;
23+
const context = str.split("\n")[previousLines.length];
24+
25+
return { row, column, context };
26+
}
27+
1528
export default memo(function (props: FileBlockProps) {
1629
const {
1730
context,
@@ -20,6 +33,8 @@ export default memo(function (props: FileBlockProps) {
2033
onUpdateMetadata,
2134
onUpdateContent,
2235
BlockComponent,
36+
isEditable,
37+
originalContent,
2338
} = props;
2439
const language = Boolean(context.path)
2540
? getLanguageFromFilename(context.path)
@@ -49,21 +64,21 @@ export default memo(function (props: FileBlockProps) {
4964
>("JavaScript");
5065

5166
const [pomskyResult, setPomskyResult] = useState<PomskyResult | null>();
52-
67+
const [didError, setDidError] = useState(false);
5368
useEffect(() => {
54-
if (didInit) setPomskyResult(compile(content, flavor.toLowerCase()));
69+
if (didInit) {
70+
const result = compile(content, flavor.toLowerCase());
71+
console.debug(result);
72+
setPomskyResult(result);
73+
setDidError(result?.output == null);
74+
}
5575
}, [didInit, content, flavor]);
5676

5777
return (
58-
<Box
59-
position="relative"
60-
display="flex"
61-
flexDirection="column"
62-
width="100%"
63-
height="100%"
64-
>
78+
<Box className="pomsky-viewer">
6579
<Show when={isPomsky}>
6680
<Box
81+
className="header"
6782
borderColor="border.default"
6883
borderWidth={1}
6984
borderStyle="solid"
@@ -73,10 +88,8 @@ export default memo(function (props: FileBlockProps) {
7388
borderRight="hidden"
7489
p={2}
7590
bg="canvas.subtle"
76-
display="flex"
77-
minHeight={48}
7891
>
79-
<ButtonGroup sx={{ display: "flex", alignItems: "center" }}>
92+
<ButtonGroup>
8093
<Button
8194
onClick={() => setTab("pomsky")}
8295
disabled={tab === "pomsky"}
@@ -147,72 +160,56 @@ export default memo(function (props: FileBlockProps) {
147160
</ActionList>
148161
</ActionMenu.Overlay>
149162
</ActionMenu>
163+
<Show when={didError}>Error!</Show>
150164
</Box>
151165
<Show when={tab === "pomsky"}>
152-
<textarea
153-
className="content"
154-
spellCheck="false"
155-
value={content}
156-
onChange={(event) => {
157-
onUpdateContent(event.target.value);
166+
<Editor
167+
text={originalContent}
168+
onChange={(text) => {
169+
onUpdateContent(text);
158170
}}
159171
/>
160-
{/* <BlockComponent
161-
block={{
162-
owner: "githubnext",
163-
repo: "blocks-examples",
164-
id: "code-block",
165-
}}
166-
/> */}
167172
</Show>
168173
<Show when={tab === "regex"}>
169174
<Show when={didInit}>
170175
<pre className="content">
171176
<code>
172-
<Show
173-
when={
174-
pomskyResult &&
175-
pomskyResult?.diagnostics.length > 0
176-
}
177-
>
178-
{JSON.stringify(
179-
pomskyResult?.diagnostics,
180-
null,
181-
"\t"
182-
)}
183-
</Show>
184-
<Show
185-
when={
186-
pomskyResult &&
187-
pomskyResult?.diagnostics.length === 0
188-
}
189-
>
190-
{pomskyResult?.output}
177+
<Show when={didError}>
178+
<Box p={3}>
179+
<Flash variant="danger">
180+
{JSON.stringify(
181+
pomskyResult?.diagnostics,
182+
null,
183+
"\t"
184+
)}
185+
</Flash>
186+
</Box>
191187
</Show>
188+
<Show when={!didError}>{pomskyResult?.output}</Show>
192189
</code>
193190
</pre>
194191
</Show>
195192
<Show when={!didInit}>
196-
<Box p={3}>Pomsky WASM is still initializing.</Box>
193+
<Box p={3}>
194+
<Flash variant="warning">
195+
Pomsky WASM is still initializing.
196+
</Flash>
197+
</Box>
197198
</Show>
198199
</Show>
199200
</Show>
200201
<Show when={!isPomsky}>
201202
<Box p={3}>
202-
<code>{context.file}</code> is not Pomsky code.
203-
<br />
204-
This block only works on files ending with <code>
205-
.pom
206-
</code> or <code>.pomsky</code>.
203+
<Flash variant="danger">
204+
<code>{context.file}</code> is not Pomsky code.
205+
<br />
206+
This block only works on files ending with <code>
207+
.pom
208+
</code>{" "}
209+
or <code>.pomsky</code>.
210+
</Flash>
207211
</Box>
208212
</Show>
209213
</Box>
210214
);
211215
});
212-
213-
function Show(props: {
214-
when: boolean | any;
215-
children?: null | string | JSX.Element | JSX.Element[];
216-
}) {
217-
return <>{props.when ? props.children : null}</>;
218-
}

package.json

+4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@
1010
},
1111
"type": "module",
1212
"dependencies": {
13+
"@codemirror/basic-setup": "^0.20.0",
14+
"@codemirror/lang-javascript": "^6.1.4",
15+
"@codemirror/language-data": "^6.1.0",
1316
"@githubnext/blocks": "^2.3.5",
17+
"codemirror": "^6.0.1",
1418
"pomsky-wasm": "^0.9.2",
1519
"react": "^18.1.0",
1620
"react-dom": "^18.1.0"

0 commit comments

Comments
 (0)