feat(playground): add configuration for default editor themes and languages

This commit is contained in:
ngc2207 2025-01-08 16:42:57 +08:00
parent 5e6065d38d
commit e24cb4a969
7 changed files with 560 additions and 286 deletions

View File

@ -1,29 +1,29 @@
import { // import {
Select, // Select,
SelectItem, // SelectItem,
SelectValue, // SelectValue,
SelectContent, // SelectContent,
SelectTrigger, // SelectTrigger,
} from "@/components/ui/select"; // } from "@/components/ui/select";
import { useCodeEditorStore } from "@/store/useCodeEditorStore"; // import { useCodeEditorStore } from "@/store/useCodeEditorStore";
import { SUPPORTED_LANGUAGES } from "@/constants/editor/languages"; // import { SUPPORTED_LANGUAGES } from "@/constants/editor/languages";
export default function LanguageSelector() { // export default function LanguageSelector() {
const { language, setLanguage } = useCodeEditorStore(); // const { language, setLanguage } = useCodeEditorStore();
return ( // return (
<Select value={language} onValueChange={setLanguage}> // <Select value={language} onValueChange={setLanguage}>
<SelectTrigger className="[&>span]:flex [&>span]:items-center [&>span]:gap-2 [&>span_svg]:shrink-0 [&>span_svg]:text-muted-foreground/80 w-36"> // <SelectTrigger className="[&>span]:flex [&>span]:items-center [&>span]:gap-2 [&>span_svg]:shrink-0 [&>span_svg]:text-muted-foreground/80 w-36">
<SelectValue placeholder="Select Language" /> // <SelectValue placeholder="Select Language" />
</SelectTrigger> // </SelectTrigger>
<SelectContent className="[&_*[role=option]>span>svg]:shrink-0 [&_*[role=option]>span>svg]:text-muted-foreground/80 [&_*[role=option]>span]:end-2 [&_*[role=option]>span]:start-auto [&_*[role=option]>span]:flex [&_*[role=option]>span]:items-center [&_*[role=option]>span]:gap-2 [&_*[role=option]]:pe-8 [&_*[role=option]]:ps-2"> // <SelectContent className="[&_*[role=option]>span>svg]:shrink-0 [&_*[role=option]>span>svg]:text-muted-foreground/80 [&_*[role=option]>span]:end-2 [&_*[role=option]>span]:start-auto [&_*[role=option]>span]:flex [&_*[role=option]>span]:items-center [&_*[role=option]>span]:gap-2 [&_*[role=option]]:pe-8 [&_*[role=option]]:ps-2">
{SUPPORTED_LANGUAGES.map((lang) => ( // {SUPPORTED_LANGUAGES.map((lang) => (
<SelectItem key={lang.key} value={lang.value}> // <SelectItem key={lang.key} value={lang.value}>
<lang.icon size={16} aria-hidden="true" /> // <lang.icon size={16} aria-hidden="true" />
<span className="truncate">{lang.label}</span> // <span className="truncate">{lang.label}</span>
</SelectItem> // </SelectItem>
))} // ))}
</SelectContent> // </SelectContent>
</Select> // </Select>
); // );
} // }

View File

