Skip to content

Commit db405b9

Browse files
committed
Add theme config
1 parent 0e6e55b commit db405b9

File tree

5 files changed

+125
-30
lines changed

5 files changed

+125
-30
lines changed

playground/src/app.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ function App() {
2525
readHash() || {
2626
mdx: defaultCode,
2727
css: defaultCss,
28-
config: { lineNumbers: false, showCopyButton: false },
28+
config: {
29+
lineNumbers: false,
30+
showCopyButton: false,
31+
theme: "material-darker",
32+
},
2933
}
3034
);
3135
}, []);

playground/src/editor.jsx

Lines changed: 68 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import MonacoEditor from "@monaco-editor/react";
22
import { useState } from "react";
3+
import { themeList } from "./themes";
34

45
const tabs = {
56
mdx: {
@@ -19,12 +20,8 @@ const tabs = {
1920
export function Editor({ setInput, input }) {
2021
const [tab, setTab] = useState("mdx");
2122

22-
function handleEditorChange(code, event) {
23+
function handleEditorChange(code) {
2324
let value = code;
24-
if (tab === "config") {
25-
console.log({ code });
26-
value = JSON.parse(code);
27-
}
2825
setInput((prev) => ({ ...prev, [tab]: value }));
2926
}
3027

@@ -53,28 +50,72 @@ export function Editor({ setInput, input }) {
5350
Config
5451
</span>
5552
</nav>
56-
<MonacoEditor
57-
className="editor"
58-
onChange={handleEditorChange}
59-
theme="vs-dark"
60-
path={tab}
61-
defaultLanguage={tabs[tab].lang}
62-
defaultValue={tabs[tab].code(input)}
63-
options={{
64-
// https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IEditorConstructionOptions.html
65-
minimap: {
66-
enabled: false,
67-
},
68-
lineNumbers: "off",
69-
scrollBeyondLastLine: false,
70-
hideCursorInOverviewRuler: true,
71-
matchBrackets: false,
72-
overviewRulerBorder: false,
73-
renderLineHighlight: "none",
74-
wordWrap: "on",
75-
tabSize: 2,
76-
}}
77-
/>
53+
{tab === "config" ? (
54+
<ConfigEditor config={input.config} onChange={handleEditorChange} />
55+
) : (
56+
<div className="editor">
57+
<MonacoEditor
58+
onChange={handleEditorChange}
59+
theme="vs-dark"
60+
path={tab}
61+
defaultLanguage={tabs[tab].lang}
62+
defaultValue={tabs[tab].code(input)}
63+
options={{
64+
// https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IEditorConstructionOptions.html
65+
minimap: {
66+
enabled: false,
67+
},
68+
lineNumbers: "off",
69+
scrollBeyondLastLine: false,
70+
hideCursorInOverviewRuler: true,
71+
matchBrackets: false,
72+
overviewRulerBorder: false,
73+
renderLineHighlight: "none",
74+
wordWrap: "on",
75+
tabSize: 2,
76+
}}
77+
/>
78+
</div>
79+
)}
7880
</div>
7981
);
8082
}
83+
84+
function ConfigEditor({ config, onChange }) {
85+
return (
86+
<form className="editor config-editor">
87+
<label>
88+
<input
89+
type="checkbox"
90+
checked={config.lineNumbers}
91+
onChange={(e) =>
92+
onChange({ ...config, lineNumbers: e.target.checked })
93+
}
94+
/>
95+
Line Numbers
96+
</label>
97+
<label>
98+
<input
99+
type="checkbox"
100+
checked={config.showCopyButton}
101+
onChange={(e) =>
102+
onChange({ ...config, showCopyButton: e.target.checked })
103+
}
104+
/>
105+
Copy Button
106+
</label>
107+
<label>
108+
Theme:
109+
<br />
110+
<select
111+
value={config.theme}
112+
onChange={(e) => onChange({ ...config, theme: e.target.value })}
113+
>
114+
{themeList().map((theme) => (
115+
<option key={theme}>{theme}</option>
116+
))}
117+
</select>
118+
</label>
119+
</form>
120+
);
121+
}

playground/src/index.css

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ main {
7979
color: #fafafa;
8080
height: 2.2rem;
8181
min-height: 2rem;
82+
max-height: 2rem;
8283
border-bottom: 1px solid #444;
8384
display: flex;
8485
align-items: center;
@@ -108,6 +109,31 @@ main {
108109
.editor-tab:hover {
109110
color: rgb(179, 209, 245);
110111
}
112+
113+
.editor {
114+
flex: 1;
115+
background-color: #1e1e1e;
116+
color: #d4d4d4;
117+
color-scheme: dark;
118+
}
119+
120+
.config-editor {
121+
padding: 0.6rem 1.5rem;
122+
}
123+
124+
.config-editor label {
125+
display: block;
126+
margin-bottom: 0.5rem;
127+
}
128+
129+
.config-editor input[type="checkbox"] {
130+
margin-right: 0.5rem;
131+
}
132+
133+
.config-editor select {
134+
font-size: 1rem;
135+
}
136+
111137
.preview {
112138
min-width: 600px;
113139
border-left: 2px solid cadetblue;

playground/src/preview.jsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { remarkCodeHike } from "@code-hike/mdx";
55
import { CH } from "@code-hike/mdx/components";
66
import "@code-hike/mdx/styles.css";
77
import { ErrorBoundary } from "react-error-boundary";
8-
import theme from "shiki/themes/material-darker.json";
8+
import { getTheme } from "./themes";
99

1010
export function Preview(props) {
1111
return (
@@ -35,7 +35,14 @@ function InnerPreview({ input }) {
3535
compile(input.mdx, {
3636
outputFormat: "function-body",
3737
remarkPlugins: [
38-
[remarkCodeHike, { ...input.config, autoImport: false, theme }],
38+
[
39+
remarkCodeHike,
40+
{
41+
...input.config,
42+
autoImport: false,
43+
theme: getTheme(input.config.theme),
44+
},
45+
],
3946
],
4047
})
4148
.then((c) => {

playground/src/themes.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const modules = import.meta.globEager("../../node_modules/shiki/themes/*.json");
2+
3+
const themes = {};
4+
Object.keys(modules).forEach((path) => {
5+
const name = path.split("/").pop().replace(".json", "");
6+
if (name !== "css-variables") {
7+
themes[name] = modules[path].default;
8+
}
9+
});
10+
11+
export function themeList() {
12+
return Object.keys(themes);
13+
}
14+
15+
export function getTheme(name) {
16+
return themes[name];
17+
}

0 commit comments

Comments
 (0)