Skip to content

Commit 2fd1ef5

Browse files
committed
fix(chart-playground-web): restore highlighted JSON editor with invalid-JSON feedback
1 parent 07635e8 commit 2fd1ef5

2 files changed

Lines changed: 65 additions & 6 deletions

File tree

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1+
import hljs from "highlight.js/lib/core";
2+
import json from "highlight.js/lib/languages/json";
13
import { ReactElement } from "react";
4+
import Editor from "react-simple-code-editor";
5+
import "highlight.js/styles/atom-one-light.css";
6+
7+
hljs.registerLanguage("json", json);
28

39
export interface CodeEditorProps {
410
value: string;
@@ -7,13 +13,49 @@ export interface CodeEditorProps {
713
height?: string;
814
}
915

16+
function highlight(code: string): string {
17+
try {
18+
return hljs.highlight(code, { language: "json", ignoreIllegals: true }).value;
19+
} catch (error) {
20+
console.warn("Syntax highlighting error:", error);
21+
return code;
22+
}
23+
}
24+
25+
function jsonError(code: string): string | null {
26+
if (code.trim() === "") {
27+
return null;
28+
}
29+
try {
30+
JSON.parse(code);
31+
return null;
32+
} catch (error) {
33+
return error instanceof Error ? error.message : "Invalid JSON";
34+
}
35+
}
36+
1037
export function CodeEditor(props: CodeEditorProps): ReactElement {
38+
const error = jsonError(props.value);
39+
1140
return (
12-
<textarea
13-
value={props.value}
14-
onChange={e => props.onChange?.(e.target.value)}
15-
style={{ height: props.height ?? "200px", width: "100%", fontFamily: "monospace" }}
16-
readOnly={props.readOnly}
17-
/>
41+
<div className="widget-charts-playground-code-editor">
42+
{error && (
43+
<div className="widget-charts-playground-code-editor-error" role="alert">
44+
{error}
45+
</div>
46+
)}
47+
<Editor
48+
value={props.value}
49+
onValueChange={value => props.onChange?.(value)}
50+
highlight={highlight}
51+
disabled={props.readOnly}
52+
padding={8}
53+
tabSize={2}
54+
insertSpaces
55+
ignoreTabKey={false}
56+
spellCheck={false}
57+
style={{ height: props.height ?? "200px", width: "100%", fontFamily: "monospace" }}
58+
/>
59+
</div>
1860
);
1961
}

packages/pluggableWidgets/chart-playground-web/src/ui/Playground.scss

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,23 @@
2424
}
2525
}
2626

27+
.widget-charts-playground-code-editor {
28+
overflow: auto;
29+
30+
.widget-charts-playground-code-editor-error {
31+
position: sticky;
32+
top: 0;
33+
z-index: 1;
34+
color: #c00;
35+
background: #fdecea;
36+
border-bottom: 1px solid #f5c6cb;
37+
font-size: 12px;
38+
font-family: monospace;
39+
padding: 4px 8px;
40+
white-space: pre-wrap;
41+
}
42+
}
43+
2744
.widget-sidebar {
2845
.sidebar-content-header {
2946
.header-content {

0 commit comments

Comments
 (0)