@ -1,32 +1,32 @@
import { // import {
Select, // Select,
SelectItem, // SelectItem,
SelectValue, // SelectValue,
SelectContent, // SelectContent,
SelectTrigger, // SelectTrigger,
} from "@/components/ui/select"; // } from "@/components/ui/select";
import { Palette } from "lucide-react"; // import { Palette } from "lucide-react";
import { SUPPORTED_THEMES } from "@/constants/editor/themes"; // import { SUPPORTED_THEMES } from "@/constants/editor/themes";
import { useCodeEditorStore } from "@/store/useCodeEditorStore"; // import { useCodeEditorStore } from "@/store/useCodeEditorStore";
export default function ThemeSelector() { // export default function ThemeSelector() {
const { theme, setTheme } = useCodeEditorStore(); // const { theme, setTheme } = useCodeEditorStore();
return ( // return (
<Select value={theme} onValueChange={setTheme}> // <Select value={theme} onValueChange={setTheme}>
<SelectTrigger className="relative ps-9 w-40"> // <SelectTrigger className="relative ps-9 w-40">
<div className="pointer-events-none absolute inset-y-0 start-0 flex items-center justify-center ps-3 text-muted-foreground/80 group-has-[[disabled]]:opacity-50"> // <div className="pointer-events-none absolute inset-y-0 start-0 flex items-center justify-center ps-3 text-muted-foreground/80 group-has-[[disabled]]:opacity-50">
<Palette size={16} strokeWidth={2} aria-hidden="true" /> // <Palette size={16} strokeWidth={2} aria-hidden="true" />
</div> // </div>
<SelectValue placeholder="Select Theme" /> // <SelectValue placeholder="Select Theme" />
</SelectTrigger> // </SelectTrigger>
<SelectContent> // <SelectContent>
{SUPPORTED_THEMES.map((theme) => ( // {SUPPORTED_THEMES.map((theme) => (
<SelectItem key={theme.key} value={theme.value}> // <SelectItem key={theme.key} value={theme.value}>
<span className="truncate">{theme.label}</span> // <span className="truncate">{theme.label}</span>
</SelectItem> // </SelectItem>
))} // ))}
</SelectContent> // </SelectContent>
</Select> // </Select>
); // );
} // }

View File

@ -1,33 +1,37 @@
"use client"; // "use client";
import * as monaco from "monaco-editor"; // import * as monaco from "monaco-editor";
import Editor from "@monaco-editor/react"; // import Editor from "@monaco-editor/react";
import { loader } from "@monaco-editor/react"; // import { loader } from "@monaco-editor/react";
import ThemeSelector from "./components/theme-selector"; // import ThemeSelector from "./components/theme-selector";
import FontSizeSlider from "./components/font-size-slider"; // import FontSizeSlider from "./components/font-size-slider";
import LanguageSelector from "./components/language-selector"; // import LanguageSelector from "./components/language-selector";
import { useCodeEditorStore } from "@/store/useCodeEditorStore"; // import { useCodeEditorStore } from "@/store/useCodeEditorStore";
import { highlightMonacoEditor } from "@/constants/editor/themes"; // import { highlightMonacoEditor } from "@/constants/editor/themes";
loader.config({ monaco }); // loader.config({ monaco });
export default function MainPage() { // export default function MainPage() {
const { language, theme, fontSize, setEditor } = useCodeEditorStore(); // const { language, theme, fontSize, setEditor } = useCodeEditorStore();
return ( // return (
<div className="h-full flex flex-col gap-2"> // <div className="h-full flex flex-col gap-2">
<div className="flex items-center px-4 gap-2"> // <div className="flex items-center px-4 gap-2">
<LanguageSelector /> // <LanguageSelector />
<ThemeSelector /> // <ThemeSelector />
<FontSizeSlider /> // <FontSizeSlider />
</div> // </div>
<Editor // <Editor
language={language} // language={language}
theme={theme} // theme={theme}
beforeMount={highlightMonacoEditor} // beforeMount={highlightMonacoEditor}
onMount={setEditor} // onMount={setEditor}
options={{ fontSize, automaticLayout: true }} // options={{ fontSize, automaticLayout: true }}
/> // />
</div> // </div>
); // );
// }
export default function HomePage() {
return null;
} }

42
src/config/index.ts Normal file
View File

@ -0,0 +1,42 @@
import { SupportedEditorLanguage } from "@/constants/editor/languages";
export const DEFAULT_EDITOR_THEME = "one-dark-pro";
export const DEFAULT_EDITOR_LANGUAGE: SupportedEditorLanguage = "c";
export interface EditorFile {
path: string;
language: SupportedEditorLanguage;
value: string;
}
export const DEFAULT_FILES: Record<SupportedEditorLanguage, EditorFile> = {
c: {
path: "playground/main.c",
language: "c",
value: `#include <stdio.h>
int main() {
printf("Hello, World!");
return 0;
}`,
},
cpp: {
path: "playground/main.cpp",
language: "cpp",
value: `#include <iostream>
using namespace std;
int main() {
cout << "Hello, World!";
return 0;
}`,
},
java: {
path: "playground/Main.java",
language: "java",
value: `public class Main {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}`,
},
};

View File

