@mdxeditor/editor
Version:
React component for rich text markdown editing
112 lines (111 loc) • 4.09 kB
JavaScript
import { BOLD_ITALIC_STAR, BOLD_ITALIC_UNDERSCORE, BOLD_STAR, BOLD_UNDERSCORE, INLINE_CODE, ITALIC_STAR, ITALIC_UNDERSCORE, QUOTE, LINK, ORDERED_LIST, UNORDERED_LIST, CHECK_LIST, CODE } from "@lexical/markdown";
import { MarkdownShortcutPlugin } from "@lexical/react/LexicalMarkdownShortcutPlugin";
import { HeadingNode, $isHeadingNode, $createHeadingNode } from "@lexical/rich-text";
import React__default from "react";
import { realmPlugin } from "../../RealmWithPlugins.js";
import { CodeBlockNode, $createCodeBlockNode } from "../codeblock/CodeBlockNode.js";
import { activePlugins$, addNestedEditorChild$, addComposerChild$ } from "../core/index.js";
import { allowedHeadingLevels$ } from "../headings/index.js";
import { HorizontalRuleNode, $createHorizontalRuleNode, $isHorizontalRuleNode } from "@lexical/react/LexicalHorizontalRuleNode";
const markdownShortcutPlugin = realmPlugin({
init(realm) {
const pluginIds = realm.getValue(activePlugins$);
const allowedHeadingLevels = pluginIds.includes("headings") ? realm.getValue(allowedHeadingLevels$) : [];
const transformers = pickTransformersForActivePlugins(pluginIds, allowedHeadingLevels);
realm.pubIn({
[addComposerChild$]: () => /* @__PURE__ */ React__default.createElement(MarkdownShortcutPlugin, { transformers }),
[addNestedEditorChild$]: () => /* @__PURE__ */ React__default.createElement(MarkdownShortcutPlugin, { transformers })
});
}
});
const createBlockNode = (createNode) => {
return (parentNode, children, match) => {
const node = createNode(match);
node.append(...children);
parentNode.replace(node);
node.select(0, 0);
};
};
const THEMATIC_BREAK = {
dependencies: [HorizontalRuleNode],
export: (node) => {
return $isHorizontalRuleNode(node) ? "***" : null;
},
regExp: /^(---|\*\*\*|___)\s?$/,
replace: (parentNode, _1, _2, isImport) => {
const line = $createHorizontalRuleNode();
if (isImport || parentNode.getNextSibling() != null) {
parentNode.replace(line);
} else {
parentNode.insertBefore(line);
}
line.selectNext();
},
type: "element"
};
function pickTransformersForActivePlugins(pluginIds, allowedHeadingLevels) {
const transformers = [
BOLD_ITALIC_STAR,
BOLD_ITALIC_UNDERSCORE,
BOLD_STAR,
BOLD_UNDERSCORE,
INLINE_CODE,
ITALIC_STAR,
ITALIC_UNDERSCORE
// HIGHLIGHT,
// STRIKETHROUGH
];
if (pluginIds.includes("headings")) {
const minHeadingLevel = Math.min(...allowedHeadingLevels);
const maxHeadingLevel = Math.max(...allowedHeadingLevels);
const headingRegExp = new RegExp(`^(#{${minHeadingLevel},${maxHeadingLevel}})\\s`);
const HEADING = {
dependencies: [HeadingNode],
export: (node, exportChildren) => {
if (!$isHeadingNode(node)) {
return null;
}
const level = Number(node.getTag().slice(1));
return "#".repeat(level) + " " + exportChildren(node);
},
regExp: headingRegExp,
replace: createBlockNode((match) => {
const tag = `h${match[1].length}`;
return $createHeadingNode(tag);
}),
type: "element"
};
transformers.push(HEADING);
}
if (pluginIds.includes("thematicBreak")) {
transformers.push(THEMATIC_BREAK);
}
if (pluginIds.includes("quote")) {
transformers.push(QUOTE);
}
if (pluginIds.includes("link")) {
transformers.push(LINK);
}
if (pluginIds.includes("lists")) {
transformers.push(ORDERED_LIST, UNORDERED_LIST, CHECK_LIST);
}
if (pluginIds.includes("codeblock")) {
const codeTransformerCopy = {
...CODE,
dependencies: [CodeBlockNode],
replace: (parentNode, _children, match) => {
const codeBlockNode = $createCodeBlockNode({ code: "", language: match[1] ?? "", meta: "" });
parentNode.selectPrevious();
parentNode.replace(codeBlockNode);
setTimeout(() => {
codeBlockNode.select();
}, 80);
}
};
transformers.push(codeTransformerCopy);
}
return transformers;
}
export {
markdownShortcutPlugin
};