@blocknote/core 0.44.1 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BlockNoteExtension-BWw0r8Gy.cjs.map +1 -1
- package/dist/BlockNoteExtension-C2X7LW-V.js.map +1 -1
- package/dist/{BlockNoteSchema-C-l154WP.js → BlockNoteSchema-BOW16JHv.js} +2 -2
- package/dist/{BlockNoteSchema-C-l154WP.js.map → BlockNoteSchema-BOW16JHv.js.map} +1 -1
- package/dist/{BlockNoteSchema-B4gm-Qco.cjs → BlockNoteSchema-CzZbr4Ed.cjs} +2 -2
- package/dist/{BlockNoteSchema-B4gm-Qco.cjs.map → BlockNoteSchema-CzZbr4Ed.cjs.map} +1 -1
- package/dist/{TrailingNode-B_zPMWxw.js → TrailingNode-8cXFaQUm.js} +484 -487
- package/dist/TrailingNode-8cXFaQUm.js.map +1 -0
- package/dist/TrailingNode-DPu6X9ym.cjs +2 -0
- package/dist/TrailingNode-DPu6X9ym.cjs.map +1 -0
- package/dist/{blockToNode-DBNbhwwC.js → blockToNode-BNoNIXU7.js} +2 -2
- package/dist/{blockToNode-DBNbhwwC.js.map → blockToNode-BNoNIXU7.js.map} +1 -1
- package/dist/{blockToNode-w7H99R6p.cjs → blockToNode-CumVjgem.cjs} +2 -2
- package/dist/{blockToNode-w7H99R6p.cjs.map → blockToNode-CumVjgem.cjs.map} +1 -1
- package/dist/blocknote.cjs +4 -4
- package/dist/blocknote.cjs.map +1 -1
- package/dist/blocknote.js +1180 -1128
- package/dist/blocknote.js.map +1 -1
- package/dist/blocks.cjs +1 -1
- package/dist/blocks.js +2 -2
- package/dist/defaultBlocks-D1cc0lV9.cjs +6 -0
- package/dist/defaultBlocks-D1cc0lV9.cjs.map +1 -0
- package/dist/{defaultBlocks-DgA_mtQV.js → defaultBlocks-DvCGYzqu.js} +164 -202
- package/dist/defaultBlocks-DvCGYzqu.js.map +1 -0
- package/dist/extensions.cjs +1 -1
- package/dist/extensions.js +3 -3
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/webpack-stats.json +1 -1
- package/dist/yjs.cjs +1 -1
- package/dist/yjs.js +1 -1
- package/package.json +15 -15
- package/src/api/blockManipulation/selections/selection.ts +9 -4
- package/src/api/blockManipulation/tables/tables.test.ts +140 -0
- package/src/api/blockManipulation/tables/tables.ts +1 -1
- package/src/api/clipboard/fromClipboard/handleFileInsertion.ts +1 -1
- package/src/api/parsers/markdown/parseMarkdown.ts +11 -0
- package/src/blocks/ListItem/CheckListItem/block.ts +2 -2
- package/src/editor/BlockNoteEditor.test.ts +60 -1
- package/src/editor/BlockNoteEditor.ts +22 -35
- package/src/editor/BlockNoteExtension.ts +5 -0
- package/src/editor/managers/EventManager.ts +1 -1
- package/src/editor/managers/ExtensionManager/extensions.ts +2 -12
- package/src/editor/managers/ExtensionManager/index.ts +7 -2
- package/src/editor/managers/SelectionManager.ts +10 -10
- package/src/extensions/BlockChange/BlockChange.ts +2 -2
- package/src/extensions/Collaboration/Collaboration.ts +55 -0
- package/src/extensions/Collaboration/ForkYDoc.ts +4 -9
- package/src/extensions/Collaboration/YCursorPlugin.ts +56 -60
- package/src/extensions/Collaboration/YSync.ts +2 -2
- package/src/extensions/Collaboration/YUndo.ts +2 -2
- package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +40 -68
- package/src/extensions/TableHandles/TableHandles.ts +9 -5
- package/src/index.ts +2 -1
- package/src/schema/blocks/createSpec.ts +3 -0
- package/src/util/expandToWords.ts +38 -0
- package/types/src/api/blockManipulation/selections/selection.d.ts +1 -1
- package/types/src/editor/BlockNoteEditor.d.ts +12 -32
- package/types/src/editor/BlockNoteExtension.d.ts +4 -0
- package/types/src/editor/managers/SelectionManager.d.ts +4 -4
- package/types/src/extensions/Collaboration/Collaboration.d.ts +76 -0
- package/types/src/extensions/Collaboration/ForkYDoc.d.ts +2 -11
- package/types/src/extensions/Collaboration/YCursorPlugin.d.ts +3 -11
- package/types/src/extensions/Collaboration/YSync.d.ts +2 -4
- package/types/src/extensions/Collaboration/YUndo.d.ts +1 -1
- package/types/src/index.d.ts +2 -1
- package/types/src/util/expandToWords.d.ts +13 -0
- package/dist/TrailingNode-B_zPMWxw.js.map +0 -1
- package/dist/TrailingNode-CRHrgOnK.cjs +0 -2
- package/dist/TrailingNode-CRHrgOnK.cjs.map +0 -1
- package/dist/defaultBlocks-DLJ4Q1_J.cjs +0 -6
- package/dist/defaultBlocks-DLJ4Q1_J.cjs.map +0 -1
- package/dist/defaultBlocks-DgA_mtQV.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blockToNode-w7H99R6p.cjs","sources":["../src/extensions/tiptap-extensions/UniqueID/UniqueID.ts","../src/schema/inlineContent/types.ts","../src/util/table.ts","../src/util/typescript.ts","../src/api/getBlockInfoFromPos.ts","../src/api/pmUtil.ts","../src/api/nodeConversions/nodeToBlock.ts","../src/api/blockManipulation/tables/tables.ts","../src/api/nodeConversions/blockToNode.ts"],"sourcesContent":["import {\n combineTransactionSteps,\n Extension,\n findChildrenInRange,\n getChangedRanges,\n} from \"@tiptap/core\";\nimport { Fragment, Slice } from \"prosemirror-model\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\nimport { v4 } from \"uuid\";\n\n/**\n * Code from Tiptap UniqueID extension (https://tiptap.dev/api/extensions/unique-id)\n * This extension is licensed under MIT (even though it's part of Tiptap pro).\n *\n * If you're a user of BlockNote, we still recommend to support their awesome work and become a sponsor!\n * https://tiptap.dev/pro\n */\n\n/**\n * Removes duplicated values within an array.\n * Supports numbers, strings and objects.\n */\nfunction removeDuplicates(array: any, by = JSON.stringify) {\n const seen: any = {};\n return array.filter((item: any) => {\n const key = by(item);\n return Object.prototype.hasOwnProperty.call(seen, key)\n ? false\n : (seen[key] = true);\n });\n}\n\n/**\n * Returns a list of duplicated items within an array.\n */\nfunction findDuplicates(items: any) {\n const filtered = items.filter(\n (el: any, index: number) => items.indexOf(el) !== index,\n );\n const duplicates = removeDuplicates(filtered);\n return duplicates;\n}\n\nconst UniqueID = Extension.create({\n name: \"uniqueID\",\n // we’ll set a very high priority to make sure this runs first\n // and is compatible with `appendTransaction` hooks of other extensions\n priority: 10000,\n addOptions() {\n return {\n attributeName: \"id\",\n types: [],\n setIdAttribute: false,\n generateID: () => {\n // Use mock ID if tests are running.\n if (typeof window !== \"undefined\" && (window as any).__TEST_OPTIONS) {\n const testOptions = (window as any).__TEST_OPTIONS;\n if (testOptions.mockID === undefined) {\n testOptions.mockID = 0;\n } else {\n testOptions.mockID++;\n }\n\n return testOptions.mockID.toString() as string;\n }\n\n return v4();\n },\n filterTransaction: null,\n };\n },\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n [this.options.attributeName]: {\n default: null,\n parseHTML: (element) =>\n element.getAttribute(`data-${this.options.attributeName}`),\n renderHTML: (attributes) => {\n const defaultIdAttributes = {\n [`data-${this.options.attributeName}`]:\n attributes[this.options.attributeName],\n };\n if (this.options.setIdAttribute) {\n return {\n ...defaultIdAttributes,\n id: attributes[this.options.attributeName],\n };\n } else {\n return defaultIdAttributes;\n }\n },\n },\n },\n },\n ];\n },\n // check initial content for missing ids\n // onCreate() {\n // // Don’t do this when the collaboration extension is active\n // // because this may update the content, so Y.js tries to merge these changes.\n // // This leads to empty block nodes.\n // // See: https://github.com/ueberdosis/tiptap/issues/2400\n // if (\n // this.editor.extensionManager.extensions.find(\n // (extension) => extension.name === \"collaboration\"\n // )\n // ) {\n // return;\n // }\n // const { view, state } = this.editor;\n // const { tr, doc } = state;\n // const { types, attributeName, generateID } = this.options;\n // const nodesWithoutId = findChildren(doc, (node) => {\n // return (\n // types.includes(node.type.name) && node.attrs[attributeName] === null\n // );\n // });\n // nodesWithoutId.forEach(({ node, pos }) => {\n // tr.setNodeMarkup(pos, undefined, {\n // ...node.attrs,\n // [attributeName]: generateID(),\n // });\n // });\n // tr.setMeta(\"addToHistory\", false);\n // view.dispatch(tr);\n // },\n addProseMirrorPlugins() {\n let dragSourceElement: any = null;\n let transformPasted = false;\n return [\n new Plugin({\n key: new PluginKey(\"uniqueID\"),\n appendTransaction: (transactions, oldState, newState) => {\n const docChanges =\n transactions.some((transaction) => transaction.docChanged) &&\n !oldState.doc.eq(newState.doc);\n const filterTransactions =\n this.options.filterTransaction &&\n transactions.some((tr) => !this.options.filterTransaction?.(tr));\n if (!docChanges || filterTransactions) {\n return;\n }\n const { tr } = newState;\n const { types, attributeName, generateID } = this.options;\n const transform = combineTransactionSteps(\n oldState.doc,\n transactions as any,\n );\n const { mapping } = transform;\n // get changed ranges based on the old state\n const changes = getChangedRanges(transform);\n\n changes.forEach(({ newRange }) => {\n const newNodes = findChildrenInRange(\n newState.doc,\n newRange,\n (node) => {\n return types.includes(node.type.name);\n },\n );\n const newIds = newNodes\n .map(({ node }) => node.attrs[attributeName])\n .filter((id) => id !== null);\n const duplicatedNewIds = findDuplicates(newIds);\n\n newNodes.forEach(({ node, pos }) => {\n // instead of checking `node.attrs[attributeName]` directly\n // we look at the current state of the node within `tr.doc`.\n // this helps to prevent adding new ids to the same node\n // if the node changed multiple times within one transaction\n const id = tr.doc.nodeAt(pos)?.attrs[attributeName];\n\n if (id === null) {\n // edge case, when using collaboration, yjs will set the id to null in `_forceRerender`\n // when loading the editor\n // this checks for this case and keeps it at initialBlockId so there will be no change\n const initialDoc = oldState.doc.type.createAndFill()!.content;\n const wasInitial =\n oldState.doc.content.findDiffStart(initialDoc) === null;\n\n if (wasInitial) {\n // the old state was the \"initial content\"\n const jsonNode = JSON.parse(\n JSON.stringify(newState.doc.toJSON()),\n );\n jsonNode.content[0].content[0].attrs.id = \"initialBlockId\";\n // would the new state with the fix also be the \"initial content\"?\n if (\n JSON.stringify(jsonNode.content) ===\n JSON.stringify(initialDoc.toJSON())\n ) {\n // yes, apply the fix\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: \"initialBlockId\",\n });\n return;\n }\n }\n\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n });\n return;\n }\n // check if the node doesn’t exist in the old state\n const { deleted } = mapping.invert().mapResult(pos);\n const newNode = deleted && duplicatedNewIds.includes(id);\n if (newNode) {\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n });\n }\n });\n });\n if (!tr.steps.length) {\n return;\n }\n // mark the transaction as having been processed by the uniqueID plugin\n tr.setMeta(\"uniqueID\", true);\n return tr;\n },\n // we register a global drag handler to track the current drag source element\n view(view) {\n const handleDragstart = (event: any) => {\n let _a;\n dragSourceElement = (\n (_a = view.dom.parentElement) === null || _a === void 0\n ? void 0\n : _a.contains(event.target)\n )\n ? view.dom.parentElement\n : null;\n };\n window.addEventListener(\"dragstart\", handleDragstart);\n return {\n destroy() {\n window.removeEventListener(\"dragstart\", handleDragstart);\n },\n };\n },\n props: {\n // `handleDOMEvents` is called before `transformPasted` so we can do\n // some checks before. However, `transformPasted` only runs when\n // editor content is pasted - not external content.\n handleDOMEvents: {\n // only create new ids for dropped content while holding `alt`\n // or content is dragged from another editor\n drop: (view, event: any) => {\n let _a;\n if (\n dragSourceElement !== view.dom.parentElement ||\n ((_a = event.dataTransfer) === null || _a === void 0\n ? void 0\n : _a.effectAllowed) === \"copy\"\n ) {\n transformPasted = true;\n } else {\n transformPasted = false;\n }\n\n dragSourceElement = null;\n\n return false;\n },\n // always create new ids on pasted content\n paste: () => {\n transformPasted = true;\n return false;\n },\n },\n // we’ll remove ids for every pasted node\n // so we can create a new one within `appendTransaction`\n transformPasted: (slice) => {\n if (!transformPasted) {\n return slice;\n }\n const { types, attributeName } = this.options;\n const removeId = (fragment: any) => {\n const list: any[] = [];\n fragment.forEach((node: any) => {\n // don’t touch text nodes\n if (node.isText) {\n list.push(node);\n return;\n }\n // check for any other child nodes\n if (!types.includes(node.type.name)) {\n list.push(node.copy(removeId(node.content)));\n return;\n }\n // remove id\n const nodeWithoutId = node.type.create(\n {\n ...node.attrs,\n [attributeName]: null,\n },\n removeId(node.content),\n node.marks,\n );\n list.push(nodeWithoutId);\n });\n return Fragment.from(list);\n };\n // reset check\n transformPasted = false;\n return new Slice(\n removeId(slice.content),\n slice.openStart,\n slice.openEnd,\n );\n },\n },\n }),\n ];\n },\n});\n\nexport { UniqueID as default, UniqueID };\n","import { Node } from \"@tiptap/core\";\nimport { PropSchema, Props } from \"../propTypes.js\";\nimport { StyleSchema, Styles } from \"../styles/types.js\";\nimport { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { ViewMutationRecord } from \"prosemirror-view\";\n\nexport type CustomInlineContentConfig = {\n type: string;\n content: \"styled\" | \"none\"; // | \"plain\"\n readonly propSchema: PropSchema;\n};\n// InlineContentConfig contains the \"schema\" info about an InlineContent type\n// i.e. what props it supports, what content it supports, etc.\nexport type InlineContentConfig = CustomInlineContentConfig | \"text\" | \"link\";\n\n// InlineContentImplementation contains the \"implementation\" info about an InlineContent element\n// such as the functions / Nodes required to render and / or serialize it\n// @ts-ignore\nexport type InlineContentImplementation<T extends InlineContentConfig> =\n T extends \"link\" | \"text\"\n ? undefined\n : {\n meta?: {\n draggable?: boolean;\n };\n node: Node;\n toExternalHTML?: (\n inlineContent: any,\n editor: BlockNoteEditor<any, any, any>,\n ) =>\n | {\n dom: HTMLElement | DocumentFragment;\n contentDOM?: HTMLElement;\n }\n | undefined;\n render: (\n inlineContent: any,\n updateInlineContent: (update: any) => void,\n editor: BlockNoteEditor<any, any, any>,\n ) => {\n dom: HTMLElement | DocumentFragment;\n contentDOM?: HTMLElement;\n ignoreMutation?: (mutation: ViewMutationRecord) => boolean;\n destroy?: () => void;\n };\n runsBefore?: string[];\n };\n\nexport type InlineContentSchemaWithInlineContent<\n IType extends string,\n C extends InlineContentConfig,\n> = {\n [k in IType]: C;\n};\n\n// Container for both the config and implementation of InlineContent,\n// and the type of `implementation` is based on that of the config\nexport type InlineContentSpec<T extends InlineContentConfig> = {\n config: T;\n implementation: InlineContentImplementation<T>;\n};\n\n// A Schema contains all the types (Configs) supported in an editor\n// The keys are the \"type\" of InlineContent elements\nexport type InlineContentSchema = Record<string, InlineContentConfig>;\n\nexport type InlineContentSpecs = {\n text: { config: \"text\"; implementation: undefined };\n link: { config: \"link\"; implementation: undefined };\n} & Record<string, InlineContentSpec<InlineContentConfig>>;\n\nexport type InlineContentSchemaFromSpecs<T extends InlineContentSpecs> = {\n [K in keyof T]: T[K][\"config\"];\n};\n\nexport type CustomInlineContentFromConfig<\n I extends CustomInlineContentConfig,\n S extends StyleSchema,\n> = {\n type: I[\"type\"];\n props: Props<I[\"propSchema\"]>;\n content: I[\"content\"] extends \"styled\"\n ? StyledText<S>[]\n : I[\"content\"] extends \"plain\"\n ? string\n : I[\"content\"] extends \"none\"\n ? undefined\n : never;\n};\n\nexport type InlineContentFromConfig<\n I extends InlineContentConfig,\n S extends StyleSchema,\n> = I extends \"text\"\n ? StyledText<S>\n : I extends \"link\"\n ? Link<S>\n : I extends CustomInlineContentConfig\n ? CustomInlineContentFromConfig<I, S>\n : never;\n\nexport type PartialCustomInlineContentFromConfig<\n I extends CustomInlineContentConfig,\n S extends StyleSchema,\n> = {\n type: I[\"type\"];\n props?: Props<I[\"propSchema\"]>;\n content?: I[\"content\"] extends \"styled\"\n ? StyledText<S>[] | string\n : I[\"content\"] extends \"plain\"\n ? string\n : I[\"content\"] extends \"none\"\n ? undefined\n : never;\n};\n\nexport type PartialInlineContentFromConfig<\n I extends InlineContentConfig,\n S extends StyleSchema,\n> = I extends \"text\"\n ? string | StyledText<S>\n : I extends \"link\"\n ? PartialLink<S>\n : I extends CustomInlineContentConfig\n ? PartialCustomInlineContentFromConfig<I, S>\n : never;\n\nexport type StyledText<T extends StyleSchema> = {\n type: \"text\";\n text: string;\n styles: Styles<T>;\n};\n\nexport type Link<T extends StyleSchema> = {\n type: \"link\";\n href: string;\n content: StyledText<T>[];\n};\n\nexport type PartialLink<T extends StyleSchema> = Omit<Link<T>, \"content\"> & {\n content: string | Link<T>[\"content\"];\n};\n\nexport type InlineContent<\n I extends InlineContentSchema,\n T extends StyleSchema,\n> = InlineContentFromConfig<I[keyof I], T>;\n\ntype PartialInlineContentElement<\n I extends InlineContentSchema,\n T extends StyleSchema,\n> = PartialInlineContentFromConfig<I[keyof I], T>;\n\nexport type PartialInlineContent<\n I extends InlineContentSchema,\n T extends StyleSchema,\n> = PartialInlineContentElement<I, T>[] | string;\n\nexport function isLinkInlineContent<T extends StyleSchema>(\n content: InlineContent<any, T>,\n): content is Link<T> {\n return content.type === \"link\";\n}\n\nexport function isPartialLinkInlineContent<T extends StyleSchema>(\n content: PartialInlineContentElement<any, T>,\n): content is PartialLink<T> {\n return typeof content !== \"string\" && content.type === \"link\";\n}\n\nexport function isStyledTextInlineContent<T extends StyleSchema>(\n content: PartialInlineContentElement<any, T>,\n): content is StyledText<T> {\n return typeof content !== \"string\" && content.type === \"text\";\n}\n","import type {\n InlineContentSchema,\n StyleSchema,\n PartialInlineContent,\n InlineContent,\n} from \"../schema\";\nimport { PartialTableCell, TableCell } from \"../schema/blocks/types.js\";\n\n/**\n * This will map a table cell to a TableCell object.\n * This is useful for when we want to get the full table cell object from a partial table cell.\n * It is guaranteed to return a new TableCell object.\n */\nexport function mapTableCell<\n T extends InlineContentSchema,\n S extends StyleSchema,\n>(\n content:\n | PartialInlineContent<T, S>\n | PartialTableCell<T, S>\n | TableCell<T, S>,\n): TableCell<T, S> {\n return isTableCell(content)\n ? { ...content }\n : isPartialTableCell(content)\n ? {\n type: \"tableCell\",\n content: ([] as InlineContent<T, S>[]).concat(content.content as any),\n props: {\n backgroundColor: content.props?.backgroundColor ?? \"default\",\n textColor: content.props?.textColor ?? \"default\",\n textAlignment: content.props?.textAlignment ?? \"left\",\n colspan: content.props?.colspan ?? 1,\n rowspan: content.props?.rowspan ?? 1,\n },\n }\n : {\n type: \"tableCell\",\n content: ([] as InlineContent<T, S>[]).concat(content as any),\n props: {\n backgroundColor: \"default\",\n textColor: \"default\",\n textAlignment: \"left\",\n colspan: 1,\n rowspan: 1,\n },\n };\n}\n\nexport function isPartialTableCell<\n T extends InlineContentSchema,\n S extends StyleSchema,\n>(\n content:\n | TableCell<T, S>\n | PartialInlineContent<T, S>\n | PartialTableCell<T, S>\n | undefined\n | null,\n): content is PartialTableCell<T, S> {\n return (\n content !== undefined &&\n content !== null &&\n typeof content !== \"string\" &&\n !Array.isArray(content) &&\n content.type === \"tableCell\"\n );\n}\n\nexport function isTableCell<\n T extends InlineContentSchema,\n S extends StyleSchema,\n>(\n content:\n | TableCell<T, S>\n | PartialInlineContent<T, S>\n | PartialTableCell<T, S>\n | undefined\n | null,\n): content is TableCell<T, S> {\n return (\n isPartialTableCell(content) &&\n content.props !== undefined &&\n content.content !== undefined\n );\n}\n\nexport function getColspan(\n cell:\n | TableCell<any, any>\n | PartialTableCell<any, any>\n | PartialInlineContent<any, any>,\n): number {\n if (isTableCell(cell)) {\n return cell.props.colspan ?? 1;\n }\n return 1;\n}\n\nexport function getRowspan(\n cell:\n | TableCell<any, any>\n | PartialTableCell<any, any>\n | PartialInlineContent<any, any>,\n): number {\n if (isTableCell(cell)) {\n return cell.props.rowspan ?? 1;\n }\n return 1;\n}\n","export class UnreachableCaseError extends Error {\n constructor(val: never) {\n super(`Unreachable case: ${val}`);\n }\n}\n\nexport function assertEmpty(obj: Record<string, never>, throwError = true) {\n const { \"data-test\": dataTest, ...rest } = obj; // exclude data-test\n\n if (Object.keys(rest).length > 0 && throwError) {\n throw new Error(\"Object must be empty \" + JSON.stringify(obj));\n }\n}\n\n// TODO: change for built-in version of typescript 5.4 after upgrade\nexport type NoInfer<T> = [T][T extends any ? 0 : never];\n","import { Node, ResolvedPos } from \"prosemirror-model\";\nimport { EditorState, Transaction } from \"prosemirror-state\";\n\ntype SingleBlockInfo = {\n node: Node;\n beforePos: number;\n afterPos: number;\n};\n\nexport type BlockInfo = {\n /**\n * The outer node that represents a BlockNote block. This is the node that has the ID.\n * Most of the time, this will be a blockContainer node, but it could also be a Column or ColumnList\n */\n bnBlock: SingleBlockInfo;\n /**\n * The type of BlockNote block that this node represents.\n * When dealing with a blockContainer, this is retrieved from the blockContent node, otherwise it's retrieved from the bnBlock node.\n */\n blockNoteType: string;\n} & (\n | {\n // In case we're not dealing with a BlockContainer, we're dealing with a \"wrapper node\" (like a Column or ColumnList), so it will always have children\n\n /**\n * The Prosemirror node that holds block.children. For non-blockContainer, this node will be the same as bnBlock.\n */\n childContainer: SingleBlockInfo;\n isBlockContainer: false;\n }\n | {\n /**\n * The Prosemirror node that holds block.children. For blockContainers, this is the blockGroup node, if it exists.\n */\n childContainer?: SingleBlockInfo;\n /**\n * The Prosemirror node that wraps block.content and has most of the props\n */\n blockContent: SingleBlockInfo;\n /**\n * Whether bnBlock is a blockContainer node\n */\n isBlockContainer: true;\n }\n);\n\n/**\n * Retrieves the position just before the nearest block node in a ProseMirror\n * doc, relative to a position. If the position is within a block node or its\n * descendants, the position just before it is returned. If the position is not\n * within a block node or its descendants, the position just before the next\n * closest block node is returned. If the position is beyond the last block, the\n * position just before the last block is returned.\n * @param doc The ProseMirror doc.\n * @param pos An integer position in the document.\n * @returns The position just before the nearest blockContainer node.\n */\nexport function getNearestBlockPos(doc: Node, pos: number) {\n const $pos = doc.resolve(pos);\n\n // Checks if the position provided is already just before a block node, in\n // which case we return the position.\n if ($pos.nodeAfter && $pos.nodeAfter.type.isInGroup(\"bnBlock\")) {\n return {\n posBeforeNode: $pos.pos,\n node: $pos.nodeAfter,\n };\n }\n\n // Checks the node containing the position and its ancestors until a\n // block node is found and returned.\n let depth = $pos.depth;\n let node = $pos.node(depth);\n while (depth > 0) {\n if (node.type.isInGroup(\"bnBlock\")) {\n return {\n posBeforeNode: $pos.before(depth),\n node: node,\n };\n }\n\n depth--;\n node = $pos.node(depth);\n }\n\n // If the position doesn't lie within a block node, we instead find the\n // position of the next closest one. If the position is beyond the last block,\n // we return the position of the last block. While running `doc.descendants`\n // is expensive, this case should be very rarely triggered. However, it's\n // possible for the position to sometimes be beyond the last block node. This\n // is a problem specifically when using the collaboration plugin.\n const allBlockContainerPositions: number[] = [];\n doc.descendants((node, pos) => {\n if (node.type.isInGroup(\"bnBlock\")) {\n allBlockContainerPositions.push(pos);\n }\n });\n\n // eslint-disable-next-line no-console\n console.warn(`Position ${pos} is not within a blockContainer node.`);\n\n const resolvedPos = doc.resolve(\n allBlockContainerPositions.find((position) => position >= pos) ||\n allBlockContainerPositions[allBlockContainerPositions.length - 1],\n );\n return {\n posBeforeNode: resolvedPos.pos,\n node: resolvedPos.nodeAfter!,\n };\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block in a\n * BlockNote document. This includes the main `blockContainer` node, the\n * `blockContent` node with the block's main body, and the optional `blockGroup`\n * node which contains the block's children. As well as the nodes, also returns\n * the ProseMirror positions just before & after each node.\n * @param node The main `blockContainer` node that the block information should\n * be retrieved from,\n * @param bnBlockBeforePosOffset the position just before the\n * `blockContainer` node in the document.\n */\nexport function getBlockInfoWithManualOffset(\n node: Node,\n bnBlockBeforePosOffset: number,\n): BlockInfo {\n if (!node.type.isInGroup(\"bnBlock\")) {\n throw new Error(\n `Attempted to get bnBlock node at position but found node of different type ${node.type.name}`,\n );\n }\n\n const bnBlockNode = node;\n const bnBlockBeforePos = bnBlockBeforePosOffset;\n const bnBlockAfterPos = bnBlockBeforePos + bnBlockNode.nodeSize;\n\n const bnBlock: SingleBlockInfo = {\n node: bnBlockNode,\n beforePos: bnBlockBeforePos,\n afterPos: bnBlockAfterPos,\n };\n\n if (bnBlockNode.type.name === \"blockContainer\") {\n let blockContent: SingleBlockInfo | undefined;\n let blockGroup: SingleBlockInfo | undefined;\n\n bnBlockNode.forEach((node, offset) => {\n if (node.type.spec.group === \"blockContent\") {\n // console.log(beforePos, offset);\n const blockContentNode = node;\n const blockContentBeforePos = bnBlockBeforePos + offset + 1;\n const blockContentAfterPos = blockContentBeforePos + node.nodeSize;\n\n blockContent = {\n node: blockContentNode,\n beforePos: blockContentBeforePos,\n afterPos: blockContentAfterPos,\n };\n } else if (node.type.name === \"blockGroup\") {\n const blockGroupNode = node;\n const blockGroupBeforePos = bnBlockBeforePos + offset + 1;\n const blockGroupAfterPos = blockGroupBeforePos + node.nodeSize;\n\n blockGroup = {\n node: blockGroupNode,\n beforePos: blockGroupBeforePos,\n afterPos: blockGroupAfterPos,\n };\n }\n });\n\n if (!blockContent) {\n throw new Error(\n `blockContainer node does not contain a blockContent node in its children: ${bnBlockNode}`,\n );\n }\n\n return {\n isBlockContainer: true,\n bnBlock,\n blockContent,\n childContainer: blockGroup,\n blockNoteType: blockContent.node.type.name,\n };\n } else {\n if (!bnBlock.node.type.isInGroup(\"childContainer\")) {\n throw new Error(\n `bnBlock node is not in the childContainer group: ${bnBlock.node}`,\n );\n }\n\n return {\n isBlockContainer: false,\n bnBlock: bnBlock,\n childContainer: bnBlock,\n blockNoteType: bnBlock.node.type.name,\n };\n }\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block in a\n * BlockNote document. This includes the main `blockContainer` node, the\n * `blockContent` node with the block's main body, and the optional `blockGroup`\n * node which contains the block's children. As well as the nodes, also returns\n * the ProseMirror positions just before & after each node.\n * @param posInfo An object with the main `blockContainer` node that the block\n * information should be retrieved from, and the position just before it in the\n * document.\n */\nexport function getBlockInfo(posInfo: { posBeforeNode: number; node: Node }) {\n return getBlockInfoWithManualOffset(posInfo.node, posInfo.posBeforeNode);\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block from a\n * resolved position just before the `blockContainer` node in the document that\n * corresponds to it.\n * @param resolvedPos The resolved position just before the `blockContainer`\n * node.\n */\nexport function getBlockInfoFromResolvedPos(resolvedPos: ResolvedPos) {\n if (!resolvedPos.nodeAfter) {\n throw new Error(\n `Attempted to get blockContainer node at position ${resolvedPos.pos} but a node at this position does not exist`,\n );\n }\n return getBlockInfoWithManualOffset(resolvedPos.nodeAfter, resolvedPos.pos);\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block. The\n * block chosen is the one currently containing the current ProseMirror\n * selection.\n * @param state The ProseMirror editor state.\n */\nexport function getBlockInfoFromSelection(state: EditorState) {\n const posInfo = getNearestBlockPos(state.doc, state.selection.anchor);\n\n return getBlockInfo(posInfo);\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block. The\n * block chosen is the one currently containing the current ProseMirror\n * selection.\n * @param tr The ProseMirror transaction.\n */\nexport function getBlockInfoFromTransaction(tr: Transaction) {\n const posInfo = getNearestBlockPos(tr.doc, tr.selection.anchor);\n\n return getBlockInfo(posInfo);\n}\n","import type { Node, Schema } from \"prosemirror-model\";\nimport { Transform } from \"prosemirror-transform\";\nimport type { BlockNoteEditor } from \"../editor/BlockNoteEditor.js\";\nimport { BlockNoteSchema } from \"../blocks/BlockNoteSchema.js\";\nimport type { BlockSchema } from \"../schema/blocks/types.js\";\nimport type { InlineContentSchema } from \"../schema/inlineContent/types.js\";\nimport type { StyleSchema } from \"../schema/styles/types.js\";\n\nexport function getPmSchema(trOrNode: Transform | Node) {\n if (\"doc\" in trOrNode) {\n return trOrNode.doc.type.schema;\n }\n return trOrNode.type.schema;\n}\n\nfunction getBlockNoteEditor<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(schema: Schema): BlockNoteEditor<BSchema, I, S> {\n return schema.cached.blockNoteEditor as BlockNoteEditor<BSchema, I, S>;\n}\n\nexport function getBlockNoteSchema<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(schema: Schema): BlockNoteSchema<BSchema, I, S> {\n return getBlockNoteEditor(schema).schema as unknown as BlockNoteSchema<\n BSchema,\n I,\n S\n >;\n}\n\nexport function getBlockSchema<BSchema extends BlockSchema>(\n schema: Schema,\n): BSchema {\n return getBlockNoteSchema(schema).blockSchema as BSchema;\n}\n\nexport function getInlineContentSchema<I extends InlineContentSchema>(\n schema: Schema,\n): I {\n return getBlockNoteSchema(schema).inlineContentSchema as I;\n}\n\nexport function getStyleSchema<S extends StyleSchema>(schema: Schema): S {\n return getBlockNoteSchema(schema).styleSchema as S;\n}\n\nexport function getBlockCache(schema: Schema) {\n return getBlockNoteEditor(schema).blockCache;\n}\n","import { Mark, Node, Schema, Slice } from \"@tiptap/pm/model\";\nimport type { Block } from \"../../blocks/defaultBlocks.js\";\nimport UniqueID from \"../../extensions/tiptap-extensions/UniqueID/UniqueID.js\";\nimport type {\n BlockSchema,\n CustomInlineContentConfig,\n CustomInlineContentFromConfig,\n InlineContent,\n InlineContentFromConfig,\n InlineContentSchema,\n StyleSchema,\n Styles,\n TableCell,\n TableContent,\n} from \"../../schema/index.js\";\nimport {\n isLinkInlineContent,\n isStyledTextInlineContent,\n} from \"../../schema/inlineContent/types.js\";\nimport { UnreachableCaseError } from \"../../util/typescript.js\";\nimport { getBlockInfoWithManualOffset } from \"../getBlockInfoFromPos.js\";\nimport {\n getBlockCache,\n getBlockSchema,\n getInlineContentSchema,\n getPmSchema,\n getStyleSchema,\n} from \"../pmUtil.js\";\n\n/**\n * Converts an internal (prosemirror) table node contentto a BlockNote Tablecontent\n */\nexport function contentNodeToTableContent<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(contentNode: Node, inlineContentSchema: I, styleSchema: S) {\n const ret: TableContent<I, S> = {\n type: \"tableContent\",\n columnWidths: [],\n headerRows: undefined,\n headerCols: undefined,\n rows: [],\n };\n\n /**\n * A matrix of boolean values indicating whether a cell is a header.\n * The first index is the row index, the second index is the cell index.\n */\n const headerMatrix: boolean[][] = [];\n\n contentNode.content.forEach((rowNode, _offset, rowIndex) => {\n const row: TableContent<I, S>[\"rows\"][0] = {\n cells: [],\n };\n\n if (rowIndex === 0) {\n rowNode.content.forEach((cellNode) => {\n let colWidth = cellNode.attrs.colwidth as null | undefined | number[];\n if (colWidth === undefined || colWidth === null) {\n colWidth = new Array(cellNode.attrs.colspan ?? 1).fill(undefined);\n }\n ret.columnWidths.push(...colWidth);\n });\n }\n\n row.cells = rowNode.content.content.map((cellNode, cellIndex) => {\n if (!headerMatrix[rowIndex]) {\n headerMatrix[rowIndex] = [];\n }\n // Mark the cell as a header if it is a tableHeader node.\n headerMatrix[rowIndex][cellIndex] = cellNode.type.name === \"tableHeader\";\n // Convert cell content to inline content and merge adjacent styled text nodes\n const content = cellNode.content.content\n .map((child) =>\n contentNodeToInlineContent(child, inlineContentSchema, styleSchema),\n )\n // The reason that we merge this content is that we allow table cells to contain multiple tableParagraph nodes\n // So that we can leverage prosemirror-tables native merging\n // If the schema only allowed a single tableParagraph node, then the merging would not work and cause prosemirror to fit the content into a new cell\n .reduce(\n (acc, contentPartial) => {\n if (!acc.length) {\n return contentPartial;\n }\n\n const last = acc[acc.length - 1];\n const first = contentPartial[0];\n\n // Only merge if the last and first content are both styled text nodes and have the same styles\n if (\n first &&\n isStyledTextInlineContent(last) &&\n isStyledTextInlineContent(first) &&\n JSON.stringify(last.styles) === JSON.stringify(first.styles)\n ) {\n // Join them together if they have the same styles\n last.text += \"\\n\" + first.text;\n acc.push(...contentPartial.slice(1));\n return acc;\n }\n acc.push(...contentPartial);\n return acc;\n },\n [] as InlineContent<I, S>[],\n );\n\n return {\n type: \"tableCell\",\n content,\n props: {\n colspan: cellNode.attrs.colspan,\n rowspan: cellNode.attrs.rowspan,\n backgroundColor: cellNode.attrs.backgroundColor,\n textColor: cellNode.attrs.textColor,\n textAlignment: cellNode.attrs.textAlignment,\n },\n } satisfies TableCell<I, S>;\n });\n\n ret.rows.push(row);\n });\n\n for (let i = 0; i < headerMatrix.length; i++) {\n if (headerMatrix[i]?.every((isHeader) => isHeader)) {\n ret.headerRows = (ret.headerRows ?? 0) + 1;\n }\n }\n\n for (let i = 0; i < headerMatrix[0]?.length; i++) {\n if (headerMatrix?.every((row) => row[i])) {\n ret.headerCols = (ret.headerCols ?? 0) + 1;\n }\n }\n\n return ret;\n}\n\n/**\n * Converts an internal (prosemirror) content node to a BlockNote InlineContent array.\n */\nexport function contentNodeToInlineContent<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(contentNode: Node, inlineContentSchema: I, styleSchema: S) {\n const content: InlineContent<any, S>[] = [];\n let currentContent: InlineContent<any, S> | undefined = undefined;\n\n // Most of the logic below is for handling links because in ProseMirror links are marks\n // while in BlockNote links are a type of inline content\n contentNode.content.forEach((node) => {\n // hardBreak nodes do not have an InlineContent equivalent, instead we\n // add a newline to the previous node.\n if (node.type.name === \"hardBreak\") {\n if (currentContent) {\n // Current content exists.\n if (isStyledTextInlineContent(currentContent)) {\n // Current content is text.\n currentContent.text += \"\\n\";\n } else if (isLinkInlineContent(currentContent)) {\n // Current content is a link.\n currentContent.content[currentContent.content.length - 1].text +=\n \"\\n\";\n } else {\n throw new Error(\"unexpected\");\n }\n } else {\n // Current content does not exist.\n currentContent = {\n type: \"text\",\n text: \"\\n\",\n styles: {},\n };\n }\n\n return;\n }\n\n if (node.type.name !== \"link\" && node.type.name !== \"text\") {\n if (!inlineContentSchema[node.type.name]) {\n // eslint-disable-next-line no-console\n console.warn(\"unrecognized inline content type\", node.type.name);\n return;\n }\n if (currentContent) {\n content.push(currentContent);\n currentContent = undefined;\n }\n\n content.push(\n nodeToCustomInlineContent(node, inlineContentSchema, styleSchema),\n );\n\n return;\n }\n\n const styles: Styles<S> = {};\n let linkMark: Mark | undefined;\n\n for (const mark of node.marks) {\n if (mark.type.name === \"link\") {\n linkMark = mark;\n } else {\n const config = styleSchema[mark.type.name];\n if (!config) {\n if (mark.type.spec.blocknoteIgnore) {\n // at this point, we don't want to show certain marks (such as comments)\n // in the BlockNote JSON output. These marks should be tagged with \"blocknoteIgnore\" in the spec\n continue;\n }\n throw new Error(`style ${mark.type.name} not found in styleSchema`);\n }\n if (config.propSchema === \"boolean\") {\n (styles as any)[config.type] = true;\n } else if (config.propSchema === \"string\") {\n (styles as any)[config.type] = mark.attrs.stringValue;\n } else {\n throw new UnreachableCaseError(config.propSchema);\n }\n }\n }\n\n // Parsing links and text.\n // Current content exists.\n if (currentContent) {\n // Current content is text.\n if (isStyledTextInlineContent(currentContent)) {\n if (!linkMark) {\n // Node is text (same type as current content).\n if (\n JSON.stringify(currentContent.styles) === JSON.stringify(styles)\n ) {\n // Styles are the same.\n currentContent.text += node.textContent;\n } else {\n // Styles are different.\n content.push(currentContent);\n currentContent = {\n type: \"text\",\n text: node.textContent,\n styles,\n };\n }\n } else {\n // Node is a link (different type to current content).\n content.push(currentContent);\n currentContent = {\n type: \"link\",\n href: linkMark.attrs.href,\n content: [\n {\n type: \"text\",\n text: node.textContent,\n styles,\n },\n ],\n };\n }\n } else if (isLinkInlineContent(currentContent)) {\n // Current content is a link.\n if (linkMark) {\n // Node is a link (same type as current content).\n // Link URLs are the same.\n if (currentContent.href === linkMark.attrs.href) {\n // Styles are the same.\n if (\n JSON.stringify(\n currentContent.content[currentContent.content.length - 1]\n .styles,\n ) === JSON.stringify(styles)\n ) {\n currentContent.content[currentContent.content.length - 1].text +=\n node.textContent;\n } else {\n // Styles are different.\n currentContent.content.push({\n type: \"text\",\n text: node.textContent,\n styles,\n });\n }\n } else {\n // Link URLs are different.\n content.push(currentContent);\n currentContent = {\n type: \"link\",\n href: linkMark.attrs.href,\n content: [\n {\n type: \"text\",\n text: node.textContent,\n styles,\n },\n ],\n };\n }\n } else {\n // Node is text (different type to current content).\n content.push(currentContent);\n currentContent = {\n type: \"text\",\n text: node.textContent,\n styles,\n };\n }\n } else {\n // TODO\n }\n }\n // Current content does not exist.\n else {\n // Node is text.\n if (!linkMark) {\n currentContent = {\n type: \"text\",\n text: node.textContent,\n styles,\n };\n }\n // Node is a link.\n else {\n currentContent = {\n type: \"link\",\n href: linkMark.attrs.href,\n content: [\n {\n type: \"text\",\n text: node.textContent,\n styles,\n },\n ],\n };\n }\n }\n });\n\n if (currentContent) {\n content.push(currentContent);\n }\n\n return content as InlineContent<I, S>[];\n}\n\nexport function nodeToCustomInlineContent<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(node: Node, inlineContentSchema: I, styleSchema: S): InlineContent<I, S> {\n if (node.type.name === \"text\" || node.type.name === \"link\") {\n throw new Error(\"unexpected\");\n }\n const props: any = {};\n const icConfig = inlineContentSchema[\n node.type.name\n ] as CustomInlineContentConfig;\n for (const [attr, value] of Object.entries(node.attrs)) {\n if (!icConfig) {\n throw Error(\"ic node is of an unrecognized type: \" + node.type.name);\n }\n\n const propSchema = icConfig.propSchema;\n\n if (attr in propSchema) {\n props[attr] = value;\n }\n }\n\n let content: CustomInlineContentFromConfig<any, any>[\"content\"];\n\n if (icConfig.content === \"styled\") {\n content = contentNodeToInlineContent(\n node,\n inlineContentSchema,\n styleSchema,\n ) as any; // TODO: is this safe? could we have Links here that are undesired?\n } else {\n content = undefined;\n }\n\n const ic = {\n type: node.type.name,\n props,\n content,\n } as InlineContentFromConfig<I[keyof I], S>;\n return ic;\n}\n\n/**\n * Convert a Prosemirror node to a BlockNote block.\n *\n * TODO: test changes\n */\nexport function nodeToBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n node: Node,\n schema: Schema,\n blockSchema: BSchema = getBlockSchema(schema) as BSchema,\n inlineContentSchema: I = getInlineContentSchema(schema) as I,\n styleSchema: S = getStyleSchema(schema) as S,\n blockCache = getBlockCache(schema),\n): Block<BSchema, I, S> {\n if (!node.type.isInGroup(\"bnBlock\")) {\n throw Error(\"Node should be a bnBlock, but is instead: \" + node.type.name);\n }\n\n const cachedBlock = blockCache?.get(node);\n\n if (cachedBlock) {\n return cachedBlock;\n }\n\n const blockInfo = getBlockInfoWithManualOffset(node, 0);\n\n let id = blockInfo.bnBlock.node.attrs.id;\n\n // Only used for blocks converted from other formats.\n if (id === null) {\n id = UniqueID.options.generateID();\n }\n\n const blockSpec = blockSchema[blockInfo.blockNoteType];\n\n if (!blockSpec) {\n throw Error(\"Block is of an unrecognized type: \" + blockInfo.blockNoteType);\n }\n\n const props: any = {};\n for (const [attr, value] of Object.entries({\n ...node.attrs,\n ...(blockInfo.isBlockContainer ? blockInfo.blockContent.node.attrs : {}),\n })) {\n const propSchema = blockSpec.propSchema;\n\n if (\n attr in propSchema &&\n !(propSchema[attr].default === undefined && value === undefined)\n ) {\n props[attr] = value;\n }\n }\n\n const blockConfig = blockSchema[blockInfo.blockNoteType];\n\n const children: Block<BSchema, I, S>[] = [];\n blockInfo.childContainer?.node.forEach((child) => {\n children.push(\n nodeToBlock(\n child,\n schema,\n blockSchema,\n inlineContentSchema,\n styleSchema,\n blockCache,\n ),\n );\n });\n\n let content: Block<any, any, any>[\"content\"];\n\n if (blockConfig.content === \"inline\") {\n if (!blockInfo.isBlockContainer) {\n throw new Error(\"impossible\");\n }\n content = contentNodeToInlineContent(\n blockInfo.blockContent.node,\n inlineContentSchema,\n styleSchema,\n );\n } else if (blockConfig.content === \"table\") {\n if (!blockInfo.isBlockContainer) {\n throw new Error(\"impossible\");\n }\n content = contentNodeToTableContent(\n blockInfo.blockContent.node,\n inlineContentSchema,\n styleSchema,\n );\n } else if (blockConfig.content === \"none\") {\n content = undefined;\n } else {\n throw new UnreachableCaseError(blockConfig.content);\n }\n\n const block = {\n id,\n type: blockConfig.type,\n props,\n content,\n children,\n } as Block<BSchema, I, S>;\n\n blockCache?.set(node, block);\n\n return block;\n}\n\n/**\n * Convert a Prosemirror document to a BlockNote document (array of blocks)\n */\nexport function docToBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n doc: Node,\n schema: Schema = getPmSchema(doc),\n blockSchema: BSchema = getBlockSchema(schema) as BSchema,\n inlineContentSchema: I = getInlineContentSchema(schema) as I,\n styleSchema: S = getStyleSchema(schema) as S,\n blockCache = getBlockCache(schema),\n) {\n const blocks: Block<BSchema, I, S>[] = [];\n if (doc.firstChild) {\n doc.firstChild.descendants((node) => {\n blocks.push(\n nodeToBlock(\n node,\n schema,\n blockSchema,\n inlineContentSchema,\n styleSchema,\n blockCache,\n ),\n );\n return false;\n });\n }\n return blocks;\n}\n\n/**\n *\n * Parse a Prosemirror Slice into a BlockNote selection. The prosemirror schema looks like this:\n *\n * <blockGroup>\n * <blockContainer> (main content of block)\n * <p, heading, etc.>\n * <blockGroup> (only if blocks has children)\n * <blockContainer> (child block)\n * <p, heading, etc.>\n * </blockContainer>\n * <blockContainer> (child block 2)\n * <p, heading, etc.>\n * </blockContainer>\n * </blockContainer>\n * </blockGroup>\n * </blockGroup>\n *\n */\nexport function prosemirrorSliceToSlicedBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n slice: Slice,\n schema: Schema,\n blockSchema: BSchema = getBlockSchema(schema) as BSchema,\n inlineContentSchema: I = getInlineContentSchema(schema) as I,\n styleSchema: S = getStyleSchema(schema) as S,\n blockCache: WeakMap<Node, Block<BSchema, I, S>> = getBlockCache(schema),\n): {\n /**\n * The blocks that are included in the selection.\n */\n blocks: Block<BSchema, I, S>[];\n /**\n * If a block was \"cut\" at the start of the selection, this will be the id of the block that was cut.\n */\n blockCutAtStart: string | undefined;\n /**\n * If a block was \"cut\" at the end of the selection, this will be the id of the block that was cut.\n */\n blockCutAtEnd: string | undefined;\n} {\n // console.log(JSON.stringify(slice.toJSON()));\n function processNode(\n node: Node,\n openStart: number,\n openEnd: number,\n ): {\n blocks: Block<BSchema, I, S>[];\n blockCutAtStart: string | undefined;\n blockCutAtEnd: string | undefined;\n } {\n if (node.type.name !== \"blockGroup\") {\n throw new Error(\"unexpected\");\n }\n const blocks: Block<BSchema, I, S>[] = [];\n let blockCutAtStart: string | undefined;\n let blockCutAtEnd: string | undefined;\n\n node.forEach((blockContainer, _offset, index) => {\n if (blockContainer.type.name !== \"blockContainer\") {\n throw new Error(\"unexpected\");\n }\n if (blockContainer.childCount === 0) {\n return;\n }\n if (blockContainer.childCount === 0 || blockContainer.childCount > 2) {\n throw new Error(\n \"unexpected, blockContainer.childCount: \" + blockContainer.childCount,\n );\n }\n\n const isFirstBlock = index === 0;\n const isLastBlock = index === node.childCount - 1;\n\n if (blockContainer.firstChild!.type.name === \"blockGroup\") {\n // this is the parent where a selection starts within one of its children,\n // e.g.:\n // A\n // ├── B\n // selection starts within B, then this blockContainer is A, but we don't care about A\n // so let's descend into B and continue processing\n if (!isFirstBlock) {\n throw new Error(\"unexpected\");\n }\n const ret = processNode(\n blockContainer.firstChild!,\n Math.max(0, openStart - 1),\n isLastBlock ? Math.max(0, openEnd - 1) : 0,\n );\n blockCutAtStart = ret.blockCutAtStart;\n if (isLastBlock) {\n blockCutAtEnd = ret.blockCutAtEnd;\n }\n blocks.push(...ret.blocks);\n return;\n }\n\n const block = nodeToBlock(\n blockContainer,\n schema,\n blockSchema,\n inlineContentSchema,\n styleSchema,\n blockCache,\n );\n const childGroup =\n blockContainer.childCount > 1 ? blockContainer.child(1) : undefined;\n\n let childBlocks: Block<BSchema, I, S>[] = [];\n if (childGroup) {\n const ret = processNode(\n childGroup,\n 0, // TODO: can this be anything other than 0?\n isLastBlock ? Math.max(0, openEnd - 1) : 0,\n );\n childBlocks = ret.blocks;\n if (isLastBlock) {\n blockCutAtEnd = ret.blockCutAtEnd;\n }\n }\n\n if (isLastBlock && !childGroup && openEnd > 1) {\n blockCutAtEnd = block.id;\n }\n\n if (isFirstBlock && openStart > 1) {\n blockCutAtStart = block.id;\n }\n\n blocks.push({\n ...(block as any),\n children: childBlocks,\n });\n });\n\n return { blocks, blockCutAtStart, blockCutAtEnd };\n }\n\n if (slice.content.childCount === 0) {\n return {\n blocks: [],\n blockCutAtStart: undefined,\n blockCutAtEnd: undefined,\n };\n }\n\n if (slice.content.childCount !== 1) {\n throw new Error(\n \"slice must be a single block, did you forget includeParents=true?\",\n );\n }\n\n return processNode(\n slice.content.firstChild!,\n Math.max(slice.openStart - 1, 0),\n Math.max(slice.openEnd - 1, 0),\n );\n}\n","import { DefaultBlockSchema } from \"../../../blocks/defaultBlocks.js\";\nimport {\n BlockFromConfigNoChildren,\n PartialTableContent,\n TableCell,\n TableContent,\n} from \"../../../schema/blocks/types.js\";\nimport {\n isPartialLinkInlineContent,\n isStyledTextInlineContent,\n} from \"../../../schema/index.js\";\nimport {\n getColspan,\n getRowspan,\n isPartialTableCell,\n mapTableCell,\n} from \"../../../util/table.js\";\n\n/**\n * Here be dragons.\n *\n * Tables are complex because of rowspan and colspan behavior.\n * The majority of this file is concerned with translating between \"relative\" and \"absolute\" indices.\n *\n * The following diagram may help explain the relationship between the different indices:\n *\n * One-based indexing of rows and columns in a table:\n * | 1-1 | 1-2 | 1-3 |\n * | 2-1 | 2-2 | 2-3 |\n * | 3-1 | 3-2 | 3-3 |\n *\n * A complicated table with colspans and rowspans:\n * | 1-1 | 1-2 | 1-2 |\n * | 2-1 | 2-1 | 2-2 |\n * | 2-1 | 2-1 | 3-1 |\n *\n * You can see here that we have:\n * - two cells that contain the value \"1-2\", because it has a colspan of 2.\n * - four cells that contain the value \"2-1\", because it has a rowspan of 2 and a colspan of 2.\n *\n * This would be represented in block note json (roughly) as:\n * [\n * {\n * \"cells\": [\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"1,1\"],\n * \"props\": {\n * \"colspan\": 1,\n * \"rowspan\": 1\n * },\n * },\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"1,2\"],\n * \"props\": {\n * \"colspan\": 2,\n * \"rowspan\": 1\n * }\n * }\n * ],\n * },\n * {\n * \"cells\": [\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"2,1\"],\n * \"props\": {\n * \"colspan\": 2,\n * \"rowspan\": 2\n * }\n * },\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"2,2\"],\n * \"props\": {\n * \"colspan\": 1,\n * \"rowspan\": 1\n * }\n * ],\n * },\n * {\n * \"cells\": [\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"3,1\"],\n * \"props\": {\n * \"colspan\": 1,\n * \"rowspan\": 1,\n * }\n * }\n * ]\n * }\n * ]\n *\n * Which maps cleanly to the following HTML:\n *\n * <table>\n * <tr>\n * <td>1-1</td>\n * <td colspan=\"2\">1-2</td>\n * </tr>\n * <tr>\n * <td rowspan=\"2\" colspan=\"2\">2-1</td>\n * <td>2-2</td>\n * </tr>\n * <tr>\n * <td>3-1</td>\n * </tr>\n * </table>\n *\n * We have a problem though, from the block json, there is no way to tell that the cell \"2-1\" is the second cell in the second row.\n * To resolve this, we created the occupancy grid, which is a grid of all the cells in the table, as though they were only 1x1 cells.\n * See {@link OccupancyGrid} for more information.\n *\n */\n\n/**\n * Relative cell indices are relative to the table block's content.\n *\n * This is a sparse representation of the table and is how HTML and BlockNote JSON represent tables.\n *\n * For example, if we have a table with a rowspan of 2, the second row may only have 1 element in a 2x2 table.\n *\n * ```\n * // Visual representation of the table\n * | 1-1 | 1-2 | // has 2 cells\n * | 1-1 | 2-2 | // has only 1 cell\n * // Relative cell indices\n * [{ row: 1, col: 1, rowspan: 2 }, { row: 1, col: 2 }] // has 2 cells\n * [{ row: 1, col: 2 }] // has only 1 cell\n * ```\n */\nexport type RelativeCellIndices = {\n row: number;\n col: number;\n};\n\n/**\n * Absolute cell indices are relative to the table's layout (it's {@link OccupancyGrid}).\n *\n * It is as though the table is a grid of 1x1 cells, and any colspan or rowspan results in multiple 1x1 cells being occupied.\n *\n * For example, if we have a table with a colspan of 2, it will occupy 2 cells in the layout grid.\n *\n * ```\n * // Visual representation of the table\n * | 1-1 | 1-1 | // has 2 cells\n * | 2-1 | 2-2 | // has 2 cell\n * // Absolute cell indices\n * [{ row: 1, col: 1, colspan: 2 }, { row: 1, col: 2, colspan: 2 }] // has 2 cells\n * [{ row: 1, col: 1 }, { row: 1, col: 2 }] // has 2 cells\n * ```\n */\nexport type AbsoluteCellIndices = {\n row: number;\n col: number;\n};\n\n/**\n * An occupancy grid is a grid of the occupied cells in the table.\n * It is used to track the occupied cells in the table to know where to place the next cell.\n *\n * Since it allows us to resolve cell indices both {@link RelativeCellIndices} and {@link AbsoluteCellIndices}, it is the core data structure for table operations.\n */\ntype OccupancyGrid = (RelativeCellIndices & {\n /**\n * The rowspan of the cell.\n */\n rowspan: number;\n /**\n * The colspan of the cell.\n */\n colspan: number;\n /**\n * The cell.\n */\n cell: TableCell<any, any>;\n})[][];\n\n/**\n * This will return the {@link OccupancyGrid} of the table.\n * By laying out the table as though it were a grid of 1x1 cells, we can easily track where the cells are located (both relatively and absolutely).\n *\n * @returns an {@link OccupancyGrid}\n */\nexport function getTableCellOccupancyGrid(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n): OccupancyGrid {\n const { height, width } = getDimensionsOfTable(block);\n\n /**\n * Create a grid to track occupied cells\n * This is used because rowspans and colspans take up multiple spaces\n * So, we need to track the occupied cells in the grid to know where to place the next cell\n */\n const grid: OccupancyGrid = new Array(height)\n .fill(false)\n .map(() => new Array(width).fill(null));\n\n // Find the next unoccupied cell in the table, row-major order\n const findNextAvailable = (row: number, col: number) => {\n for (let i = row; i < height; i++) {\n for (let j = col; j < width; j++) {\n if (!grid[i][j]) {\n return { row: i, col: j };\n }\n }\n }\n\n throw new Error(\n \"Unable to create occupancy grid for table, no more available cells\",\n );\n };\n\n // Build up the grid, trying to fill in the cells with the correct relative row and column indices\n for (let row = 0; row < block.content.rows.length; row++) {\n for (let col = 0; col < block.content.rows[row].cells.length; col++) {\n const cell = mapTableCell(block.content.rows[row].cells[col]);\n const rowspan = getRowspan(cell);\n const colspan = getColspan(cell);\n\n // Rowspan and colspan complicate things, by taking up multiple cells in the grid\n // We need to iterate over the cells that the rowspan and colspan take up\n // and fill in the grid with the correct relative row and column indices\n const { row: startRow, col: startCol } = findNextAvailable(row, col);\n\n // Fill in the rowspan X colspan cells, starting from the next available cell, with the correct relative row and column indices\n for (let i = startRow; i < startRow + rowspan; i++) {\n for (let j = startCol; j < startCol + colspan; j++) {\n if (grid[i][j]) {\n // The cell is already occupied, the table is malformed\n throw new Error(\n `Unable to create occupancy grid for table, cell at ${i},${j} is already occupied`,\n );\n }\n\n grid[i][j] = {\n row,\n col,\n rowspan,\n colspan,\n cell,\n };\n }\n }\n }\n }\n\n // console.log(grid);\n\n return grid;\n}\n\n/**\n * Given an {@link OccupancyGrid}, this will return the {@link TableContent} rows.\n *\n * @note This will remove duplicates from the occupancy grid. And does no bounds checking for validity of the occupancy grid.\n */\nexport function getTableRowsFromOccupancyGrid(\n occupancyGrid: OccupancyGrid,\n): TableContent<any, any>[\"rows\"] {\n // Because a cell can have a rowspan or colspan, it can occupy multiple cells in the occupancy grid\n // So, we need to remove duplicates from the occupancy grid before we can return the table rows\n const seen = new Set<string>();\n\n return occupancyGrid.map((row) => {\n // Just read out the cells in the occupancy grid, removing duplicates\n return {\n cells: row\n .map((cell) => {\n if (seen.has(cell.row + \":\" + cell.col)) {\n return false;\n }\n seen.add(cell.row + \":\" + cell.col);\n return cell.cell;\n })\n .filter((cell): cell is TableCell<any, any> => cell !== false),\n };\n });\n}\n\n/**\n * This will resolve the relative cell indices within the table block to the absolute cell indices within the table, accounting for colspan and rowspan.\n *\n * @note It will return only the first cell (i.e. top-left) that matches the relative cell indices. To find the other absolute cell indices this cell occupies, you can assume it is the rowspan and colspan number of cells away from the top-left cell.\n *\n * @returns The {@link AbsoluteCellIndices} and the {@link TableCell} at the absolute position.\n */\nexport function getAbsoluteTableCells(\n /**\n * The relative position of the cell in the table.\n */\n relativeCellIndices: RelativeCellIndices,\n /**\n * The table block containing the cell.\n */\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n /**\n * The occupancy grid of the table.\n */\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): AbsoluteCellIndices & {\n cell: TableCell<any, any>;\n} {\n for (let r = 0; r < occupancyGrid.length; r++) {\n for (let c = 0; c < occupancyGrid[r].length; c++) {\n // console.log(r, c, occupancyGrid);\n const cell = occupancyGrid[r][c];\n if (\n cell.row === relativeCellIndices.row &&\n cell.col === relativeCellIndices.col\n ) {\n return { row: r, col: c, cell: cell.cell };\n }\n }\n }\n\n throw new Error(\n `Unable to resolve relative table cell indices for table, cell at ${relativeCellIndices.row},${relativeCellIndices.col} is not occupied`,\n );\n}\n\n/**\n * This will get the dimensions of the table block.\n *\n * @returns The height and width of the table.\n */\nexport function getDimensionsOfTable(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n): {\n /**\n * The number of rows in the table.\n */\n height: number;\n /**\n * The number of columns in the table.\n */\n width: number;\n} {\n // Due to the way we store the table, the height is always the number of rows\n const height = block.content.rows.length;\n\n // Calculating the width is a bit more complex, as it is the maximum width of any row\n let width = 0;\n block.content.rows.forEach((row) => {\n // Find the width of the row by summing the colspan of each cell\n let rowWidth = 0;\n row.cells.forEach((cell) => {\n rowWidth += getColspan(cell);\n });\n\n // Update the width if the row is wider than the current width\n width = Math.max(width, rowWidth);\n });\n\n return { height, width };\n}\n\n/**\n * This will resolve the absolute cell indices within the table block to the relative cell indices within the table, accounting for colspan and rowspan.\n *\n * @returns The {@link RelativeCellIndices} and the {@link TableCell} at the relative position.\n */\nexport function getRelativeTableCells(\n /**\n * The {@link AbsoluteCellIndices} of the cell in the table.\n */\n absoluteCellIndices: AbsoluteCellIndices,\n /**\n * The table block containing the cell.\n */\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n /**\n * The occupancy grid of the table.\n */\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n):\n | (RelativeCellIndices & {\n cell: TableContent<any, any>[\"rows\"][number][\"cells\"][number];\n })\n | undefined {\n const occupancyCell =\n occupancyGrid[absoluteCellIndices.row]?.[absoluteCellIndices.col];\n\n // Double check that the cell can be accessed\n if (!occupancyCell) {\n // The cell is not occupied, so it is invalid\n return undefined;\n }\n\n return {\n row: occupancyCell.row,\n col: occupancyCell.col,\n cell: occupancyCell.cell,\n };\n}\n\n/**\n * This will get all the cells within a relative row of a table block.\n *\n * This method always starts the search for the row at the first column of the table.\n *\n * ```\n * // Visual representation of a table\n * | A | B | C |\n * | | D | E |\n * | F | G | H |\n * // \"A\" has a rowspan of 2\n *\n * // getCellsAtRowHandle(0)\n * // returns [\n * { row: 0, col: 0, cell: \"A\" },\n * { row: 0, col: 1, cell: \"B\" },\n * { row: 0, col: 2, cell: \"C\" },\n * ]\n *\n * // getCellsAtColumnHandle(1)\n * // returns [\n * { row: 1, col: 0, cell: \"F\" },\n * { row: 1, col: 1, cell: \"G\" },\n * { row: 1, col: 2, cell: \"H\" },\n * ]\n * ```\n *\n * As you can see, you may not be able to retrieve all nodes given a relative row index, as cells can span multiple rows.\n *\n * @returns All of the cells associated with the relative row of the table. (All cells that have the same relative row index)\n */\nexport function getCellsAtRowHandle(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n relativeRowIndex: RelativeCellIndices[\"row\"],\n) {\n const occupancyGrid = getTableCellOccupancyGrid(block);\n\n if (relativeRowIndex < 0 || relativeRowIndex >= occupancyGrid.length) {\n return [];\n }\n\n // First need to resolve the relative row index to an absolute row index\n let absoluteRow = 0;\n\n // Jump through the occupied cells ${relativeCellIndices.row} times to find the absolute row position\n for (let i = 0; i < relativeRowIndex; i++) {\n const cell = occupancyGrid[absoluteRow]?.[0];\n\n if (!cell) {\n return [];\n }\n\n // Skip the cells that the rowspan takes up\n absoluteRow += cell.rowspan;\n }\n\n // Then for each column, get the cell at the absolute row index as a relative cell index\n const cells = new Array(occupancyGrid[0].length)\n .fill(false)\n .map((_v, col) => {\n return getRelativeTableCells(\n { row: absoluteRow, col },\n block,\n occupancyGrid,\n );\n })\n .filter(\n (a): a is RelativeCellIndices & { cell: TableCell<any, any> } =>\n a !== undefined,\n );\n\n // Filter out duplicates based on row and col properties\n return cells.filter((cell, index) => {\n return (\n cells.findIndex((c) => c.row === cell.row && c.col === cell.col) === index\n );\n });\n}\n\n/**\n * This will get all the cells within a relative column of a table block.\n *\n * This method always starts the search for the column at the first row of the table.\n *\n * ```\n * // Visual representation of a table\n * | A | B |\n * | C | D | E |\n * | F | G | H |\n * // \"A\" has a colspan of 2\n *\n * // getCellsAtColumnHandle(0)\n * // returns [\n * { row: 0, col: 0, cell: \"A\" },\n * { row: 1, col: 0, cell: \"C\" },\n * { row: 2, col: 0, cell: \"F\" },\n * ]\n *\n * // getCellsAtColumnHandle(1)\n * // returns [\n * { row: 0, col: 1, cell: \"B\" },\n * { row: 1, col: 2, cell: \"E\" },\n * { row: 2, col: 2, cell: \"F\" },\n * ]\n * ```\n *\n * As you can see, you may not be able to retrieve all nodes given a relative column index, as cells can span multiple columns.\n *\n * @returns All of the cells associated with the relative column of the table. (All cells that have the same relative column index)\n */\nexport function getCellsAtColumnHandle(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n relativeColumnIndex: RelativeCellIndices[\"col\"],\n) {\n const occupancyGrid = getTableCellOccupancyGrid(block);\n\n if (\n relativeColumnIndex < 0 ||\n relativeColumnIndex >= occupancyGrid[0].length\n ) {\n return [];\n }\n\n // First need to resolve the relative column index to an absolute column index\n let absoluteCol = 0;\n\n // Now that we've already resolved the absolute row position, we can jump through the occupied cells ${relativeCellIndices.col} times to find the absolute column position\n for (let i = 0; i < relativeColumnIndex; i++) {\n const cell = occupancyGrid[0]?.[absoluteCol];\n\n if (!cell) {\n return [];\n }\n\n // Skip the cells that the colspan takes up\n absoluteCol += cell.colspan;\n }\n\n // Then for each row, get the cell at the absolute column index as a relative cell index\n const cells = new Array(occupancyGrid.length)\n .fill(false)\n .map((_v, row) => {\n return getRelativeTableCells(\n { row, col: absoluteCol },\n block,\n occupancyGrid,\n );\n })\n .filter(\n (a): a is RelativeCellIndices & { cell: TableCell<any, any> } =>\n a !== undefined,\n );\n\n // Filter out duplicates based on row and col properties\n return cells.filter((cell, index) => {\n return (\n cells.findIndex((c) => c.row === cell.row && c.col === cell.col) === index\n );\n });\n}\n\n/**\n * This moves a column from one index to another.\n *\n * @note This is a destructive operation, it will modify the provided {@link OccupancyGrid} in place.\n */\nexport function moveColumn(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n fromColIndex: RelativeCellIndices[\"col\"],\n toColIndex: RelativeCellIndices[\"col\"],\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): TableContent<any, any>[\"rows\"] {\n // To move cells in a column, we need to layout the whole table\n // and then move the cells accordingly.\n const { col: absoluteSourceCol } = getAbsoluteTableCells(\n {\n row: 0,\n col: fromColIndex,\n },\n block,\n occupancyGrid,\n );\n const { col: absoluteTargetCol } = getAbsoluteTableCells(\n {\n row: 0,\n col: toColIndex,\n },\n block,\n occupancyGrid,\n );\n\n /**\n * Currently, this function assumes that the caller has already checked that the source and target columns are valid.\n * Such as by using {@link canColumnBeDraggedInto}. In the future, we may want to have the move logic be smarter\n * and handle invalid column indices in some way.\n */\n occupancyGrid.forEach((row) => {\n // Move the cell to the target column\n const [sourceCell] = row.splice(absoluteSourceCol, 1);\n row.splice(absoluteTargetCol, 0, sourceCell);\n });\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n}\n\n/**\n * This moves a row from one index to another.\n *\n * @note This is a destructive operation, it will modify the {@link OccupancyGrid} in place.\n */\nexport function moveRow(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n fromRowIndex: RelativeCellIndices[\"row\"],\n toRowIndex: RelativeCellIndices[\"row\"],\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): TableContent<any, any>[\"rows\"] {\n // To move cells in a column, we need to layout the whole table\n // and then move the cells accordingly.\n const { row: absoluteSourceRow } = getAbsoluteTableCells(\n {\n row: fromRowIndex,\n col: 0,\n },\n block,\n occupancyGrid,\n );\n const { row: absoluteTargetRow } = getAbsoluteTableCells(\n {\n row: toRowIndex,\n col: 0,\n },\n block,\n occupancyGrid,\n );\n\n /**\n * Currently, this function assumes that the caller has already checked that the source and target rows are valid.\n * Such as by using {@link canRowBeDraggedInto}. In the future, we may want to have the move logic be smarter\n * and handle invalid row indices in some way.\n */\n const [sourceRow] = occupancyGrid.splice(absoluteSourceRow, 1);\n occupancyGrid.splice(absoluteTargetRow, 0, sourceRow);\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n}\n\n/**\n * This will check if a cell is empty.\n *\n * @returns True if the cell is empty, false otherwise.\n */\nfunction isCellEmpty(\n cell:\n | PartialTableContent<any, any>[\"rows\"][number][\"cells\"][number]\n | undefined,\n): boolean {\n if (!cell) {\n return true;\n }\n if (isPartialTableCell(cell)) {\n return isCellEmpty(cell.content);\n } else if (typeof cell === \"string\") {\n return cell.length === 0;\n } else if (Array.isArray(cell)) {\n return cell.every((c) =>\n typeof c === \"string\"\n ? c.length === 0\n : isStyledTextInlineContent(c)\n ? c.text.length === 0\n : isPartialLinkInlineContent(c)\n ? typeof c.content === \"string\"\n ? c.content.length === 0\n : c.content.every((s) => s.text.length === 0)\n : false,\n );\n } else {\n return false;\n }\n}\n\n/**\n * This will remove empty rows or columns from the table.\n *\n * @note This is a destructive operation, it will modify the {@link OccupancyGrid} in place.\n */\nexport function cropEmptyRowsOrColumns(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n removeEmpty: \"columns\" | \"rows\",\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): TableContent<any, any>[\"rows\"] {\n if (removeEmpty === \"columns\") {\n // strips empty columns on the right\n let emptyColsOnRight = 0;\n for (\n let cellIndex = occupancyGrid[0].length - 1;\n cellIndex >= 0;\n cellIndex--\n ) {\n const isEmpty = occupancyGrid.every(\n (row) =>\n isCellEmpty(row[cellIndex].cell) && row[cellIndex].colspan === 1,\n );\n if (!isEmpty) {\n break;\n }\n\n emptyColsOnRight++;\n }\n\n for (let i = occupancyGrid.length - 1; i >= 0; i--) {\n // We maintain at least one cell, even if all the cells are empty\n const cellsToRemove = Math.max(\n occupancyGrid[i].length - emptyColsOnRight,\n 1,\n );\n occupancyGrid[i] = occupancyGrid[i].slice(0, cellsToRemove);\n }\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n }\n\n // strips empty rows at the bottom\n let emptyRowsOnBottom = 0;\n for (let rowIndex = occupancyGrid.length - 1; rowIndex >= 0; rowIndex--) {\n const isEmpty = occupancyGrid[rowIndex].every(\n (cell) => isCellEmpty(cell.cell) && cell.rowspan === 1,\n );\n if (!isEmpty) {\n break;\n }\n\n emptyRowsOnBottom++;\n }\n\n // We maintain at least one row, even if all the rows are empty\n const rowsToRemove = Math.min(emptyRowsOnBottom, occupancyGrid.length - 1);\n\n occupancyGrid.splice(occupancyGrid.length - rowsToRemove, rowsToRemove);\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n}\n\n/**\n * This will add a specified number of rows or columns to the table (filling with empty cells).\n *\n * @note This is a destructive operation, it will modify the {@link OccupancyGrid} in place.\n */\nexport function addRowsOrColumns(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n addType: \"columns\" | \"rows\",\n /**\n * The number of rows or columns to add.\n *\n * @note if negative, it will remove rows or columns.\n */\n numToAdd: number,\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): TableContent<any, any>[\"rows\"] {\n const { width, height } = getDimensionsOfTable(block);\n\n if (addType === \"columns\") {\n // Add empty columns to the right\n occupancyGrid.forEach((row, rowIndex) => {\n if (numToAdd >= 0) {\n for (let i = 0; i < numToAdd; i++) {\n row.push({\n row: rowIndex,\n col: Math.max(...row.map((r) => r.col)) + 1,\n rowspan: 1,\n colspan: 1,\n cell: mapTableCell(\"\"),\n });\n }\n } else {\n // Remove columns on the right\n row.splice(width + numToAdd, -1 * numToAdd);\n }\n });\n } else {\n if (numToAdd > 0) {\n // Add empty rows to the bottom\n for (let i = 0; i < numToAdd; i++) {\n const newRow = new Array(width).fill(null).map((_, colIndex) => ({\n row: height + i,\n col: colIndex,\n rowspan: 1,\n colspan: 1,\n cell: mapTableCell(\"\"),\n }));\n occupancyGrid.push(newRow);\n }\n } else if (numToAdd < 0) {\n // Remove rows at the bottom\n occupancyGrid.splice(height + numToAdd, -1 * numToAdd);\n }\n }\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n}\n\n/**\n * Checks if a row can be safely dropped at the target row index without splitting merged cells.\n */\nexport function canRowBeDraggedInto(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n draggingIndex: RelativeCellIndices[\"row\"],\n targetRowIndex: RelativeCellIndices[\"row\"],\n) {\n // Check cells at the target row\n const targetCells = getCellsAtRowHandle(block, targetRowIndex);\n\n // If no cells have rowspans > 1, dragging is always allowed\n const hasMergedCells = targetCells.some((cell) => getRowspan(cell.cell) > 1);\n if (!hasMergedCells) {\n return true;\n }\n\n let endRowIndex = targetRowIndex;\n let startRowIndex = targetRowIndex;\n targetCells.forEach((cell) => {\n const rowspan = getRowspan(cell.cell);\n endRowIndex = Math.max(endRowIndex, cell.row + rowspan - 1);\n startRowIndex = Math.min(startRowIndex, cell.row);\n });\n\n // Check the direction of the drag\n const isDraggingDown = draggingIndex < targetRowIndex;\n\n // Allow dragging only at the start/end of merged cells\n // Otherwise, the target row was within a merged cell which we don't allow\n return isDraggingDown\n ? targetRowIndex === endRowIndex\n : targetRowIndex === startRowIndex;\n}\n\n/**\n * Checks if a column can be safely dropped at the target column index without splitting merged cells.\n */\nexport function canColumnBeDraggedInto(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n draggingIndex: RelativeCellIndices[\"col\"],\n targetColumnIndex: RelativeCellIndices[\"col\"],\n) {\n // Check cells at the target column\n const targetCells = getCellsAtColumnHandle(block, targetColumnIndex);\n\n // If no cells have colspans > 1, dragging is always allowed\n const hasMergedCells = targetCells.some((cell) => getColspan(cell.cell) > 1);\n if (!hasMergedCells) {\n return true;\n }\n\n let endColumnIndex = targetColumnIndex;\n let startColumnIndex = targetColumnIndex;\n targetCells.forEach((cell) => {\n const colspan = getColspan(cell.cell);\n endColumnIndex = Math.max(endColumnIndex, cell.col + colspan - 1);\n startColumnIndex = Math.min(startColumnIndex, cell.col);\n });\n\n // Check the direction of the drag\n const isDraggingRight = draggingIndex < targetColumnIndex;\n\n // Allow dragging only at the start/end of merged cells\n // Otherwise, the target column was within a merged cell which we don't allow\n return isDraggingRight\n ? targetColumnIndex === endColumnIndex\n : targetColumnIndex === startColumnIndex;\n}\n\n/**\n * Checks if two cells are in the same column.\n *\n * @returns True if the cells are in the same column, false otherwise.\n */\nexport function areInSameColumn(\n from: RelativeCellIndices,\n to: RelativeCellIndices,\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n) {\n // Table indices are relative to the table, so we need to resolve the absolute cell indices\n const anchorAbsoluteCellIndices = getAbsoluteTableCells(from, block);\n\n // Table indices are relative to the table, so we need to resolve the absolute cell indices\n const headAbsoluteCellIndices = getAbsoluteTableCells(to, block);\n\n // Compare the column indices to determine the merge direction\n return anchorAbsoluteCellIndices.col === headAbsoluteCellIndices.col;\n}\n","import { Attrs, Fragment, Mark, Node, Schema } from \"@tiptap/pm/model\";\n\nimport UniqueID from \"../../extensions/tiptap-extensions/UniqueID/UniqueID.js\";\nimport type {\n InlineContentSchema,\n PartialCustomInlineContentFromConfig,\n PartialInlineContent,\n PartialLink,\n PartialTableContent,\n StyleSchema,\n StyledText,\n} from \"../../schema\";\n\nimport type { PartialBlock } from \"../../blocks/defaultBlocks\";\nimport {\n isPartialLinkInlineContent,\n isStyledTextInlineContent,\n} from \"../../schema/inlineContent/types.js\";\nimport { getColspan, isPartialTableCell } from \"../../util/table.js\";\nimport { UnreachableCaseError } from \"../../util/typescript.js\";\nimport { getAbsoluteTableCells } from \"../blockManipulation/tables/tables.js\";\nimport { getStyleSchema } from \"../pmUtil.js\";\n\n/**\n * Convert a StyledText inline element to a\n * prosemirror text node with the appropriate marks\n */\nfunction styledTextToNodes<T extends StyleSchema>(\n styledText: StyledText<T>,\n schema: Schema,\n styleSchema: T,\n blockType?: string,\n): Node[] {\n const marks: Mark[] = [];\n\n for (const [style, value] of Object.entries(styledText.styles || {})) {\n const config = styleSchema[style];\n if (!config) {\n throw new Error(`style ${style} not found in styleSchema`);\n }\n\n if (config.propSchema === \"boolean\") {\n if (value) {\n marks.push(schema.mark(style));\n }\n } else if (config.propSchema === \"string\") {\n if (value) {\n marks.push(schema.mark(style, { stringValue: value }));\n }\n } else {\n throw new UnreachableCaseError(config.propSchema);\n }\n }\n\n const parseHardBreaks = !blockType || !schema.nodes[blockType].spec.code;\n\n if (!parseHardBreaks) {\n return styledText.text.length > 0\n ? [schema.text(styledText.text, marks)]\n : [];\n }\n\n return (\n styledText.text\n // Splits text & line breaks.\n .split(/(\\n)/g)\n // If the content ends with a line break, an empty string is added to the\n // end, which this removes.\n .filter((text) => text.length > 0)\n // Converts text & line breaks to nodes.\n .map((text) => {\n if (text === \"\\n\") {\n return schema.nodes[\"hardBreak\"].createChecked();\n } else {\n return schema.text(text, marks);\n }\n })\n );\n}\n\n/**\n * Converts a Link inline content element to\n * prosemirror text nodes with the appropriate marks\n */\nfunction linkToNodes(\n link: PartialLink<StyleSchema>,\n schema: Schema,\n styleSchema: StyleSchema,\n): Node[] {\n const linkMark = schema.marks.link.create({\n href: link.href,\n });\n\n return styledTextArrayToNodes(link.content, schema, styleSchema).map(\n (node) => {\n if (node.type.name === \"text\") {\n return node.mark([...node.marks, linkMark]);\n }\n\n if (node.type.name === \"hardBreak\") {\n return node;\n }\n throw new Error(\"unexpected node type\");\n },\n );\n}\n\n/**\n * Converts an array of StyledText inline content elements to\n * prosemirror text nodes with the appropriate marks\n */\nfunction styledTextArrayToNodes<S extends StyleSchema>(\n content: string | StyledText<S>[],\n schema: Schema,\n styleSchema: S,\n blockType?: string,\n): Node[] {\n const nodes: Node[] = [];\n\n if (typeof content === \"string\") {\n nodes.push(\n ...styledTextToNodes(\n { type: \"text\", text: content, styles: {} },\n schema,\n styleSchema,\n blockType,\n ),\n );\n return nodes;\n }\n\n for (const styledText of content) {\n nodes.push(\n ...styledTextToNodes(styledText, schema, styleSchema, blockType),\n );\n }\n return nodes;\n}\n\n/**\n * converts an array of inline content elements to prosemirror nodes\n */\nexport function inlineContentToNodes<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n blockContent: PartialInlineContent<I, S>,\n schema: Schema,\n blockType?: string,\n styleSchema: S = getStyleSchema(schema),\n): Node[] {\n const nodes: Node[] = [];\n\n for (const content of blockContent) {\n if (typeof content === \"string\") {\n nodes.push(\n ...styledTextArrayToNodes(content, schema, styleSchema, blockType),\n );\n } else if (isPartialLinkInlineContent(content)) {\n nodes.push(...linkToNodes(content, schema, styleSchema));\n } else if (isStyledTextInlineContent(content)) {\n nodes.push(\n ...styledTextArrayToNodes([content], schema, styleSchema, blockType),\n );\n } else {\n nodes.push(\n blockOrInlineContentToContentNode(content, schema, styleSchema),\n );\n }\n }\n return nodes;\n}\n\n/**\n * converts an array of inline content elements to prosemirror nodes\n */\nexport function tableContentToNodes<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n tableContent: PartialTableContent<I, S>,\n schema: Schema,\n styleSchema: StyleSchema = getStyleSchema(schema),\n): Node[] {\n const rowNodes: Node[] = [];\n // Header rows and columns are used to determine the type of the cell\n // If headerRows is 1, then the first row is a header row\n const headerRows = new Array(tableContent.headerRows ?? 0).fill(true);\n // If headerCols is 1, then the first column is a header column\n const headerCols = new Array(tableContent.headerCols ?? 0).fill(true);\n\n const columnWidths: (number | undefined)[] = tableContent.columnWidths ?? [];\n\n for (let rowIndex = 0; rowIndex < tableContent.rows.length; rowIndex++) {\n const row = tableContent.rows[rowIndex];\n const columnNodes: Node[] = [];\n const isHeaderRow = headerRows[rowIndex];\n for (let cellIndex = 0; cellIndex < row.cells.length; cellIndex++) {\n const cell = row.cells[cellIndex];\n const isHeaderCol = headerCols[cellIndex];\n /**\n * The attributes of the cell to apply to the node\n */\n const attrs: Attrs | undefined = undefined;\n /**\n * The content of the cell to apply to the node\n */\n let content: Fragment | Node | readonly Node[] | null = null;\n\n // Colwidths are absolutely referenced to the table, so we need to resolve the relative cell index to the absolute cell index\n const absoluteCellIndex = getAbsoluteTableCells(\n {\n row: rowIndex,\n col: cellIndex,\n },\n { type: \"table\", content: tableContent } as any,\n );\n\n // Assume the column width is the width of the cell at the absolute cell index\n let colwidth: (number | undefined)[] | null = columnWidths[\n absoluteCellIndex.col\n ]\n ? [columnWidths[absoluteCellIndex.col]]\n : null;\n\n if (!cell) {\n // No-op\n } else if (typeof cell === \"string\") {\n content = schema.text(cell);\n } else if (isPartialTableCell(cell)) {\n if (cell.content) {\n content = inlineContentToNodes(\n cell.content,\n schema,\n \"tableParagraph\",\n styleSchema,\n );\n }\n const colspan = getColspan(cell);\n\n if (colspan > 1) {\n // If the cell has a > 1 colspan, we need to get the column width for each cell in the span\n colwidth = new Array(colspan).fill(false).map((_, i) => {\n // Starting from the absolute column index, get the column width for each cell in the span\n return columnWidths[absoluteCellIndex.col + i] ?? undefined;\n });\n }\n } else {\n content = inlineContentToNodes(\n cell,\n schema,\n \"tableParagraph\",\n styleSchema,\n );\n }\n\n const cellNode = schema.nodes[\n isHeaderCol || isHeaderRow ? \"tableHeader\" : \"tableCell\"\n ].createChecked(\n {\n ...(isPartialTableCell(cell) ? cell.props : {}),\n colwidth,\n },\n schema.nodes[\"tableParagraph\"].createChecked(attrs, content),\n );\n columnNodes.push(cellNode);\n }\n\n const rowNode = schema.nodes[\"tableRow\"].createChecked({}, columnNodes);\n rowNodes.push(rowNode);\n }\n return rowNodes;\n}\n\nfunction blockOrInlineContentToContentNode(\n block:\n | PartialBlock<any, any, any>\n | PartialCustomInlineContentFromConfig<any, any>,\n schema: Schema,\n styleSchema: StyleSchema,\n) {\n let contentNode: Node;\n let type = block.type;\n\n // TODO: needed? came from previous code\n if (type === undefined) {\n type = \"paragraph\";\n }\n\n if (!schema.nodes[type]) {\n throw new Error(`node type ${type} not found in schema`);\n }\n\n if (!block.content) {\n contentNode = schema.nodes[type].createChecked(block.props);\n } else if (typeof block.content === \"string\") {\n const nodes = inlineContentToNodes(\n [block.content],\n schema,\n type,\n styleSchema,\n );\n contentNode = schema.nodes[type].createChecked(block.props, nodes);\n } else if (Array.isArray(block.content)) {\n const nodes = inlineContentToNodes(\n block.content,\n schema,\n type,\n styleSchema,\n );\n contentNode = schema.nodes[type].createChecked(block.props, nodes);\n } else if (block.content.type === \"tableContent\") {\n const nodes = tableContentToNodes(block.content, schema, styleSchema);\n contentNode = schema.nodes[type].createChecked(block.props, nodes);\n } else {\n throw new UnreachableCaseError(block.content.type);\n }\n return contentNode;\n}\n\n/**\n * Converts a BlockNote block to a Prosemirror node.\n */\nexport function blockToNode(\n block: PartialBlock<any, any, any>,\n schema: Schema,\n styleSchema: StyleSchema = getStyleSchema(schema),\n) {\n let id = block.id;\n\n if (id === undefined) {\n id = UniqueID.options.generateID();\n }\n\n const children: Node[] = [];\n\n if (block.children) {\n for (const child of block.children) {\n children.push(blockToNode(child, schema, styleSchema));\n }\n }\n\n const isBlockContent =\n !block.type || // can happen if block.type is not defined (this should create the default node)\n schema.nodes[block.type].isInGroup(\"blockContent\");\n\n if (isBlockContent) {\n // Blocks with a type that matches \"blockContent\" group always need to be wrapped in a blockContainer\n\n const contentNode = blockOrInlineContentToContentNode(\n block,\n schema,\n styleSchema,\n );\n\n const groupNode =\n children.length > 0\n ? schema.nodes[\"blockGroup\"].createChecked({}, children)\n : undefined;\n\n return schema.nodes[\"blockContainer\"].createChecked(\n {\n id: id,\n ...block.props,\n },\n groupNode ? [contentNode, groupNode] : contentNode,\n );\n } else if (schema.nodes[block.type].isInGroup(\"bnBlock\")) {\n // this is a bnBlock node like Column or ColumnList that directly translates to a prosemirror node\n return schema.nodes[block.type].createChecked(\n {\n id: id,\n ...block.props,\n },\n children,\n );\n } else {\n throw new Error(\n `block type ${block.type} doesn't match blockContent or bnBlock group`,\n );\n }\n}\n"],"names":["removeDuplicates","array","by","seen","item","key","findDuplicates","items","filtered","el","index","UniqueID","Extension","testOptions","v4","element","attributes","defaultIdAttributes","dragSourceElement","transformPasted","Plugin","PluginKey","transactions","oldState","newState","docChanges","transaction","filterTransactions","tr","_b","_a","types","attributeName","generateID","transform","combineTransactionSteps","mapping","getChangedRanges","newRange","newNodes","findChildrenInRange","node","newIds","id","duplicatedNewIds","pos","initialDoc","jsonNode","deleted","view","handleDragstart","event","slice","removeId","fragment","list","nodeWithoutId","Fragment","Slice","isLinkInlineContent","content","isPartialLinkInlineContent","isStyledTextInlineContent","mapTableCell","isTableCell","isPartialTableCell","_c","_d","_e","getColspan","cell","getRowspan","UnreachableCaseError","val","assertEmpty","obj","throwError","dataTest","rest","getNearestBlockPos","doc","$pos","depth","allBlockContainerPositions","resolvedPos","position","getBlockInfoWithManualOffset","bnBlockBeforePosOffset","bnBlockNode","bnBlockBeforePos","bnBlockAfterPos","bnBlock","blockContent","blockGroup","offset","blockContentNode","blockContentBeforePos","blockContentAfterPos","blockGroupNode","blockGroupBeforePos","blockGroupAfterPos","getBlockInfo","posInfo","getBlockInfoFromResolvedPos","getBlockInfoFromSelection","state","getBlockInfoFromTransaction","getPmSchema","trOrNode","getBlockNoteEditor","schema","getBlockNoteSchema","getBlockSchema","getInlineContentSchema","getStyleSchema","getBlockCache","contentNodeToTableContent","contentNode","inlineContentSchema","styleSchema","ret","headerMatrix","rowNode","_offset","rowIndex","row","cellNode","colWidth","cellIndex","child","contentNodeToInlineContent","acc","contentPartial","last","first","isHeader","currentContent","nodeToCustomInlineContent","styles","linkMark","mark","config","props","icConfig","attr","value","propSchema","nodeToBlock","blockSchema","blockCache","cachedBlock","blockInfo","blockSpec","blockConfig","children","block","docToBlocks","blocks","prosemirrorSliceToSlicedBlocks","processNode","openStart","openEnd","blockCutAtStart","blockCutAtEnd","blockContainer","isFirstBlock","isLastBlock","childGroup","childBlocks","getTableCellOccupancyGrid","height","width","getDimensionsOfTable","grid","findNextAvailable","col","j","rowspan","colspan","startRow","startCol","i","getTableRowsFromOccupancyGrid","occupancyGrid","getAbsoluteTableCells","relativeCellIndices","r","c","rowWidth","getRelativeTableCells","absoluteCellIndices","occupancyCell","getCellsAtRowHandle","relativeRowIndex","absoluteRow","cells","_v","a","getCellsAtColumnHandle","relativeColumnIndex","absoluteCol","moveColumn","fromColIndex","toColIndex","absoluteSourceCol","absoluteTargetCol","sourceCell","moveRow","fromRowIndex","toRowIndex","absoluteSourceRow","absoluteTargetRow","sourceRow","isCellEmpty","s","cropEmptyRowsOrColumns","removeEmpty","emptyColsOnRight","cellsToRemove","emptyRowsOnBottom","rowsToRemove","addRowsOrColumns","addType","numToAdd","newRow","_","colIndex","canRowBeDraggedInto","draggingIndex","targetRowIndex","targetCells","endRowIndex","startRowIndex","canColumnBeDraggedInto","targetColumnIndex","endColumnIndex","startColumnIndex","areInSameColumn","from","to","anchorAbsoluteCellIndices","headAbsoluteCellIndices","styledTextToNodes","styledText","blockType","marks","style","text","linkToNodes","link","styledTextArrayToNodes","nodes","inlineContentToNodes","blockOrInlineContentToContentNode","tableContentToNodes","tableContent","rowNodes","headerRows","headerCols","columnWidths","columnNodes","isHeaderRow","isHeaderCol","attrs","absoluteCellIndex","colwidth","type","blockToNode","groupNode"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"blockToNode-CumVjgem.cjs","sources":["../src/extensions/tiptap-extensions/UniqueID/UniqueID.ts","../src/schema/inlineContent/types.ts","../src/util/table.ts","../src/util/typescript.ts","../src/api/getBlockInfoFromPos.ts","../src/api/pmUtil.ts","../src/api/nodeConversions/nodeToBlock.ts","../src/api/blockManipulation/tables/tables.ts","../src/api/nodeConversions/blockToNode.ts"],"sourcesContent":["import {\n combineTransactionSteps,\n Extension,\n findChildrenInRange,\n getChangedRanges,\n} from \"@tiptap/core\";\nimport { Fragment, Slice } from \"prosemirror-model\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\nimport { v4 } from \"uuid\";\n\n/**\n * Code from Tiptap UniqueID extension (https://tiptap.dev/api/extensions/unique-id)\n * This extension is licensed under MIT (even though it's part of Tiptap pro).\n *\n * If you're a user of BlockNote, we still recommend to support their awesome work and become a sponsor!\n * https://tiptap.dev/pro\n */\n\n/**\n * Removes duplicated values within an array.\n * Supports numbers, strings and objects.\n */\nfunction removeDuplicates(array: any, by = JSON.stringify) {\n const seen: any = {};\n return array.filter((item: any) => {\n const key = by(item);\n return Object.prototype.hasOwnProperty.call(seen, key)\n ? false\n : (seen[key] = true);\n });\n}\n\n/**\n * Returns a list of duplicated items within an array.\n */\nfunction findDuplicates(items: any) {\n const filtered = items.filter(\n (el: any, index: number) => items.indexOf(el) !== index,\n );\n const duplicates = removeDuplicates(filtered);\n return duplicates;\n}\n\nconst UniqueID = Extension.create({\n name: \"uniqueID\",\n // we’ll set a very high priority to make sure this runs first\n // and is compatible with `appendTransaction` hooks of other extensions\n priority: 10000,\n addOptions() {\n return {\n attributeName: \"id\",\n types: [],\n setIdAttribute: false,\n generateID: () => {\n // Use mock ID if tests are running.\n if (typeof window !== \"undefined\" && (window as any).__TEST_OPTIONS) {\n const testOptions = (window as any).__TEST_OPTIONS;\n if (testOptions.mockID === undefined) {\n testOptions.mockID = 0;\n } else {\n testOptions.mockID++;\n }\n\n return testOptions.mockID.toString() as string;\n }\n\n return v4();\n },\n filterTransaction: null,\n };\n },\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n [this.options.attributeName]: {\n default: null,\n parseHTML: (element) =>\n element.getAttribute(`data-${this.options.attributeName}`),\n renderHTML: (attributes) => {\n const defaultIdAttributes = {\n [`data-${this.options.attributeName}`]:\n attributes[this.options.attributeName],\n };\n if (this.options.setIdAttribute) {\n return {\n ...defaultIdAttributes,\n id: attributes[this.options.attributeName],\n };\n } else {\n return defaultIdAttributes;\n }\n },\n },\n },\n },\n ];\n },\n // check initial content for missing ids\n // onCreate() {\n // // Don’t do this when the collaboration extension is active\n // // because this may update the content, so Y.js tries to merge these changes.\n // // This leads to empty block nodes.\n // // See: https://github.com/ueberdosis/tiptap/issues/2400\n // if (\n // this.editor.extensionManager.extensions.find(\n // (extension) => extension.name === \"collaboration\"\n // )\n // ) {\n // return;\n // }\n // const { view, state } = this.editor;\n // const { tr, doc } = state;\n // const { types, attributeName, generateID } = this.options;\n // const nodesWithoutId = findChildren(doc, (node) => {\n // return (\n // types.includes(node.type.name) && node.attrs[attributeName] === null\n // );\n // });\n // nodesWithoutId.forEach(({ node, pos }) => {\n // tr.setNodeMarkup(pos, undefined, {\n // ...node.attrs,\n // [attributeName]: generateID(),\n // });\n // });\n // tr.setMeta(\"addToHistory\", false);\n // view.dispatch(tr);\n // },\n addProseMirrorPlugins() {\n let dragSourceElement: any = null;\n let transformPasted = false;\n return [\n new Plugin({\n key: new PluginKey(\"uniqueID\"),\n appendTransaction: (transactions, oldState, newState) => {\n const docChanges =\n transactions.some((transaction) => transaction.docChanged) &&\n !oldState.doc.eq(newState.doc);\n const filterTransactions =\n this.options.filterTransaction &&\n transactions.some((tr) => !this.options.filterTransaction?.(tr));\n if (!docChanges || filterTransactions) {\n return;\n }\n const { tr } = newState;\n const { types, attributeName, generateID } = this.options;\n const transform = combineTransactionSteps(\n oldState.doc,\n transactions as any,\n );\n const { mapping } = transform;\n // get changed ranges based on the old state\n const changes = getChangedRanges(transform);\n\n changes.forEach(({ newRange }) => {\n const newNodes = findChildrenInRange(\n newState.doc,\n newRange,\n (node) => {\n return types.includes(node.type.name);\n },\n );\n const newIds = newNodes\n .map(({ node }) => node.attrs[attributeName])\n .filter((id) => id !== null);\n const duplicatedNewIds = findDuplicates(newIds);\n\n newNodes.forEach(({ node, pos }) => {\n // instead of checking `node.attrs[attributeName]` directly\n // we look at the current state of the node within `tr.doc`.\n // this helps to prevent adding new ids to the same node\n // if the node changed multiple times within one transaction\n const id = tr.doc.nodeAt(pos)?.attrs[attributeName];\n\n if (id === null) {\n // edge case, when using collaboration, yjs will set the id to null in `_forceRerender`\n // when loading the editor\n // this checks for this case and keeps it at initialBlockId so there will be no change\n const initialDoc = oldState.doc.type.createAndFill()!.content;\n const wasInitial =\n oldState.doc.content.findDiffStart(initialDoc) === null;\n\n if (wasInitial) {\n // the old state was the \"initial content\"\n const jsonNode = JSON.parse(\n JSON.stringify(newState.doc.toJSON()),\n );\n jsonNode.content[0].content[0].attrs.id = \"initialBlockId\";\n // would the new state with the fix also be the \"initial content\"?\n if (\n JSON.stringify(jsonNode.content) ===\n JSON.stringify(initialDoc.toJSON())\n ) {\n // yes, apply the fix\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: \"initialBlockId\",\n });\n return;\n }\n }\n\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n });\n return;\n }\n // check if the node doesn’t exist in the old state\n const { deleted } = mapping.invert().mapResult(pos);\n const newNode = deleted && duplicatedNewIds.includes(id);\n if (newNode) {\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n });\n }\n });\n });\n if (!tr.steps.length) {\n return;\n }\n // mark the transaction as having been processed by the uniqueID plugin\n tr.setMeta(\"uniqueID\", true);\n return tr;\n },\n // we register a global drag handler to track the current drag source element\n view(view) {\n const handleDragstart = (event: any) => {\n let _a;\n dragSourceElement = (\n (_a = view.dom.parentElement) === null || _a === void 0\n ? void 0\n : _a.contains(event.target)\n )\n ? view.dom.parentElement\n : null;\n };\n window.addEventListener(\"dragstart\", handleDragstart);\n return {\n destroy() {\n window.removeEventListener(\"dragstart\", handleDragstart);\n },\n };\n },\n props: {\n // `handleDOMEvents` is called before `transformPasted` so we can do\n // some checks before. However, `transformPasted` only runs when\n // editor content is pasted - not external content.\n handleDOMEvents: {\n // only create new ids for dropped content while holding `alt`\n // or content is dragged from another editor\n drop: (view, event: any) => {\n let _a;\n if (\n dragSourceElement !== view.dom.parentElement ||\n ((_a = event.dataTransfer) === null || _a === void 0\n ? void 0\n : _a.effectAllowed) === \"copy\"\n ) {\n transformPasted = true;\n } else {\n transformPasted = false;\n }\n\n dragSourceElement = null;\n\n return false;\n },\n // always create new ids on pasted content\n paste: () => {\n transformPasted = true;\n return false;\n },\n },\n // we’ll remove ids for every pasted node\n // so we can create a new one within `appendTransaction`\n transformPasted: (slice) => {\n if (!transformPasted) {\n return slice;\n }\n const { types, attributeName } = this.options;\n const removeId = (fragment: any) => {\n const list: any[] = [];\n fragment.forEach((node: any) => {\n // don’t touch text nodes\n if (node.isText) {\n list.push(node);\n return;\n }\n // check for any other child nodes\n if (!types.includes(node.type.name)) {\n list.push(node.copy(removeId(node.content)));\n return;\n }\n // remove id\n const nodeWithoutId = node.type.create(\n {\n ...node.attrs,\n [attributeName]: null,\n },\n removeId(node.content),\n node.marks,\n );\n list.push(nodeWithoutId);\n });\n return Fragment.from(list);\n };\n // reset check\n transformPasted = false;\n return new Slice(\n removeId(slice.content),\n slice.openStart,\n slice.openEnd,\n );\n },\n },\n }),\n ];\n },\n});\n\nexport { UniqueID as default, UniqueID };\n","import { Node } from \"@tiptap/core\";\nimport { PropSchema, Props } from \"../propTypes.js\";\nimport { StyleSchema, Styles } from \"../styles/types.js\";\nimport { BlockNoteEditor } from \"../../editor/BlockNoteEditor.js\";\nimport { ViewMutationRecord } from \"prosemirror-view\";\n\nexport type CustomInlineContentConfig = {\n type: string;\n content: \"styled\" | \"none\"; // | \"plain\"\n readonly propSchema: PropSchema;\n};\n// InlineContentConfig contains the \"schema\" info about an InlineContent type\n// i.e. what props it supports, what content it supports, etc.\nexport type InlineContentConfig = CustomInlineContentConfig | \"text\" | \"link\";\n\n// InlineContentImplementation contains the \"implementation\" info about an InlineContent element\n// such as the functions / Nodes required to render and / or serialize it\n// @ts-ignore\nexport type InlineContentImplementation<T extends InlineContentConfig> =\n T extends \"link\" | \"text\"\n ? undefined\n : {\n meta?: {\n draggable?: boolean;\n };\n node: Node;\n toExternalHTML?: (\n inlineContent: any,\n editor: BlockNoteEditor<any, any, any>,\n ) =>\n | {\n dom: HTMLElement | DocumentFragment;\n contentDOM?: HTMLElement;\n }\n | undefined;\n render: (\n inlineContent: any,\n updateInlineContent: (update: any) => void,\n editor: BlockNoteEditor<any, any, any>,\n ) => {\n dom: HTMLElement | DocumentFragment;\n contentDOM?: HTMLElement;\n ignoreMutation?: (mutation: ViewMutationRecord) => boolean;\n destroy?: () => void;\n };\n runsBefore?: string[];\n };\n\nexport type InlineContentSchemaWithInlineContent<\n IType extends string,\n C extends InlineContentConfig,\n> = {\n [k in IType]: C;\n};\n\n// Container for both the config and implementation of InlineContent,\n// and the type of `implementation` is based on that of the config\nexport type InlineContentSpec<T extends InlineContentConfig> = {\n config: T;\n implementation: InlineContentImplementation<T>;\n};\n\n// A Schema contains all the types (Configs) supported in an editor\n// The keys are the \"type\" of InlineContent elements\nexport type InlineContentSchema = Record<string, InlineContentConfig>;\n\nexport type InlineContentSpecs = {\n text: { config: \"text\"; implementation: undefined };\n link: { config: \"link\"; implementation: undefined };\n} & Record<string, InlineContentSpec<InlineContentConfig>>;\n\nexport type InlineContentSchemaFromSpecs<T extends InlineContentSpecs> = {\n [K in keyof T]: T[K][\"config\"];\n};\n\nexport type CustomInlineContentFromConfig<\n I extends CustomInlineContentConfig,\n S extends StyleSchema,\n> = {\n type: I[\"type\"];\n props: Props<I[\"propSchema\"]>;\n content: I[\"content\"] extends \"styled\"\n ? StyledText<S>[]\n : I[\"content\"] extends \"plain\"\n ? string\n : I[\"content\"] extends \"none\"\n ? undefined\n : never;\n};\n\nexport type InlineContentFromConfig<\n I extends InlineContentConfig,\n S extends StyleSchema,\n> = I extends \"text\"\n ? StyledText<S>\n : I extends \"link\"\n ? Link<S>\n : I extends CustomInlineContentConfig\n ? CustomInlineContentFromConfig<I, S>\n : never;\n\nexport type PartialCustomInlineContentFromConfig<\n I extends CustomInlineContentConfig,\n S extends StyleSchema,\n> = {\n type: I[\"type\"];\n props?: Props<I[\"propSchema\"]>;\n content?: I[\"content\"] extends \"styled\"\n ? StyledText<S>[] | string\n : I[\"content\"] extends \"plain\"\n ? string\n : I[\"content\"] extends \"none\"\n ? undefined\n : never;\n};\n\nexport type PartialInlineContentFromConfig<\n I extends InlineContentConfig,\n S extends StyleSchema,\n> = I extends \"text\"\n ? string | StyledText<S>\n : I extends \"link\"\n ? PartialLink<S>\n : I extends CustomInlineContentConfig\n ? PartialCustomInlineContentFromConfig<I, S>\n : never;\n\nexport type StyledText<T extends StyleSchema> = {\n type: \"text\";\n text: string;\n styles: Styles<T>;\n};\n\nexport type Link<T extends StyleSchema> = {\n type: \"link\";\n href: string;\n content: StyledText<T>[];\n};\n\nexport type PartialLink<T extends StyleSchema> = Omit<Link<T>, \"content\"> & {\n content: string | Link<T>[\"content\"];\n};\n\nexport type InlineContent<\n I extends InlineContentSchema,\n T extends StyleSchema,\n> = InlineContentFromConfig<I[keyof I], T>;\n\ntype PartialInlineContentElement<\n I extends InlineContentSchema,\n T extends StyleSchema,\n> = PartialInlineContentFromConfig<I[keyof I], T>;\n\nexport type PartialInlineContent<\n I extends InlineContentSchema,\n T extends StyleSchema,\n> = PartialInlineContentElement<I, T>[] | string;\n\nexport function isLinkInlineContent<T extends StyleSchema>(\n content: InlineContent<any, T>,\n): content is Link<T> {\n return content.type === \"link\";\n}\n\nexport function isPartialLinkInlineContent<T extends StyleSchema>(\n content: PartialInlineContentElement<any, T>,\n): content is PartialLink<T> {\n return typeof content !== \"string\" && content.type === \"link\";\n}\n\nexport function isStyledTextInlineContent<T extends StyleSchema>(\n content: PartialInlineContentElement<any, T>,\n): content is StyledText<T> {\n return typeof content !== \"string\" && content.type === \"text\";\n}\n","import type {\n InlineContentSchema,\n StyleSchema,\n PartialInlineContent,\n InlineContent,\n} from \"../schema\";\nimport { PartialTableCell, TableCell } from \"../schema/blocks/types.js\";\n\n/**\n * This will map a table cell to a TableCell object.\n * This is useful for when we want to get the full table cell object from a partial table cell.\n * It is guaranteed to return a new TableCell object.\n */\nexport function mapTableCell<\n T extends InlineContentSchema,\n S extends StyleSchema,\n>(\n content:\n | PartialInlineContent<T, S>\n | PartialTableCell<T, S>\n | TableCell<T, S>,\n): TableCell<T, S> {\n return isTableCell(content)\n ? { ...content }\n : isPartialTableCell(content)\n ? {\n type: \"tableCell\",\n content: ([] as InlineContent<T, S>[]).concat(content.content as any),\n props: {\n backgroundColor: content.props?.backgroundColor ?? \"default\",\n textColor: content.props?.textColor ?? \"default\",\n textAlignment: content.props?.textAlignment ?? \"left\",\n colspan: content.props?.colspan ?? 1,\n rowspan: content.props?.rowspan ?? 1,\n },\n }\n : {\n type: \"tableCell\",\n content: ([] as InlineContent<T, S>[]).concat(content as any),\n props: {\n backgroundColor: \"default\",\n textColor: \"default\",\n textAlignment: \"left\",\n colspan: 1,\n rowspan: 1,\n },\n };\n}\n\nexport function isPartialTableCell<\n T extends InlineContentSchema,\n S extends StyleSchema,\n>(\n content:\n | TableCell<T, S>\n | PartialInlineContent<T, S>\n | PartialTableCell<T, S>\n | undefined\n | null,\n): content is PartialTableCell<T, S> {\n return (\n content !== undefined &&\n content !== null &&\n typeof content !== \"string\" &&\n !Array.isArray(content) &&\n content.type === \"tableCell\"\n );\n}\n\nexport function isTableCell<\n T extends InlineContentSchema,\n S extends StyleSchema,\n>(\n content:\n | TableCell<T, S>\n | PartialInlineContent<T, S>\n | PartialTableCell<T, S>\n | undefined\n | null,\n): content is TableCell<T, S> {\n return (\n isPartialTableCell(content) &&\n content.props !== undefined &&\n content.content !== undefined\n );\n}\n\nexport function getColspan(\n cell:\n | TableCell<any, any>\n | PartialTableCell<any, any>\n | PartialInlineContent<any, any>,\n): number {\n if (isTableCell(cell)) {\n return cell.props.colspan ?? 1;\n }\n return 1;\n}\n\nexport function getRowspan(\n cell:\n | TableCell<any, any>\n | PartialTableCell<any, any>\n | PartialInlineContent<any, any>,\n): number {\n if (isTableCell(cell)) {\n return cell.props.rowspan ?? 1;\n }\n return 1;\n}\n","export class UnreachableCaseError extends Error {\n constructor(val: never) {\n super(`Unreachable case: ${val}`);\n }\n}\n\nexport function assertEmpty(obj: Record<string, never>, throwError = true) {\n const { \"data-test\": dataTest, ...rest } = obj; // exclude data-test\n\n if (Object.keys(rest).length > 0 && throwError) {\n throw new Error(\"Object must be empty \" + JSON.stringify(obj));\n }\n}\n\n// TODO: change for built-in version of typescript 5.4 after upgrade\nexport type NoInfer<T> = [T][T extends any ? 0 : never];\n","import { Node, ResolvedPos } from \"prosemirror-model\";\nimport { EditorState, Transaction } from \"prosemirror-state\";\n\ntype SingleBlockInfo = {\n node: Node;\n beforePos: number;\n afterPos: number;\n};\n\nexport type BlockInfo = {\n /**\n * The outer node that represents a BlockNote block. This is the node that has the ID.\n * Most of the time, this will be a blockContainer node, but it could also be a Column or ColumnList\n */\n bnBlock: SingleBlockInfo;\n /**\n * The type of BlockNote block that this node represents.\n * When dealing with a blockContainer, this is retrieved from the blockContent node, otherwise it's retrieved from the bnBlock node.\n */\n blockNoteType: string;\n} & (\n | {\n // In case we're not dealing with a BlockContainer, we're dealing with a \"wrapper node\" (like a Column or ColumnList), so it will always have children\n\n /**\n * The Prosemirror node that holds block.children. For non-blockContainer, this node will be the same as bnBlock.\n */\n childContainer: SingleBlockInfo;\n isBlockContainer: false;\n }\n | {\n /**\n * The Prosemirror node that holds block.children. For blockContainers, this is the blockGroup node, if it exists.\n */\n childContainer?: SingleBlockInfo;\n /**\n * The Prosemirror node that wraps block.content and has most of the props\n */\n blockContent: SingleBlockInfo;\n /**\n * Whether bnBlock is a blockContainer node\n */\n isBlockContainer: true;\n }\n);\n\n/**\n * Retrieves the position just before the nearest block node in a ProseMirror\n * doc, relative to a position. If the position is within a block node or its\n * descendants, the position just before it is returned. If the position is not\n * within a block node or its descendants, the position just before the next\n * closest block node is returned. If the position is beyond the last block, the\n * position just before the last block is returned.\n * @param doc The ProseMirror doc.\n * @param pos An integer position in the document.\n * @returns The position just before the nearest blockContainer node.\n */\nexport function getNearestBlockPos(doc: Node, pos: number) {\n const $pos = doc.resolve(pos);\n\n // Checks if the position provided is already just before a block node, in\n // which case we return the position.\n if ($pos.nodeAfter && $pos.nodeAfter.type.isInGroup(\"bnBlock\")) {\n return {\n posBeforeNode: $pos.pos,\n node: $pos.nodeAfter,\n };\n }\n\n // Checks the node containing the position and its ancestors until a\n // block node is found and returned.\n let depth = $pos.depth;\n let node = $pos.node(depth);\n while (depth > 0) {\n if (node.type.isInGroup(\"bnBlock\")) {\n return {\n posBeforeNode: $pos.before(depth),\n node: node,\n };\n }\n\n depth--;\n node = $pos.node(depth);\n }\n\n // If the position doesn't lie within a block node, we instead find the\n // position of the next closest one. If the position is beyond the last block,\n // we return the position of the last block. While running `doc.descendants`\n // is expensive, this case should be very rarely triggered. However, it's\n // possible for the position to sometimes be beyond the last block node. This\n // is a problem specifically when using the collaboration plugin.\n const allBlockContainerPositions: number[] = [];\n doc.descendants((node, pos) => {\n if (node.type.isInGroup(\"bnBlock\")) {\n allBlockContainerPositions.push(pos);\n }\n });\n\n // eslint-disable-next-line no-console\n console.warn(`Position ${pos} is not within a blockContainer node.`);\n\n const resolvedPos = doc.resolve(\n allBlockContainerPositions.find((position) => position >= pos) ||\n allBlockContainerPositions[allBlockContainerPositions.length - 1],\n );\n return {\n posBeforeNode: resolvedPos.pos,\n node: resolvedPos.nodeAfter!,\n };\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block in a\n * BlockNote document. This includes the main `blockContainer` node, the\n * `blockContent` node with the block's main body, and the optional `blockGroup`\n * node which contains the block's children. As well as the nodes, also returns\n * the ProseMirror positions just before & after each node.\n * @param node The main `blockContainer` node that the block information should\n * be retrieved from,\n * @param bnBlockBeforePosOffset the position just before the\n * `blockContainer` node in the document.\n */\nexport function getBlockInfoWithManualOffset(\n node: Node,\n bnBlockBeforePosOffset: number,\n): BlockInfo {\n if (!node.type.isInGroup(\"bnBlock\")) {\n throw new Error(\n `Attempted to get bnBlock node at position but found node of different type ${node.type.name}`,\n );\n }\n\n const bnBlockNode = node;\n const bnBlockBeforePos = bnBlockBeforePosOffset;\n const bnBlockAfterPos = bnBlockBeforePos + bnBlockNode.nodeSize;\n\n const bnBlock: SingleBlockInfo = {\n node: bnBlockNode,\n beforePos: bnBlockBeforePos,\n afterPos: bnBlockAfterPos,\n };\n\n if (bnBlockNode.type.name === \"blockContainer\") {\n let blockContent: SingleBlockInfo | undefined;\n let blockGroup: SingleBlockInfo | undefined;\n\n bnBlockNode.forEach((node, offset) => {\n if (node.type.spec.group === \"blockContent\") {\n // console.log(beforePos, offset);\n const blockContentNode = node;\n const blockContentBeforePos = bnBlockBeforePos + offset + 1;\n const blockContentAfterPos = blockContentBeforePos + node.nodeSize;\n\n blockContent = {\n node: blockContentNode,\n beforePos: blockContentBeforePos,\n afterPos: blockContentAfterPos,\n };\n } else if (node.type.name === \"blockGroup\") {\n const blockGroupNode = node;\n const blockGroupBeforePos = bnBlockBeforePos + offset + 1;\n const blockGroupAfterPos = blockGroupBeforePos + node.nodeSize;\n\n blockGroup = {\n node: blockGroupNode,\n beforePos: blockGroupBeforePos,\n afterPos: blockGroupAfterPos,\n };\n }\n });\n\n if (!blockContent) {\n throw new Error(\n `blockContainer node does not contain a blockContent node in its children: ${bnBlockNode}`,\n );\n }\n\n return {\n isBlockContainer: true,\n bnBlock,\n blockContent,\n childContainer: blockGroup,\n blockNoteType: blockContent.node.type.name,\n };\n } else {\n if (!bnBlock.node.type.isInGroup(\"childContainer\")) {\n throw new Error(\n `bnBlock node is not in the childContainer group: ${bnBlock.node}`,\n );\n }\n\n return {\n isBlockContainer: false,\n bnBlock: bnBlock,\n childContainer: bnBlock,\n blockNoteType: bnBlock.node.type.name,\n };\n }\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block in a\n * BlockNote document. This includes the main `blockContainer` node, the\n * `blockContent` node with the block's main body, and the optional `blockGroup`\n * node which contains the block's children. As well as the nodes, also returns\n * the ProseMirror positions just before & after each node.\n * @param posInfo An object with the main `blockContainer` node that the block\n * information should be retrieved from, and the position just before it in the\n * document.\n */\nexport function getBlockInfo(posInfo: { posBeforeNode: number; node: Node }) {\n return getBlockInfoWithManualOffset(posInfo.node, posInfo.posBeforeNode);\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block from a\n * resolved position just before the `blockContainer` node in the document that\n * corresponds to it.\n * @param resolvedPos The resolved position just before the `blockContainer`\n * node.\n */\nexport function getBlockInfoFromResolvedPos(resolvedPos: ResolvedPos) {\n if (!resolvedPos.nodeAfter) {\n throw new Error(\n `Attempted to get blockContainer node at position ${resolvedPos.pos} but a node at this position does not exist`,\n );\n }\n return getBlockInfoWithManualOffset(resolvedPos.nodeAfter, resolvedPos.pos);\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block. The\n * block chosen is the one currently containing the current ProseMirror\n * selection.\n * @param state The ProseMirror editor state.\n */\nexport function getBlockInfoFromSelection(state: EditorState) {\n const posInfo = getNearestBlockPos(state.doc, state.selection.anchor);\n\n return getBlockInfo(posInfo);\n}\n\n/**\n * Gets information regarding the ProseMirror nodes that make up a block. The\n * block chosen is the one currently containing the current ProseMirror\n * selection.\n * @param tr The ProseMirror transaction.\n */\nexport function getBlockInfoFromTransaction(tr: Transaction) {\n const posInfo = getNearestBlockPos(tr.doc, tr.selection.anchor);\n\n return getBlockInfo(posInfo);\n}\n","import type { Node, Schema } from \"prosemirror-model\";\nimport { Transform } from \"prosemirror-transform\";\nimport type { BlockNoteEditor } from \"../editor/BlockNoteEditor.js\";\nimport { BlockNoteSchema } from \"../blocks/BlockNoteSchema.js\";\nimport type { BlockSchema } from \"../schema/blocks/types.js\";\nimport type { InlineContentSchema } from \"../schema/inlineContent/types.js\";\nimport type { StyleSchema } from \"../schema/styles/types.js\";\n\nexport function getPmSchema(trOrNode: Transform | Node) {\n if (\"doc\" in trOrNode) {\n return trOrNode.doc.type.schema;\n }\n return trOrNode.type.schema;\n}\n\nfunction getBlockNoteEditor<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(schema: Schema): BlockNoteEditor<BSchema, I, S> {\n return schema.cached.blockNoteEditor as BlockNoteEditor<BSchema, I, S>;\n}\n\nexport function getBlockNoteSchema<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(schema: Schema): BlockNoteSchema<BSchema, I, S> {\n return getBlockNoteEditor(schema).schema as unknown as BlockNoteSchema<\n BSchema,\n I,\n S\n >;\n}\n\nexport function getBlockSchema<BSchema extends BlockSchema>(\n schema: Schema,\n): BSchema {\n return getBlockNoteSchema(schema).blockSchema as BSchema;\n}\n\nexport function getInlineContentSchema<I extends InlineContentSchema>(\n schema: Schema,\n): I {\n return getBlockNoteSchema(schema).inlineContentSchema as I;\n}\n\nexport function getStyleSchema<S extends StyleSchema>(schema: Schema): S {\n return getBlockNoteSchema(schema).styleSchema as S;\n}\n\nexport function getBlockCache(schema: Schema) {\n return getBlockNoteEditor(schema).blockCache;\n}\n","import { Mark, Node, Schema, Slice } from \"@tiptap/pm/model\";\nimport type { Block } from \"../../blocks/defaultBlocks.js\";\nimport UniqueID from \"../../extensions/tiptap-extensions/UniqueID/UniqueID.js\";\nimport type {\n BlockSchema,\n CustomInlineContentConfig,\n CustomInlineContentFromConfig,\n InlineContent,\n InlineContentFromConfig,\n InlineContentSchema,\n StyleSchema,\n Styles,\n TableCell,\n TableContent,\n} from \"../../schema/index.js\";\nimport {\n isLinkInlineContent,\n isStyledTextInlineContent,\n} from \"../../schema/inlineContent/types.js\";\nimport { UnreachableCaseError } from \"../../util/typescript.js\";\nimport { getBlockInfoWithManualOffset } from \"../getBlockInfoFromPos.js\";\nimport {\n getBlockCache,\n getBlockSchema,\n getInlineContentSchema,\n getPmSchema,\n getStyleSchema,\n} from \"../pmUtil.js\";\n\n/**\n * Converts an internal (prosemirror) table node contentto a BlockNote Tablecontent\n */\nexport function contentNodeToTableContent<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(contentNode: Node, inlineContentSchema: I, styleSchema: S) {\n const ret: TableContent<I, S> = {\n type: \"tableContent\",\n columnWidths: [],\n headerRows: undefined,\n headerCols: undefined,\n rows: [],\n };\n\n /**\n * A matrix of boolean values indicating whether a cell is a header.\n * The first index is the row index, the second index is the cell index.\n */\n const headerMatrix: boolean[][] = [];\n\n contentNode.content.forEach((rowNode, _offset, rowIndex) => {\n const row: TableContent<I, S>[\"rows\"][0] = {\n cells: [],\n };\n\n if (rowIndex === 0) {\n rowNode.content.forEach((cellNode) => {\n let colWidth = cellNode.attrs.colwidth as null | undefined | number[];\n if (colWidth === undefined || colWidth === null) {\n colWidth = new Array(cellNode.attrs.colspan ?? 1).fill(undefined);\n }\n ret.columnWidths.push(...colWidth);\n });\n }\n\n row.cells = rowNode.content.content.map((cellNode, cellIndex) => {\n if (!headerMatrix[rowIndex]) {\n headerMatrix[rowIndex] = [];\n }\n // Mark the cell as a header if it is a tableHeader node.\n headerMatrix[rowIndex][cellIndex] = cellNode.type.name === \"tableHeader\";\n // Convert cell content to inline content and merge adjacent styled text nodes\n const content = cellNode.content.content\n .map((child) =>\n contentNodeToInlineContent(child, inlineContentSchema, styleSchema),\n )\n // The reason that we merge this content is that we allow table cells to contain multiple tableParagraph nodes\n // So that we can leverage prosemirror-tables native merging\n // If the schema only allowed a single tableParagraph node, then the merging would not work and cause prosemirror to fit the content into a new cell\n .reduce(\n (acc, contentPartial) => {\n if (!acc.length) {\n return contentPartial;\n }\n\n const last = acc[acc.length - 1];\n const first = contentPartial[0];\n\n // Only merge if the last and first content are both styled text nodes and have the same styles\n if (\n first &&\n isStyledTextInlineContent(last) &&\n isStyledTextInlineContent(first) &&\n JSON.stringify(last.styles) === JSON.stringify(first.styles)\n ) {\n // Join them together if they have the same styles\n last.text += \"\\n\" + first.text;\n acc.push(...contentPartial.slice(1));\n return acc;\n }\n acc.push(...contentPartial);\n return acc;\n },\n [] as InlineContent<I, S>[],\n );\n\n return {\n type: \"tableCell\",\n content,\n props: {\n colspan: cellNode.attrs.colspan,\n rowspan: cellNode.attrs.rowspan,\n backgroundColor: cellNode.attrs.backgroundColor,\n textColor: cellNode.attrs.textColor,\n textAlignment: cellNode.attrs.textAlignment,\n },\n } satisfies TableCell<I, S>;\n });\n\n ret.rows.push(row);\n });\n\n for (let i = 0; i < headerMatrix.length; i++) {\n if (headerMatrix[i]?.every((isHeader) => isHeader)) {\n ret.headerRows = (ret.headerRows ?? 0) + 1;\n }\n }\n\n for (let i = 0; i < headerMatrix[0]?.length; i++) {\n if (headerMatrix?.every((row) => row[i])) {\n ret.headerCols = (ret.headerCols ?? 0) + 1;\n }\n }\n\n return ret;\n}\n\n/**\n * Converts an internal (prosemirror) content node to a BlockNote InlineContent array.\n */\nexport function contentNodeToInlineContent<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(contentNode: Node, inlineContentSchema: I, styleSchema: S) {\n const content: InlineContent<any, S>[] = [];\n let currentContent: InlineContent<any, S> | undefined = undefined;\n\n // Most of the logic below is for handling links because in ProseMirror links are marks\n // while in BlockNote links are a type of inline content\n contentNode.content.forEach((node) => {\n // hardBreak nodes do not have an InlineContent equivalent, instead we\n // add a newline to the previous node.\n if (node.type.name === \"hardBreak\") {\n if (currentContent) {\n // Current content exists.\n if (isStyledTextInlineContent(currentContent)) {\n // Current content is text.\n currentContent.text += \"\\n\";\n } else if (isLinkInlineContent(currentContent)) {\n // Current content is a link.\n currentContent.content[currentContent.content.length - 1].text +=\n \"\\n\";\n } else {\n throw new Error(\"unexpected\");\n }\n } else {\n // Current content does not exist.\n currentContent = {\n type: \"text\",\n text: \"\\n\",\n styles: {},\n };\n }\n\n return;\n }\n\n if (node.type.name !== \"link\" && node.type.name !== \"text\") {\n if (!inlineContentSchema[node.type.name]) {\n // eslint-disable-next-line no-console\n console.warn(\"unrecognized inline content type\", node.type.name);\n return;\n }\n if (currentContent) {\n content.push(currentContent);\n currentContent = undefined;\n }\n\n content.push(\n nodeToCustomInlineContent(node, inlineContentSchema, styleSchema),\n );\n\n return;\n }\n\n const styles: Styles<S> = {};\n let linkMark: Mark | undefined;\n\n for (const mark of node.marks) {\n if (mark.type.name === \"link\") {\n linkMark = mark;\n } else {\n const config = styleSchema[mark.type.name];\n if (!config) {\n if (mark.type.spec.blocknoteIgnore) {\n // at this point, we don't want to show certain marks (such as comments)\n // in the BlockNote JSON output. These marks should be tagged with \"blocknoteIgnore\" in the spec\n continue;\n }\n throw new Error(`style ${mark.type.name} not found in styleSchema`);\n }\n if (config.propSchema === \"boolean\") {\n (styles as any)[config.type] = true;\n } else if (config.propSchema === \"string\") {\n (styles as any)[config.type] = mark.attrs.stringValue;\n } else {\n throw new UnreachableCaseError(config.propSchema);\n }\n }\n }\n\n // Parsing links and text.\n // Current content exists.\n if (currentContent) {\n // Current content is text.\n if (isStyledTextInlineContent(currentContent)) {\n if (!linkMark) {\n // Node is text (same type as current content).\n if (\n JSON.stringify(currentContent.styles) === JSON.stringify(styles)\n ) {\n // Styles are the same.\n currentContent.text += node.textContent;\n } else {\n // Styles are different.\n content.push(currentContent);\n currentContent = {\n type: \"text\",\n text: node.textContent,\n styles,\n };\n }\n } else {\n // Node is a link (different type to current content).\n content.push(currentContent);\n currentContent = {\n type: \"link\",\n href: linkMark.attrs.href,\n content: [\n {\n type: \"text\",\n text: node.textContent,\n styles,\n },\n ],\n };\n }\n } else if (isLinkInlineContent(currentContent)) {\n // Current content is a link.\n if (linkMark) {\n // Node is a link (same type as current content).\n // Link URLs are the same.\n if (currentContent.href === linkMark.attrs.href) {\n // Styles are the same.\n if (\n JSON.stringify(\n currentContent.content[currentContent.content.length - 1]\n .styles,\n ) === JSON.stringify(styles)\n ) {\n currentContent.content[currentContent.content.length - 1].text +=\n node.textContent;\n } else {\n // Styles are different.\n currentContent.content.push({\n type: \"text\",\n text: node.textContent,\n styles,\n });\n }\n } else {\n // Link URLs are different.\n content.push(currentContent);\n currentContent = {\n type: \"link\",\n href: linkMark.attrs.href,\n content: [\n {\n type: \"text\",\n text: node.textContent,\n styles,\n },\n ],\n };\n }\n } else {\n // Node is text (different type to current content).\n content.push(currentContent);\n currentContent = {\n type: \"text\",\n text: node.textContent,\n styles,\n };\n }\n } else {\n // TODO\n }\n }\n // Current content does not exist.\n else {\n // Node is text.\n if (!linkMark) {\n currentContent = {\n type: \"text\",\n text: node.textContent,\n styles,\n };\n }\n // Node is a link.\n else {\n currentContent = {\n type: \"link\",\n href: linkMark.attrs.href,\n content: [\n {\n type: \"text\",\n text: node.textContent,\n styles,\n },\n ],\n };\n }\n }\n });\n\n if (currentContent) {\n content.push(currentContent);\n }\n\n return content as InlineContent<I, S>[];\n}\n\nexport function nodeToCustomInlineContent<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(node: Node, inlineContentSchema: I, styleSchema: S): InlineContent<I, S> {\n if (node.type.name === \"text\" || node.type.name === \"link\") {\n throw new Error(\"unexpected\");\n }\n const props: any = {};\n const icConfig = inlineContentSchema[\n node.type.name\n ] as CustomInlineContentConfig;\n for (const [attr, value] of Object.entries(node.attrs)) {\n if (!icConfig) {\n throw Error(\"ic node is of an unrecognized type: \" + node.type.name);\n }\n\n const propSchema = icConfig.propSchema;\n\n if (attr in propSchema) {\n props[attr] = value;\n }\n }\n\n let content: CustomInlineContentFromConfig<any, any>[\"content\"];\n\n if (icConfig.content === \"styled\") {\n content = contentNodeToInlineContent(\n node,\n inlineContentSchema,\n styleSchema,\n ) as any; // TODO: is this safe? could we have Links here that are undesired?\n } else {\n content = undefined;\n }\n\n const ic = {\n type: node.type.name,\n props,\n content,\n } as InlineContentFromConfig<I[keyof I], S>;\n return ic;\n}\n\n/**\n * Convert a Prosemirror node to a BlockNote block.\n *\n * TODO: test changes\n */\nexport function nodeToBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n node: Node,\n schema: Schema,\n blockSchema: BSchema = getBlockSchema(schema) as BSchema,\n inlineContentSchema: I = getInlineContentSchema(schema) as I,\n styleSchema: S = getStyleSchema(schema) as S,\n blockCache = getBlockCache(schema),\n): Block<BSchema, I, S> {\n if (!node.type.isInGroup(\"bnBlock\")) {\n throw Error(\"Node should be a bnBlock, but is instead: \" + node.type.name);\n }\n\n const cachedBlock = blockCache?.get(node);\n\n if (cachedBlock) {\n return cachedBlock;\n }\n\n const blockInfo = getBlockInfoWithManualOffset(node, 0);\n\n let id = blockInfo.bnBlock.node.attrs.id;\n\n // Only used for blocks converted from other formats.\n if (id === null) {\n id = UniqueID.options.generateID();\n }\n\n const blockSpec = blockSchema[blockInfo.blockNoteType];\n\n if (!blockSpec) {\n throw Error(\"Block is of an unrecognized type: \" + blockInfo.blockNoteType);\n }\n\n const props: any = {};\n for (const [attr, value] of Object.entries({\n ...node.attrs,\n ...(blockInfo.isBlockContainer ? blockInfo.blockContent.node.attrs : {}),\n })) {\n const propSchema = blockSpec.propSchema;\n\n if (\n attr in propSchema &&\n !(propSchema[attr].default === undefined && value === undefined)\n ) {\n props[attr] = value;\n }\n }\n\n const blockConfig = blockSchema[blockInfo.blockNoteType];\n\n const children: Block<BSchema, I, S>[] = [];\n blockInfo.childContainer?.node.forEach((child) => {\n children.push(\n nodeToBlock(\n child,\n schema,\n blockSchema,\n inlineContentSchema,\n styleSchema,\n blockCache,\n ),\n );\n });\n\n let content: Block<any, any, any>[\"content\"];\n\n if (blockConfig.content === \"inline\") {\n if (!blockInfo.isBlockContainer) {\n throw new Error(\"impossible\");\n }\n content = contentNodeToInlineContent(\n blockInfo.blockContent.node,\n inlineContentSchema,\n styleSchema,\n );\n } else if (blockConfig.content === \"table\") {\n if (!blockInfo.isBlockContainer) {\n throw new Error(\"impossible\");\n }\n content = contentNodeToTableContent(\n blockInfo.blockContent.node,\n inlineContentSchema,\n styleSchema,\n );\n } else if (blockConfig.content === \"none\") {\n content = undefined;\n } else {\n throw new UnreachableCaseError(blockConfig.content);\n }\n\n const block = {\n id,\n type: blockConfig.type,\n props,\n content,\n children,\n } as Block<BSchema, I, S>;\n\n blockCache?.set(node, block);\n\n return block;\n}\n\n/**\n * Convert a Prosemirror document to a BlockNote document (array of blocks)\n */\nexport function docToBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n doc: Node,\n schema: Schema = getPmSchema(doc),\n blockSchema: BSchema = getBlockSchema(schema) as BSchema,\n inlineContentSchema: I = getInlineContentSchema(schema) as I,\n styleSchema: S = getStyleSchema(schema) as S,\n blockCache = getBlockCache(schema),\n) {\n const blocks: Block<BSchema, I, S>[] = [];\n if (doc.firstChild) {\n doc.firstChild.descendants((node) => {\n blocks.push(\n nodeToBlock(\n node,\n schema,\n blockSchema,\n inlineContentSchema,\n styleSchema,\n blockCache,\n ),\n );\n return false;\n });\n }\n return blocks;\n}\n\n/**\n *\n * Parse a Prosemirror Slice into a BlockNote selection. The prosemirror schema looks like this:\n *\n * <blockGroup>\n * <blockContainer> (main content of block)\n * <p, heading, etc.>\n * <blockGroup> (only if blocks has children)\n * <blockContainer> (child block)\n * <p, heading, etc.>\n * </blockContainer>\n * <blockContainer> (child block 2)\n * <p, heading, etc.>\n * </blockContainer>\n * </blockContainer>\n * </blockGroup>\n * </blockGroup>\n *\n */\nexport function prosemirrorSliceToSlicedBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n slice: Slice,\n schema: Schema,\n blockSchema: BSchema = getBlockSchema(schema) as BSchema,\n inlineContentSchema: I = getInlineContentSchema(schema) as I,\n styleSchema: S = getStyleSchema(schema) as S,\n blockCache: WeakMap<Node, Block<BSchema, I, S>> = getBlockCache(schema),\n): {\n /**\n * The blocks that are included in the selection.\n */\n blocks: Block<BSchema, I, S>[];\n /**\n * If a block was \"cut\" at the start of the selection, this will be the id of the block that was cut.\n */\n blockCutAtStart: string | undefined;\n /**\n * If a block was \"cut\" at the end of the selection, this will be the id of the block that was cut.\n */\n blockCutAtEnd: string | undefined;\n} {\n // console.log(JSON.stringify(slice.toJSON()));\n function processNode(\n node: Node,\n openStart: number,\n openEnd: number,\n ): {\n blocks: Block<BSchema, I, S>[];\n blockCutAtStart: string | undefined;\n blockCutAtEnd: string | undefined;\n } {\n if (node.type.name !== \"blockGroup\") {\n throw new Error(\"unexpected\");\n }\n const blocks: Block<BSchema, I, S>[] = [];\n let blockCutAtStart: string | undefined;\n let blockCutAtEnd: string | undefined;\n\n node.forEach((blockContainer, _offset, index) => {\n if (blockContainer.type.name !== \"blockContainer\") {\n throw new Error(\"unexpected\");\n }\n if (blockContainer.childCount === 0) {\n return;\n }\n if (blockContainer.childCount === 0 || blockContainer.childCount > 2) {\n throw new Error(\n \"unexpected, blockContainer.childCount: \" + blockContainer.childCount,\n );\n }\n\n const isFirstBlock = index === 0;\n const isLastBlock = index === node.childCount - 1;\n\n if (blockContainer.firstChild!.type.name === \"blockGroup\") {\n // this is the parent where a selection starts within one of its children,\n // e.g.:\n // A\n // ├── B\n // selection starts within B, then this blockContainer is A, but we don't care about A\n // so let's descend into B and continue processing\n if (!isFirstBlock) {\n throw new Error(\"unexpected\");\n }\n const ret = processNode(\n blockContainer.firstChild!,\n Math.max(0, openStart - 1),\n isLastBlock ? Math.max(0, openEnd - 1) : 0,\n );\n blockCutAtStart = ret.blockCutAtStart;\n if (isLastBlock) {\n blockCutAtEnd = ret.blockCutAtEnd;\n }\n blocks.push(...ret.blocks);\n return;\n }\n\n const block = nodeToBlock(\n blockContainer,\n schema,\n blockSchema,\n inlineContentSchema,\n styleSchema,\n blockCache,\n );\n const childGroup =\n blockContainer.childCount > 1 ? blockContainer.child(1) : undefined;\n\n let childBlocks: Block<BSchema, I, S>[] = [];\n if (childGroup) {\n const ret = processNode(\n childGroup,\n 0, // TODO: can this be anything other than 0?\n isLastBlock ? Math.max(0, openEnd - 1) : 0,\n );\n childBlocks = ret.blocks;\n if (isLastBlock) {\n blockCutAtEnd = ret.blockCutAtEnd;\n }\n }\n\n if (isLastBlock && !childGroup && openEnd > 1) {\n blockCutAtEnd = block.id;\n }\n\n if (isFirstBlock && openStart > 1) {\n blockCutAtStart = block.id;\n }\n\n blocks.push({\n ...(block as any),\n children: childBlocks,\n });\n });\n\n return { blocks, blockCutAtStart, blockCutAtEnd };\n }\n\n if (slice.content.childCount === 0) {\n return {\n blocks: [],\n blockCutAtStart: undefined,\n blockCutAtEnd: undefined,\n };\n }\n\n if (slice.content.childCount !== 1) {\n throw new Error(\n \"slice must be a single block, did you forget includeParents=true?\",\n );\n }\n\n return processNode(\n slice.content.firstChild!,\n Math.max(slice.openStart - 1, 0),\n Math.max(slice.openEnd - 1, 0),\n );\n}\n","import { DefaultBlockSchema } from \"../../../blocks/defaultBlocks.js\";\nimport {\n BlockFromConfigNoChildren,\n PartialTableContent,\n TableCell,\n TableContent,\n} from \"../../../schema/blocks/types.js\";\nimport {\n isPartialLinkInlineContent,\n isStyledTextInlineContent,\n} from \"../../../schema/index.js\";\nimport {\n getColspan,\n getRowspan,\n isPartialTableCell,\n mapTableCell,\n} from \"../../../util/table.js\";\n\n/**\n * Here be dragons.\n *\n * Tables are complex because of rowspan and colspan behavior.\n * The majority of this file is concerned with translating between \"relative\" and \"absolute\" indices.\n *\n * The following diagram may help explain the relationship between the different indices:\n *\n * One-based indexing of rows and columns in a table:\n * | 1-1 | 1-2 | 1-3 |\n * | 2-1 | 2-2 | 2-3 |\n * | 3-1 | 3-2 | 3-3 |\n *\n * A complicated table with colspans and rowspans:\n * | 1-1 | 1-2 | 1-2 |\n * | 2-1 | 2-1 | 2-2 |\n * | 2-1 | 2-1 | 3-1 |\n *\n * You can see here that we have:\n * - two cells that contain the value \"1-2\", because it has a colspan of 2.\n * - four cells that contain the value \"2-1\", because it has a rowspan of 2 and a colspan of 2.\n *\n * This would be represented in block note json (roughly) as:\n * [\n * {\n * \"cells\": [\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"1,1\"],\n * \"props\": {\n * \"colspan\": 1,\n * \"rowspan\": 1\n * },\n * },\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"1,2\"],\n * \"props\": {\n * \"colspan\": 2,\n * \"rowspan\": 1\n * }\n * }\n * ],\n * },\n * {\n * \"cells\": [\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"2,1\"],\n * \"props\": {\n * \"colspan\": 2,\n * \"rowspan\": 2\n * }\n * },\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"2,2\"],\n * \"props\": {\n * \"colspan\": 1,\n * \"rowspan\": 1\n * }\n * ],\n * },\n * {\n * \"cells\": [\n * {\n * \"type\": \"tableCell\",\n * \"content\": [\"3,1\"],\n * \"props\": {\n * \"colspan\": 1,\n * \"rowspan\": 1,\n * }\n * }\n * ]\n * }\n * ]\n *\n * Which maps cleanly to the following HTML:\n *\n * <table>\n * <tr>\n * <td>1-1</td>\n * <td colspan=\"2\">1-2</td>\n * </tr>\n * <tr>\n * <td rowspan=\"2\" colspan=\"2\">2-1</td>\n * <td>2-2</td>\n * </tr>\n * <tr>\n * <td>3-1</td>\n * </tr>\n * </table>\n *\n * We have a problem though, from the block json, there is no way to tell that the cell \"2-1\" is the second cell in the second row.\n * To resolve this, we created the occupancy grid, which is a grid of all the cells in the table, as though they were only 1x1 cells.\n * See {@link OccupancyGrid} for more information.\n *\n */\n\n/**\n * Relative cell indices are relative to the table block's content.\n *\n * This is a sparse representation of the table and is how HTML and BlockNote JSON represent tables.\n *\n * For example, if we have a table with a rowspan of 2, the second row may only have 1 element in a 2x2 table.\n *\n * ```\n * // Visual representation of the table\n * | 1-1 | 1-2 | // has 2 cells\n * | 1-1 | 2-2 | // has only 1 cell\n * // Relative cell indices\n * [{ row: 1, col: 1, rowspan: 2 }, { row: 1, col: 2 }] // has 2 cells\n * [{ row: 1, col: 2 }] // has only 1 cell\n * ```\n */\nexport type RelativeCellIndices = {\n row: number;\n col: number;\n};\n\n/**\n * Absolute cell indices are relative to the table's layout (it's {@link OccupancyGrid}).\n *\n * It is as though the table is a grid of 1x1 cells, and any colspan or rowspan results in multiple 1x1 cells being occupied.\n *\n * For example, if we have a table with a colspan of 2, it will occupy 2 cells in the layout grid.\n *\n * ```\n * // Visual representation of the table\n * | 1-1 | 1-1 | // has 2 cells\n * | 2-1 | 2-2 | // has 2 cell\n * // Absolute cell indices\n * [{ row: 1, col: 1, colspan: 2 }, { row: 1, col: 2, colspan: 2 }] // has 2 cells\n * [{ row: 1, col: 1 }, { row: 1, col: 2 }] // has 2 cells\n * ```\n */\nexport type AbsoluteCellIndices = {\n row: number;\n col: number;\n};\n\n/**\n * An occupancy grid is a grid of the occupied cells in the table.\n * It is used to track the occupied cells in the table to know where to place the next cell.\n *\n * Since it allows us to resolve cell indices both {@link RelativeCellIndices} and {@link AbsoluteCellIndices}, it is the core data structure for table operations.\n */\ntype OccupancyGrid = (RelativeCellIndices & {\n /**\n * The rowspan of the cell.\n */\n rowspan: number;\n /**\n * The colspan of the cell.\n */\n colspan: number;\n /**\n * The cell.\n */\n cell: TableCell<any, any>;\n})[][];\n\n/**\n * This will return the {@link OccupancyGrid} of the table.\n * By laying out the table as though it were a grid of 1x1 cells, we can easily track where the cells are located (both relatively and absolutely).\n *\n * @returns an {@link OccupancyGrid}\n */\nexport function getTableCellOccupancyGrid(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n): OccupancyGrid {\n const { height, width } = getDimensionsOfTable(block);\n\n /**\n * Create a grid to track occupied cells\n * This is used because rowspans and colspans take up multiple spaces\n * So, we need to track the occupied cells in the grid to know where to place the next cell\n */\n const grid: OccupancyGrid = new Array(height)\n .fill(false)\n .map(() => new Array(width).fill(null));\n\n // Find the next unoccupied cell in the table, row-major order\n const findNextAvailable = (row: number, col: number) => {\n for (let i = row; i < height; i++) {\n for (let j = col; j < width; j++) {\n if (!grid[i][j]) {\n return { row: i, col: j };\n }\n }\n }\n\n throw new Error(\n \"Unable to create occupancy grid for table, no more available cells\",\n );\n };\n\n // Build up the grid, trying to fill in the cells with the correct relative row and column indices\n for (let row = 0; row < block.content.rows.length; row++) {\n for (let col = 0; col < block.content.rows[row].cells.length; col++) {\n const cell = mapTableCell(block.content.rows[row].cells[col]);\n const rowspan = getRowspan(cell);\n const colspan = getColspan(cell);\n\n // Rowspan and colspan complicate things, by taking up multiple cells in the grid\n // We need to iterate over the cells that the rowspan and colspan take up\n // and fill in the grid with the correct relative row and column indices\n const { row: startRow, col: startCol } = findNextAvailable(row, col);\n\n // Fill in the rowspan X colspan cells, starting from the next available cell, with the correct relative row and column indices\n for (let i = startRow; i < startRow + rowspan; i++) {\n for (let j = startCol; j < startCol + colspan; j++) {\n if (grid[i][j]) {\n // The cell is already occupied, the table is malformed\n throw new Error(\n `Unable to create occupancy grid for table, cell at ${i},${j} is already occupied`,\n );\n }\n\n grid[i][j] = {\n row,\n col,\n rowspan,\n colspan,\n cell,\n };\n }\n }\n }\n }\n\n // console.log(grid);\n\n return grid;\n}\n\n/**\n * Given an {@link OccupancyGrid}, this will return the {@link TableContent} rows.\n *\n * @note This will remove duplicates from the occupancy grid. And does no bounds checking for validity of the occupancy grid.\n */\nexport function getTableRowsFromOccupancyGrid(\n occupancyGrid: OccupancyGrid,\n): TableContent<any, any>[\"rows\"] {\n // Because a cell can have a rowspan or colspan, it can occupy multiple cells in the occupancy grid\n // So, we need to remove duplicates from the occupancy grid before we can return the table rows\n const seen = new Set<string>();\n\n return occupancyGrid.map((row) => {\n // Just read out the cells in the occupancy grid, removing duplicates\n return {\n cells: row\n .map((cell) => {\n if (seen.has(cell.row + \":\" + cell.col)) {\n return false;\n }\n seen.add(cell.row + \":\" + cell.col);\n return cell.cell;\n })\n .filter((cell): cell is TableCell<any, any> => cell !== false),\n };\n });\n}\n\n/**\n * This will resolve the relative cell indices within the table block to the absolute cell indices within the table, accounting for colspan and rowspan.\n *\n * @note It will return only the first cell (i.e. top-left) that matches the relative cell indices. To find the other absolute cell indices this cell occupies, you can assume it is the rowspan and colspan number of cells away from the top-left cell.\n *\n * @returns The {@link AbsoluteCellIndices} and the {@link TableCell} at the absolute position.\n */\nexport function getAbsoluteTableCells(\n /**\n * The relative position of the cell in the table.\n */\n relativeCellIndices: RelativeCellIndices,\n /**\n * The table block containing the cell.\n */\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n /**\n * The occupancy grid of the table.\n */\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): AbsoluteCellIndices & {\n cell: TableCell<any, any>;\n} {\n for (let r = 0; r < occupancyGrid.length; r++) {\n for (let c = 0; c < occupancyGrid[r].length; c++) {\n const cell = occupancyGrid[r][c];\n if (\n cell &&\n cell.row === relativeCellIndices.row &&\n cell.col === relativeCellIndices.col\n ) {\n return { row: r, col: c, cell: cell.cell };\n }\n }\n }\n\n throw new Error(\n `Unable to resolve relative table cell indices for table, cell at ${relativeCellIndices.row},${relativeCellIndices.col} is not occupied`,\n );\n}\n\n/**\n * This will get the dimensions of the table block.\n *\n * @returns The height and width of the table.\n */\nexport function getDimensionsOfTable(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n): {\n /**\n * The number of rows in the table.\n */\n height: number;\n /**\n * The number of columns in the table.\n */\n width: number;\n} {\n // Due to the way we store the table, the height is always the number of rows\n const height = block.content.rows.length;\n\n // Calculating the width is a bit more complex, as it is the maximum width of any row\n let width = 0;\n block.content.rows.forEach((row) => {\n // Find the width of the row by summing the colspan of each cell\n let rowWidth = 0;\n row.cells.forEach((cell) => {\n rowWidth += getColspan(cell);\n });\n\n // Update the width if the row is wider than the current width\n width = Math.max(width, rowWidth);\n });\n\n return { height, width };\n}\n\n/**\n * This will resolve the absolute cell indices within the table block to the relative cell indices within the table, accounting for colspan and rowspan.\n *\n * @returns The {@link RelativeCellIndices} and the {@link TableCell} at the relative position.\n */\nexport function getRelativeTableCells(\n /**\n * The {@link AbsoluteCellIndices} of the cell in the table.\n */\n absoluteCellIndices: AbsoluteCellIndices,\n /**\n * The table block containing the cell.\n */\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n /**\n * The occupancy grid of the table.\n */\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n):\n | (RelativeCellIndices & {\n cell: TableContent<any, any>[\"rows\"][number][\"cells\"][number];\n })\n | undefined {\n const occupancyCell =\n occupancyGrid[absoluteCellIndices.row]?.[absoluteCellIndices.col];\n\n // Double check that the cell can be accessed\n if (!occupancyCell) {\n // The cell is not occupied, so it is invalid\n return undefined;\n }\n\n return {\n row: occupancyCell.row,\n col: occupancyCell.col,\n cell: occupancyCell.cell,\n };\n}\n\n/**\n * This will get all the cells within a relative row of a table block.\n *\n * This method always starts the search for the row at the first column of the table.\n *\n * ```\n * // Visual representation of a table\n * | A | B | C |\n * | | D | E |\n * | F | G | H |\n * // \"A\" has a rowspan of 2\n *\n * // getCellsAtRowHandle(0)\n * // returns [\n * { row: 0, col: 0, cell: \"A\" },\n * { row: 0, col: 1, cell: \"B\" },\n * { row: 0, col: 2, cell: \"C\" },\n * ]\n *\n * // getCellsAtColumnHandle(1)\n * // returns [\n * { row: 1, col: 0, cell: \"F\" },\n * { row: 1, col: 1, cell: \"G\" },\n * { row: 1, col: 2, cell: \"H\" },\n * ]\n * ```\n *\n * As you can see, you may not be able to retrieve all nodes given a relative row index, as cells can span multiple rows.\n *\n * @returns All of the cells associated with the relative row of the table. (All cells that have the same relative row index)\n */\nexport function getCellsAtRowHandle(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n relativeRowIndex: RelativeCellIndices[\"row\"],\n) {\n const occupancyGrid = getTableCellOccupancyGrid(block);\n\n if (relativeRowIndex < 0 || relativeRowIndex >= occupancyGrid.length) {\n return [];\n }\n\n // First need to resolve the relative row index to an absolute row index\n let absoluteRow = 0;\n\n // Jump through the occupied cells ${relativeCellIndices.row} times to find the absolute row position\n for (let i = 0; i < relativeRowIndex; i++) {\n const cell = occupancyGrid[absoluteRow]?.[0];\n\n if (!cell) {\n return [];\n }\n\n // Skip the cells that the rowspan takes up\n absoluteRow += cell.rowspan;\n }\n\n // Then for each column, get the cell at the absolute row index as a relative cell index\n const cells = new Array(occupancyGrid[0].length)\n .fill(false)\n .map((_v, col) => {\n return getRelativeTableCells(\n { row: absoluteRow, col },\n block,\n occupancyGrid,\n );\n })\n .filter(\n (a): a is RelativeCellIndices & { cell: TableCell<any, any> } =>\n a !== undefined,\n );\n\n // Filter out duplicates based on row and col properties\n return cells.filter((cell, index) => {\n return (\n cells.findIndex((c) => c.row === cell.row && c.col === cell.col) === index\n );\n });\n}\n\n/**\n * This will get all the cells within a relative column of a table block.\n *\n * This method always starts the search for the column at the first row of the table.\n *\n * ```\n * // Visual representation of a table\n * | A | B |\n * | C | D | E |\n * | F | G | H |\n * // \"A\" has a colspan of 2\n *\n * // getCellsAtColumnHandle(0)\n * // returns [\n * { row: 0, col: 0, cell: \"A\" },\n * { row: 1, col: 0, cell: \"C\" },\n * { row: 2, col: 0, cell: \"F\" },\n * ]\n *\n * // getCellsAtColumnHandle(1)\n * // returns [\n * { row: 0, col: 1, cell: \"B\" },\n * { row: 1, col: 2, cell: \"E\" },\n * { row: 2, col: 2, cell: \"F\" },\n * ]\n * ```\n *\n * As you can see, you may not be able to retrieve all nodes given a relative column index, as cells can span multiple columns.\n *\n * @returns All of the cells associated with the relative column of the table. (All cells that have the same relative column index)\n */\nexport function getCellsAtColumnHandle(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n relativeColumnIndex: RelativeCellIndices[\"col\"],\n) {\n const occupancyGrid = getTableCellOccupancyGrid(block);\n\n if (\n relativeColumnIndex < 0 ||\n relativeColumnIndex >= occupancyGrid[0].length\n ) {\n return [];\n }\n\n // First need to resolve the relative column index to an absolute column index\n let absoluteCol = 0;\n\n // Now that we've already resolved the absolute row position, we can jump through the occupied cells ${relativeCellIndices.col} times to find the absolute column position\n for (let i = 0; i < relativeColumnIndex; i++) {\n const cell = occupancyGrid[0]?.[absoluteCol];\n\n if (!cell) {\n return [];\n }\n\n // Skip the cells that the colspan takes up\n absoluteCol += cell.colspan;\n }\n\n // Then for each row, get the cell at the absolute column index as a relative cell index\n const cells = new Array(occupancyGrid.length)\n .fill(false)\n .map((_v, row) => {\n return getRelativeTableCells(\n { row, col: absoluteCol },\n block,\n occupancyGrid,\n );\n })\n .filter(\n (a): a is RelativeCellIndices & { cell: TableCell<any, any> } =>\n a !== undefined,\n );\n\n // Filter out duplicates based on row and col properties\n return cells.filter((cell, index) => {\n return (\n cells.findIndex((c) => c.row === cell.row && c.col === cell.col) === index\n );\n });\n}\n\n/**\n * This moves a column from one index to another.\n *\n * @note This is a destructive operation, it will modify the provided {@link OccupancyGrid} in place.\n */\nexport function moveColumn(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n fromColIndex: RelativeCellIndices[\"col\"],\n toColIndex: RelativeCellIndices[\"col\"],\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): TableContent<any, any>[\"rows\"] {\n // To move cells in a column, we need to layout the whole table\n // and then move the cells accordingly.\n const { col: absoluteSourceCol } = getAbsoluteTableCells(\n {\n row: 0,\n col: fromColIndex,\n },\n block,\n occupancyGrid,\n );\n const { col: absoluteTargetCol } = getAbsoluteTableCells(\n {\n row: 0,\n col: toColIndex,\n },\n block,\n occupancyGrid,\n );\n\n /**\n * Currently, this function assumes that the caller has already checked that the source and target columns are valid.\n * Such as by using {@link canColumnBeDraggedInto}. In the future, we may want to have the move logic be smarter\n * and handle invalid column indices in some way.\n */\n occupancyGrid.forEach((row) => {\n // Move the cell to the target column\n const [sourceCell] = row.splice(absoluteSourceCol, 1);\n row.splice(absoluteTargetCol, 0, sourceCell);\n });\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n}\n\n/**\n * This moves a row from one index to another.\n *\n * @note This is a destructive operation, it will modify the {@link OccupancyGrid} in place.\n */\nexport function moveRow(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n fromRowIndex: RelativeCellIndices[\"row\"],\n toRowIndex: RelativeCellIndices[\"row\"],\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): TableContent<any, any>[\"rows\"] {\n // To move cells in a column, we need to layout the whole table\n // and then move the cells accordingly.\n const { row: absoluteSourceRow } = getAbsoluteTableCells(\n {\n row: fromRowIndex,\n col: 0,\n },\n block,\n occupancyGrid,\n );\n const { row: absoluteTargetRow } = getAbsoluteTableCells(\n {\n row: toRowIndex,\n col: 0,\n },\n block,\n occupancyGrid,\n );\n\n /**\n * Currently, this function assumes that the caller has already checked that the source and target rows are valid.\n * Such as by using {@link canRowBeDraggedInto}. In the future, we may want to have the move logic be smarter\n * and handle invalid row indices in some way.\n */\n const [sourceRow] = occupancyGrid.splice(absoluteSourceRow, 1);\n occupancyGrid.splice(absoluteTargetRow, 0, sourceRow);\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n}\n\n/**\n * This will check if a cell is empty.\n *\n * @returns True if the cell is empty, false otherwise.\n */\nfunction isCellEmpty(\n cell:\n | PartialTableContent<any, any>[\"rows\"][number][\"cells\"][number]\n | undefined,\n): boolean {\n if (!cell) {\n return true;\n }\n if (isPartialTableCell(cell)) {\n return isCellEmpty(cell.content);\n } else if (typeof cell === \"string\") {\n return cell.length === 0;\n } else if (Array.isArray(cell)) {\n return cell.every((c) =>\n typeof c === \"string\"\n ? c.length === 0\n : isStyledTextInlineContent(c)\n ? c.text.length === 0\n : isPartialLinkInlineContent(c)\n ? typeof c.content === \"string\"\n ? c.content.length === 0\n : c.content.every((s) => s.text.length === 0)\n : false,\n );\n } else {\n return false;\n }\n}\n\n/**\n * This will remove empty rows or columns from the table.\n *\n * @note This is a destructive operation, it will modify the {@link OccupancyGrid} in place.\n */\nexport function cropEmptyRowsOrColumns(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n removeEmpty: \"columns\" | \"rows\",\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): TableContent<any, any>[\"rows\"] {\n if (removeEmpty === \"columns\") {\n // strips empty columns on the right\n let emptyColsOnRight = 0;\n for (\n let cellIndex = occupancyGrid[0].length - 1;\n cellIndex >= 0;\n cellIndex--\n ) {\n const isEmpty = occupancyGrid.every(\n (row) =>\n isCellEmpty(row[cellIndex].cell) && row[cellIndex].colspan === 1,\n );\n if (!isEmpty) {\n break;\n }\n\n emptyColsOnRight++;\n }\n\n for (let i = occupancyGrid.length - 1; i >= 0; i--) {\n // We maintain at least one cell, even if all the cells are empty\n const cellsToRemove = Math.max(\n occupancyGrid[i].length - emptyColsOnRight,\n 1,\n );\n occupancyGrid[i] = occupancyGrid[i].slice(0, cellsToRemove);\n }\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n }\n\n // strips empty rows at the bottom\n let emptyRowsOnBottom = 0;\n for (let rowIndex = occupancyGrid.length - 1; rowIndex >= 0; rowIndex--) {\n const isEmpty = occupancyGrid[rowIndex].every(\n (cell) => isCellEmpty(cell.cell) && cell.rowspan === 1,\n );\n if (!isEmpty) {\n break;\n }\n\n emptyRowsOnBottom++;\n }\n\n // We maintain at least one row, even if all the rows are empty\n const rowsToRemove = Math.min(emptyRowsOnBottom, occupancyGrid.length - 1);\n\n occupancyGrid.splice(occupancyGrid.length - rowsToRemove, rowsToRemove);\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n}\n\n/**\n * This will add a specified number of rows or columns to the table (filling with empty cells).\n *\n * @note This is a destructive operation, it will modify the {@link OccupancyGrid} in place.\n */\nexport function addRowsOrColumns(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n addType: \"columns\" | \"rows\",\n /**\n * The number of rows or columns to add.\n *\n * @note if negative, it will remove rows or columns.\n */\n numToAdd: number,\n occupancyGrid: OccupancyGrid = getTableCellOccupancyGrid(block),\n): TableContent<any, any>[\"rows\"] {\n const { width, height } = getDimensionsOfTable(block);\n\n if (addType === \"columns\") {\n // Add empty columns to the right\n occupancyGrid.forEach((row, rowIndex) => {\n if (numToAdd >= 0) {\n for (let i = 0; i < numToAdd; i++) {\n row.push({\n row: rowIndex,\n col: Math.max(...row.map((r) => r.col)) + 1,\n rowspan: 1,\n colspan: 1,\n cell: mapTableCell(\"\"),\n });\n }\n } else {\n // Remove columns on the right\n row.splice(width + numToAdd, -1 * numToAdd);\n }\n });\n } else {\n if (numToAdd > 0) {\n // Add empty rows to the bottom\n for (let i = 0; i < numToAdd; i++) {\n const newRow = new Array(width).fill(null).map((_, colIndex) => ({\n row: height + i,\n col: colIndex,\n rowspan: 1,\n colspan: 1,\n cell: mapTableCell(\"\"),\n }));\n occupancyGrid.push(newRow);\n }\n } else if (numToAdd < 0) {\n // Remove rows at the bottom\n occupancyGrid.splice(height + numToAdd, -1 * numToAdd);\n }\n }\n\n return getTableRowsFromOccupancyGrid(occupancyGrid);\n}\n\n/**\n * Checks if a row can be safely dropped at the target row index without splitting merged cells.\n */\nexport function canRowBeDraggedInto(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n draggingIndex: RelativeCellIndices[\"row\"],\n targetRowIndex: RelativeCellIndices[\"row\"],\n) {\n // Check cells at the target row\n const targetCells = getCellsAtRowHandle(block, targetRowIndex);\n\n // If no cells have rowspans > 1, dragging is always allowed\n const hasMergedCells = targetCells.some((cell) => getRowspan(cell.cell) > 1);\n if (!hasMergedCells) {\n return true;\n }\n\n let endRowIndex = targetRowIndex;\n let startRowIndex = targetRowIndex;\n targetCells.forEach((cell) => {\n const rowspan = getRowspan(cell.cell);\n endRowIndex = Math.max(endRowIndex, cell.row + rowspan - 1);\n startRowIndex = Math.min(startRowIndex, cell.row);\n });\n\n // Check the direction of the drag\n const isDraggingDown = draggingIndex < targetRowIndex;\n\n // Allow dragging only at the start/end of merged cells\n // Otherwise, the target row was within a merged cell which we don't allow\n return isDraggingDown\n ? targetRowIndex === endRowIndex\n : targetRowIndex === startRowIndex;\n}\n\n/**\n * Checks if a column can be safely dropped at the target column index without splitting merged cells.\n */\nexport function canColumnBeDraggedInto(\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n draggingIndex: RelativeCellIndices[\"col\"],\n targetColumnIndex: RelativeCellIndices[\"col\"],\n) {\n // Check cells at the target column\n const targetCells = getCellsAtColumnHandle(block, targetColumnIndex);\n\n // If no cells have colspans > 1, dragging is always allowed\n const hasMergedCells = targetCells.some((cell) => getColspan(cell.cell) > 1);\n if (!hasMergedCells) {\n return true;\n }\n\n let endColumnIndex = targetColumnIndex;\n let startColumnIndex = targetColumnIndex;\n targetCells.forEach((cell) => {\n const colspan = getColspan(cell.cell);\n endColumnIndex = Math.max(endColumnIndex, cell.col + colspan - 1);\n startColumnIndex = Math.min(startColumnIndex, cell.col);\n });\n\n // Check the direction of the drag\n const isDraggingRight = draggingIndex < targetColumnIndex;\n\n // Allow dragging only at the start/end of merged cells\n // Otherwise, the target column was within a merged cell which we don't allow\n return isDraggingRight\n ? targetColumnIndex === endColumnIndex\n : targetColumnIndex === startColumnIndex;\n}\n\n/**\n * Checks if two cells are in the same column.\n *\n * @returns True if the cells are in the same column, false otherwise.\n */\nexport function areInSameColumn(\n from: RelativeCellIndices,\n to: RelativeCellIndices,\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], any, any>,\n) {\n // Table indices are relative to the table, so we need to resolve the absolute cell indices\n const anchorAbsoluteCellIndices = getAbsoluteTableCells(from, block);\n\n // Table indices are relative to the table, so we need to resolve the absolute cell indices\n const headAbsoluteCellIndices = getAbsoluteTableCells(to, block);\n\n // Compare the column indices to determine the merge direction\n return anchorAbsoluteCellIndices.col === headAbsoluteCellIndices.col;\n}\n","import { Attrs, Fragment, Mark, Node, Schema } from \"@tiptap/pm/model\";\n\nimport UniqueID from \"../../extensions/tiptap-extensions/UniqueID/UniqueID.js\";\nimport type {\n InlineContentSchema,\n PartialCustomInlineContentFromConfig,\n PartialInlineContent,\n PartialLink,\n PartialTableContent,\n StyleSchema,\n StyledText,\n} from \"../../schema\";\n\nimport type { PartialBlock } from \"../../blocks/defaultBlocks\";\nimport {\n isPartialLinkInlineContent,\n isStyledTextInlineContent,\n} from \"../../schema/inlineContent/types.js\";\nimport { getColspan, isPartialTableCell } from \"../../util/table.js\";\nimport { UnreachableCaseError } from \"../../util/typescript.js\";\nimport { getAbsoluteTableCells } from \"../blockManipulation/tables/tables.js\";\nimport { getStyleSchema } from \"../pmUtil.js\";\n\n/**\n * Convert a StyledText inline element to a\n * prosemirror text node with the appropriate marks\n */\nfunction styledTextToNodes<T extends StyleSchema>(\n styledText: StyledText<T>,\n schema: Schema,\n styleSchema: T,\n blockType?: string,\n): Node[] {\n const marks: Mark[] = [];\n\n for (const [style, value] of Object.entries(styledText.styles || {})) {\n const config = styleSchema[style];\n if (!config) {\n throw new Error(`style ${style} not found in styleSchema`);\n }\n\n if (config.propSchema === \"boolean\") {\n if (value) {\n marks.push(schema.mark(style));\n }\n } else if (config.propSchema === \"string\") {\n if (value) {\n marks.push(schema.mark(style, { stringValue: value }));\n }\n } else {\n throw new UnreachableCaseError(config.propSchema);\n }\n }\n\n const parseHardBreaks = !blockType || !schema.nodes[blockType].spec.code;\n\n if (!parseHardBreaks) {\n return styledText.text.length > 0\n ? [schema.text(styledText.text, marks)]\n : [];\n }\n\n return (\n styledText.text\n // Splits text & line breaks.\n .split(/(\\n)/g)\n // If the content ends with a line break, an empty string is added to the\n // end, which this removes.\n .filter((text) => text.length > 0)\n // Converts text & line breaks to nodes.\n .map((text) => {\n if (text === \"\\n\") {\n return schema.nodes[\"hardBreak\"].createChecked();\n } else {\n return schema.text(text, marks);\n }\n })\n );\n}\n\n/**\n * Converts a Link inline content element to\n * prosemirror text nodes with the appropriate marks\n */\nfunction linkToNodes(\n link: PartialLink<StyleSchema>,\n schema: Schema,\n styleSchema: StyleSchema,\n): Node[] {\n const linkMark = schema.marks.link.create({\n href: link.href,\n });\n\n return styledTextArrayToNodes(link.content, schema, styleSchema).map(\n (node) => {\n if (node.type.name === \"text\") {\n return node.mark([...node.marks, linkMark]);\n }\n\n if (node.type.name === \"hardBreak\") {\n return node;\n }\n throw new Error(\"unexpected node type\");\n },\n );\n}\n\n/**\n * Converts an array of StyledText inline content elements to\n * prosemirror text nodes with the appropriate marks\n */\nfunction styledTextArrayToNodes<S extends StyleSchema>(\n content: string | StyledText<S>[],\n schema: Schema,\n styleSchema: S,\n blockType?: string,\n): Node[] {\n const nodes: Node[] = [];\n\n if (typeof content === \"string\") {\n nodes.push(\n ...styledTextToNodes(\n { type: \"text\", text: content, styles: {} },\n schema,\n styleSchema,\n blockType,\n ),\n );\n return nodes;\n }\n\n for (const styledText of content) {\n nodes.push(\n ...styledTextToNodes(styledText, schema, styleSchema, blockType),\n );\n }\n return nodes;\n}\n\n/**\n * converts an array of inline content elements to prosemirror nodes\n */\nexport function inlineContentToNodes<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n blockContent: PartialInlineContent<I, S>,\n schema: Schema,\n blockType?: string,\n styleSchema: S = getStyleSchema(schema),\n): Node[] {\n const nodes: Node[] = [];\n\n for (const content of blockContent) {\n if (typeof content === \"string\") {\n nodes.push(\n ...styledTextArrayToNodes(content, schema, styleSchema, blockType),\n );\n } else if (isPartialLinkInlineContent(content)) {\n nodes.push(...linkToNodes(content, schema, styleSchema));\n } else if (isStyledTextInlineContent(content)) {\n nodes.push(\n ...styledTextArrayToNodes([content], schema, styleSchema, blockType),\n );\n } else {\n nodes.push(\n blockOrInlineContentToContentNode(content, schema, styleSchema),\n );\n }\n }\n return nodes;\n}\n\n/**\n * converts an array of inline content elements to prosemirror nodes\n */\nexport function tableContentToNodes<\n I extends InlineContentSchema,\n S extends StyleSchema,\n>(\n tableContent: PartialTableContent<I, S>,\n schema: Schema,\n styleSchema: StyleSchema = getStyleSchema(schema),\n): Node[] {\n const rowNodes: Node[] = [];\n // Header rows and columns are used to determine the type of the cell\n // If headerRows is 1, then the first row is a header row\n const headerRows = new Array(tableContent.headerRows ?? 0).fill(true);\n // If headerCols is 1, then the first column is a header column\n const headerCols = new Array(tableContent.headerCols ?? 0).fill(true);\n\n const columnWidths: (number | undefined)[] = tableContent.columnWidths ?? [];\n\n for (let rowIndex = 0; rowIndex < tableContent.rows.length; rowIndex++) {\n const row = tableContent.rows[rowIndex];\n const columnNodes: Node[] = [];\n const isHeaderRow = headerRows[rowIndex];\n for (let cellIndex = 0; cellIndex < row.cells.length; cellIndex++) {\n const cell = row.cells[cellIndex];\n const isHeaderCol = headerCols[cellIndex];\n /**\n * The attributes of the cell to apply to the node\n */\n const attrs: Attrs | undefined = undefined;\n /**\n * The content of the cell to apply to the node\n */\n let content: Fragment | Node | readonly Node[] | null = null;\n\n // Colwidths are absolutely referenced to the table, so we need to resolve the relative cell index to the absolute cell index\n const absoluteCellIndex = getAbsoluteTableCells(\n {\n row: rowIndex,\n col: cellIndex,\n },\n { type: \"table\", content: tableContent } as any,\n );\n\n // Assume the column width is the width of the cell at the absolute cell index\n let colwidth: (number | undefined)[] | null = columnWidths[\n absoluteCellIndex.col\n ]\n ? [columnWidths[absoluteCellIndex.col]]\n : null;\n\n if (!cell) {\n // No-op\n } else if (typeof cell === \"string\") {\n content = schema.text(cell);\n } else if (isPartialTableCell(cell)) {\n if (cell.content) {\n content = inlineContentToNodes(\n cell.content,\n schema,\n \"tableParagraph\",\n styleSchema,\n );\n }\n const colspan = getColspan(cell);\n\n if (colspan > 1) {\n // If the cell has a > 1 colspan, we need to get the column width for each cell in the span\n colwidth = new Array(colspan).fill(false).map((_, i) => {\n // Starting from the absolute column index, get the column width for each cell in the span\n return columnWidths[absoluteCellIndex.col + i] ?? undefined;\n });\n }\n } else {\n content = inlineContentToNodes(\n cell,\n schema,\n \"tableParagraph\",\n styleSchema,\n );\n }\n\n const cellNode = schema.nodes[\n isHeaderCol || isHeaderRow ? \"tableHeader\" : \"tableCell\"\n ].createChecked(\n {\n ...(isPartialTableCell(cell) ? cell.props : {}),\n colwidth,\n },\n schema.nodes[\"tableParagraph\"].createChecked(attrs, content),\n );\n columnNodes.push(cellNode);\n }\n\n const rowNode = schema.nodes[\"tableRow\"].createChecked({}, columnNodes);\n rowNodes.push(rowNode);\n }\n return rowNodes;\n}\n\nfunction blockOrInlineContentToContentNode(\n block:\n | PartialBlock<any, any, any>\n | PartialCustomInlineContentFromConfig<any, any>,\n schema: Schema,\n styleSchema: StyleSchema,\n) {\n let contentNode: Node;\n let type = block.type;\n\n // TODO: needed? came from previous code\n if (type === undefined) {\n type = \"paragraph\";\n }\n\n if (!schema.nodes[type]) {\n throw new Error(`node type ${type} not found in schema`);\n }\n\n if (!block.content) {\n contentNode = schema.nodes[type].createChecked(block.props);\n } else if (typeof block.content === \"string\") {\n const nodes = inlineContentToNodes(\n [block.content],\n schema,\n type,\n styleSchema,\n );\n contentNode = schema.nodes[type].createChecked(block.props, nodes);\n } else if (Array.isArray(block.content)) {\n const nodes = inlineContentToNodes(\n block.content,\n schema,\n type,\n styleSchema,\n );\n contentNode = schema.nodes[type].createChecked(block.props, nodes);\n } else if (block.content.type === \"tableContent\") {\n const nodes = tableContentToNodes(block.content, schema, styleSchema);\n contentNode = schema.nodes[type].createChecked(block.props, nodes);\n } else {\n throw new UnreachableCaseError(block.content.type);\n }\n return contentNode;\n}\n\n/**\n * Converts a BlockNote block to a Prosemirror node.\n */\nexport function blockToNode(\n block: PartialBlock<any, any, any>,\n schema: Schema,\n styleSchema: StyleSchema = getStyleSchema(schema),\n) {\n let id = block.id;\n\n if (id === undefined) {\n id = UniqueID.options.generateID();\n }\n\n const children: Node[] = [];\n\n if (block.children) {\n for (const child of block.children) {\n children.push(blockToNode(child, schema, styleSchema));\n }\n }\n\n const isBlockContent =\n !block.type || // can happen if block.type is not defined (this should create the default node)\n schema.nodes[block.type].isInGroup(\"blockContent\");\n\n if (isBlockContent) {\n // Blocks with a type that matches \"blockContent\" group always need to be wrapped in a blockContainer\n\n const contentNode = blockOrInlineContentToContentNode(\n block,\n schema,\n styleSchema,\n );\n\n const groupNode =\n children.length > 0\n ? schema.nodes[\"blockGroup\"].createChecked({}, children)\n : undefined;\n\n return schema.nodes[\"blockContainer\"].createChecked(\n {\n id: id,\n ...block.props,\n },\n groupNode ? [contentNode, groupNode] : contentNode,\n );\n } else if (schema.nodes[block.type].isInGroup(\"bnBlock\")) {\n // this is a bnBlock node like Column or ColumnList that directly translates to a prosemirror node\n return schema.nodes[block.type].createChecked(\n {\n id: id,\n ...block.props,\n },\n children,\n );\n } else {\n throw new Error(\n `block type ${block.type} doesn't match blockContent or bnBlock group`,\n );\n }\n}\n"],"names":["removeDuplicates","array","by","seen","item","key","findDuplicates","items","filtered","el","index","UniqueID","Extension","testOptions","v4","element","attributes","defaultIdAttributes","dragSourceElement","transformPasted","Plugin","PluginKey","transactions","oldState","newState","docChanges","transaction","filterTransactions","tr","_b","_a","types","attributeName","generateID","transform","combineTransactionSteps","mapping","getChangedRanges","newRange","newNodes","findChildrenInRange","node","newIds","id","duplicatedNewIds","pos","initialDoc","jsonNode","deleted","view","handleDragstart","event","slice","removeId","fragment","list","nodeWithoutId","Fragment","Slice","isLinkInlineContent","content","isPartialLinkInlineContent","isStyledTextInlineContent","mapTableCell","isTableCell","isPartialTableCell","_c","_d","_e","getColspan","cell","getRowspan","UnreachableCaseError","val","assertEmpty","obj","throwError","dataTest","rest","getNearestBlockPos","doc","$pos","depth","allBlockContainerPositions","resolvedPos","position","getBlockInfoWithManualOffset","bnBlockBeforePosOffset","bnBlockNode","bnBlockBeforePos","bnBlockAfterPos","bnBlock","blockContent","blockGroup","offset","blockContentNode","blockContentBeforePos","blockContentAfterPos","blockGroupNode","blockGroupBeforePos","blockGroupAfterPos","getBlockInfo","posInfo","getBlockInfoFromResolvedPos","getBlockInfoFromSelection","state","getBlockInfoFromTransaction","getPmSchema","trOrNode","getBlockNoteEditor","schema","getBlockNoteSchema","getBlockSchema","getInlineContentSchema","getStyleSchema","getBlockCache","contentNodeToTableContent","contentNode","inlineContentSchema","styleSchema","ret","headerMatrix","rowNode","_offset","rowIndex","row","cellNode","colWidth","cellIndex","child","contentNodeToInlineContent","acc","contentPartial","last","first","isHeader","currentContent","nodeToCustomInlineContent","styles","linkMark","mark","config","props","icConfig","attr","value","propSchema","nodeToBlock","blockSchema","blockCache","cachedBlock","blockInfo","blockSpec","blockConfig","children","block","docToBlocks","blocks","prosemirrorSliceToSlicedBlocks","processNode","openStart","openEnd","blockCutAtStart","blockCutAtEnd","blockContainer","isFirstBlock","isLastBlock","childGroup","childBlocks","getTableCellOccupancyGrid","height","width","getDimensionsOfTable","grid","findNextAvailable","col","j","rowspan","colspan","startRow","startCol","i","getTableRowsFromOccupancyGrid","occupancyGrid","getAbsoluteTableCells","relativeCellIndices","r","c","rowWidth","getRelativeTableCells","absoluteCellIndices","occupancyCell","getCellsAtRowHandle","relativeRowIndex","absoluteRow","cells","_v","a","getCellsAtColumnHandle","relativeColumnIndex","absoluteCol","moveColumn","fromColIndex","toColIndex","absoluteSourceCol","absoluteTargetCol","sourceCell","moveRow","fromRowIndex","toRowIndex","absoluteSourceRow","absoluteTargetRow","sourceRow","isCellEmpty","s","cropEmptyRowsOrColumns","removeEmpty","emptyColsOnRight","cellsToRemove","emptyRowsOnBottom","rowsToRemove","addRowsOrColumns","addType","numToAdd","newRow","_","colIndex","canRowBeDraggedInto","draggingIndex","targetRowIndex","targetCells","endRowIndex","startRowIndex","canColumnBeDraggedInto","targetColumnIndex","endColumnIndex","startColumnIndex","areInSameColumn","from","to","anchorAbsoluteCellIndices","headAbsoluteCellIndices","styledTextToNodes","styledText","blockType","marks","style","text","linkToNodes","link","styledTextArrayToNodes","nodes","inlineContentToNodes","blockOrInlineContentToContentNode","tableContentToNodes","tableContent","rowNodes","headerRows","headerCols","columnWidths","columnNodes","isHeaderRow","isHeaderCol","attrs","absoluteCellIndex","colwidth","type","blockToNode","groupNode"],"mappings":"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"}
|