@ -1,15 +1,40 @@
import { // import {
COriginal, // COriginal,
CplusplusOriginal, // CplusplusOriginal,
JavaOriginal, // JavaOriginal,
PythonOriginal, // PythonOriginal,
} from "devicons-react"; // } from "devicons-react";
export const SUPPORTED_LANGUAGES = [ // export const SUPPORTED_LANGUAGES = [
{ key: "c", value: "c", label: "C", icon: COriginal }, // { key: "c", value: "c", label: "C", icon: COriginal },
{ key: "cpp", value: "cpp", label: "C++", icon: CplusplusOriginal }, // { key: "cpp", value: "cpp", label: "C++", icon: CplusplusOriginal },
{ key: "java", value: "java", label: "Java", icon: JavaOriginal }, // { key: "java", value: "java", label: "Java", icon: JavaOriginal },
{ key: "python", value: "python", label: "Python", icon: PythonOriginal }, // { key: "python", value: "python", label: "Python", icon: PythonOriginal },
]; // ];
export const DEFAULT_LANGUAGE = SUPPORTED_LANGUAGES[0].value; // export const DEFAULT_LANGUAGE = SUPPORTED_LANGUAGES[0].value;
import { COriginal, CplusplusOriginal, JavaOriginal } from "devicons-react";
export const SUPPORTED_EDITOR_LANGUAGES = ["c", "cpp", "java"];
export const SUPPORTED_EDITOR_LANGUAGES_CONFIG = {
c: {
id: "c",
label: "C",
icon: COriginal,
},
cpp: {
id: "cpp",
label: "C++",
icon: CplusplusOriginal,
},
java: {
id: "java",
label: "Java",
icon: JavaOriginal,
},
};
export type SupportedEditorLanguage =
(typeof SUPPORTED_EDITOR_LANGUAGES)[number];

View File

