Spaces:
Paused
Paused
import { useRef, useState } from "react"; | |
import { IKeyboardEvent } from "monaco-editor"; | |
import { useDebounce } from "use-debounce"; | |
import { OnChange, OnMount } from "@monaco-editor/react"; | |
import parserHtml from "prettier/parser-html"; | |
import parserCss from "prettier/parser-postcss"; | |
import parserBabel from "prettier/parser-babel"; | |
import prettier from "prettier"; | |
import { useAppSelector } from "../store/hook"; | |
import { theme_state } from "../store/features/themeSlice"; | |
export const useMonaco = () => { | |
const { theme } = useAppSelector(theme_state); | |
const codeEditor = useRef<any>(); | |
const [input, setInput] = useState<string | undefined>(""); | |
const [code] = useDebounce(input, 1000); | |
const onChange: OnChange = (value) => { | |
setInput(value); | |
}; | |
const onMount: OnMount = async (monacoEditor, monaco) => { | |
codeEditor.current = monacoEditor; | |
monaco.editor.defineTheme("myTheme", { | |
base: "vs-dark", | |
inherit: true, | |
rules: [{ background: theme.background, token: "" }], | |
colors: { | |
"editor.background": theme.foreground, | |
}, | |
}); | |
monaco.editor.setTheme("myTheme"); | |
const { default: traverse } = await import("@babel/traverse"); | |
const { parse } = await import("@babel/parser"); | |
const { default: MonacoJSXHighlighter } = await import( | |
"monaco-jsx-highlighter" | |
); | |
//jsx syntax highlight | |
const babelParse = (code: any) => | |
parse(code, { sourceType: "module", plugins: ["jsx"] }); | |
const monacoJSXHighlighter = new MonacoJSXHighlighter( | |
//@ts-ignore | |
monaco, | |
babelParse, | |
traverse, | |
monacoEditor | |
); | |
monacoJSXHighlighter.highLightOnDidChangeModelContent( | |
0, | |
() => {}, | |
() => {}, | |
undefined, | |
() => {} | |
); | |
//format code | |
function formatOnSave() { | |
const unformattedCode = codeEditor.current.getModel().getValue(); | |
const lang = codeEditor.current.getModel()._languageIdentifier.language; | |
let config; | |
switch (lang) { | |
case "html": | |
config = { parser: "html", plugin: [parserHtml] }; | |
break; | |
case "css": | |
config = { parser: "css", plugin: [parserCss] }; | |
break; | |
case "javascript": | |
config = { parser: "babel", plugin: [parserBabel] }; | |
break; | |
default: | |
break; | |
} | |
const formattedCode = prettier.format(unformattedCode, { | |
parser: config && config.parser, | |
plugins: config && config.plugin, | |
useTabs: false, | |
semi: true, | |
}); | |
codeEditor.current.setValue(formattedCode); | |
} | |
//save command | |
let handleOnKeyDown = codeEditor.current.onKeyDown( | |
(event: IKeyboardEvent) => { | |
if ( | |
(window.navigator.platform.match("Mac") | |
? event.metaKey | |
: event.ctrlKey) && | |
event.code === "KeyS" | |
) { | |
event.preventDefault(); | |
formatOnSave(); | |
} | |
} | |
); | |
//cleaning up | |
return () => handleOnKeyDown.dispose(); | |
}; | |
return { onMount, onChange, code }; | |
}; | |