@churchapps/apphelper-markdown
Version:
ChurchApps markdown/lexical editor components
106 lines (95 loc) • 3.21 kB
text/typescript
import type { ElementTransformer, Transformer } from "@lexical/markdown";
import type { LexicalNode, TextFormatType } from "lexical";
import {
ELEMENT_TRANSFORMERS,
TRANSFORMERS
} from "@lexical/markdown";
import {
$createHorizontalRuleNode,
$isHorizontalRuleNode,
HorizontalRuleNode
} from "@lexical/react/LexicalHorizontalRuleNode";
import { CUSTOM_LINK_NODE_TRANSFORMER } from "./customLink/CustomLinkNodeTransformer";
import { EMOJI_NODE_MARKDOWN_TRANSFORM } from "./emoji/EmojiNodeTransform";
export const HR: ElementTransformer = {
dependencies: [HorizontalRuleNode],
export: (node: LexicalNode) => ($isHorizontalRuleNode(node) ? "***" : null),
regExp: /^(---|\*\*\*|___)\s?$/,
replace: (parentNode, _1, _2, isImport) => {
const line = $createHorizontalRuleNode();
// TODO: Get rid of isImport flag
if (isImport || parentNode.getNextSibling() != null) {
parentNode.replace(line);
} else {
parentNode.insertBefore(line);
}
line.selectNext();
},
type: "element"
};
export type TextFormatTransformer = Readonly<{
format: ReadonlyArray<TextFormatType>;
tag: string;
intraword?: boolean;
type: "text-format";
}>;
/*
export type TextMatchTransformer = Readonly<{
dependencies: Array<Klass<LexicalNode>>;
export: (
node: LexicalNode,
// eslint-disable-next-line no-shadow
exportChildren: (node: ElementNode) => string,
// eslint-disable-next-line no-shadow
exportFormat: (node: TextNode, textContent: string) => string,
) => string | null;
importRegExp: RegExp;
regExp: RegExp;
replace: (node: TextNode, match: RegExpMatchArray) => void;
trigger: string;
type: 'text-match';
}>;
*/
export const UNDERLINE: TextFormatTransformer = {
format: ["underline"],
intraword: false,
tag: "__",
type: "text-format"
};
/*
export const UNDERLINE: TextMatchTransformer = {
dependencies: [],
export: (node, exportChildren, exportFormat) => {
const linkContent = `[${node.getTextContent()}](${node.getURL()})`;
const firstChild = node.getFirstChild();
// Add text styles only if link has single text node inside. If it's more
// then one we ignore it as markdown does not support nested styles for links
if (node.getChildrenSize() === 1 && $isTextNode(firstChild)) {
return exportFormat(firstChild, linkContent);
} else {
return linkContent;
}
},
importRegExp: /(?:\[([^[]+)\])(?:\(([^()]+)\))/,
regExp: /(?:\[([^[]+)\])(?:\(([^()]+)\))$/,
replace: (textNode, match) => {
const [, linkText, linkUrl] = match;
const linkNode = $createLinkNode(linkUrl);
const linkTextNode = $createTextNode(linkText);
linkTextNode.setFormat(textNode.getFormat());
linkNode.append(linkTextNode);
textNode.replace(linkNode);
},
trigger: ')',
type: 'text-match',
};
*/
const modifiedTextTransformers = [EMOJI_NODE_MARKDOWN_TRANSFORM];
export const PLAYGROUND_TRANSFORMERS: Array<Transformer> = [
...modifiedTextTransformers,
HR,
...ELEMENT_TRANSFORMERS,
CUSTOM_LINK_NODE_TRANSFORMER,
...TRANSFORMERS.splice(0, 13),
UNDERLINE,
];