Created
January 3, 2024 10:35
-
-
Save zbeyens/568502cef103daf3607d02c5f7833241 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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