UNPKG

@blocknote/core

Version:

A "Notion-style" block-based extensible text editor built on top of Prosemirror and Tiptap.

151 lines (141 loc) 4.33 kB
import { prosemirrorToYDoc, prosemirrorToYXmlFragment, yXmlFragmentToProseMirrorRootNode, } from "y-prosemirror"; import * as Y from "yjs"; import { type Block, type BlockNoteEditor, type BlockSchema, type InlineContentSchema, type PartialBlock, type StyleSchema, blockToNode, docToBlocks, } from "../index.js"; /** * Turn Prosemirror JSON to BlockNote style JSON * @param editor BlockNote editor * @param json Prosemirror JSON * @returns BlockNote style JSON */ export function _prosemirrorJSONToBlocks< BSchema extends BlockSchema, ISchema extends InlineContentSchema, SSchema extends StyleSchema, >(editor: BlockNoteEditor<BSchema, ISchema, SSchema>, json: any) { // note: theoretically this should also be possible without creating prosemirror nodes, // but this is definitely the easiest way const doc = editor.pmSchema.nodeFromJSON(json); return docToBlocks<BSchema, ISchema, SSchema>(doc); } /** * Turn BlockNote JSON to Prosemirror node / state * @param editor BlockNote editor * @param blocks BlockNote blocks * @returns Prosemirror root node */ export function _blocksToProsemirrorNode< BSchema extends BlockSchema, ISchema extends InlineContentSchema, SSchema extends StyleSchema, >( editor: BlockNoteEditor<BSchema, ISchema, SSchema>, blocks: PartialBlock<BSchema, ISchema, SSchema>[], ) { const pmNodes = blocks.map((b) => blockToNode(b, editor.pmSchema)); const doc = editor.pmSchema.topNodeType.create( null, editor.pmSchema.nodes["blockGroup"].create(null, pmNodes), ); return doc; } /** YJS / BLOCKNOTE conversions */ /** * Turn a Y.XmlFragment collaborative doc into a BlockNote document (BlockNote style JSON of all blocks) * @param editor BlockNote editor * @param xmlFragment Y.XmlFragment * @returns BlockNote document (BlockNote style JSON of all blocks) */ export function yXmlFragmentToBlocks< BSchema extends BlockSchema, ISchema extends InlineContentSchema, SSchema extends StyleSchema, >( editor: BlockNoteEditor<BSchema, ISchema, SSchema>, xmlFragment: Y.XmlFragment, ) { const pmNode = yXmlFragmentToProseMirrorRootNode( xmlFragment, editor.pmSchema, ); return docToBlocks<BSchema, ISchema, SSchema>(pmNode); } /** * Convert blocks to a Y.XmlFragment * * This can be used when importing existing content to Y.Doc for the first time, * note that this should not be used to rehydrate a Y.Doc from a database once * collaboration has begun as all history will be lost * * @param editor BlockNote editor * @param blocks the blocks to convert * @param xmlFragment XML fragment name * @returns Y.XmlFragment */ export function blocksToYXmlFragment< BSchema extends BlockSchema, ISchema extends InlineContentSchema, SSchema extends StyleSchema, >( editor: BlockNoteEditor<BSchema, ISchema, SSchema>, blocks: Block<BSchema, ISchema, SSchema>[], xmlFragment?: Y.XmlFragment, ) { return prosemirrorToYXmlFragment( _blocksToProsemirrorNode(editor, blocks), xmlFragment, ); } /** * Turn a Y.Doc collaborative doc into a BlockNote document (BlockNote style JSON of all blocks) * @param editor BlockNote editor * @param ydoc Y.Doc * @param xmlFragment XML fragment name * @returns BlockNote document (BlockNote style JSON of all blocks) */ export function yDocToBlocks< BSchema extends BlockSchema, ISchema extends InlineContentSchema, SSchema extends StyleSchema, >( editor: BlockNoteEditor<BSchema, ISchema, SSchema>, ydoc: Y.Doc, xmlFragment = "prosemirror", ) { return yXmlFragmentToBlocks(editor, ydoc.getXmlFragment(xmlFragment)); } /** * This can be used when importing existing content to Y.Doc for the first time, * note that this should not be used to rehydrate a Y.Doc from a database once * collaboration has begun as all history will be lost * * @param editor BlockNote editor * @param blocks the blocks to convert * @param xmlFragment XML fragment name */ export function blocksToYDoc< BSchema extends BlockSchema, ISchema extends InlineContentSchema, SSchema extends StyleSchema, >( editor: BlockNoteEditor<BSchema, ISchema, SSchema>, blocks: PartialBlock<BSchema, ISchema, SSchema>[], xmlFragment = "prosemirror", ) { return prosemirrorToYDoc( _blocksToProsemirrorNode(editor, blocks), xmlFragment, ); }