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(); const [input, setInput] = useState(""); 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 }; };