@ -1,292 +1,495 @@
import { createHighlighter } from "shiki"; // import { createHighlighter } from "shiki";
import { Monaco } from "@monaco-editor/react"; // import { Monaco } from "@monaco-editor/react";
import { shikiToMonaco } from "@shikijs/monaco"; // import { shikiToMonaco } from "@shikijs/monaco";
import { SUPPORTED_LANGUAGES } from "./languages"; // import { SUPPORTED_LANGUAGES } from "./languages";
export const SUPPORTED_THEMES = [ // export const SUPPORTED_THEMES = [
// {
// key: "andromeeda",
// value: "andromeeda",
// label: "Andromeeda",
// },
// {
// key: "aurora-x",
// value: "aurora-x",
// label: "Aurora X",
// },
// {
// key: "ayu-dark",
// value: "ayu-dark",
// label: "Ayu Dark",
// },
// {
// key: "catppuccin-frappe",
// value: "catppuccin-frappe",
// label: "Catppuccin Frappé",
// },
// {
// key: "catppuccin-latte",
// value: "catppuccin-latte",
// label: "Catppuccin Latte",
// },
// {
// key: "catppuccin-macchiato",
// value: "catppuccin-macchiato",
// label: "Catppuccin Macchiato",
// },
// {
// key: "catppuccin-mocha",
// value: "catppuccin-mocha",
// label: "Catppuccin Mocha",
// },
// {
// key: "dark-plus",
// value: "dark-plus",
// label: "Dark Plus",
// },
// {
// key: "dracula",
// value: "dracula",
// label: "Dracula",
// },
// {
// key: "dracula-soft",
// value: "dracula-soft",
// label: "Dracula Soft",
// },
// {
// key: "everforest-dark",
// value: "everforest-dark",
// label: "Everforest Dark",
// },
// {
// key: "everforest-light",
// value: "everforest-light",
// label: "Everforest Light",
// },
// {
// key: "github-dark",
// value: "github-dark",
// label: "GitHub Dark",
// },
// // {
// // key: "github-dark-default",
// // value: "github-dark-default",
// // label: "GitHub Dark Default",
// // },
// // {
// // key: "github-dark-dimmed",
// // value: "github-dark-dimmed",
// // label: "GitHub Dark Dimmed",
// // },
// // {
// // key: "github-dark-high-contrast",
// // value: "github-dark-high-contrast",
// // label: "GitHub Dark High Contrast",
// // },
// {
// key: "github-light",
// value: "github-light",
// label: "GitHub Light",
// },
// {
// key: "github-light-default",
// value: "github-light-default",
// label: "GitHub Light Default",
// },
// {
// key: "github-light-high-contrast",
// value: "github-light-high-contrast",
// label: "GitHub Light High Contrast",
// },
// {
// key: "houston",
// value: "houston",
// label: "Houston",
// },
// {
// key: "kanagawa-dragon",
// value: "kanagawa-dragon",
// label: "Kanagawa Dragon",
// },
// {
// key: "kanagawa-lotus",
// value: "kanagawa-lotus",
// label: "Kanagawa Lotus",
// },
// {
// key: "kanagawa-wave",
// value: "kanagawa-wave",
// label: "Kanagawa Wave",
// },
// {
// key: "laserwave",
// value: "laserwave",
// label: "Laserwave",
// },
// {
// key: "light-plus",
// value: "light-plus",
// label: "Light Plus",
// },
// {
// key: "material-theme",
// value: "material-theme",
// label: "Material Theme",
// },
// {
// key: "material-theme-darker",
// value: "material-theme-darker",
// label: "Material Theme Darker",
// },
// {
// key: "material-theme-lighter",
// value: "material-theme-lighter",
// label: "Material Theme Lighter",
// },
// {
// key: "material-theme-ocean",
// value: "material-theme-ocean",
// label: "Material Theme Ocean",
// },
// {
// key: "material-theme-palenight",
// value: "material-theme-palenight",
// label: "Material Theme Palenight",
// },
// {
// key: "min-dark",
// value: "min-dark",
// label: "Min Dark",
// },
// {
// key: "min-light",
// value: "min-light",
// label: "Min Light",
// },
// {
// key: "monokai",
// value: "monokai",
// label: "Monokai",
// },
// {
// key: "night-owl",
// value: "night-owl",
// label: "Night Owl",
// },
// {
// key: "nord",
// value: "nord",
// label: "Nord",
// },
// {
// key: "one-dark-pro",
// value: "one-dark-pro",
// label: "One Dark Pro",
// },
// {
// key: "one-light",
// value: "one-light",
// label: "One Light",
// },
// {
// key: "plastic",
// value: "plastic",
// label: "Plastic",
// },
// {
// key: "poimandres",
// value: "poimandres",
// label: "Poimandres",
// },
// {
// key: "red",
// value: "red",
// label: "Red",
// },
// {
// key: "rose-pine",
// value: "rose-pine",
// label: "Rosé Pine",
// },
// {
// key: "rose-pine-dawn",
// value: "rose-pine-dawn",
// label: "Rosé Pine Dawn",
// },
// {
// key: "rose-pine-moon",
// value: "rose-pine-moon",
// label: "Rosé Pine Moon",
// },
// {
// key: "slack-dark",
// value: "slack-dark",
// label: "Slack Dark",
// },
// {
// key: "slack-ochin",
// value: "slack-ochin",
// label: "Slack Ochin",
// },
// {
// key: "snazzy-light",
// value: "snazzy-light",
// label: "Snazzy Light",
// },
// {
// key: "solarized-dark",
// value: "solarized-dark",
// label: "Solarized Dark",
// },
// {
// key: "solarized-light",
// value: "solarized-light",
// label: "Solarized Light",
// },
// {
// key: "synthwave-84",
// value: "synthwave-84",
// label: "Synthwave '84",
// },
// {
// key: "tokyo-night",
// value: "tokyo-night",
// label: "Tokyo Night",
// },
// // {
// // key: "vesper",
// // value: "vesper",
// // label: "Vesper",
// // },
// {
// key: "vitesse-black",
// value: "vitesse-black",
// label: "Vitesse Black",
// },
// {
// key: "vitesse-dark",
// value: "vitesse-dark",
// label: "Vitesse Dark",
// },
// {
// key: "vitesse-light",
// value: "vitesse-light",
// label: "Vitesse Light",
// },
// ];
// export const DEFAULT_THEME = SUPPORTED_THEMES[0].value;
// export const highlightMonacoEditor = async (monaco: Monaco) => {
// const highlighter = await createHighlighter({
// themes: SUPPORTED_THEMES.map((theme) => theme.value),
// langs: SUPPORTED_LANGUAGES.map((lang) => lang.value),
// });
// for (const lang of SUPPORTED_LANGUAGES) {
// monaco.languages.register({ id: lang.value });
// }
// shikiToMonaco(highlighter, monaco);
// };
export const SUPPORTED_EDITOR_THEMES = [
{ {
key: "andromeeda", id: "andromeeda",
value: "andromeeda",
label: "Andromeeda", label: "Andromeeda",
}, },
{ {
key: "aurora-x", id: "aurora-x",
value: "aurora-x",
label: "Aurora X", label: "Aurora X",
}, },
{ {
key: "ayu-dark", id: "ayu-dark",
value: "ayu-dark",
label: "Ayu Dark", label: "Ayu Dark",
}, },
{ {
key: "catppuccin-frappe", id: "catppuccin-frappe",
value: "catppuccin-frappe",
label: "Catppuccin Frappé", label: "Catppuccin Frappé",
}, },
{ {
key: "catppuccin-latte", id: "catppuccin-latte",
value: "catppuccin-latte",
label: "Catppuccin Latte", label: "Catppuccin Latte",
}, },
{ {
key: "catppuccin-macchiato", id: "catppuccin-macchiato",
value: "catppuccin-macchiato",
label: "Catppuccin Macchiato", label: "Catppuccin Macchiato",
}, },
{ {
key: "catppuccin-mocha", id: "catppuccin-mocha",
value: "catppuccin-mocha",
label: "Catppuccin Mocha", label: "Catppuccin Mocha",
}, },
{ {
key: "dark-plus", id: "dark-plus",
value: "dark-plus",
label: "Dark Plus", label: "Dark Plus",
}, },
{ {
key: "dracula", id: "dracula",
value: "dracula",
label: "Dracula", label: "Dracula",
}, },
{ {
key: "dracula-soft", id: "dracula-soft",
value: "dracula-soft",
label: "Dracula Soft", label: "Dracula Soft",
}, },
{ {
key: "everforest-dark", id: "everforest-dark",
value: "everforest-dark",
label: "Everforest Dark", label: "Everforest Dark",
}, },
{ {
key: "everforest-light", id: "everforest-light",
value: "everforest-light",
label: "Everforest Light", label: "Everforest Light",
}, },
{ {
key: "github-dark", id: "github-dark",
value: "github-dark",
label: "GitHub Dark", label: "GitHub Dark",
}, },
// {
// key: "github-dark-default",
// value: "github-dark-default",
// label: "GitHub Dark Default",
// },
// {
// key: "github-dark-dimmed",
// value: "github-dark-dimmed",
// label: "GitHub Dark Dimmed",
// },
// {
// key: "github-dark-high-contrast",
// value: "github-dark-high-contrast",
// label: "GitHub Dark High Contrast",
// },
{ {
key: "github-light", id: "github-light",
value: "github-light",
label: "GitHub Light", label: "GitHub Light",
}, },
{ {
key: "github-light-default", id: "github-light-default",
value: "github-light-default",
label: "GitHub Light Default", label: "GitHub Light Default",
}, },
{ {
key: "github-light-high-contrast", id: "github-light-high-contrast",
value: "github-light-high-contrast",
label: "GitHub Light High Contrast", label: "GitHub Light High Contrast",
}, },
{ {
key: "houston", id: "houston",
value: "houston",
label: "Houston", label: "Houston",
}, },
{ {
key: "kanagawa-dragon", id: "kanagawa-dragon",
value: "kanagawa-dragon",
label: "Kanagawa Dragon", label: "Kanagawa Dragon",
}, },
{ {
key: "kanagawa-lotus", id: "kanagawa-lotus",
value: "kanagawa-lotus",
label: "Kanagawa Lotus", label: "Kanagawa Lotus",
}, },
{ {
key: "kanagawa-wave", id: "kanagawa-wave",
value: "kanagawa-wave",
label: "Kanagawa Wave", label: "Kanagawa Wave",
}, },
{ {
key: "laserwave", id: "laserwave",
value: "laserwave",
label: "Laserwave", label: "Laserwave",
}, },
{ {
key: "light-plus", id: "light-plus",
value: "light-plus",
label: "Light Plus", label: "Light Plus",
}, },
{ {
key: "material-theme", id: "material-theme",
value: "material-theme",
label: "Material Theme", label: "Material Theme",
}, },
{ {
key: "material-theme-darker", id: "material-theme-darker",
value: "material-theme-darker",
label: "Material Theme Darker", label: "Material Theme Darker",
}, },
{ {
key: "material-theme-lighter", id: "material-theme-lighter",
value: "material-theme-lighter",
label: "Material Theme Lighter", label: "Material Theme Lighter",
}, },
{ {
key: "material-theme-ocean", id: "material-theme-ocean",
value: "material-theme-ocean",
label: "Material Theme Ocean", label: "Material Theme Ocean",
}, },
{ {
key: "material-theme-palenight", id: "material-theme-palenight",
value: "material-theme-palenight",
label: "Material Theme Palenight", label: "Material Theme Palenight",
}, },
{ {
key: "min-dark", id: "min-dark",
value: "min-dark",
label: "Min Dark", label: "Min Dark",
}, },
{ {
key: "min-light", id: "min-light",
value: "min-light",
label: "Min Light", label: "Min Light",
}, },
{ {
key: "monokai", id: "monokai",
value: "monokai",
label: "Monokai", label: "Monokai",
}, },
{ {
key: "night-owl", id: "night-owl",
value: "night-owl",
label: "Night Owl", label: "Night Owl",
}, },
{ {
key: "nord", id: "nord",
value: "nord",
label: "Nord", label: "Nord",
}, },
{ {
key: "one-dark-pro", id: "one-dark-pro",
value: "one-dark-pro",
label: "One Dark Pro", label: "One Dark Pro",
}, },
{ {
key: "one-light", id: "one-light",
value: "one-light",
label: "One Light", label: "One Light",
}, },
{ {
key: "plastic", id: "plastic",
value: "plastic",
label: "Plastic", label: "Plastic",
}, },
{ {
key: "poimandres", id: "poimandres",
value: "poimandres",
label: "Poimandres", label: "Poimandres",
}, },
{ {
key: "red", id: "red",
value: "red",
label: "Red", label: "Red",
}, },
{ {
key: "rose-pine", id: "rose-pine",
value: "rose-pine",
label: "Rosé Pine", label: "Rosé Pine",
}, },
{ {
key: "rose-pine-dawn", id: "rose-pine-dawn",
value: "rose-pine-dawn",
label: "Rosé Pine Dawn", label: "Rosé Pine Dawn",
}, },
{ {
key: "rose-pine-moon", id: "rose-pine-moon",
value: "rose-pine-moon",
label: "Rosé Pine Moon", label: "Rosé Pine Moon",
}, },
{ {
key: "slack-dark", id: "slack-dark",
value: "slack-dark",
label: "Slack Dark", label: "Slack Dark",
}, },
{ {
key: "slack-ochin", id: "slack-ochin",
value: "slack-ochin",
label: "Slack Ochin", label: "Slack Ochin",
}, },
{ {
key: "snazzy-light", id: "snazzy-light",
value: "snazzy-light",
label: "Snazzy Light", label: "Snazzy Light",
}, },
{ {
key: "solarized-dark", id: "solarized-dark",
value: "solarized-dark",
label: "Solarized Dark", label: "Solarized Dark",
}, },
{ {
key: "solarized-light", id: "solarized-light",
value: "solarized-light",
label: "Solarized Light", label: "Solarized Light",
}, },
{ {
key: "synthwave-84", id: "synthwave-84",
value: "synthwave-84",
label: "Synthwave '84", label: "Synthwave '84",
}, },
{ {
key: "tokyo-night", id: "tokyo-night",
value: "tokyo-night",
label: "Tokyo Night", label: "Tokyo Night",
}, },
// {
// key: "vesper",
// value: "vesper",
// label: "Vesper",
// },
{ {
key: "vitesse-black", id: "vitesse-black",
value: "vitesse-black",
label: "Vitesse Black", label: "Vitesse Black",
}, },
{ {
key: "vitesse-dark", id: "vitesse-dark",
value: "vitesse-dark",
label: "Vitesse Dark", label: "Vitesse Dark",
}, },
{ {
key: "vitesse-light", id: "vitesse-light",
value: "vitesse-light",
label: "Vitesse Light", label: "Vitesse Light",
}, },
]; ];
export const DEFAULT_THEME = SUPPORTED_THEMES[0].value;
export const highlightMonacoEditor = async (monaco: Monaco) => {
const highlighter = await createHighlighter({
themes: SUPPORTED_THEMES.map((theme) => theme.value),
langs: SUPPORTED_LANGUAGES.map((lang) => lang.value),
});
for (const lang of SUPPORTED_LANGUAGES) {
monaco.languages.register({ id: lang.value });
}
shikiToMonaco(highlighter, monaco);
};

