|
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" |
|
); |
|
|
|
|
|
const babelParse = (code: any) => |
|
parse(code, { sourceType: "module", plugins: ["jsx"] }); |
|
|
|
const monacoJSXHighlighter = new MonacoJSXHighlighter( |
|
|
|
monaco, |
|
babelParse, |
|
traverse, |
|
monacoEditor |
|
); |
|
|
|
monacoJSXHighlighter.highLightOnDidChangeModelContent( |
|
0, |
|
() => {}, |
|
() => {}, |
|
undefined, |
|
() => {} |
|
); |
|
|
|
|
|
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); |
|
} |
|
|
|
|
|
let handleOnKeyDown = codeEditor.current.onKeyDown( |
|
(event: IKeyboardEvent) => { |
|
if ( |
|
(window.navigator.platform.match("Mac") |
|
? event.metaKey |
|
: event.ctrlKey) && |
|
event.code === "KeyS" |
|
) { |
|
event.preventDefault(); |
|
formatOnSave(); |
|
} |
|
} |
|
); |
|
|
|
|
|
return () => handleOnKeyDown.dispose(); |
|
}; |
|
|
|
return { onMount, onChange, code }; |
|
}; |
|
|