mirror of
https://github.com/khairul169/code-share.git
synced 2026-10-24 11:53:58 +07:00
feat: using codeium editor instead of codemirror
This commit is contained in:
+117
-86
@@ -1,27 +1,17 @@
|
||||
/* eslint-disable react/display-name */
|
||||
import ReactCodeMirror, {
|
||||
EditorView,
|
||||
ReactCodeMirrorRef,
|
||||
keymap,
|
||||
} from "@uiw/react-codemirror";
|
||||
import { javascript } from "@codemirror/lang-javascript";
|
||||
import { css } from "@codemirror/lang-css";
|
||||
import { html } from "@codemirror/lang-html";
|
||||
import { json } from "@codemirror/lang-json";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { tokyoNight } from "@uiw/codemirror-theme-tokyo-night";
|
||||
import { vscodeKeymap } from "@replit/codemirror-vscode-keymap";
|
||||
import { CodeiumEditor } from "@codeium/react-code-editor/dist/esm";
|
||||
import prettier from "prettier/standalone";
|
||||
import prettierHtmlPlugin from "prettier/plugins/html";
|
||||
import prettierCssPlugin from "prettier/plugins/postcss";
|
||||
import prettierBabelPlugin from "prettier/plugins/babel";
|
||||
import * as prettierPluginEstree from "prettier/plugins/estree";
|
||||
import { abbreviationTracker } from "@emmetio/codemirror6-plugin";
|
||||
import { useDebounce } from "~/hooks/useDebounce";
|
||||
import useCommandKey from "~/hooks/useCommandKey";
|
||||
import { getFileExt } from "~/lib/utils";
|
||||
|
||||
type Props = {
|
||||
lang?: string;
|
||||
filename?: string;
|
||||
path?: string;
|
||||
value: string;
|
||||
wordWrap?: boolean;
|
||||
onChange: (val: string) => void;
|
||||
@@ -29,114 +19,155 @@ type Props = {
|
||||
};
|
||||
|
||||
const CodeEditor = (props: Props) => {
|
||||
const codeMirror = useRef<ReactCodeMirrorRef>(null);
|
||||
const { lang, value, formatOnSave, wordWrap, onChange } = props;
|
||||
const { filename, path, value, formatOnSave, wordWrap, onChange } = props;
|
||||
const editorRef = useRef<any>(null);
|
||||
const [data, setData] = useState(value);
|
||||
const [debounceChange, resetDebounceChange] = useDebounce(onChange, 3000);
|
||||
const langMetadata = useMemo(() => getLangMetadata(lang || "plain"), [lang]);
|
||||
const language = useMemo(() => getLanguage(filename), [filename]);
|
||||
|
||||
const onSave = useCallback(async () => {
|
||||
const editor = editorRef.current;
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const model = editor.getModel();
|
||||
const content = model.getValue();
|
||||
|
||||
const formatter = language.formatter;
|
||||
if (!formatOnSave || !formatter) {
|
||||
return onChange(content);
|
||||
}
|
||||
|
||||
try {
|
||||
const cm = codeMirror.current?.view;
|
||||
const content = cm ? cm.state.doc.toString() : data;
|
||||
const formatter = langMetadata.formatter;
|
||||
const [parser, ...plugins] = formatter;
|
||||
|
||||
if (formatOnSave && cm && formatter != null) {
|
||||
const [parser, ...plugins] = formatter;
|
||||
const cursor = cm.state.selection.main.head || 0;
|
||||
const { formatted, cursorOffset } = await prettier.formatWithCursor(
|
||||
content,
|
||||
{
|
||||
parser,
|
||||
plugins,
|
||||
cursorOffset: cursor,
|
||||
printWidth: 64,
|
||||
}
|
||||
);
|
||||
|
||||
setData(formatted);
|
||||
onChange(formatted);
|
||||
|
||||
if (cm) {
|
||||
cm.dispatch({
|
||||
changes: { from: 0, to: cm?.state.doc.length, insert: formatted },
|
||||
});
|
||||
cm.dispatch({
|
||||
selection: { anchor: cursorOffset },
|
||||
});
|
||||
const cursor = model.getOffsetAt(editor.getPosition());
|
||||
const { formatted, cursorOffset } = await prettier.formatWithCursor(
|
||||
content,
|
||||
{
|
||||
parser,
|
||||
plugins,
|
||||
cursorOffset: cursor || 0,
|
||||
printWidth: 64,
|
||||
}
|
||||
} else {
|
||||
onChange(content);
|
||||
}
|
||||
);
|
||||
|
||||
model.setValue(formatted);
|
||||
const newCursor = model.getPositionAt(cursorOffset);
|
||||
editor.setPosition(newCursor);
|
||||
console.log("huhu set cursor");
|
||||
|
||||
onChange(formatted);
|
||||
} catch (err) {
|
||||
console.log("prettier error", err);
|
||||
onChange(content);
|
||||
}
|
||||
|
||||
setTimeout(() => resetDebounceChange(), 100);
|
||||
}, [
|
||||
data,
|
||||
langMetadata.formatter,
|
||||
formatOnSave,
|
||||
onChange,
|
||||
resetDebounceChange,
|
||||
]);
|
||||
|
||||
useCommandKey("s", onSave);
|
||||
}, [language.formatter, formatOnSave, onChange, resetDebounceChange]);
|
||||
|
||||
useEffect(() => {
|
||||
setData(value);
|
||||
}, [value]);
|
||||
|
||||
const extensions = [...langMetadata.extensions, keymap.of(vscodeKeymap)];
|
||||
if (wordWrap) {
|
||||
extensions.push(EditorView.lineWrapping);
|
||||
}
|
||||
useCommandKey("s", onSave);
|
||||
|
||||
return (
|
||||
<ReactCodeMirror
|
||||
ref={codeMirror}
|
||||
extensions={extensions}
|
||||
indentWithTab={false}
|
||||
basicSetup={{ defaultKeymap: false }}
|
||||
value={data}
|
||||
onChange={(val) => {
|
||||
setData(val);
|
||||
debounceChange(val);
|
||||
}}
|
||||
height="100%"
|
||||
theme={tokyoNight}
|
||||
/>
|
||||
<div className="w-full h-full code-editor">
|
||||
<CodeiumEditor
|
||||
language={language.name}
|
||||
theme="vs-dark"
|
||||
path={path || filename}
|
||||
value={data}
|
||||
height="100%"
|
||||
onMount={(editor: any, _monaco: any) => {
|
||||
editorRef.current = editor;
|
||||
}}
|
||||
onChange={(e: string) => debounceChange(e)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
function getLangMetadata(lang: string) {
|
||||
let extensions: any[] = [];
|
||||
// generate this as enum of languages
|
||||
enum Languages {
|
||||
Abap = "abap",
|
||||
Apex = "apex",
|
||||
Azcli = "azcli",
|
||||
Bat = "bat",
|
||||
C = "c",
|
||||
Clojure = "clojure",
|
||||
Coffeescript = "coffeescript",
|
||||
Cpp = "cpp",
|
||||
Csharp = "csharp",
|
||||
Csp = "csp",
|
||||
Css = "css",
|
||||
Dockerfile = "dockerfile",
|
||||
Fsharp = "fsharp",
|
||||
Go = "go",
|
||||
Graphql = "graphql",
|
||||
Handlebars = "handlebars",
|
||||
Html = "html",
|
||||
Ini = "ini",
|
||||
Java = "java",
|
||||
Javascript = "javascript",
|
||||
Json = "json",
|
||||
Less = "less",
|
||||
Lua = "lua",
|
||||
Markdown = "markdown",
|
||||
M3 = "m3",
|
||||
Msdax = "msdax",
|
||||
Mysql = "mysql",
|
||||
Objective = "objective",
|
||||
Pgsql = "pgsql",
|
||||
Php = "php",
|
||||
Postiats = "postiats",
|
||||
Powershell = "powershell",
|
||||
Pug = "pug",
|
||||
Python = "python",
|
||||
R = "r",
|
||||
Razor = "razor",
|
||||
Redis = "redis",
|
||||
Redshift = "redshift",
|
||||
Ruby = "ruby",
|
||||
Sb = "sb",
|
||||
Scss = "scss",
|
||||
Shell = "shell",
|
||||
Solidity = "solidity",
|
||||
Sql = "sql",
|
||||
Swift = "swift",
|
||||
Typescript = "typescript",
|
||||
Vb = "vb",
|
||||
Xml = "xml",
|
||||
Yaml = "yaml",
|
||||
Common = "common",
|
||||
}
|
||||
|
||||
function getLanguage(filename?: string | null) {
|
||||
const ext = getFileExt(filename || "");
|
||||
let name: Languages = Languages.Common;
|
||||
let formatter: any = null;
|
||||
|
||||
switch (lang) {
|
||||
switch (ext) {
|
||||
case "html":
|
||||
extensions = [html({ selfClosingTags: true }), abbreviationTracker()];
|
||||
name = Languages.Html;
|
||||
formatter = ["html", prettierHtmlPlugin];
|
||||
break;
|
||||
case "css":
|
||||
extensions = [css()];
|
||||
name = Languages.Css;
|
||||
formatter = ["css", prettierCssPlugin];
|
||||
break;
|
||||
case "json":
|
||||
extensions = [json()];
|
||||
name = Languages.Json;
|
||||
formatter = ["json", prettierBabelPlugin, prettierPluginEstree];
|
||||
break;
|
||||
case "jsx":
|
||||
case "js":
|
||||
case "ts":
|
||||
case "tsx":
|
||||
const isTypescript = ["tsx", "ts"].includes(lang);
|
||||
extensions = [
|
||||
javascript({
|
||||
jsx: ["jsx", "tsx"].includes(lang),
|
||||
typescript: isTypescript,
|
||||
}),
|
||||
];
|
||||
const isTypescript = ["tsx", "ts"].includes(ext);
|
||||
name = isTypescript ? Languages.Typescript : Languages.Javascript;
|
||||
formatter = [
|
||||
isTypescript ? "babel-ts" : "babel",
|
||||
prettierBabelPlugin,
|
||||
@@ -145,7 +176,7 @@ function getLangMetadata(lang: string) {
|
||||
break;
|
||||
}
|
||||
|
||||
return { extensions, formatter };
|
||||
return { name, formatter };
|
||||
}
|
||||
|
||||
export default CodeEditor;
|
||||
|
||||
Reference in New Issue
Block a user