View File

@ -1,52 +1,52 @@
import { create } from "zustand"; // import { create } from "zustand";
import { editor } from "monaco-editor"; // import { editor } from "monaco-editor";
import { CodeEditorState } from "@/types"; // import { CodeEditorState } from "@/types";
import { DEFAULT_THEME } from "@/constants/editor/themes"; // import { DEFAULT_THEME } from "@/constants/editor/themes";
import { DEFAULT_VALUE } from "@/constants/editor/values"; // import { DEFAULT_VALUE } from "@/constants/editor/values";
import { DEFAULT_FONT_SIZE } from "@/constants/editor/options"; // import { DEFAULT_FONT_SIZE } from "@/constants/editor/options";
import { DEFAULT_LANGUAGE } from "@/constants/editor/languages"; // import { DEFAULT_LANGUAGE } from "@/constants/editor/languages";
import { persist, createJSONStorage } from "zustand/middleware"; // import { persist, createJSONStorage } from "zustand/middleware";
const getSavedCode = (language: string) => // const getSavedCode = (language: string) =>
localStorage.getItem(`code-editor-${language}`) || // localStorage.getItem(`code-editor-${language}`) ||
DEFAULT_VALUE.find((v) => v.key === language)?.value || // DEFAULT_VALUE.find((v) => v.key === language)?.value ||
""; // "";
const saveCode = (language: string, code: string) => // const saveCode = (language: string, code: string) =>
localStorage.setItem(`code-editor-${language}`, code); // localStorage.setItem(`code-editor-${language}`, code);
export const useCodeEditorStore = create<CodeEditorState>()( // export const useCodeEditorStore = create<CodeEditorState>()(
persist( // persist(
(set, get) => ({ // (set, get) => ({
language: DEFAULT_LANGUAGE, // language: DEFAULT_LANGUAGE,
theme: DEFAULT_THEME, // theme: DEFAULT_THEME,
fontSize: DEFAULT_FONT_SIZE, // fontSize: DEFAULT_FONT_SIZE,
editor: null, // editor: null,
setLanguage: (language: string) => { // setLanguage: (language: string) => {
const { editor: currentEditor, language: currentLanguage } = get(); // const { editor: currentEditor, language: currentLanguage } = get();
const currentCode = currentEditor?.getValue() || ""; // const currentCode = currentEditor?.getValue() || "";
if (currentEditor) saveCode(currentLanguage, currentCode); // if (currentEditor) saveCode(currentLanguage, currentCode);
const savedCode = getSavedCode(language); // const savedCode = getSavedCode(language);
if (savedCode && currentEditor) currentEditor.setValue(savedCode); // if (savedCode && currentEditor) currentEditor.setValue(savedCode);
set({ language }); // set({ language });
}, // },
setTheme: (theme: string) => set({ theme }), // setTheme: (theme: string) => set({ theme }),
setFontSize: (fontSize: number) => set({ fontSize }), // setFontSize: (fontSize: number) => set({ fontSize }),
setEditor: (editor: editor.IStandaloneCodeEditor) => { // setEditor: (editor: editor.IStandaloneCodeEditor) => {
const savedCode = getSavedCode(get().language); // const savedCode = getSavedCode(get().language);
if (savedCode) editor.setValue(savedCode); // if (savedCode) editor.setValue(savedCode);
set({ editor }); // set({ editor });
}, // },
}), // }),
{ // {
name: "code-editor-storage", // name: "code-editor-storage",
storage: createJSONStorage(() => localStorage), // storage: createJSONStorage(() => localStorage),
partialize: (state) => ({ // partialize: (state) => ({
language: state.language, // language: state.language,
theme: state.theme, // theme: state.theme,
fontSize: state.fontSize, // fontSize: state.fontSize,
}), // }),
} // }
) // )
); // );