Skip to content

Instantly share code, notes, and snippets.

@zbeyens
Created January 3, 2024 10:35
Show Gist options
  • Save zbeyens/568502cef103daf3607d02c5f7833241 to your computer and use it in GitHub Desktop.
Save zbeyens/568502cef103daf3607d02c5f7833241 to your computer and use it in GitHub Desktop.
import {
getPluginType,
type PlatePlugin,
type TDescendant,
type TElement,
type TText,
} from '@udecode/plate-common';
import {
remarkTransformElementChildren,
type DeserializeMdPlugin,
type MdastNode,
} from '@udecode/plate-serializer-md';
import { slateTypes } from '@/lib/plate/slate-types';
export const deserializeMdPlugin: Partial<PlatePlugin<DeserializeMdPlugin>> = {
options: {
elementRules: {
heading: {
transform: (node, options) => {
const headingType = {
1: slateTypes.h1,
2: slateTypes.h2,
3: slateTypes.h3,
4: slateTypes.h4,
5: slateTypes.h5,
6: slateTypes.h6,
}[node.depth ?? 1];
return {
type: getPluginType(options.editor, headingType),
children: remarkTransformElementChildren(node, options),
};
},
},
list: {
transform: (node, options) => {
const listStyleType = node.ordered ? 'decimal' : 'disc';
const parseListItems = (
node: MdastNode,
listItems: TElement[] = [],
indent = 1
) => {
node.children!.forEach((listItem) => {
const [paragraph, ...subLists] = listItem.children!;
listItems.push({
type: getPluginType(options.editor, slateTypes.p),
listStyleType,
indent,
children: remarkTransformElementChildren(paragraph, options),
});
subLists.forEach((subList) => {
parseListItems(subList, listItems, indent + 1);
});
});
return listItems;
};
return parseListItems(node);
},
},
paragraph: {
transform: (node, options) => {
const children = remarkTransformElementChildren(node, options);
const paragraphType = getPluginType(options.editor, slateTypes.p);
const splitBlockTypes = new Set([
getPluginType(options.editor, 'img'),
]);
const elements: TElement[] = [];
let inlineNodes: TDescendant[] = [];
const flushInlineNodes = () => {
if (inlineNodes.length > 0) {
elements.push({
type: paragraphType,
children: inlineNodes,
});
inlineNodes = [];
}
};
children.forEach((child) => {
const { type } = child;
if (type && splitBlockTypes.has(type as string)) {
flushInlineNodes();
elements.push(child as TElement);
} else {
inlineNodes.push(child);
}
});
flushInlineNodes();
return elements;
},
},
link: {
transform: (node, options) => ({
type: getPluginType(options.editor, slateTypes.link),
url: node.url,
children: remarkTransformElementChildren(node, options),
}),
},
// image: {
// transform: (node, options) => ({
// type: getPluginType(options.editor, slateTypes.img),
// children: [{ text: '' } as TText],
// url: node.url,
// caption: [{ text: node.alt } as TText],
// }),
// },
blockquote: {
transform: (node, options) => {
return {
type: getPluginType(options.editor, slateTypes.blockquote),
children: node.children!.flatMap((paragraph) =>
remarkTransformElementChildren(paragraph, options)
),
};
},
},
code: {
transform: (node, options) => ({
type: getPluginType(options.editor, slateTypes.code_block),
lang: node.lang ?? undefined,
children: (node.value || '').split('\n').map((line) => ({
type: getPluginType(options.editor, slateTypes.code_line),
children: [{ text: line } as TText],
})),
}),
},
thematicBreak: {
transform: (node, options) => ({
type: getPluginType(options.editor, slateTypes.hr),
children: [{ text: '' } as TText],
}),
},
},
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment