@mdxeditor/editor
Version:
React component for rich text markdown editing
123 lines (122 loc) • 4.55 kB
JavaScript
import { useCellValues } from "@mdxeditor/gurx";
import React__default from "react";
import styles from "../../styles/ui.module.css.js";
import { useCodeBlockEditorContext } from "../codeblock/CodeBlockNode.js";
import { useTranslation, readOnly$, iconComponentFor$ } from "../core/index.js";
import { languages } from "@codemirror/language-data";
import { EditorState } from "@codemirror/state";
import { lineNumbers, EditorView } from "@codemirror/view";
import { basicLight } from "cm6-theme-basic-light";
import { basicSetup } from "codemirror";
import { codeMirrorExtensions$, codeMirrorAutoLoadLanguageSupport$, codeBlockLanguages$ } from "./index.js";
import { useCodeMirrorRef } from "../sandpack/useCodeMirrorRef.js";
import { Select } from "../toolbar/primitives/select.js";
const COMMON_STATE_CONFIG_EXTENSIONS = [];
const EMPTY_VALUE = "__EMPTY_VALUE__";
const CodeMirrorEditor = ({ language, nodeKey, code, focusEmitter }) => {
const t = useTranslation();
const { parentEditor, lexicalNode } = useCodeBlockEditorContext();
const [readOnly, codeMirrorExtensions, autoLoadLanguageSupport, iconComponentFor, codeBlockLanguages] = useCellValues(
readOnly$,
codeMirrorExtensions$,
codeMirrorAutoLoadLanguageSupport$,
iconComponentFor$,
codeBlockLanguages$
);
const codeMirrorRef = useCodeMirrorRef(nodeKey, "codeblock", language, focusEmitter);
const { setCode } = useCodeBlockEditorContext();
const editorViewRef = React__default.useRef(null);
const elRef = React__default.useRef(null);
const setCodeRef = React__default.useRef(setCode);
setCodeRef.current = setCode;
codeMirrorRef.current = {
getCodemirror: () => editorViewRef.current
};
React__default.useEffect(() => {
void (async () => {
const extensions = [
...codeMirrorExtensions,
basicSetup,
basicLight,
lineNumbers(),
EditorView.lineWrapping,
EditorView.updateListener.of(({ state }) => {
setCodeRef.current(state.doc.toString());
})
];
if (readOnly) {
extensions.push(EditorState.readOnly.of(true));
}
if (language !== "" && autoLoadLanguageSupport) {
const languageData = languages.find((l) => {
return l.name === language || l.alias.includes(language) || l.extensions.includes(language);
});
if (languageData) {
try {
const languageSupport = await languageData.load();
extensions.push(languageSupport.extension);
} catch (e) {
console.warn("failed to load language support for", language);
}
}
}
elRef.current.innerHTML = "";
editorViewRef.current = new EditorView({
parent: elRef.current,
state: EditorState.create({ doc: code, extensions })
});
})();
return () => {
var _a;
(_a = editorViewRef.current) == null ? void 0 : _a.destroy();
editorViewRef.current = null;
};
}, [readOnly, language]);
return /* @__PURE__ */ React__default.createElement(
"div",
{
className: styles.codeMirrorWrapper,
onKeyDown: (e) => {
e.stopPropagation();
}
},
/* @__PURE__ */ React__default.createElement("div", { className: styles.codeMirrorToolbar }, /* @__PURE__ */ React__default.createElement(
Select,
{
value: language,
onChange: (language2) => {
parentEditor.update(() => {
lexicalNode.setLanguage(language2 === EMPTY_VALUE ? "" : language2);
setTimeout(() => {
parentEditor.update(() => {
lexicalNode.getLatest().select();
});
});
});
},
triggerTitle: t("codeBlock.selectLanguage", "Select code block language"),
placeholder: t("codeBlock.inlineLanguage", "Language"),
items: Object.entries(codeBlockLanguages).map(([value, label]) => ({ value: value ? value : EMPTY_VALUE, label }))
}
), /* @__PURE__ */ React__default.createElement(
"button",
{
className: styles.iconButton,
type: "button",
title: t("codeblock.delete", "Delete code block"),
onClick: (e) => {
e.preventDefault();
parentEditor.update(() => {
lexicalNode.remove();
});
}
},
iconComponentFor("delete_small")
)),
/* @__PURE__ */ React__default.createElement("div", { ref: elRef })
);
};
export {
COMMON_STATE_CONFIG_EXTENSIONS,
CodeMirrorEditor
};