@blocknote/core 0.12.3 → 0.12.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"blocknote.umd.cjs","sources":["../src/extensions/UniqueID/UniqueID.ts","../src/api/getBlockInfoFromPos.ts","../src/schema/inlineContent/types.ts","../src/util/typescript.ts","../src/api/nodeConversions/nodeConversions.ts","../src/api/exporters/html/util/sharedHTMLConversion.ts","../src/api/exporters/html/util/simplifyBlocksRehypePlugin.ts","../src/api/exporters/html/externalHTMLExporter.ts","../src/api/exporters/html/internalHTMLSerializer.ts","../src/blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts","../src/util/browser.ts","../src/blocks/defaultBlockHelpers.ts","../src/blocks/defaultProps.ts","../src/util/string.ts","../src/schema/blocks/internal.ts","../src/schema/blocks/createSpec.ts","../src/schema/inlineContent/internal.ts","../src/schema/inlineContent/createSpec.ts","../src/schema/styles/internal.ts","../src/schema/styles/createSpec.ts","../src/extensions/BackgroundColor/BackgroundColorMark.ts","../src/extensions/TextColor/TextColorMark.ts","../src/api/getCurrentBlockContentType.ts","../src/blocks/HeadingBlockContent/HeadingBlockContent.ts","../src/blocks/ImageBlockContent/ImageBlockContent.ts","../src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts","../src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts","../src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts","../src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts","../src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts","../src/blocks/TableBlockContent/TableExtension.ts","../src/blocks/TableBlockContent/TableBlockContent.ts","../src/blocks/defaultBlocks.ts","../src/blocks/defaultBlockTypeGuards.ts","../src/api/nodeUtil.ts","../src/api/blockManipulation/blockManipulation.ts","../src/api/exporters/markdown/removeUnderlinesRehypePlugin.ts","../src/api/exporters/markdown/markdownExporter.ts","../src/api/parsers/html/util/nestedLists.ts","../src/api/parsers/html/parseHTML.ts","../src/api/parsers/markdown/parseMarkdown.ts","../src/util/EventEmitter.ts","../src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts","../src/extensions/LinkToolbar/LinkToolbarPlugin.ts","../src/extensions/SuggestionMenu/SuggestionPlugin.ts","../src/extensions/SideMenu/MultipleNodeSelection.ts","../src/extensions/SideMenu/SideMenuPlugin.ts","../src/extensions/ImagePanel/ImageToolbarPlugin.ts","../src/extensions/TableHandles/TableHandlesPlugin.ts","../src/api/exporters/copyExtension.ts","../src/api/parsers/pasteExtension.ts","../src/extensions/BackgroundColor/BackgroundColorExtension.ts","../src/extensions/Placeholder/PlaceholderExtension.ts","../src/extensions/TextAlignment/TextAlignmentExtension.ts","../src/extensions/TextColor/TextColorExtension.ts","../src/extensions/TrailingNode/TrailingNodeExtension.ts","../src/extensions/NonEditableBlocks/NonEditableBlockPlugin.ts","../src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts","../src/pm-nodes/BlockContainer.ts","../src/pm-nodes/BlockGroup.ts","../src/pm-nodes/Doc.ts","../src/editor/BlockNoteExtensions.ts","../src/editor/transformPasted.ts","../src/editor/BlockNoteSchema.ts","../src/editor/BlockNoteTipTapEditor.ts","../src/editor/BlockNoteEditor.ts","../src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts","../src/api/testUtil/partialBlockTestUtil.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 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 [`data-${this.options.attributeName}`]:\n attributes[this.options.attributeName],\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 // console.log(\"appendTransaction\");\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) => {\n let _a, _b;\n return !((_b = (_a = this.options).filterTransaction) === null ||\n _b === void 0\n ? void 0\n : _b.call(_a, tr));\n });\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 newNodes.forEach(({ node, pos }) => {\n let _a;\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 =\n (_a = tr.doc.nodeAt(pos)) === null || _a === void 0\n ? void 0\n : _a.attrs[attributeName];\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 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`\n // so we can do some checks before\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 dragSourceElement = null;\n transformPasted = true;\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, NodeType } from \"prosemirror-model\";\n\nexport type BlockInfoWithoutPositions = {\n id: string;\n node: Node;\n contentNode: Node;\n contentType: NodeType;\n numChildBlocks: number;\n};\n\nexport type BlockInfo = BlockInfoWithoutPositions & {\n startPos: number;\n endPos: number;\n depth: number;\n};\n\n/**\n * Helper function for `getBlockInfoFromPos`, returns information regarding\n * provided blockContainer node.\n * @param blockContainer The blockContainer node to retrieve info for.\n */\nexport function getBlockInfo(blockContainer: Node): BlockInfoWithoutPositions {\n const id = blockContainer.attrs[\"id\"];\n const contentNode = blockContainer.firstChild!;\n const contentType = contentNode.type;\n const numChildBlocks =\n blockContainer.childCount === 2 ? blockContainer.lastChild!.childCount : 0;\n\n return {\n id,\n node: blockContainer,\n contentNode,\n contentType,\n numChildBlocks,\n };\n}\n\n/**\n * Retrieves information regarding the nearest blockContainer node in a\n * ProseMirror doc, relative to a position.\n * @param doc The ProseMirror doc.\n * @param pos An integer position.\n * @returns A BlockInfo object for the nearest blockContainer node.\n */\nexport function getBlockInfoFromPos(doc: Node, pos: number): BlockInfo {\n // If the position is outside the outer block group, we need to move it to the\n // nearest block. This happens when the collaboration plugin is active, where\n // the selection is placed at the very end of the doc.\n const outerBlockGroupStartPos = 1;\n const outerBlockGroupEndPos = doc.nodeSize - 2;\n if (pos <= outerBlockGroupStartPos) {\n pos = outerBlockGroupStartPos + 1;\n\n while (\n doc.resolve(pos).parent.type.name !== \"blockContainer\" &&\n pos < outerBlockGroupEndPos\n ) {\n pos++;\n }\n } else if (pos >= outerBlockGroupEndPos) {\n pos = outerBlockGroupEndPos - 1;\n\n while (\n doc.resolve(pos).parent.type.name !== \"blockContainer\" &&\n pos > outerBlockGroupStartPos\n ) {\n pos--;\n }\n }\n\n // This gets triggered when a node selection on a block is active, i.e. when\n // you drag and drop a block.\n if (doc.resolve(pos).parent.type.name === \"blockGroup\") {\n pos++;\n }\n\n const $pos = doc.resolve(pos);\n\n const maxDepth = $pos.depth;\n let node = $pos.node(maxDepth);\n let depth = maxDepth;\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n if (depth < 0) {\n throw new Error(\n \"Could not find blockContainer node. This can only happen if the underlying BlockNote schema has been edited.\"\n );\n }\n\n if (node.type.name === \"blockContainer\") {\n break;\n }\n\n depth -= 1;\n node = $pos.node(depth);\n }\n\n const { id, contentNode, contentType, numChildBlocks } = getBlockInfo(node);\n\n const startPos = $pos.start(depth);\n const endPos = $pos.end(depth);\n\n return {\n id,\n node,\n contentNode,\n contentType,\n numChildBlocks,\n startPos,\n endPos,\n depth,\n };\n}\n","import { Node } from \"@tiptap/core\";\nimport { PropSchema, Props } from \"../propTypes\";\nimport { StyleSchema, Styles } from \"../styles/types\";\n\nexport type CustomInlineContentConfig = {\n type: string;\n content: \"styled\" | \"none\"; // | \"plain\"\n readonly propSchema: PropSchema;\n // content: \"inline\" | \"none\" | \"table\";\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 node: Node;\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","export class UnreachableCaseError extends Error {\n constructor(val: never) {\n super(`Unreachable case: ${val}`);\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 { Mark, Node, Schema } from \"@tiptap/pm/model\";\n\nimport UniqueID from \"../../extensions/UniqueID/UniqueID\";\nimport type {\n BlockSchema,\n CustomInlineContentConfig,\n CustomInlineContentFromConfig,\n InlineContent,\n InlineContentFromConfig,\n InlineContentSchema,\n PartialCustomInlineContentFromConfig,\n PartialInlineContent,\n PartialLink,\n PartialTableContent,\n StyleSchema,\n StyledText,\n Styles,\n TableContent,\n} from \"../../schema\";\nimport { getBlockInfo } from \"../getBlockInfoFromPos\";\n\nimport type { Block, PartialBlock } from \"../../blocks/defaultBlocks\";\nimport {\n isLinkInlineContent,\n isPartialLinkInlineContent,\n isStyledTextInlineContent,\n} from \"../../schema/inlineContent/types\";\nimport { UnreachableCaseError } from \"../../util/typescript\";\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): 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 marks.push(schema.mark(style));\n } else if (config.propSchema === \"string\") {\n marks.push(schema.mark(style, { stringValue: value }));\n } else {\n throw new UnreachableCaseError(config.propSchema);\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\"].create();\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): 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 )\n );\n return nodes;\n }\n\n for (const styledText of content) {\n nodes.push(...styledTextToNodes(styledText, schema, styleSchema));\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 styleSchema: S\n): Node[] {\n const nodes: Node[] = [];\n\n for (const content of blockContent) {\n if (typeof content === \"string\") {\n nodes.push(...styledTextArrayToNodes(content, schema, styleSchema));\n } else if (isPartialLinkInlineContent(content)) {\n nodes.push(...linkToNodes(content, schema, styleSchema));\n } else if (isStyledTextInlineContent(content)) {\n nodes.push(...styledTextArrayToNodes([content], schema, styleSchema));\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\n): Node[] {\n const rowNodes: Node[] = [];\n\n for (const row of tableContent.rows) {\n const columnNodes: Node[] = [];\n for (const cell of row.cells) {\n let pNode: Node;\n if (!cell) {\n pNode = schema.nodes[\"tableParagraph\"].create({});\n } else if (typeof cell === \"string\") {\n pNode = schema.nodes[\"tableParagraph\"].create({}, schema.text(cell));\n } else {\n const textNodes = inlineContentToNodes(cell, schema, styleSchema);\n pNode = schema.nodes[\"tableParagraph\"].create({}, textNodes);\n }\n\n const cellNode = schema.nodes[\"tableCell\"].create({}, pNode);\n columnNodes.push(cellNode);\n }\n const rowNode = schema.nodes[\"tableRow\"].create({}, 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].create(block.props);\n } else if (typeof block.content === \"string\") {\n contentNode = schema.nodes[type].create(\n block.props,\n schema.text(block.content)\n );\n } else if (Array.isArray(block.content)) {\n const nodes = inlineContentToNodes(block.content, schema, styleSchema);\n contentNode = schema.nodes[type].create(block.props, nodes);\n } else if (block.content.type === \"tableContent\") {\n const nodes = tableContentToNodes(block.content, schema, styleSchema);\n contentNode = schema.nodes[type].create(block.props, nodes);\n } else {\n throw new UnreachableCaseError(block.content.type);\n }\n return contentNode;\n}\n/**\n * Converts a BlockNote block to a TipTap node.\n */\nexport function blockToNode(\n block: PartialBlock<any, any, any>,\n schema: Schema,\n styleSchema: StyleSchema\n) {\n let id = block.id;\n\n if (id === undefined) {\n id = UniqueID.options.generateID();\n }\n\n const contentNode = blockOrInlineContentToContentNode(\n block,\n schema,\n styleSchema\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 groupNode = schema.nodes[\"blockGroup\"].create({}, children);\n\n return schema.nodes[\"blockContainer\"].create(\n {\n id: id,\n ...block.props,\n },\n children.length > 0 ? [contentNode, groupNode] : contentNode\n );\n}\n\n/**\n * Converts an internal (prosemirror) table node contentto a BlockNote Tablecontent\n */\nfunction 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 rows: [],\n };\n\n contentNode.content.forEach((rowNode) => {\n const row: TableContent<I, S>[\"rows\"][0] = {\n cells: [],\n };\n\n rowNode.content.forEach((cellNode) => {\n row.cells.push(\n contentNodeToInlineContent(\n cellNode.firstChild!,\n inlineContentSchema,\n styleSchema\n )\n );\n });\n\n ret.rows.push(row);\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 (\n node.type.name !== \"link\" &&\n node.type.name !== \"text\" &&\n inlineContentSchema[node.type.name]\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 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].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 TipTap node to a BlockNote block.\n */\nexport function nodeToBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n node: Node,\n blockSchema: BSchema,\n inlineContentSchema: I,\n styleSchema: S,\n blockCache?: WeakMap<Node, Block<BSchema, I, S>>\n): Block<BSchema, I, S> {\n if (node.type.name !== \"blockContainer\") {\n throw Error(\n \"Node must be of type blockContainer, but is of type\" +\n node.type.name +\n \".\"\n );\n }\n\n const cachedBlock = blockCache?.get(node);\n\n if (cachedBlock) {\n return cachedBlock;\n }\n\n const blockInfo = getBlockInfo(node);\n\n let id = blockInfo.id;\n\n // Only used for blocks converted from other formats.\n if (id === null) {\n id = UniqueID.options.generateID();\n }\n\n const props: any = {};\n for (const [attr, value] of Object.entries({\n ...node.attrs,\n ...blockInfo.contentNode.attrs,\n })) {\n const blockSpec = blockSchema[blockInfo.contentType.name];\n\n if (!blockSpec) {\n throw Error(\n \"Block is of an unrecognized type: \" + blockInfo.contentType.name\n );\n }\n\n const propSchema = blockSpec.propSchema;\n\n if (attr in propSchema) {\n props[attr] = value;\n }\n }\n\n const blockConfig = blockSchema[blockInfo.contentType.name];\n\n const children: Block<BSchema, I, S>[] = [];\n for (let i = 0; i < blockInfo.numChildBlocks; i++) {\n children.push(\n nodeToBlock(\n node.lastChild!.child(i),\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 content = contentNodeToInlineContent(\n blockInfo.contentNode,\n inlineContentSchema,\n styleSchema\n );\n } else if (blockConfig.content === \"table\") {\n content = contentNodeToTableContent(\n blockInfo.contentNode,\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","import { DOMSerializer, Fragment, Node } from \"prosemirror-model\";\n\nimport type { BlockNoteEditor } from \"../../../../editor/BlockNoteEditor\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../../schema\";\nimport { nodeToBlock } from \"../../../nodeConversions/nodeConversions\";\n\nfunction doc(options: { document?: Document }) {\n return options.document || window.document;\n}\n\n// Used to implement `serializeNodeInner` for the `internalHTMLSerializer` and\n// `externalHTMLExporter`. Changes how the content of `blockContainer` nodes is\n// serialized vs the default `DOMSerializer` implementation. For the\n// `blockContent` node, the `toInternalHTML` or `toExternalHTML` function of its\n// corresponding block is used for serialization instead of the node's\n// `renderHTML` method.\nexport const serializeNodeInner = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n node: Node,\n options: { document?: Document },\n serializer: DOMSerializer,\n editor: BlockNoteEditor<BSchema, I, S>,\n toExternalHTML: boolean\n) => {\n if (!serializer.nodes[node.type.name]) {\n throw new Error(\"Serializer is missing a node type: \" + node.type.name);\n }\n\n const { dom, contentDOM } = DOMSerializer.renderSpec(\n doc(options),\n serializer.nodes[node.type.name](node)\n );\n\n if (contentDOM) {\n if (node.isLeaf) {\n throw new RangeError(\"Content hole not allowed in a leaf node spec\");\n }\n\n // Handles converting `blockContainer` nodes to HTML.\n if (node.type.name === \"blockContainer\") {\n const blockContentNode =\n node.childCount > 0 &&\n node.firstChild!.type.spec.group === \"blockContent\"\n ? node.firstChild!\n : undefined;\n const blockGroupNode =\n node.childCount > 0 && node.lastChild!.type.spec.group === \"blockGroup\"\n ? node.lastChild!\n : undefined;\n\n // Converts `blockContent` node using the custom `blockSpec`'s\n // `toExternalHTML` or `toInternalHTML` function.\n // Note: While `blockContainer` nodes should always contain a\n // `blockContent` node according to the schema, PM Fragments don't always\n // conform to the schema. This is unintuitive but important as it occurs\n // when copying only nested blocks.\n if (blockContentNode !== undefined) {\n const impl =\n editor.blockImplementations[blockContentNode.type.name]\n .implementation;\n const toHTML = toExternalHTML\n ? impl.toExternalHTML\n : impl.toInternalHTML;\n const blockContent = toHTML(\n nodeToBlock(\n node,\n editor.schema.blockSchema,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n editor.blockCache\n ),\n editor as any\n );\n\n // Converts inline nodes in the `blockContent` node's content to HTML\n // using their `renderHTML` methods.\n if (blockContent.contentDOM !== undefined) {\n if (node.isLeaf) {\n throw new RangeError(\n \"Content hole not allowed in a leaf node spec\"\n );\n }\n\n blockContent.contentDOM.appendChild(\n serializer.serializeFragment(blockContentNode.content, options)\n );\n }\n\n contentDOM.appendChild(blockContent.dom);\n }\n\n // Converts `blockGroup` node to HTML using its `renderHTML` method.\n if (blockGroupNode !== undefined) {\n serializer.serializeFragment(\n Fragment.from(blockGroupNode),\n options,\n contentDOM\n );\n }\n } else {\n // Converts the node normally, i.e. using its `renderHTML method`.\n serializer.serializeFragment(node.content, options, contentDOM);\n }\n }\n\n return dom as HTMLElement;\n};\n\n// Used to implement `serializeProseMirrorFragment` for the\n// `internalHTMLSerializer` and `externalHTMLExporter`. Does basically the same\n// thing as `serializer.serializeFragment`, but takes fewer arguments and\n// returns a string instead, to make it easier to use.\nexport const serializeProseMirrorFragment = (\n fragment: Fragment,\n serializer: DOMSerializer\n) => {\n const internalHTML = serializer.serializeFragment(fragment);\n const parent = document.createElement(\"div\");\n parent.appendChild(internalHTML);\n\n return parent.innerHTML;\n};\n","import { Element as HASTElement, Parent as HASTParent } from \"hast\";\nimport { fromDom } from \"hast-util-from-dom\";\n\ntype SimplifyBlocksOptions = {\n orderedListItemBlockTypes: Set<string>;\n unorderedListItemBlockTypes: Set<string>;\n};\n\n/**\n * Rehype plugin which converts the HTML output string rendered by BlockNote into a simplified structure which better\n * follows HTML standards. It does several things:\n * - Removes all block related div elements, leaving only the actual content inside the block.\n * - Lifts nested blocks to a higher level for all block types that don't represent list items.\n * - Wraps blocks which represent list items in corresponding ul/ol HTML elements and restructures them to comply\n * with HTML list structure.\n * @param options Options for specifying which block types represent ordered and unordered list items.\n */\nexport function simplifyBlocks(options: SimplifyBlocksOptions) {\n const listItemBlockTypes = new Set<string>([\n ...options.orderedListItemBlockTypes,\n ...options.unorderedListItemBlockTypes,\n ]);\n\n const simplifyBlocksHelper = (tree: HASTParent) => {\n // Checks whether blocks in the tree are wrapped by a parent `blockGroup`\n // element, in which case the `blockGroup`'s children are lifted out, and it\n // is removed.\n if (\n tree.children.length === 1 &&\n (tree.children[0] as HASTElement).properties?.[\"dataNodeType\"] ===\n \"blockGroup\"\n ) {\n const blockGroup = tree.children[0] as HASTElement;\n tree.children.pop();\n tree.children.push(...blockGroup.children);\n }\n\n let numChildElements = tree.children.length;\n let activeList: HASTElement | undefined;\n\n for (let i = 0; i < numChildElements; i++) {\n const blockOuter = tree.children[i] as HASTElement;\n const blockContainer = blockOuter.children[0] as HASTElement;\n const blockContent = blockContainer.children[0] as HASTElement;\n const blockGroup =\n blockContainer.children.length === 2\n ? (blockContainer.children[1] as HASTElement)\n : null;\n\n const isListItemBlock = listItemBlockTypes.has(\n blockContent.properties![\"dataContentType\"] as string\n );\n\n const listItemBlockType = isListItemBlock\n ? options.orderedListItemBlockTypes.has(\n blockContent.properties![\"dataContentType\"] as string\n )\n ? \"ol\"\n : \"ul\"\n : null;\n\n // Plugin runs recursively to process nested blocks.\n if (blockGroup !== null) {\n simplifyBlocksHelper(blockGroup);\n }\n\n // Checks that there is an active list, but the block can't be added to it as it's of a different type.\n if (activeList && activeList.tagName !== listItemBlockType) {\n // Blocks that were copied into the list are removed and the list is inserted in their place.\n tree.children.splice(\n i - activeList.children.length,\n activeList.children.length,\n activeList\n );\n\n // Updates the current index and number of child elements.\n const numElementsRemoved = activeList.children.length - 1;\n i -= numElementsRemoved;\n numChildElements -= numElementsRemoved;\n\n activeList = undefined;\n }\n\n // Checks if the block represents a list item.\n if (isListItemBlock) {\n // Checks if a list isn't already active. We don't have to check if the block and the list are of the same\n // type as this was already done earlier.\n if (!activeList) {\n // Creates a new list element to represent an active list.\n activeList = fromDom(\n document.createElement(listItemBlockType!)\n ) as HASTElement;\n }\n\n // Creates a new list item element to represent the block.\n const listItemElement = fromDom(\n document.createElement(\"li\")\n ) as HASTElement;\n\n // Adds only the content inside the block to the active list.\n listItemElement.children.push(blockContent.children[0]);\n // Nested blocks have already been processed in the recursive function call, so the resulting elements are\n // also added to the active list.\n if (blockGroup !== null) {\n listItemElement.children.push(...blockGroup.children);\n }\n\n // Adds the list item representing the block to the active list.\n activeList.children.push(listItemElement);\n } else if (blockGroup !== null) {\n // Lifts all children out of the current block, as only list items should allow nesting.\n tree.children.splice(i + 1, 0, ...blockGroup.children);\n // Replaces the block with only the content inside it.\n tree.children[i] = blockContent.children[0];\n\n // Updates the current index and number of child elements.\n const numElementsAdded = blockGroup.children.length;\n i += numElementsAdded;\n numChildElements += numElementsAdded;\n } else {\n // Replaces the block with only the content inside it.\n tree.children[i] = blockContent.children[0];\n }\n }\n\n // Since the active list is only inserted after encountering a block which can't be added to it, there are cases\n // where it remains un-inserted after processing all blocks, which are handled here.\n if (activeList) {\n tree.children.splice(\n numChildElements - activeList.children.length,\n activeList.children.length,\n activeList\n );\n }\n };\n\n return simplifyBlocksHelper;\n}\n","import { DOMSerializer, Fragment, Node, Schema } from \"prosemirror-model\";\nimport rehypeParse from \"rehype-parse\";\nimport rehypeStringify from \"rehype-stringify\";\nimport { unified } from \"unified\";\n\nimport { PartialBlock } from \"../../../blocks/defaultBlocks\";\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../../schema\";\nimport { blockToNode } from \"../../nodeConversions/nodeConversions\";\nimport {\n serializeNodeInner,\n serializeProseMirrorFragment,\n} from \"./util/sharedHTMLConversion\";\nimport { simplifyBlocks } from \"./util/simplifyBlocksRehypePlugin\";\n\n// Used to export BlockNote blocks and ProseMirror nodes to HTML for use outside\n// the editor. Blocks are exported using the `toExternalHTML` method in their\n// `blockSpec`, or `toInternalHTML` if `toExternalHTML` is not defined.\n//\n// The HTML created by this serializer is different to what's rendered by the\n// editor to the DOM. This also means that data is likely to be lost when\n// converting back to original blocks. The differences in the output HTML are:\n// 1. It doesn't include the `blockGroup` and `blockContainer` wrappers meaning\n// that nesting is not preserved for non-list-item blocks.\n// 2. `li` items in the output HTML are wrapped in `ul` or `ol` elements.\n// 3. While nesting for list items is preserved, other types of blocks nested\n// inside a list are un-nested and a new list is created after them.\n// 4. The HTML is wrapped in a single `div` element.\n//\n// The serializer has 2 main methods:\n// `exportBlocks`: Exports an array of blocks to HTML.\n// `exportFragment`: Exports a ProseMirror fragment to HTML. This is mostly\n// useful if you want to export a selection which may not start/end at the\n// start/end of a block.\nexport interface ExternalHTMLExporter<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n> {\n exportBlocks: (blocks: PartialBlock<BSchema, I, S>[]) => string;\n exportProseMirrorFragment: (fragment: Fragment) => string;\n}\n\nexport const createExternalHTMLExporter = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n schema: Schema,\n editor: BlockNoteEditor<BSchema, I, S>\n): ExternalHTMLExporter<BSchema, I, S> => {\n const serializer = DOMSerializer.fromSchema(schema) as DOMSerializer & {\n serializeNodeInner: (\n node: Node,\n options: { document?: Document }\n ) => HTMLElement;\n // TODO: Should not be async, but is since we're using a rehype plugin to\n // convert internal HTML to external HTML.\n exportProseMirrorFragment: (fragment: Fragment) => string;\n exportBlocks: (blocks: PartialBlock<BSchema, I, S>[]) => string;\n };\n\n serializer.serializeNodeInner = (\n node: Node,\n options: { document?: Document }\n ) => serializeNodeInner(node, options, serializer, editor, true);\n\n // Like the `internalHTMLSerializer`, also uses `serializeProseMirrorFragment`\n // but additionally runs it through the `simplifyBlocks` rehype plugin to\n // convert the internal HTML to external.\n serializer.exportProseMirrorFragment = (fragment) => {\n const externalHTML = unified()\n .use(rehypeParse, { fragment: true })\n .use(simplifyBlocks, {\n orderedListItemBlockTypes: new Set<string>([\"numberedListItem\"]),\n unorderedListItemBlockTypes: new Set<string>([\"bulletListItem\"]),\n })\n .use(rehypeStringify)\n .processSync(serializeProseMirrorFragment(fragment, serializer));\n\n return externalHTML.value as string;\n };\n\n serializer.exportBlocks = (blocks: PartialBlock<BSchema, I, S>[]) => {\n const nodes = blocks.map((block) =>\n blockToNode(block, schema, editor.schema.styleSchema)\n );\n const blockGroup = schema.nodes[\"blockGroup\"].create(null, nodes);\n\n return serializer.exportProseMirrorFragment(Fragment.from(blockGroup));\n };\n\n return serializer;\n};\n","import { DOMSerializer, Fragment, Node, Schema } from \"prosemirror-model\";\nimport { PartialBlock } from \"../../../blocks/defaultBlocks\";\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../../schema\";\nimport { blockToNode } from \"../../nodeConversions/nodeConversions\";\nimport {\n serializeNodeInner,\n serializeProseMirrorFragment,\n} from \"./util/sharedHTMLConversion\";\n\n// Used to serialize BlockNote blocks and ProseMirror nodes to HTML without\n// losing data. Blocks are exported using the `toInternalHTML` method in their\n// `blockSpec`.\n//\n// The HTML created by this serializer is the same as what's rendered by the\n// editor to the DOM. This means that it retains the same structure as the\n// editor, including the `blockGroup` and `blockContainer` wrappers. This also\n// means that it can be converted back to the original blocks without any data\n// loss.\n//\n// The serializer has 2 main methods:\n// `serializeFragment`: Serializes a ProseMirror fragment to HTML. This is\n// mostly useful if you want to serialize a selection which may not start/end at\n// the start/end of a block.\n// `serializeBlocks`: Serializes an array of blocks to HTML.\nexport interface InternalHTMLSerializer<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n> {\n // TODO: Ideally we would expand the BlockNote API to support partial\n // selections so we don't need this.\n serializeProseMirrorFragment: (fragment: Fragment) => string;\n serializeBlocks: (blocks: PartialBlock<BSchema, I, S>[]) => string;\n}\n\nexport const createInternalHTMLSerializer = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n schema: Schema,\n editor: BlockNoteEditor<BSchema, I, S>\n): InternalHTMLSerializer<BSchema, I, S> => {\n const serializer = DOMSerializer.fromSchema(schema) as DOMSerializer & {\n serializeNodeInner: (\n node: Node,\n options: { document?: Document }\n ) => HTMLElement;\n serializeBlocks: (blocks: PartialBlock<BSchema, I, S>[]) => string;\n serializeProseMirrorFragment: (\n fragment: Fragment,\n options?: { document?: Document | undefined } | undefined,\n target?: HTMLElement | DocumentFragment | undefined\n ) => string;\n };\n\n serializer.serializeNodeInner = (\n node: Node,\n options: { document?: Document }\n ) => serializeNodeInner(node, options, serializer, editor, false);\n\n serializer.serializeProseMirrorFragment = (fragment: Fragment) =>\n serializeProseMirrorFragment(fragment, serializer);\n\n serializer.serializeBlocks = (blocks: PartialBlock<BSchema, I, S>[]) => {\n const nodes = blocks.map((block) =>\n blockToNode(block, schema, editor.schema.styleSchema)\n );\n const blockGroup = schema.nodes[\"blockGroup\"].create(null, nodes);\n\n return serializer.serializeProseMirrorFragment(Fragment.from(blockGroup));\n };\n\n return serializer;\n};\n","/**\n * Uploads a file to tmpfiles.org and returns the URL to the uploaded file.\n *\n * @warning This function should only be used for development purposes, replace with your own backend!\n */\nexport const uploadToTmpFilesDotOrg_DEV_ONLY = async (\n file: File\n): Promise<string> => {\n const body = new FormData();\n body.append(\"file\", file);\n\n const ret = await fetch(\"https://tmpfiles.org/api/v1/upload\", {\n method: \"POST\",\n body: body,\n });\n return (await ret.json()).data.url.replace(\n \"tmpfiles.org/\",\n \"tmpfiles.org/dl/\"\n );\n};\n","export const isAppleOS = () =>\n typeof navigator !== \"undefined\" &&\n (/Mac/.test(navigator.platform) ||\n (/AppleWebKit/.test(navigator.userAgent) &&\n /Mobile\\/\\w+/.test(navigator.userAgent)));\n\nexport function formatKeyboardShortcut(shortcut: string) {\n if (isAppleOS()) {\n return shortcut.replace(\"Mod\", \"⌘\");\n } else {\n return shortcut.replace(\"Mod\", \"Ctrl\");\n }\n}\n\nexport function mergeCSSClasses(...classes: string[]) {\n return classes.filter((c) => c).join(\" \");\n}\n\nexport const isSafari = () =>\n /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n","import { blockToNode } from \"../api/nodeConversions/nodeConversions\";\nimport type { BlockNoteEditor } from \"../editor/BlockNoteEditor\";\nimport type {\n BlockNoDefaults,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../schema\";\nimport { mergeCSSClasses } from \"../util/browser\";\n\n// Function that creates a ProseMirror `DOMOutputSpec` for a default block.\n// Since all default blocks have the same structure (`blockContent` div with a\n// `inlineContent` element inside), this function only needs the block's name\n// for the `data-content-type` attribute of the `blockContent` element and the\n// HTML tag of the `inlineContent` element, as well as any HTML attributes to\n// add to those.\nexport function createDefaultBlockDOMOutputSpec(\n blockName: string,\n htmlTag: string,\n blockContentHTMLAttributes: Record<string, string>,\n inlineContentHTMLAttributes: Record<string, string>\n) {\n const blockContent = document.createElement(\"div\");\n blockContent.className = mergeCSSClasses(\n \"bn-block-content\",\n blockContentHTMLAttributes.class\n );\n blockContent.setAttribute(\"data-content-type\", blockName);\n for (const [attribute, value] of Object.entries(blockContentHTMLAttributes)) {\n if (attribute !== \"class\") {\n blockContent.setAttribute(attribute, value);\n }\n }\n\n const inlineContent = document.createElement(htmlTag);\n inlineContent.className = mergeCSSClasses(\n \"bn-inline-content\",\n inlineContentHTMLAttributes.class\n );\n for (const [attribute, value] of Object.entries(\n inlineContentHTMLAttributes\n )) {\n if (attribute !== \"class\") {\n inlineContent.setAttribute(attribute, value);\n }\n }\n\n blockContent.appendChild(inlineContent);\n\n return {\n dom: blockContent,\n contentDOM: inlineContent,\n };\n}\n\n// Function used to convert default blocks to HTML. It uses the corresponding\n// node's `renderHTML` method to do the conversion by using a default\n// `DOMSerializer`.\nexport const defaultBlockToHTML = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n block: BlockNoDefaults<BSchema, I, S>,\n editor: BlockNoteEditor<BSchema, I, S>\n): {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n} => {\n const node = blockToNode(\n block,\n editor._tiptapEditor.schema,\n editor.schema.styleSchema\n ).firstChild!;\n const toDOM = editor._tiptapEditor.schema.nodes[node.type.name].spec.toDOM;\n\n if (toDOM === undefined) {\n throw new Error(\n \"This block has no default HTML serialization as its corresponding TipTap node doesn't implement `renderHTML`.\"\n );\n }\n\n const renderSpec = toDOM(node);\n\n if (typeof renderSpec !== \"object\" || !(\"dom\" in renderSpec)) {\n throw new Error(\n \"Cannot use this block's default HTML serialization as its corresponding TipTap node's `renderHTML` function does not return an object with the `dom` property.\"\n );\n }\n\n return renderSpec as {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n};\n","import type { Props, PropSchema } from \"../schema\";\n\n// TODO: this system should probably be moved / refactored.\n// The dependency from schema on this file doesn't make sense\n\nexport const defaultProps = {\n backgroundColor: {\n default: \"default\" as const,\n },\n textColor: {\n default: \"default\" as const,\n },\n textAlignment: {\n default: \"left\" as const,\n values: [\"left\", \"center\", \"right\", \"justify\"] as const,\n },\n} satisfies PropSchema;\n\nexport type DefaultProps = Props<typeof defaultProps>;\n\n// Default props which are set on `blockContainer` nodes rather than\n// `blockContent` nodes. Ensures that they are not redundantly added to\n// a custom block's TipTap node attributes.\nexport const inheritedProps = [\"backgroundColor\", \"textColor\"];\n","export function camelToDataKebab(str: string): string {\n return \"data-\" + str.replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase();\n}\n","import {\n Attribute,\n Attributes,\n Editor,\n Extension,\n Node,\n NodeConfig,\n} from \"@tiptap/core\";\nimport { defaultBlockToHTML } from \"../../blocks/defaultBlockHelpers\";\nimport { inheritedProps } from \"../../blocks/defaultProps\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport { mergeCSSClasses } from \"../../util/browser\";\nimport { camelToDataKebab } from \"../../util/string\";\nimport { InlineContentSchema } from \"../inlineContent/types\";\nimport { PropSchema, Props } from \"../propTypes\";\nimport { StyleSchema } from \"../styles/types\";\nimport {\n BlockConfig,\n BlockSchemaFromSpecs,\n BlockSchemaWithBlock,\n BlockSpec,\n BlockSpecs,\n SpecificBlock,\n TiptapBlockImplementation,\n} from \"./types\";\n\n// Function that uses the 'propSchema' of a blockConfig to create a TipTap\n// node's `addAttributes` property.\n// TODO: extract function\nexport function propsToAttributes(propSchema: PropSchema): Attributes {\n const tiptapAttributes: Record<string, Attribute> = {};\n\n Object.entries(propSchema)\n .filter(([name, _spec]) => !inheritedProps.includes(name))\n .forEach(([name, spec]) => {\n tiptapAttributes[name] = {\n default: spec.default,\n keepOnSplit: true,\n // Props are displayed in kebab-case as HTML attributes. If a prop's\n // value is the same as its default, we don't display an HTML\n // attribute for it.\n parseHTML: (element) => {\n const value = element.getAttribute(camelToDataKebab(name));\n\n if (value === null) {\n return null;\n }\n\n if (typeof spec.default === \"boolean\") {\n if (value === \"true\") {\n return true;\n }\n\n if (value === \"false\") {\n return false;\n }\n\n return null;\n }\n\n if (typeof spec.default === \"number\") {\n const asNumber = parseFloat(value);\n const isNumeric =\n !Number.isNaN(asNumber) && Number.isFinite(asNumber);\n\n if (isNumeric) {\n return asNumber;\n }\n\n return null;\n }\n\n return value;\n },\n renderHTML: (attributes) =>\n attributes[name] !== spec.default\n ? {\n [camelToDataKebab(name)]: attributes[name],\n }\n : {},\n };\n });\n\n return tiptapAttributes;\n}\n\n// Used to figure out which block should be rendered. This block is then used to\n// create the node view.\nexport function getBlockFromPos<\n BType extends string,\n Config extends BlockConfig,\n BSchema extends BlockSchemaWithBlock<BType, Config>,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n getPos: (() => number) | boolean,\n editor: BlockNoteEditor<BSchema, I, S>,\n tipTapEditor: Editor,\n type: BType\n) {\n // Gets position of the node\n if (typeof getPos === \"boolean\") {\n throw new Error(\n \"Cannot find node position as getPos is a boolean, not a function.\"\n );\n }\n const pos = getPos();\n // Gets parent blockContainer node\n const blockContainer = tipTapEditor.state.doc.resolve(pos!).node();\n // Gets block identifier\n const blockIdentifier = blockContainer.attrs.id;\n // Gets the block\n const block = editor.getBlock(blockIdentifier)! as SpecificBlock<\n BSchema,\n BType,\n I,\n S\n >;\n if (block.type !== type) {\n throw new Error(\"Block type does not match\");\n }\n\n return block;\n}\n\n// Function that wraps the `dom` element returned from 'blockConfig.render' in a\n// `blockContent` div, which contains the block type and props as HTML\n// attributes. If `blockConfig.render` also returns a `contentDOM`, it also adds\n// an `inlineContent` class to it.\nexport function wrapInBlockStructure<\n BType extends string,\n PSchema extends PropSchema\n>(\n element: {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n destroy?: () => void;\n },\n blockType: BType,\n blockProps: Props<PSchema>,\n propSchema: PSchema,\n domAttributes?: Record<string, string>\n): {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n destroy?: () => void;\n} {\n // Creates `blockContent` element\n const blockContent = document.createElement(\"div\");\n\n // Adds custom HTML attributes\n if (domAttributes !== undefined) {\n for (const [attr, value] of Object.entries(domAttributes)) {\n if (attr !== \"class\") {\n blockContent.setAttribute(attr, value);\n }\n }\n }\n // Sets blockContent class\n blockContent.className = mergeCSSClasses(\n \"bn-block-content\",\n domAttributes?.class || \"\"\n );\n // Sets content type attribute\n blockContent.setAttribute(\"data-content-type\", blockType);\n // Adds props as HTML attributes in kebab-case with \"data-\" prefix. Skips props\n // which are already added as HTML attributes to the parent `blockContent`\n // element (inheritedProps) and props set to their default values.\n for (const [prop, value] of Object.entries(blockProps)) {\n if (!inheritedProps.includes(prop) && value !== propSchema[prop].default) {\n blockContent.setAttribute(camelToDataKebab(prop), value);\n }\n }\n\n blockContent.appendChild(element.dom);\n\n if (element.contentDOM !== undefined) {\n element.contentDOM.className = mergeCSSClasses(\n \"bn-inline-content\",\n element.contentDOM.className\n );\n element.contentDOM.setAttribute(\"data-editable\", \"\");\n }\n\n return {\n ...element,\n dom: blockContent,\n };\n}\n\n// Helper type to keep track of the `name` and `content` properties after calling Node.create.\ntype StronglyTypedTipTapNode<\n Name extends string,\n Content extends \"inline*\" | \"tableRow+\" | \"\"\n> = Node & { name: Name; config: { content: Content } };\n\nexport function createStronglyTypedTiptapNode<\n Name extends string,\n Content extends \"inline*\" | \"tableRow+\" | \"\"\n>(config: NodeConfig & { name: Name; content: Content }) {\n return Node.create(config) as StronglyTypedTipTapNode<Name, Content>; // force re-typing (should be safe as it's type-checked from the config)\n}\n\n// This helper function helps to instantiate a blockspec with a\n// config and implementation that conform to the type of Config\nexport function createInternalBlockSpec<T extends BlockConfig>(\n config: T,\n implementation: TiptapBlockImplementation<\n T,\n any,\n InlineContentSchema,\n StyleSchema\n >\n) {\n return {\n config,\n implementation,\n } satisfies BlockSpec<T, any, InlineContentSchema, StyleSchema>;\n}\n\nexport function createBlockSpecFromStronglyTypedTiptapNode<\n T extends Node,\n P extends PropSchema\n>(node: T, propSchema: P, requiredExtensions?: Array<Extension | Node>) {\n return createInternalBlockSpec(\n {\n type: node.name as T[\"name\"],\n content: (node.config.content === \"inline*\"\n ? \"inline\"\n : node.config.content === \"tableRow+\"\n ? \"table\"\n : \"none\") as T[\"config\"][\"content\"] extends \"inline*\"\n ? \"inline\"\n : T[\"config\"][\"content\"] extends \"tableRow+\"\n ? \"table\"\n : \"none\",\n propSchema,\n },\n {\n node,\n requiredExtensions,\n toInternalHTML: defaultBlockToHTML,\n toExternalHTML: defaultBlockToHTML,\n // parse: () => undefined, // parse rules are in node already\n }\n );\n}\n\nexport function getBlockSchemaFromSpecs<T extends BlockSpecs>(specs: T) {\n return Object.fromEntries(\n Object.entries(specs).map(([key, value]) => [key, value.config])\n ) as BlockSchemaFromSpecs<T>;\n}\n","import { ParseRule } from \"@tiptap/pm/model\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport { InlineContentSchema } from \"../inlineContent/types\";\nimport { StyleSchema } from \"../styles/types\";\nimport {\n createInternalBlockSpec,\n createStronglyTypedTiptapNode,\n getBlockFromPos,\n propsToAttributes,\n wrapInBlockStructure,\n} from \"./internal\";\nimport {\n BlockConfig,\n BlockFromConfig,\n BlockSchemaWithBlock,\n PartialBlockFromConfig,\n} from \"./types\";\n\n// restrict content to \"inline\" and \"none\" only\nexport type CustomBlockConfig = BlockConfig & {\n content: \"inline\" | \"none\";\n};\n\nexport type CustomBlockImplementation<\n T extends CustomBlockConfig,\n I extends InlineContentSchema,\n S extends StyleSchema\n> = {\n render: (\n /**\n * The custom block to render\n */\n block: BlockFromConfig<T, I, S>,\n /**\n * The BlockNote editor instance\n * This is typed generically. If you want an editor with your custom schema, you need to\n * cast it manually, e.g.: `const e = editor as BlockNoteEditor<typeof mySchema>;`\n */\n editor: BlockNoteEditor<BlockSchemaWithBlock<T[\"type\"], T>, I, S>\n // (note) if we want to fix the manual cast, we need to prevent circular references and separate block definition and render implementations\n // or allow manually passing <BSchema>, but that's not possible without passing the other generics because Typescript doesn't support partial inferred generics\n ) => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n destroy?: () => void;\n };\n // Exports block to external HTML. If not defined, the output will be the same\n // as `render(...).dom`. Used to create clipboard data when pasting outside\n // BlockNote.\n // TODO: Maybe can return undefined to ignore when serializing?\n toExternalHTML?: (\n block: BlockFromConfig<T, I, S>,\n editor: BlockNoteEditor<BlockSchemaWithBlock<T[\"type\"], T>, I, S>\n ) => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n\n parse?: (\n el: HTMLElement\n ) => PartialBlockFromConfig<T, I, S>[\"props\"] | undefined;\n};\n\n// Function that uses the 'parse' function of a blockConfig to create a\n// TipTap node's `parseHTML` property. This is only used for parsing content\n// from the clipboard.\nexport function getParseRules(\n config: BlockConfig,\n customParseFunction: CustomBlockImplementation<any, any, any>[\"parse\"]\n) {\n const rules: ParseRule[] = [\n {\n tag: \"[data-content-type=\" + config.type + \"]\",\n contentElement: \"[data-editable]\",\n },\n ];\n\n if (customParseFunction) {\n rules.push({\n tag: \"*\",\n getAttrs(node: string | HTMLElement) {\n if (typeof node === \"string\") {\n return false;\n }\n\n const props = customParseFunction?.(node);\n\n if (props === undefined) {\n return false;\n }\n\n return props;\n },\n });\n }\n // getContent(node, schema) {\n // const block = blockConfig.parse?.(node as HTMLElement);\n //\n // if (block !== undefined && block.content !== undefined) {\n // return Fragment.from(\n // typeof block.content === \"string\"\n // ? schema.text(block.content)\n // : inlineContentToNodes(block.content, schema)\n // );\n // }\n //\n // return Fragment.empty;\n // },\n // });\n // }\n\n return rules;\n}\n\n// A function to create custom block for API consumers\n// we want to hide the tiptap node from API consumers and provide a simpler API surface instead\nexport function createBlockSpec<\n T extends CustomBlockConfig,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(blockConfig: T, blockImplementation: CustomBlockImplementation<T, I, S>) {\n const node = createStronglyTypedTiptapNode({\n name: blockConfig.type as T[\"type\"],\n content: (blockConfig.content === \"inline\"\n ? \"inline*\"\n : \"\") as T[\"content\"] extends \"inline\" ? \"inline*\" : \"\",\n group: \"blockContent\",\n selectable: true,\n\n addAttributes() {\n return propsToAttributes(blockConfig.propSchema);\n },\n\n parseHTML() {\n return getParseRules(blockConfig, blockImplementation.parse);\n },\n\n renderHTML() {\n // renderHTML is not really used, as we always use a nodeView, and we use toExternalHTML / toInternalHTML for serialization\n // There's an edge case when this gets called nevertheless; before the nodeviews have been mounted\n // this is why we implement it with a temporary placeholder\n const div = document.createElement(\"div\");\n div.setAttribute(\"data-tmp-placeholder\", \"true\");\n return {\n dom: div,\n };\n },\n\n addNodeView() {\n return ({ getPos }) => {\n // Gets the BlockNote editor instance\n const editor = this.options.editor;\n // Gets the block\n const block = getBlockFromPos(\n getPos,\n editor,\n this.editor,\n blockConfig.type\n );\n // Gets the custom HTML attributes for `blockContent` nodes\n const blockContentDOMAttributes =\n this.options.domAttributes?.blockContent || {};\n\n const output = blockImplementation.render(block as any, editor);\n\n return wrapInBlockStructure(\n output,\n block.type,\n block.props,\n blockConfig.propSchema,\n blockContentDOMAttributes\n );\n };\n },\n });\n\n if (node.name !== blockConfig.type) {\n throw new Error(\n \"Node name does not match block type. This is a bug in BlockNote.\"\n );\n }\n\n return createInternalBlockSpec(blockConfig, {\n node,\n toInternalHTML: (block, editor) => {\n const blockContentDOMAttributes =\n node.options.domAttributes?.blockContent || {};\n\n const output = blockImplementation.render(block as any, editor as any);\n\n return wrapInBlockStructure(\n output,\n block.type,\n block.props,\n blockConfig.propSchema,\n blockContentDOMAttributes\n );\n },\n toExternalHTML: (block, editor) => {\n const blockContentDOMAttributes =\n node.options.domAttributes?.blockContent || {};\n\n let output = blockImplementation.toExternalHTML?.(\n block as any,\n editor as any\n );\n if (output === undefined) {\n output = blockImplementation.render(block as any, editor as any);\n }\n\n return wrapInBlockStructure(\n output,\n block.type,\n block.props,\n blockConfig.propSchema,\n blockContentDOMAttributes\n );\n },\n });\n}\n","import { KeyboardShortcutCommand, Node } from \"@tiptap/core\";\n\nimport { camelToDataKebab } from \"../../util/string\";\nimport { PropSchema, Props } from \"../propTypes\";\nimport {\n CustomInlineContentConfig,\n InlineContentConfig,\n InlineContentImplementation,\n InlineContentSchemaFromSpecs,\n InlineContentSpec,\n InlineContentSpecs,\n} from \"./types\";\n\n// Function that adds necessary classes and attributes to the `dom` element\n// returned from a custom inline content's 'render' function, to ensure no data\n// is lost on internal copy & paste.\nexport function addInlineContentAttributes<\n IType extends string,\n PSchema extends PropSchema\n>(\n element: {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n },\n inlineContentType: IType,\n inlineContentProps: Props<PSchema>,\n propSchema: PSchema\n): {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n} {\n // Sets content type attribute\n element.dom.setAttribute(\"data-inline-content-type\", inlineContentType);\n // Adds props as HTML attributes in kebab-case with \"data-\" prefix. Skips props\n // set to their default values.\n Object.entries(inlineContentProps)\n .filter(([prop, value]) => value !== propSchema[prop].default)\n .map(([prop, value]) => {\n return [camelToDataKebab(prop), value];\n })\n .forEach(([prop, value]) => element.dom.setAttribute(prop, value));\n\n if (element.contentDOM !== undefined) {\n element.contentDOM.setAttribute(\"data-editable\", \"\");\n }\n\n return element;\n}\n\n// see https://github.com/TypeCellOS/BlockNote/pull/435\nexport function addInlineContentKeyboardShortcuts<\n T extends CustomInlineContentConfig\n>(\n config: T\n): {\n [p: string]: KeyboardShortcutCommand;\n} {\n return {\n Backspace: ({ editor }) => {\n const resolvedPos = editor.state.selection.$from;\n\n return (\n editor.state.selection.empty &&\n resolvedPos.node().type.name === config.type &&\n resolvedPos.parentOffset === 0\n );\n },\n };\n}\n\n// This helper function helps to instantiate a InlineContentSpec with a\n// config and implementation that conform to the type of Config\nexport function createInternalInlineContentSpec<T extends InlineContentConfig>(\n config: T,\n implementation: InlineContentImplementation<T>\n) {\n return {\n config,\n implementation,\n } satisfies InlineContentSpec<T>;\n}\n\nexport function createInlineContentSpecFromTipTapNode<\n T extends Node,\n P extends PropSchema\n>(node: T, propSchema: P) {\n return createInternalInlineContentSpec(\n {\n type: node.name as T[\"name\"],\n propSchema,\n content: node.config.content === \"inline*\" ? \"styled\" : \"none\",\n },\n {\n node,\n }\n );\n}\n\nexport function getInlineContentSchemaFromSpecs<T extends InlineContentSpecs>(\n specs: T\n) {\n return Object.fromEntries(\n Object.entries(specs).map(([key, value]) => [key, value.config])\n ) as InlineContentSchemaFromSpecs<T>;\n}\n","import { Node } from \"@tiptap/core\";\nimport { ParseRule } from \"@tiptap/pm/model\";\nimport { nodeToCustomInlineContent } from \"../../api/nodeConversions/nodeConversions\";\nimport { propsToAttributes } from \"../blocks/internal\";\nimport { Props } from \"../propTypes\";\nimport { StyleSchema } from \"../styles/types\";\nimport {\n addInlineContentAttributes,\n addInlineContentKeyboardShortcuts,\n createInlineContentSpecFromTipTapNode,\n} from \"./internal\";\nimport {\n CustomInlineContentConfig,\n InlineContentConfig,\n InlineContentFromConfig,\n InlineContentSpec,\n} from \"./types\";\n\n// TODO: support serialization\n\nexport type CustomInlineContentImplementation<\n T extends InlineContentConfig,\n // B extends BlockSchema,\n // I extends InlineContentSchema,\n S extends StyleSchema\n> = {\n render: (\n /**\n * The custom inline content to render\n */\n inlineContent: InlineContentFromConfig<T, S>\n /**\n * The BlockNote editor instance\n * This is typed generically. If you want an editor with your custom schema, you need to\n * cast it manually, e.g.: `const e = editor as BlockNoteEditor<typeof mySchema>;`\n */\n // editor: BlockNoteEditor<B, I, S>\n // (note) if we want to fix the manual cast, we need to prevent circular references and separate block definition and render implementations\n // or allow manually passing <BSchema>, but that's not possible without passing the other generics because Typescript doesn't support partial inferred generics\n ) => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n // destroy?: () => void;\n };\n};\n\nexport function getInlineContentParseRules(\n config: CustomInlineContentConfig\n): ParseRule[] {\n return [\n {\n tag: `[data-inline-content-type=\"${config.type}\"]`,\n contentElement: (element) => {\n const htmlElement = element as HTMLElement;\n\n if (htmlElement.matches(\"[data-editable]\")) {\n return htmlElement;\n }\n\n return htmlElement.querySelector(\"[data-editable]\") || htmlElement;\n },\n },\n ];\n}\n\nexport function createInlineContentSpec<\n T extends CustomInlineContentConfig,\n S extends StyleSchema\n>(\n inlineContentConfig: T,\n inlineContentImplementation: CustomInlineContentImplementation<T, S>\n): InlineContentSpec<T> {\n const node = Node.create({\n name: inlineContentConfig.type,\n inline: true,\n group: \"inline\",\n selectable: inlineContentConfig.content === \"styled\",\n atom: inlineContentConfig.content === \"none\",\n content: (inlineContentConfig.content === \"styled\"\n ? \"inline*\"\n : \"\") as T[\"content\"] extends \"styled\" ? \"inline*\" : \"\",\n\n addAttributes() {\n return propsToAttributes(inlineContentConfig.propSchema);\n },\n\n addKeyboardShortcuts() {\n return addInlineContentKeyboardShortcuts(inlineContentConfig);\n },\n\n parseHTML() {\n return getInlineContentParseRules(inlineContentConfig);\n },\n\n renderHTML({ node }) {\n const editor = this.options.editor;\n\n const output = inlineContentImplementation.render(\n nodeToCustomInlineContent(\n node,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema\n ) as any as InlineContentFromConfig<T, S> // TODO: fix cast\n );\n\n return addInlineContentAttributes(\n output,\n inlineContentConfig.type,\n node.attrs as Props<T[\"propSchema\"]>,\n inlineContentConfig.propSchema\n );\n },\n });\n\n return createInlineContentSpecFromTipTapNode(\n node,\n inlineContentConfig.propSchema\n ) as InlineContentSpec<T>; // TODO: fix cast\n}\n","import { Attributes, Mark } from \"@tiptap/core\";\nimport {\n StyleConfig,\n StyleImplementation,\n StylePropSchema,\n StyleSchemaFromSpecs,\n StyleSpec,\n StyleSpecs,\n} from \"./types\";\n\nexport function stylePropsToAttributes(\n propSchema: StylePropSchema\n): Attributes {\n if (propSchema === \"boolean\") {\n return {};\n }\n return {\n stringValue: {\n default: undefined,\n keepOnSplit: true,\n parseHTML: (element) => element.getAttribute(\"data-value\"),\n renderHTML: (attributes) =>\n attributes.stringValue !== undefined\n ? {\n \"data-value\": attributes.stringValue,\n }\n : {},\n },\n };\n}\n\n// Function that adds necessary classes and attributes to the `dom` element\n// returned from a custom style's 'render' function, to ensure no data is lost\n// on internal copy & paste.\nexport function addStyleAttributes<\n SType extends string,\n PSchema extends StylePropSchema\n>(\n element: {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n },\n styleType: SType,\n styleValue: PSchema extends \"boolean\" ? undefined : string,\n propSchema: PSchema\n): {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n} {\n // Sets content type attribute\n element.dom.setAttribute(\"data-style-type\", styleType);\n // Adds style value as an HTML attribute in kebab-case with \"data-\" prefix, if\n // the style takes a string value.\n if (propSchema === \"string\") {\n element.dom.setAttribute(\"data-value\", styleValue as string);\n }\n\n if (element.contentDOM !== undefined) {\n element.contentDOM.setAttribute(\"data-editable\", \"\");\n }\n\n return element;\n}\n\n// This helper function helps to instantiate a stylespec with a\n// config and implementation that conform to the type of Config\nexport function createInternalStyleSpec<T extends StyleConfig>(\n config: T,\n implementation: StyleImplementation\n) {\n return {\n config,\n implementation,\n } satisfies StyleSpec<T>;\n}\n\nexport function createStyleSpecFromTipTapMark<\n T extends Mark,\n P extends StylePropSchema\n>(mark: T, propSchema: P) {\n return createInternalStyleSpec(\n {\n type: mark.name as T[\"name\"],\n propSchema,\n },\n {\n mark,\n }\n );\n}\n\nexport function getStyleSchemaFromSpecs<T extends StyleSpecs>(specs: T) {\n return Object.fromEntries(\n Object.entries(specs).map(([key, value]) => [key, value.config])\n ) as StyleSchemaFromSpecs<T>;\n}\n","import { Mark } from \"@tiptap/core\";\nimport { ParseRule } from \"@tiptap/pm/model\";\nimport {\n addStyleAttributes,\n createInternalStyleSpec,\n stylePropsToAttributes,\n} from \"./internal\";\nimport { StyleConfig, StyleSpec } from \"./types\";\nimport {UnreachableCaseError} from \"../../util/typescript\";\n\nexport type CustomStyleImplementation<T extends StyleConfig> = {\n render: T[\"propSchema\"] extends \"boolean\"\n ? () => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n }\n : (value: string) => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n};\n\n// TODO: support serialization\n\nexport function getStyleParseRules(config: StyleConfig): ParseRule[] {\n return [\n {\n tag: `[data-style-type=\"${config.type}\"]`,\n contentElement: (element) => {\n const htmlElement = element as HTMLElement;\n\n if (htmlElement.matches(\"[data-editable]\")) {\n return htmlElement;\n }\n\n return htmlElement.querySelector(\"[data-editable]\") || htmlElement;\n },\n },\n ];\n}\n\nexport function createStyleSpec<T extends StyleConfig>(\n styleConfig: T,\n styleImplementation: CustomStyleImplementation<T>\n): StyleSpec<T> {\n const mark = Mark.create({\n name: styleConfig.type,\n\n addAttributes() {\n return stylePropsToAttributes(styleConfig.propSchema);\n },\n\n parseHTML() {\n return getStyleParseRules(styleConfig);\n },\n\n renderHTML({ mark }) {\n let renderResult: {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n\n if (styleConfig.propSchema === \"boolean\") {\n // @ts-ignore not sure why this is complaining\n renderResult = styleImplementation.render();\n } else if (styleConfig.propSchema === \"string\") {\n renderResult = styleImplementation.render(mark.attrs.stringValue);\n } else {\n throw new UnreachableCaseError(styleConfig.propSchema);\n }\n\n // const renderResult = styleImplementation.render();\n return addStyleAttributes(\n renderResult,\n styleConfig.type,\n mark.attrs.stringValue,\n styleConfig.propSchema\n );\n },\n });\n\n return createInternalStyleSpec(styleConfig, {\n mark,\n });\n}\n","import { Mark } from \"@tiptap/core\";\nimport { createStyleSpecFromTipTapMark } from \"../../schema\";\n\nconst BackgroundColorMark = Mark.create({\n name: \"backgroundColor\",\n\n addAttributes() {\n return {\n stringValue: {\n default: undefined,\n parseHTML: (element) => element.getAttribute(\"data-background-color\"),\n renderHTML: (attributes) => ({\n \"data-background-color\": attributes.stringValue,\n }),\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"span\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n if (element.hasAttribute(\"data-background-color\")) {\n return {\n stringValue: element.getAttribute(\"data-background-color\"),\n };\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"span\", HTMLAttributes, 0];\n },\n});\n\nexport const BackgroundColor = createStyleSpecFromTipTapMark(\n BackgroundColorMark,\n \"string\"\n);\n","import { Mark } from \"@tiptap/core\";\nimport { createStyleSpecFromTipTapMark } from \"../../schema\";\n\nconst TextColorMark = Mark.create({\n name: \"textColor\",\n\n addAttributes() {\n return {\n stringValue: {\n default: undefined,\n parseHTML: (element) => element.getAttribute(\"data-text-color\"),\n renderHTML: (attributes) => ({\n \"data-text-color\": attributes.stringValue,\n }),\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"span\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n if (element.hasAttribute(\"data-text-color\")) {\n return { stringValue: element.getAttribute(\"data-text-color\") };\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"span\", HTMLAttributes, 0];\n },\n});\n\nexport const TextColor = createStyleSpecFromTipTapMark(TextColorMark, \"string\");\n","import { Editor } from \"@tiptap/core\";\nimport { getBlockInfoFromPos } from \"./getBlockInfoFromPos\";\n\n// Used to get the content type of the block that the text cursor is in. This is\n// a band-aid fix to prevent input rules and keyboard shortcuts from triggering\n// in tables, but really those should be extended to work with block selections.\nexport const getCurrentBlockContentType = (editor: Editor) => {\n const { contentType } = getBlockInfoFromPos(\n editor.state.doc,\n editor.state.selection.from\n );\n\n return contentType.spec.content;\n};\n","import { InputRule } from \"@tiptap/core\";\nimport {\n PropSchema,\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../schema\";\nimport { createDefaultBlockDOMOutputSpec } from \"../defaultBlockHelpers\";\nimport { defaultProps } from \"../defaultProps\";\nimport { getCurrentBlockContentType } from \"../../api/getCurrentBlockContentType\";\n\nexport const headingPropSchema = {\n ...defaultProps,\n level: { default: 1, values: [1, 2, 3] as const },\n} satisfies PropSchema;\n\nconst HeadingBlockContent = createStronglyTypedTiptapNode({\n name: \"heading\",\n content: \"inline*\",\n group: \"blockContent\",\n addAttributes() {\n return {\n level: {\n default: 1,\n // instead of \"level\" attributes, use \"data-level\"\n parseHTML: (element) => {\n const attr = element.getAttribute(\"data-level\")!;\n const parsed = parseInt(attr);\n if (isFinite(parsed)) {\n return parsed;\n }\n return undefined;\n },\n renderHTML: (attributes) => {\n return {\n \"data-level\": (attributes.level as number).toString(),\n };\n },\n },\n };\n },\n\n addInputRules() {\n return [\n ...[1, 2, 3].map((level) => {\n // Creates a heading of appropriate level when starting with \"#\", \"##\", or \"###\".\n return new InputRule({\n find: new RegExp(`^(#{${level}})\\\\s$`),\n handler: ({ state, chain, range }) => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return;\n }\n\n chain()\n .BNUpdateBlock(state.selection.from, {\n type: \"heading\",\n props: {\n level: level as any,\n },\n })\n // Removes the \"#\" character(s) used to set the heading.\n .deleteRange({ from: range.from, to: range.to });\n },\n });\n }),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n \"Mod-Alt-1\": () => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return true;\n }\n\n return this.editor.commands.BNUpdateBlock(\n this.editor.state.selection.anchor,\n {\n type: \"heading\",\n props: {\n level: 1 as any,\n },\n }\n );\n },\n \"Mod-Alt-2\": () => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return true;\n }\n\n return this.editor.commands.BNUpdateBlock(\n this.editor.state.selection.anchor,\n {\n type: \"heading\",\n props: {\n level: 2 as any,\n },\n }\n );\n },\n \"Mod-Alt-3\": () => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return true;\n }\n\n return this.editor.commands.BNUpdateBlock(\n this.editor.state.selection.anchor,\n {\n type: \"heading\",\n props: {\n level: 3 as any,\n },\n }\n );\n },\n };\n },\n parseHTML() {\n return [\n {\n tag: \"div[data-content-type=\" + this.name + \"]\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n return {\n level: element.getAttribute(\"data-level\"),\n };\n },\n },\n {\n tag: \"h1\",\n attrs: { level: 1 },\n node: \"heading\",\n },\n {\n tag: \"h2\",\n attrs: { level: 2 },\n node: \"heading\",\n },\n {\n tag: \"h3\",\n attrs: { level: 3 },\n node: \"heading\",\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n `h${node.attrs.level}`,\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {}\n );\n },\n});\n\nexport const Heading = createBlockSpecFromStronglyTypedTiptapNode(\n HeadingBlockContent,\n headingPropSchema\n);\n","import type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\n\nimport {\n BlockFromConfig,\n BlockSchemaWithBlock,\n CustomBlockConfig,\n InlineContentSchema,\n PropSchema,\n StyleSchema,\n createBlockSpec,\n} from \"../../schema\";\nimport { defaultProps } from \"../defaultProps\";\n\nexport const imagePropSchema = {\n textAlignment: defaultProps.textAlignment,\n backgroundColor: defaultProps.backgroundColor,\n // Image url.\n url: {\n default: \"\" as const,\n },\n // Image caption.\n caption: {\n default: \"\" as const,\n },\n // Image width in px.\n width: {\n default: 512 as const,\n },\n} satisfies PropSchema;\n\n// Converts text alignment prop values to the flexbox `align-items` values.\nconst textAlignmentToAlignItems = (\n textAlignment: \"left\" | \"center\" | \"right\" | \"justify\"\n): \"flex-start\" | \"center\" | \"flex-end\" => {\n switch (textAlignment) {\n case \"left\":\n return \"flex-start\";\n case \"center\":\n return \"center\";\n case \"right\":\n return \"flex-end\";\n default:\n return \"flex-start\";\n }\n};\n\n// Min image width in px.\nconst minWidth = 64;\n\nconst blockConfig = {\n type: \"image\" as const,\n propSchema: imagePropSchema,\n content: \"none\",\n} satisfies CustomBlockConfig;\n\nexport const renderImage = (\n block: BlockFromConfig<typeof blockConfig, InlineContentSchema, StyleSchema>,\n editor: BlockNoteEditor<BlockSchemaWithBlock<\"image\", typeof blockConfig>>\n) => {\n // Wrapper element to set the image alignment, contains both image/image\n // upload dashboard and caption.\n const wrapper = document.createElement(\"div\");\n wrapper.className = \"bn-image-block-content-wrapper\";\n wrapper.style.alignItems = textAlignmentToAlignItems(\n block.props.textAlignment\n );\n\n // Button element that acts as a placeholder for images with no src.\n const addImageButton = document.createElement(\"div\");\n addImageButton.className = \"bn-add-image-button\";\n\n // Icon for the add image button.\n const addImageButtonIcon = document.createElement(\"div\");\n addImageButtonIcon.className = \"bn-add-image-button-icon\";\n\n // Text for the add image button.\n const addImageButtonText = document.createElement(\"p\");\n addImageButtonText.className = \"bn-add-image-button-text\";\n addImageButtonText.innerText = \"Add Image\";\n\n // Wrapper element for the image, resize handles and caption.\n const imageAndCaptionWrapper = document.createElement(\"div\");\n imageAndCaptionWrapper.className = \"bn-image-and-caption-wrapper\";\n\n // Wrapper element for the image and resize handles.\n const imageWrapper = document.createElement(\"div\");\n imageWrapper.className = \"bn-image-wrapper\";\n\n // Image element.\n const image = document.createElement(\"img\");\n image.className = \"bn-image\";\n image.src = block.props.url;\n image.alt = \"placeholder\";\n image.contentEditable = \"false\";\n image.draggable = false;\n image.style.width = `${Math.min(\n block.props.width,\n editor.domElement.firstElementChild!.clientWidth\n )}px`;\n\n // Resize handle elements.\n const leftResizeHandle = document.createElement(\"div\");\n leftResizeHandle.className = \"bn-image-resize-handle\";\n leftResizeHandle.style.left = \"4px\";\n const rightResizeHandle = document.createElement(\"div\");\n rightResizeHandle.className = \"bn-image-resize-handle\";\n rightResizeHandle.style.right = \"4px\";\n\n // Caption element.\n const caption = document.createElement(\"p\");\n caption.className = \"bn-image-caption\";\n caption.innerText = block.props.caption;\n caption.style.padding = block.props.caption ? \"4px\" : \"\";\n\n // Adds a light blue outline to selected image blocks.\n const handleEditorUpdate = () => {\n const selection = editor.getSelection()?.blocks || [];\n const currentBlock = editor.getTextCursorPosition().block;\n\n const isSelected =\n [currentBlock, ...selection].find(\n (selectedBlock) => selectedBlock.id === block.id\n ) !== undefined;\n\n if (isSelected) {\n addImageButton.style.outline = \"4px solid rgb(100, 160, 255)\";\n imageAndCaptionWrapper.style.outline = \"4px solid rgb(100, 160, 255)\";\n } else {\n addImageButton.style.outline = \"\";\n imageAndCaptionWrapper.style.outline = \"\";\n }\n };\n editor.onEditorContentChange(handleEditorUpdate);\n editor.onEditorSelectionChange(handleEditorUpdate);\n\n // Temporary parameters set when the user begins resizing the image, used to\n // calculate the new width of the image.\n let resizeParams:\n | {\n handleUsed: \"left\" | \"right\";\n initialWidth: number;\n initialClientX: number;\n }\n | undefined;\n\n // Updates the image width with an updated width depending on the cursor X\n // offset from when the resize began, and which resize handle is being used.\n const windowMouseMoveHandler = (event: MouseEvent) => {\n if (!resizeParams) {\n if (\n !editor.isEditable &&\n imageWrapper.contains(leftResizeHandle) &&\n imageWrapper.contains(rightResizeHandle)\n ) {\n imageWrapper.removeChild(leftResizeHandle);\n imageWrapper.removeChild(rightResizeHandle);\n }\n\n return;\n }\n\n let newWidth: number;\n\n if (textAlignmentToAlignItems(block.props.textAlignment) === \"center\") {\n if (resizeParams.handleUsed === \"left\") {\n newWidth =\n resizeParams.initialWidth +\n (resizeParams.initialClientX - event.clientX) * 2;\n } else {\n newWidth =\n resizeParams.initialWidth +\n (event.clientX - resizeParams.initialClientX) * 2;\n }\n } else {\n if (resizeParams.handleUsed === \"left\") {\n newWidth =\n resizeParams.initialWidth +\n resizeParams.initialClientX -\n event.clientX;\n } else {\n newWidth =\n resizeParams.initialWidth +\n event.clientX -\n resizeParams.initialClientX;\n }\n }\n\n // Ensures the image is not wider than the editor and not smaller than a\n // predetermined minimum width.\n if (newWidth < minWidth) {\n image.style.width = `${minWidth}px`;\n } else if (newWidth > editor.domElement.firstElementChild!.clientWidth) {\n image.style.width = `${\n editor.domElement.firstElementChild!.clientWidth\n }px`;\n } else {\n image.style.width = `${newWidth}px`;\n }\n };\n // Stops mouse movements from resizing the image and updates the block's\n // `width` prop to the new value.\n const windowMouseUpHandler = (event: MouseEvent) => {\n // Hides the drag handles if the cursor is no longer over the image.\n if (\n (!event.target ||\n !imageWrapper.contains(event.target as Node) ||\n !editor.isEditable) &&\n imageWrapper.contains(leftResizeHandle) &&\n imageWrapper.contains(rightResizeHandle)\n ) {\n imageWrapper.removeChild(leftResizeHandle);\n imageWrapper.removeChild(rightResizeHandle);\n }\n\n if (!resizeParams) {\n return;\n }\n\n resizeParams = undefined;\n\n editor.updateBlock(block, {\n type: \"image\",\n props: {\n // Removes \"px\" from the end of the width string and converts to float.\n width: parseFloat(image.style.width.slice(0, -2)) as any,\n },\n });\n };\n\n // Prevents focus from moving to the button.\n const addImageButtonMouseDownHandler = (event: MouseEvent) => {\n event.preventDefault();\n };\n // Opens the image toolbar.\n const addImageButtonClickHandler = () => {\n editor._tiptapEditor.view.dispatch(\n editor._tiptapEditor.state.tr.setMeta(editor.imagePanel!.plugin, {\n block: block,\n })\n );\n };\n\n // Shows the resize handles when hovering over the image with the cursor.\n const imageMouseEnterHandler = () => {\n if (editor.isEditable) {\n imageWrapper.appendChild(leftResizeHandle);\n imageWrapper.appendChild(rightResizeHandle);\n }\n };\n // Hides the resize handles when the cursor leaves the image, unless the\n // cursor moves to one of the resize handles.\n const imageMouseLeaveHandler = (event: MouseEvent) => {\n if (\n event.relatedTarget === leftResizeHandle ||\n event.relatedTarget === rightResizeHandle\n ) {\n return;\n }\n\n if (resizeParams) {\n return;\n }\n\n if (\n editor.isEditable &&\n imageWrapper.contains(leftResizeHandle) &&\n imageWrapper.contains(rightResizeHandle)\n ) {\n imageWrapper.removeChild(leftResizeHandle);\n imageWrapper.removeChild(rightResizeHandle);\n }\n };\n\n // Sets the resize params, allowing the user to begin resizing the image by\n // moving the cursor left or right.\n const leftResizeHandleMouseDownHandler = (event: MouseEvent) => {\n event.preventDefault();\n\n imageWrapper.appendChild(leftResizeHandle);\n imageWrapper.appendChild(rightResizeHandle);\n\n resizeParams = {\n handleUsed: \"left\",\n initialWidth: block.props.width,\n initialClientX: event.clientX,\n };\n };\n const rightResizeHandleMouseDownHandler = (event: MouseEvent) => {\n event.preventDefault();\n\n imageWrapper.appendChild(leftResizeHandle);\n imageWrapper.appendChild(rightResizeHandle);\n\n resizeParams = {\n handleUsed: \"right\",\n initialWidth: block.props.width,\n initialClientX: event.clientX,\n };\n };\n\n addImageButton.appendChild(addImageButtonIcon);\n addImageButton.appendChild(addImageButtonText);\n\n imageAndCaptionWrapper.appendChild(imageWrapper);\n imageWrapper.appendChild(image);\n imageAndCaptionWrapper.appendChild(caption);\n\n if (block.props.url === \"\") {\n wrapper.appendChild(addImageButton);\n } else {\n wrapper.appendChild(imageAndCaptionWrapper);\n }\n\n window.addEventListener(\"mousemove\", windowMouseMoveHandler);\n window.addEventListener(\"mouseup\", windowMouseUpHandler);\n addImageButton.addEventListener(\"mousedown\", addImageButtonMouseDownHandler);\n addImageButton.addEventListener(\"click\", addImageButtonClickHandler);\n image.addEventListener(\"mouseenter\", imageMouseEnterHandler);\n image.addEventListener(\"mouseleave\", imageMouseLeaveHandler);\n leftResizeHandle.addEventListener(\n \"mousedown\",\n leftResizeHandleMouseDownHandler\n );\n rightResizeHandle.addEventListener(\n \"mousedown\",\n rightResizeHandleMouseDownHandler\n );\n\n return {\n dom: wrapper,\n destroy: () => {\n window.removeEventListener(\"mousemove\", windowMouseMoveHandler);\n window.removeEventListener(\"mouseup\", windowMouseUpHandler);\n addImageButton.removeEventListener(\n \"mousedown\",\n addImageButtonMouseDownHandler\n );\n addImageButton.removeEventListener(\"click\", addImageButtonClickHandler);\n leftResizeHandle.removeEventListener(\n \"mousedown\",\n leftResizeHandleMouseDownHandler\n );\n rightResizeHandle.removeEventListener(\n \"mousedown\",\n rightResizeHandleMouseDownHandler\n );\n },\n };\n};\n\nexport const Image = createBlockSpec(\n {\n type: \"image\" as const,\n propSchema: imagePropSchema,\n content: \"none\",\n },\n {\n render: renderImage,\n toExternalHTML: (block) => {\n if (block.props.url === \"\") {\n const div = document.createElement(\"p\");\n div.innerHTML = \"Add Image\";\n\n return {\n dom: div,\n };\n }\n\n const figure = document.createElement(\"figure\");\n\n const img = document.createElement(\"img\");\n img.src = block.props.url;\n figure.appendChild(img);\n\n if (block.props.caption !== \"\") {\n const figcaption = document.createElement(\"figcaption\");\n figcaption.innerHTML = block.props.caption;\n figure.appendChild(figcaption);\n }\n\n return {\n dom: figure,\n };\n },\n parse: (element: HTMLElement) => {\n if (element.tagName === \"FIGURE\") {\n const img = element.querySelector(\"img\");\n const caption = element.querySelector(\"figcaption\");\n return {\n url: img?.getAttribute(\"src\") || \"\",\n caption:\n caption?.textContent || img?.getAttribute(\"alt\") || undefined,\n };\n } else if (element.tagName === \"IMG\") {\n return {\n url: element.getAttribute(\"src\") || \"\",\n caption: element.getAttribute(\"alt\") || undefined,\n };\n }\n\n return undefined;\n },\n }\n);\n","import { Editor } from \"@tiptap/core\";\nimport { getBlockInfoFromPos } from \"../../api/getBlockInfoFromPos\";\n\nexport const handleEnter = (editor: Editor) => {\n const { node, contentType } = getBlockInfoFromPos(\n editor.state.doc,\n editor.state.selection.from\n )!;\n\n const selectionEmpty =\n editor.state.selection.anchor === editor.state.selection.head;\n\n if (\n !(\n contentType.name === \"bulletListItem\" ||\n contentType.name === \"numberedListItem\"\n ) ||\n !selectionEmpty\n ) {\n return false;\n }\n\n return editor.commands.first(({ state, chain, commands }) => [\n () =>\n // Changes list item block to a text block if the content is empty.\n commands.command(() => {\n if (node.textContent.length === 0) {\n return commands.BNUpdateBlock(state.selection.from, {\n type: \"paragraph\",\n props: {},\n });\n }\n\n return false;\n }),\n\n () =>\n // Splits the current block, moving content inside that's after the cursor to a new block of the same type\n // below.\n commands.command(() => {\n if (node.textContent.length > 0) {\n chain()\n .deleteSelection()\n .BNSplitBlock(state.selection.from, true)\n .run();\n\n return true;\n }\n\n return false;\n }),\n ]);\n};\n","import { InputRule } from \"@tiptap/core\";\nimport {\n PropSchema,\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../../schema\";\nimport { createDefaultBlockDOMOutputSpec } from \"../../defaultBlockHelpers\";\nimport { defaultProps } from \"../../defaultProps\";\nimport { handleEnter } from \"../ListItemKeyboardShortcuts\";\nimport { getCurrentBlockContentType } from \"../../../api/getCurrentBlockContentType\";\n\nexport const bulletListItemPropSchema = {\n ...defaultProps,\n} satisfies PropSchema;\n\nconst BulletListItemBlockContent = createStronglyTypedTiptapNode({\n name: \"bulletListItem\",\n content: \"inline*\",\n group: \"blockContent\",\n addInputRules() {\n return [\n // Creates an unordered list when starting with \"-\", \"+\", or \"*\".\n new InputRule({\n find: new RegExp(`^[-+*]\\\\s$`),\n handler: ({ state, chain, range }) => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return;\n }\n\n chain()\n .BNUpdateBlock(state.selection.from, {\n type: \"bulletListItem\",\n props: {},\n })\n // Removes the \"-\", \"+\", or \"*\" character used to set the list.\n .deleteRange({ from: range.from, to: range.to });\n },\n }),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n Enter: () => handleEnter(this.editor),\n \"Mod-Shift-8\": () => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return true;\n }\n\n return this.editor.commands.BNUpdateBlock(\n this.editor.state.selection.anchor,\n {\n type: \"bulletListItem\",\n props: {},\n }\n );\n },\n };\n },\n\n parseHTML() {\n return [\n // Case for regular HTML list structure.\n {\n tag: \"div[data-content-type=\" + this.name + \"]\", // TODO: remove if we can't come up with test case that needs this\n },\n {\n tag: \"li\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const parent = element.parentElement;\n\n if (parent === null) {\n return false;\n }\n\n if (\n parent.tagName === \"UL\" ||\n (parent.tagName === \"DIV\" && parent.parentElement!.tagName === \"UL\")\n ) {\n return {};\n }\n\n return false;\n },\n node: \"bulletListItem\",\n },\n // Case for BlockNote list structure.\n {\n tag: \"p\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const parent = element.parentElement;\n\n if (parent === null) {\n return false;\n }\n\n if (parent.getAttribute(\"data-content-type\") === \"bulletListItem\") {\n return {};\n }\n\n return false;\n },\n priority: 300,\n node: \"bulletListItem\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n // We use a <p> tag, because for <li> tags we'd need a <ul> element to put\n // them in to be semantically correct, which we can't have due to the\n // schema.\n \"p\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {}\n );\n },\n});\n\nexport const BulletListItem = createBlockSpecFromStronglyTypedTiptapNode(\n BulletListItemBlockContent,\n bulletListItemPropSchema\n);\n","import { Plugin, PluginKey } from \"prosemirror-state\";\nimport { getBlockInfoFromPos } from \"../../../api/getBlockInfoFromPos\";\n\n// ProseMirror Plugin which automatically assigns indices to ordered list items per nesting level.\nconst PLUGIN_KEY = new PluginKey(`numbered-list-indexing`);\nexport const NumberedListIndexingPlugin = () => {\n return new Plugin({\n key: PLUGIN_KEY,\n appendTransaction: (_transactions, _oldState, newState) => {\n const tr = newState.tr;\n tr.setMeta(\"numberedListIndexing\", true);\n\n let modified = false;\n\n // Traverses each node the doc using DFS, so blocks which are on the same nesting level will be traversed in the\n // same order they appear. This means the index of each list item block can be calculated by incrementing the\n // index of the previous list item block.\n newState.doc.descendants((node, pos) => {\n if (\n node.type.name === \"blockContainer\" &&\n node.firstChild!.type.name === \"numberedListItem\"\n ) {\n let newIndex = \"1\";\n const isFirstBlockInDoc = pos === 1;\n\n const blockInfo = getBlockInfoFromPos(tr.doc, pos + 1)!;\n if (blockInfo === undefined) {\n return;\n }\n\n // Checks if this block is the start of a new ordered list, i.e. if it's the first block in the document, the\n // first block in its nesting level, or the previous block is not an ordered list item.\n if (!isFirstBlockInDoc) {\n const prevBlockInfo = getBlockInfoFromPos(tr.doc, pos - 2)!;\n if (prevBlockInfo === undefined) {\n return;\n }\n\n const isFirstBlockInNestingLevel =\n blockInfo.depth !== prevBlockInfo.depth;\n\n if (!isFirstBlockInNestingLevel) {\n const prevBlockContentNode = prevBlockInfo.contentNode;\n const prevBlockContentType = prevBlockInfo.contentType;\n\n const isPrevBlockOrderedListItem =\n prevBlockContentType.name === \"numberedListItem\";\n\n if (isPrevBlockOrderedListItem) {\n const prevBlockIndex = prevBlockContentNode.attrs[\"index\"];\n\n newIndex = (parseInt(prevBlockIndex) + 1).toString();\n }\n }\n }\n\n const contentNode = blockInfo.contentNode;\n const index = contentNode.attrs[\"index\"];\n\n if (index !== newIndex) {\n modified = true;\n\n tr.setNodeMarkup(pos + 1, undefined, {\n index: newIndex,\n });\n }\n }\n });\n\n return modified ? tr : null;\n },\n });\n};\n","import { InputRule } from \"@tiptap/core\";\nimport {\n PropSchema,\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../../schema\";\nimport { createDefaultBlockDOMOutputSpec } from \"../../defaultBlockHelpers\";\nimport { defaultProps } from \"../../defaultProps\";\nimport { handleEnter } from \"../ListItemKeyboardShortcuts\";\nimport { NumberedListIndexingPlugin } from \"./NumberedListIndexingPlugin\";\nimport { getCurrentBlockContentType } from \"../../../api/getCurrentBlockContentType\";\n\nexport const numberedListItemPropSchema = {\n ...defaultProps,\n} satisfies PropSchema;\n\nconst NumberedListItemBlockContent = createStronglyTypedTiptapNode({\n name: \"numberedListItem\",\n content: \"inline*\",\n group: \"blockContent\",\n addAttributes() {\n return {\n index: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-index\"),\n renderHTML: (attributes) => {\n return {\n \"data-index\": attributes.index,\n };\n },\n },\n };\n },\n\n addInputRules() {\n return [\n // Creates an ordered list when starting with \"1.\".\n new InputRule({\n find: new RegExp(`^1\\\\.\\\\s$`),\n handler: ({ state, chain, range }) => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return;\n }\n\n chain()\n .BNUpdateBlock(state.selection.from, {\n type: \"numberedListItem\",\n props: {},\n })\n // Removes the \"1.\" characters used to set the list.\n .deleteRange({ from: range.from, to: range.to });\n },\n }),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n Enter: () => handleEnter(this.editor),\n \"Mod-Shift-7\": () => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return true;\n }\n\n return this.editor.commands.BNUpdateBlock(\n this.editor.state.selection.anchor,\n {\n type: \"numberedListItem\",\n props: {},\n }\n );\n },\n };\n },\n\n addProseMirrorPlugins() {\n return [NumberedListIndexingPlugin()];\n },\n\n parseHTML() {\n return [\n {\n tag: \"div[data-content-type=\" + this.name + \"]\", // TODO: remove if we can't come up with test case that needs this\n },\n // Case for regular HTML list structure.\n // (e.g.: when pasting from other apps)\n {\n tag: \"li\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const parent = element.parentElement;\n\n if (parent === null) {\n return false;\n }\n\n if (\n parent.tagName === \"OL\" ||\n (parent.tagName === \"DIV\" && parent.parentElement!.tagName === \"OL\")\n ) {\n return {};\n }\n\n return false;\n },\n node: \"numberedListItem\",\n },\n // Case for BlockNote list structure.\n // (e.g.: when pasting from blocknote)\n {\n tag: \"p\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const parent = element.parentElement;\n\n if (parent === null) {\n return false;\n }\n\n if (parent.getAttribute(\"data-content-type\") === \"numberedListItem\") {\n return {};\n }\n\n return false;\n },\n priority: 300,\n node: \"numberedListItem\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n // We use a <p> tag, because for <li> tags we'd need an <ol> element to\n // put them in to be semantically correct, which we can't have due to the\n // schema.\n \"p\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {}\n );\n },\n});\n\nexport const NumberedListItem = createBlockSpecFromStronglyTypedTiptapNode(\n NumberedListItemBlockContent,\n numberedListItemPropSchema\n);\n","import {\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../schema\";\nimport { createDefaultBlockDOMOutputSpec } from \"../defaultBlockHelpers\";\nimport { defaultProps } from \"../defaultProps\";\nimport { handleEnter } from \"../ListItemBlockContent/ListItemKeyboardShortcuts\";\nimport { getCurrentBlockContentType } from \"../../api/getCurrentBlockContentType\";\n\nexport const paragraphPropSchema = {\n ...defaultProps,\n};\n\nexport const ParagraphBlockContent = createStronglyTypedTiptapNode({\n name: \"paragraph\",\n content: \"inline*\",\n group: \"blockContent\",\n\n addKeyboardShortcuts() {\n return {\n Enter: () => handleEnter(this.editor),\n \"Mod-Alt-0\": () => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return true;\n }\n\n return this.editor.commands.BNUpdateBlock(\n this.editor.state.selection.anchor,\n {\n type: \"paragraph\",\n props: {},\n }\n );\n },\n };\n },\n\n parseHTML() {\n return [\n { tag: \"div[data-content-type=\" + this.name + \"]\" },\n {\n tag: \"p\",\n priority: 200,\n node: \"paragraph\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n \"p\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {}\n );\n },\n});\n\nexport const Paragraph = createBlockSpecFromStronglyTypedTiptapNode(\n ParagraphBlockContent,\n paragraphPropSchema\n);\n","import { callOrReturn, Extension, getExtensionField } from \"@tiptap/core\";\nimport { columnResizing, tableEditing } from \"prosemirror-tables\";\n\nexport const TableExtension = Extension.create({\n name: \"BlockNoteTableExtension\",\n\n addProseMirrorPlugins: () => {\n return [\n columnResizing({\n cellMinWidth: 100,\n }),\n tableEditing(),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n // Makes enter create a new line within the cell.\n Enter: () => {\n if (\n this.editor.state.selection.empty &&\n this.editor.state.selection.$head.parent.type.name ===\n \"tableParagraph\"\n ) {\n this.editor.commands.setHardBreak();\n\n return true;\n }\n\n return false;\n },\n // Ensures that backspace won't delete the table if the text cursor is at\n // the start of a cell and the selection is empty.\n Backspace: () => {\n const selection = this.editor.state.selection;\n const selectionIsEmpty = selection.empty;\n const selectionIsAtStartOfNode = selection.$head.parentOffset === 0;\n const selectionIsInTableParagraphNode =\n selection.$head.node().type.name === \"tableParagraph\";\n\n return (\n selectionIsEmpty &&\n selectionIsAtStartOfNode &&\n selectionIsInTableParagraphNode\n );\n },\n };\n },\n\n extendNodeSchema(extension) {\n const context = {\n name: extension.name,\n options: extension.options,\n storage: extension.storage,\n };\n\n return {\n tableRole: callOrReturn(\n getExtensionField(extension, \"tableRole\", context)\n ),\n };\n },\n});\n","import { mergeAttributes, Node } from \"@tiptap/core\";\nimport { TableCell } from \"@tiptap/extension-table-cell\";\nimport { TableHeader } from \"@tiptap/extension-table-header\";\nimport { TableRow } from \"@tiptap/extension-table-row\";\nimport {\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../schema\";\nimport { createDefaultBlockDOMOutputSpec } from \"../defaultBlockHelpers\";\nimport { defaultProps } from \"../defaultProps\";\nimport { TableExtension } from \"./TableExtension\";\n\nexport const tablePropSchema = {\n ...defaultProps,\n};\n\nexport const TableBlockContent = createStronglyTypedTiptapNode({\n name: \"table\",\n content: \"tableRow+\",\n group: \"blockContent\",\n tableRole: \"table\",\n\n isolating: true,\n\n parseHTML() {\n return [{ tag: \"table\" }];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n \"table\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {}\n );\n },\n});\n\nconst TableParagraph = Node.create({\n name: \"tableParagraph\",\n group: \"tableContent\",\n content: \"inline*\",\n\n parseHTML() {\n return [{ tag: \"p\" }];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"p\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),\n 0,\n ];\n },\n});\n\nexport const Table = createBlockSpecFromStronglyTypedTiptapNode(\n TableBlockContent,\n tablePropSchema,\n [\n TableExtension,\n TableParagraph,\n TableHeader.extend({\n content: \"tableContent\",\n }),\n TableCell.extend({\n content: \"tableContent\",\n }),\n TableRow,\n ]\n);\n","import Bold from \"@tiptap/extension-bold\";\nimport Code from \"@tiptap/extension-code\";\nimport Italic from \"@tiptap/extension-italic\";\nimport Strike from \"@tiptap/extension-strike\";\nimport Underline from \"@tiptap/extension-underline\";\nimport { BackgroundColor } from \"../extensions/BackgroundColor/BackgroundColorMark\";\nimport { TextColor } from \"../extensions/TextColor/TextColorMark\";\nimport {\n BlockNoDefaults,\n BlockSchema,\n BlockSpecs,\n InlineContentSchema,\n InlineContentSpecs,\n PartialBlockNoDefaults,\n StyleSchema,\n StyleSpecs,\n createStyleSpecFromTipTapMark,\n getBlockSchemaFromSpecs,\n getInlineContentSchemaFromSpecs,\n getStyleSchemaFromSpecs,\n} from \"../schema\";\nimport { Heading } from \"./HeadingBlockContent/HeadingBlockContent\";\nimport { Image } from \"./ImageBlockContent/ImageBlockContent\";\nimport { BulletListItem } from \"./ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent\";\nimport { NumberedListItem } from \"./ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent\";\nimport { Paragraph } from \"./ParagraphBlockContent/ParagraphBlockContent\";\nimport { Table } from \"./TableBlockContent/TableBlockContent\";\n\nexport const defaultBlockSpecs = {\n paragraph: Paragraph,\n heading: Heading,\n bulletListItem: BulletListItem,\n numberedListItem: NumberedListItem,\n image: Image,\n table: Table,\n} satisfies BlockSpecs;\n\nexport const defaultBlockSchema = getBlockSchemaFromSpecs(defaultBlockSpecs);\n\n// underscore is used that in case a user overrides DefaultBlockSchema,\n// they can still access the original default block schema\nexport type _DefaultBlockSchema = typeof defaultBlockSchema;\nexport type DefaultBlockSchema = _DefaultBlockSchema;\n\nexport const defaultStyleSpecs = {\n bold: createStyleSpecFromTipTapMark(Bold, \"boolean\"),\n italic: createStyleSpecFromTipTapMark(Italic, \"boolean\"),\n underline: createStyleSpecFromTipTapMark(Underline, \"boolean\"),\n strike: createStyleSpecFromTipTapMark(Strike, \"boolean\"),\n code: createStyleSpecFromTipTapMark(Code, \"boolean\"),\n textColor: TextColor,\n backgroundColor: BackgroundColor,\n} satisfies StyleSpecs;\n\nexport const defaultStyleSchema = getStyleSchemaFromSpecs(defaultStyleSpecs);\n\n// underscore is used that in case a user overrides DefaultStyleSchema,\n// they can still access the original default style schema\nexport type _DefaultStyleSchema = typeof defaultStyleSchema;\nexport type DefaultStyleSchema = _DefaultStyleSchema;\n\nexport const defaultInlineContentSpecs = {\n text: { config: \"text\", implementation: {} as any },\n link: { config: \"link\", implementation: {} as any },\n} satisfies InlineContentSpecs;\n\nexport const defaultInlineContentSchema = getInlineContentSchemaFromSpecs(\n defaultInlineContentSpecs\n);\n\n// underscore is used that in case a user overrides DefaultInlineContentSchema,\n// they can still access the original default inline content schema\nexport type _DefaultInlineContentSchema = typeof defaultInlineContentSchema;\nexport type DefaultInlineContentSchema = _DefaultInlineContentSchema;\n\nexport type PartialBlock<\n BSchema extends BlockSchema = DefaultBlockSchema,\n I extends InlineContentSchema = DefaultInlineContentSchema,\n S extends StyleSchema = DefaultStyleSchema\n> = PartialBlockNoDefaults<BSchema, I, S>;\n\nexport type Block<\n BSchema extends BlockSchema = DefaultBlockSchema,\n I extends InlineContentSchema = DefaultInlineContentSchema,\n S extends StyleSchema = DefaultStyleSchema\n> = BlockNoDefaults<BSchema, I, S>;\n","import type { BlockNoteEditor } from \"../editor/BlockNoteEditor\";\nimport { BlockFromConfig, InlineContentSchema, StyleSchema } from \"../schema\";\nimport { Block, DefaultBlockSchema, defaultBlockSchema } from \"./defaultBlocks\";\nimport { defaultProps } from \"./defaultProps\";\n\nexport function checkDefaultBlockTypeInSchema<\n BlockType extends keyof DefaultBlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n blockType: BlockType,\n editor: BlockNoteEditor<any, I, S>\n): editor is BlockNoteEditor<{ Type: DefaultBlockSchema[BlockType] }, I, S> {\n return (\n blockType in editor.schema.blockSchema &&\n editor.schema.blockSchema[blockType] === defaultBlockSchema[blockType]\n );\n}\n\nexport function checkBlockIsDefaultType<\n BlockType extends keyof DefaultBlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n blockType: BlockType,\n block: Block<any, I, S>,\n editor: BlockNoteEditor<any, I, S>\n): block is BlockFromConfig<DefaultBlockSchema[BlockType], I, S> {\n return (\n block.type === blockType &&\n block.type in editor.schema.blockSchema &&\n checkDefaultBlockTypeInSchema(block.type, editor)\n );\n}\n\nexport function checkBlockTypeHasDefaultProp<\n Prop extends keyof typeof defaultProps,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n prop: Prop,\n blockType: string,\n editor: BlockNoteEditor<any, I, S>\n): editor is BlockNoteEditor<\n {\n [BT in string]: {\n type: BT;\n propSchema: {\n [P in Prop]: (typeof defaultProps)[P];\n };\n content: \"table\" | \"inline\" | \"none\";\n };\n },\n I,\n S\n> {\n return (\n blockType in editor.schema.blockSchema &&\n prop in editor.schema.blockSchema[blockType].propSchema &&\n editor.schema.blockSchema[blockType].propSchema[prop] === defaultProps[prop]\n );\n}\n\nexport function checkBlockHasDefaultProp<\n Prop extends keyof typeof defaultProps,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n prop: Prop,\n block: Block<any, I, S>,\n editor: BlockNoteEditor<any, I, S>\n): block is BlockFromConfig<\n {\n type: string;\n propSchema: {\n [P in Prop]: (typeof defaultProps)[P];\n };\n content: \"table\" | \"inline\" | \"none\";\n },\n I,\n S\n> {\n return checkBlockTypeHasDefaultProp(prop, block.type, editor);\n}\n","import { Node } from \"prosemirror-model\";\n\n/**\n * Get a TipTap node by id\n */\nexport function getNodeById(\n id: string,\n doc: Node\n): { node: Node; posBeforeNode: number } {\n let targetNode: Node | undefined = undefined;\n let posBeforeNode: number | undefined = undefined;\n\n doc.firstChild!.descendants((node, pos) => {\n // Skips traversing nodes after node with target ID has been found.\n if (targetNode) {\n return false;\n }\n\n // Keeps traversing nodes if block with target ID has not been found.\n if (node.type.name !== \"blockContainer\" || node.attrs.id !== id) {\n return true;\n }\n\n targetNode = node;\n posBeforeNode = pos + 1;\n\n return false;\n });\n\n if (targetNode === undefined || posBeforeNode === undefined) {\n throw Error(\"Could not find block in the editor with matching ID.\");\n }\n\n return {\n node: targetNode,\n posBeforeNode: posBeforeNode,\n };\n}\n","import { Node } from \"prosemirror-model\";\n\nimport { selectionToInsertionEnd } from \"@tiptap/core\";\nimport { Transaction } from \"prosemirror-state\";\nimport { Block, PartialBlock } from \"../../blocks/defaultBlocks\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport {\n BlockIdentifier,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema\";\nimport { blockToNode, nodeToBlock } from \"../nodeConversions/nodeConversions\";\nimport { getNodeById } from \"../nodeUtil\";\n\nexport function insertBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n blocksToInsert: PartialBlock<BSchema, I, S>[],\n referenceBlock: BlockIdentifier,\n placement: \"before\" | \"after\" | \"nested\" = \"before\",\n editor: BlockNoteEditor<BSchema, I, S>\n): Block<BSchema, I, S>[] {\n const ttEditor = editor._tiptapEditor;\n\n const id =\n typeof referenceBlock === \"string\" ? referenceBlock : referenceBlock.id;\n\n const nodesToInsert: Node[] = [];\n for (const blockSpec of blocksToInsert) {\n nodesToInsert.push(\n blockToNode(blockSpec, ttEditor.schema, editor.schema.styleSchema)\n );\n }\n\n const { node, posBeforeNode } = getNodeById(id, ttEditor.state.doc);\n\n if (placement === \"before\") {\n ttEditor.view.dispatch(\n ttEditor.state.tr.insert(posBeforeNode, nodesToInsert)\n );\n }\n\n if (placement === \"after\") {\n ttEditor.view.dispatch(\n ttEditor.state.tr.insert(posBeforeNode + node.nodeSize, nodesToInsert)\n );\n }\n\n if (placement === \"nested\") {\n // Case if block doesn't already have children.\n if (node.childCount < 2) {\n const blockGroupNode = ttEditor.state.schema.nodes[\"blockGroup\"].create(\n {},\n nodesToInsert\n );\n\n ttEditor.view.dispatch(\n ttEditor.state.tr.insert(\n posBeforeNode + node.firstChild!.nodeSize + 1,\n blockGroupNode\n )\n );\n }\n }\n\n // Now that the `PartialBlock`s have been converted to nodes, we can\n // re-convert them into full `Block`s.\n const insertedBlocks: Block<BSchema, I, S>[] = [];\n for (const node of nodesToInsert) {\n insertedBlocks.push(\n nodeToBlock(\n node,\n editor.schema.blockSchema,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n editor.blockCache\n )\n );\n }\n\n return insertedBlocks;\n}\n\nexport function updateBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n blockToUpdate: BlockIdentifier,\n update: PartialBlock<BSchema, I, S>,\n editor: BlockNoteEditor<BSchema, I, S>\n): Block<BSchema, I, S> {\n const ttEditor = editor._tiptapEditor;\n\n const id =\n typeof blockToUpdate === \"string\" ? blockToUpdate : blockToUpdate.id;\n const { posBeforeNode } = getNodeById(id, ttEditor.state.doc);\n\n ttEditor.commands.BNUpdateBlock(posBeforeNode + 1, update);\n\n const blockContainerNode = ttEditor.state.doc\n .resolve(posBeforeNode + 1)\n .node();\n\n return nodeToBlock(\n blockContainerNode,\n editor.schema.blockSchema,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n editor.blockCache\n );\n}\n\nfunction removeBlocksWithCallback<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n blocksToRemove: BlockIdentifier[],\n editor: BlockNoteEditor<BSchema, I, S>,\n // Should return new removedSize.\n callback?: (\n node: Node,\n pos: number,\n tr: Transaction,\n removedSize: number\n ) => number\n): Block<BSchema, I, S>[] {\n const ttEditor = editor._tiptapEditor;\n const tr = ttEditor.state.tr;\n\n const idsOfBlocksToRemove = new Set<string>(\n blocksToRemove.map((block) =>\n typeof block === \"string\" ? block : block.id\n )\n );\n const removedBlocks: Block<BSchema, I, S>[] = [];\n let removedSize = 0;\n\n ttEditor.state.doc.descendants((node, pos) => {\n // Skips traversing nodes after all target blocks have been removed.\n if (idsOfBlocksToRemove.size === 0) {\n return false;\n }\n\n // Keeps traversing nodes if block with target ID has not been found.\n if (\n node.type.name !== \"blockContainer\" ||\n !idsOfBlocksToRemove.has(node.attrs.id)\n ) {\n return true;\n }\n\n // Saves the block that is being deleted.\n removedBlocks.push(\n nodeToBlock(\n node,\n editor.schema.blockSchema,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n editor.blockCache\n )\n );\n idsOfBlocksToRemove.delete(node.attrs.id);\n\n // Removes the block and calculates the change in document size.\n removedSize = callback?.(node, pos, tr, removedSize) || removedSize;\n const oldDocSize = tr.doc.nodeSize;\n tr.delete(pos - removedSize - 1, pos - removedSize + node.nodeSize + 1);\n const newDocSize = tr.doc.nodeSize;\n removedSize += oldDocSize - newDocSize;\n\n return false;\n });\n\n // Throws an error if now all blocks could be found.\n if (idsOfBlocksToRemove.size > 0) {\n const notFoundIds = [...idsOfBlocksToRemove].join(\"\\n\");\n\n throw Error(\n \"Blocks with the following IDs could not be found in the editor: \" +\n notFoundIds\n );\n }\n\n ttEditor.view.dispatch(tr);\n\n return removedBlocks;\n}\n\nexport function removeBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n blocksToRemove: BlockIdentifier[],\n editor: BlockNoteEditor<BSchema, I, S>\n): Block<BSchema, I, S>[] {\n return removeBlocksWithCallback(blocksToRemove, editor);\n}\n\nexport function replaceBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n blocksToRemove: BlockIdentifier[],\n blocksToInsert: PartialBlock<BSchema, I, S>[],\n editor: BlockNoteEditor<BSchema, I, S>\n): {\n insertedBlocks: Block<BSchema, I, S>[];\n removedBlocks: Block<BSchema, I, S>[];\n} {\n const ttEditor = editor._tiptapEditor;\n\n const nodesToInsert: Node[] = [];\n for (const block of blocksToInsert) {\n nodesToInsert.push(\n blockToNode(block, ttEditor.schema, editor.schema.styleSchema)\n );\n }\n\n const idOfFirstBlock =\n typeof blocksToRemove[0] === \"string\"\n ? blocksToRemove[0]\n : blocksToRemove[0].id;\n const removedBlocks = removeBlocksWithCallback(\n blocksToRemove,\n editor,\n (node, pos, tr, removedSize) => {\n if (node.attrs.id === idOfFirstBlock) {\n const oldDocSize = tr.doc.nodeSize;\n tr.insert(pos, nodesToInsert);\n const newDocSize = tr.doc.nodeSize;\n\n return removedSize + oldDocSize - newDocSize;\n }\n\n return removedSize;\n }\n );\n\n // Now that the `PartialBlock`s have been converted to nodes, we can\n // re-convert them into full `Block`s.\n const insertedBlocks: Block<BSchema, I, S>[] = [];\n for (const node of nodesToInsert) {\n insertedBlocks.push(\n nodeToBlock(\n node,\n editor.schema.blockSchema,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n editor.blockCache\n )\n );\n }\n\n return { insertedBlocks, removedBlocks };\n}\n\n// similar to tiptap insertContentAt\nexport function insertContentAt<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n position: any,\n nodes: Node[],\n editor: BlockNoteEditor<BSchema, I, S>,\n options: {\n updateSelection: boolean;\n } = { updateSelection: true }\n) {\n const ttEditor = editor._tiptapEditor;\n const tr = ttEditor.state.tr;\n\n // don’t dispatch an empty fragment because this can lead to strange errors\n // if (content.toString() === \"<>\") {\n // return true;\n // }\n\n let { from, to } =\n typeof position === \"number\"\n ? { from: position, to: position }\n : { from: position.from, to: position.to };\n\n let isOnlyTextContent = true;\n let isOnlyBlockContent = true;\n // const nodes = isFragment(content) ? content : [content];\n\n let text = \"\";\n\n nodes.forEach((node) => {\n // check if added node is valid\n node.check();\n\n if (isOnlyTextContent && node.isText && node.marks.length === 0) {\n text += node.text;\n } else {\n isOnlyTextContent = false;\n }\n\n isOnlyBlockContent = isOnlyBlockContent ? node.isBlock : false;\n });\n\n // check if we can replace the wrapping node by\n // the newly inserted content\n // example:\n // replace an empty paragraph by an inserted image\n // instead of inserting the image below the paragraph\n if (from === to && isOnlyBlockContent) {\n const { parent } = tr.doc.resolve(from);\n const isEmptyTextBlock =\n parent.isTextblock && !parent.type.spec.code && !parent.childCount;\n\n if (isEmptyTextBlock) {\n from -= 1;\n to += 1;\n }\n }\n\n // if there is only plain text we have to use `insertText`\n // because this will keep the current marks\n if (isOnlyTextContent) {\n // if value is string, we can use it directly\n // otherwise if it is an array, we have to join it\n // if (Array.isArray(value)) {\n // tr.insertText(value.map((v) => v.text || \"\").join(\"\"), from, to);\n // } else if (typeof value === \"object\" && !!value && !!value.text) {\n // tr.insertText(value.text, from, to);\n // } else {\n // tr.insertText(value as string, from, to);\n // }\n tr.insertText(text, from, to);\n } else {\n tr.replaceWith(from, to, nodes);\n }\n\n // set cursor at end of inserted content\n if (options.updateSelection) {\n selectionToInsertionEnd(tr, tr.steps.length - 1, -1);\n }\n\n ttEditor.view.dispatch(tr);\n\n return true;\n}\n","import { Element as HASTElement, Parent as HASTParent } from \"hast\";\n\n/**\n * Rehype plugin which removes <u> tags. Used to remove underlines before converting HTML to markdown, as Markdown\n * doesn't support underlines.\n */\nexport function removeUnderlines() {\n const removeUnderlinesHelper = (tree: HASTParent) => {\n let numChildElements = tree.children.length;\n\n for (let i = 0; i < numChildElements; i++) {\n const node = tree.children[i];\n\n if (node.type === \"element\") {\n // Recursively removes underlines from child elements.\n removeUnderlinesHelper(node);\n\n if ((node as HASTElement).tagName === \"u\") {\n // Lifts child nodes outside underline element, deletes the underline element, and updates current index &\n // the number of child elements.\n if (node.children.length > 0) {\n tree.children.splice(i, 1, ...node.children);\n\n const numElementsAdded = node.children.length - 1;\n numChildElements += numElementsAdded;\n i += numElementsAdded;\n } else {\n tree.children.splice(i, 1);\n\n numChildElements--;\n i--;\n }\n }\n }\n }\n };\n\n return removeUnderlinesHelper;\n}\n","import { Schema } from \"prosemirror-model\";\nimport rehypeParse from \"rehype-parse\";\nimport rehypeRemark from \"rehype-remark\";\nimport remarkGfm from \"remark-gfm\";\nimport remarkStringify from \"remark-stringify\";\nimport { unified } from \"unified\";\nimport { Block } from \"../../../blocks/defaultBlocks\";\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../../schema\";\nimport { createExternalHTMLExporter } from \"../html/externalHTMLExporter\";\nimport { removeUnderlines } from \"./removeUnderlinesRehypePlugin\";\n\nexport function cleanHTMLToMarkdown(cleanHTMLString: string) {\n const markdownString = unified()\n .use(rehypeParse, { fragment: true })\n .use(removeUnderlines)\n .use(rehypeRemark)\n .use(remarkGfm)\n .use(remarkStringify)\n .processSync(cleanHTMLString);\n\n return markdownString.value as string;\n}\n\nexport function blocksToMarkdown<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n blocks: Block<BSchema, I, S>[],\n schema: Schema,\n editor: BlockNoteEditor<BSchema, I, S>\n): string {\n const exporter = createExternalHTMLExporter(schema, editor);\n const externalHTML = exporter.exportBlocks(blocks);\n\n return cleanHTMLToMarkdown(externalHTML);\n}\n","function getChildIndex(node: Element) {\n return Array.prototype.indexOf.call(node.parentElement!.childNodes, node);\n}\n\nfunction isWhitespaceNode(node: Node) {\n return node.nodeType === 3 && !/\\S/.test(node.nodeValue || \"\");\n}\n\n/**\n * Step 1, Turns:\n *\n * <ul>\n * <li>item</li>\n * <li>\n * <ul>\n * <li>...</li>\n * <li>...</li>\n * </ul>\n * </li>\n *\n * Into:\n * <ul>\n * <li>item</li>\n * <ul>\n * <li>...</li>\n * <li>...</li>\n * </ul>\n * </ul>\n *\n */\nfunction liftNestedListsToParent(element: HTMLElement) {\n element.querySelectorAll(\"li > ul, li > ol\").forEach((list) => {\n const index = getChildIndex(list);\n const parentListItem = list.parentElement!;\n const siblingsAfter = Array.from(parentListItem.childNodes).slice(\n index + 1\n );\n list.remove();\n siblingsAfter.forEach((sibling) => {\n sibling.remove();\n });\n\n parentListItem.insertAdjacentElement(\"afterend\", list);\n\n siblingsAfter.reverse().forEach((sibling) => {\n if (isWhitespaceNode(sibling)) {\n return;\n }\n const siblingContainer = document.createElement(\"li\");\n siblingContainer.append(sibling);\n list.insertAdjacentElement(\"afterend\", siblingContainer);\n });\n if (parentListItem.childNodes.length === 0) {\n parentListItem.remove();\n }\n });\n}\n\n/**\n * Step 2, Turns (output of liftNestedListsToParent):\n *\n * <li>item</li>\n * <ul>\n * <li>...</li>\n * <li>...</li>\n * </ul>\n *\n * Into:\n * <div>\n * <li>item</li>\n * <div data-node-type=\"blockGroup\">\n * <ul>\n * <li>...</li>\n * <li>...</li>\n * </ul>\n * </div>\n * </div>\n *\n * This resulting format is parsed\n */\nfunction createGroups(element: HTMLElement) {\n element.querySelectorAll(\"li + ul, li + ol\").forEach((list) => {\n const listItem = list.previousElementSibling as HTMLElement;\n const blockContainer = document.createElement(\"div\");\n\n listItem.insertAdjacentElement(\"afterend\", blockContainer);\n blockContainer.append(listItem);\n\n const blockGroup = document.createElement(\"div\");\n blockGroup.setAttribute(\"data-node-type\", \"blockGroup\");\n blockContainer.append(blockGroup);\n\n while (\n blockContainer.nextElementSibling?.nodeName === \"UL\" ||\n blockContainer.nextElementSibling?.nodeName === \"OL\"\n ) {\n blockGroup.append(blockContainer.nextElementSibling);\n }\n });\n}\n\n// prevent XSS, similar to https://github.com/ProseMirror/prosemirror-view/blob/1251b2b412656a2a06263e4187574beb43651273/src/clipboard.ts#L204\n// https://github.com/TypeCellOS/BlockNote/issues/601\nlet _detachedDoc: Document | null = null;\nfunction detachedDoc() {\n return (\n _detachedDoc ||\n (_detachedDoc = document.implementation.createHTMLDocument(\"title\"))\n );\n}\n\nexport function nestedListsToBlockNoteStructure(\n elementOrHTML: HTMLElement | string\n) {\n if (typeof elementOrHTML === \"string\") {\n const element = detachedDoc().createElement(\"div\");\n element.innerHTML = elementOrHTML;\n elementOrHTML = element;\n }\n liftNestedListsToParent(elementOrHTML);\n createGroups(elementOrHTML);\n return elementOrHTML;\n}\n","import { DOMParser, Schema } from \"prosemirror-model\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../../schema\";\n\nimport { Block } from \"../../../blocks/defaultBlocks\";\nimport { nodeToBlock } from \"../../nodeConversions/nodeConversions\";\nimport { nestedListsToBlockNoteStructure } from \"./util/nestedLists\";\nexport async function HTMLToBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n html: string,\n blockSchema: BSchema,\n icSchema: I,\n styleSchema: S,\n pmSchema: Schema\n): Promise<Block<BSchema, I, S>[]> {\n const htmlNode = nestedListsToBlockNoteStructure(html);\n const parser = DOMParser.fromSchema(pmSchema);\n\n // Other approach might be to use\n // const doc = pmSchema.nodes[\"doc\"].createAndFill()!;\n // and context: doc.resolve(3),\n\n const parentNode = parser.parse(htmlNode, {\n topNode: pmSchema.nodes[\"blockGroup\"].create(),\n });\n\n const blocks: Block<BSchema, I, S>[] = [];\n\n for (let i = 0; i < parentNode.childCount; i++) {\n blocks.push(\n nodeToBlock(parentNode.child(i), blockSchema, icSchema, styleSchema)\n );\n }\n\n return blocks;\n}\n","import { Schema } from \"prosemirror-model\";\nimport rehypeStringify from \"rehype-stringify\";\nimport remarkGfm from \"remark-gfm\";\nimport remarkParse from \"remark-parse\";\nimport remarkRehype, { defaultHandlers } from \"remark-rehype\";\nimport { unified } from \"unified\";\nimport { Block } from \"../../../blocks/defaultBlocks\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../../schema\";\nimport { HTMLToBlocks } from \"../html/parseHTML\";\n\n// modified version of https://github.com/syntax-tree/mdast-util-to-hast/blob/main/lib/handlers/code.js\n// that outputs a data-language attribute instead of a CSS class (e.g.: language-typescript)\nfunction code(state: any, node: any) {\n const value = node.value ? node.value + \"\\n\" : \"\";\n /** @type {Properties} */\n const properties: any = {};\n\n if (node.lang) {\n // changed line\n properties[\"data-language\"] = node.lang;\n }\n\n // Create `<code>`.\n /** @type {Element} */\n let result: any = {\n type: \"element\",\n tagName: \"code\",\n properties,\n children: [{ type: \"text\", value }],\n };\n\n if (node.meta) {\n result.data = { meta: node.meta };\n }\n\n state.patch(node, result);\n result = state.applyData(node, result);\n\n // Create `<pre>`.\n result = {\n type: \"element\",\n tagName: \"pre\",\n properties: {},\n children: [result],\n };\n state.patch(node, result);\n return result;\n}\n\nexport function markdownToBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n markdown: string,\n blockSchema: BSchema,\n icSchema: I,\n styleSchema: S,\n pmSchema: Schema\n): Promise<Block<BSchema, I, S>[]> {\n const htmlString = unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkRehype, {\n handlers: {\n ...(defaultHandlers as any),\n code,\n },\n })\n .use(rehypeStringify)\n .processSync(markdown);\n\n return HTMLToBlocks(\n htmlString.value as string,\n blockSchema,\n icSchema,\n styleSchema,\n pmSchema\n );\n}\n","// from https://raw.githubusercontent.com/ueberdosis/tiptap/develop/packages/core/src/EventEmitter.ts (MIT)\n\ntype StringKeyOf<T> = Extract<keyof T, string>;\ntype CallbackType<\n T extends Record<string, any>,\n EventName extends StringKeyOf<T>\n> = T[EventName] extends any[] ? T[EventName] : [T[EventName]];\ntype CallbackFunction<\n T extends Record<string, any>,\n EventName extends StringKeyOf<T>\n> = (...props: CallbackType<T, EventName>) => any;\n\nexport class EventEmitter<T extends Record<string, any>> {\n // eslint-disable-next-line @typescript-eslint/ban-types\n private callbacks: { [key: string]: Function[] } = {};\n\n public on<EventName extends StringKeyOf<T>>(\n event: EventName,\n fn: CallbackFunction<T, EventName>\n ) {\n if (!this.callbacks[event]) {\n this.callbacks[event] = [];\n }\n\n this.callbacks[event].push(fn);\n\n return () => this.off(event, fn);\n }\n\n protected emit<EventName extends StringKeyOf<T>>(\n event: EventName,\n ...args: CallbackType<T, EventName>\n ) {\n const callbacks = this.callbacks[event];\n\n if (callbacks) {\n callbacks.forEach((callback) => callback.apply(this, args));\n }\n }\n\n public off<EventName extends StringKeyOf<T>>(\n event: EventName,\n fn?: CallbackFunction<T, EventName>\n ) {\n const callbacks = this.callbacks[event];\n\n if (callbacks) {\n if (fn) {\n this.callbacks[event] = callbacks.filter((callback) => callback !== fn);\n } else {\n delete this.callbacks[event];\n }\n }\n }\n\n protected removeAllListeners(): void {\n this.callbacks = {};\n }\n}\n","import { isNodeSelection, posToDOMRect } from \"@tiptap/core\";\nimport { EditorState, Plugin, PluginKey } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\n\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../schema\";\nimport { EventEmitter } from \"../../util/EventEmitter\";\n\nexport type FormattingToolbarState = UiElementPosition;\n\nexport class FormattingToolbarView {\n public state?: FormattingToolbarState;\n public emitUpdate: () => void;\n\n public preventHide = false;\n public preventShow = false;\n public prevWasEditable: boolean | null = null;\n\n public shouldShow: (props: {\n view: EditorView;\n state: EditorState;\n from: number;\n to: number;\n }) => boolean = ({ state }) => !state.selection.empty;\n\n constructor(\n private readonly editor: BlockNoteEditor<\n BlockSchema,\n InlineContentSchema,\n StyleSchema\n >,\n private readonly pmView: EditorView,\n emitUpdate: (state: FormattingToolbarState) => void\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\n \"Attempting to update uninitialized formatting toolbar\"\n );\n }\n\n emitUpdate(this.state);\n };\n\n pmView.dom.addEventListener(\"mousedown\", this.viewMousedownHandler);\n pmView.dom.addEventListener(\"mouseup\", this.viewMouseupHandler);\n pmView.dom.addEventListener(\"dragstart\", this.dragHandler);\n pmView.dom.addEventListener(\"dragover\", this.dragHandler);\n\n pmView.dom.addEventListener(\"focus\", this.focusHandler);\n pmView.dom.addEventListener(\"blur\", this.blurHandler);\n\n document.addEventListener(\"scroll\", this.scrollHandler);\n }\n\n viewMousedownHandler = () => {\n this.preventShow = true;\n };\n\n viewMouseupHandler = () => {\n this.preventShow = false;\n setTimeout(() => this.update(this.pmView));\n };\n\n // For dragging the whole editor.\n dragHandler = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n focusHandler = () => {\n // we use `setTimeout` to make sure `selection` is already updated\n setTimeout(() => this.update(this.pmView));\n };\n\n blurHandler = (event: FocusEvent) => {\n if (this.preventHide) {\n this.preventHide = false;\n\n return;\n }\n\n const editorWrapper = this.pmView.dom.parentElement!;\n\n // Checks if the focus is moving to an element outside the editor. If it is,\n // the toolbar is hidden.\n if (\n // An element is clicked.\n event &&\n event.relatedTarget &&\n // Element is inside the editor.\n (editorWrapper === (event.relatedTarget as Node) ||\n editorWrapper.contains(event.relatedTarget as Node))\n ) {\n return;\n }\n\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n scrollHandler = () => {\n if (this.state?.show) {\n this.state.referencePos = this.getSelectionBoundingBox();\n this.emitUpdate();\n }\n };\n\n update(view: EditorView, oldState?: EditorState) {\n const { state, composing } = view;\n const { doc, selection } = state;\n const isSame =\n oldState && oldState.doc.eq(doc) && oldState.selection.eq(selection);\n\n if (\n (this.prevWasEditable === null ||\n this.prevWasEditable === this.editor.isEditable) &&\n (composing || isSame)\n ) {\n return;\n }\n\n this.prevWasEditable = this.editor.isEditable;\n\n // support for CellSelections\n const { ranges } = selection;\n const from = Math.min(...ranges.map((range) => range.$from.pos));\n const to = Math.max(...ranges.map((range) => range.$to.pos));\n\n const shouldShow = this.shouldShow?.({\n view,\n state,\n from,\n to,\n });\n\n // Checks if menu should be shown/updated.\n if (\n this.editor.isEditable &&\n !this.preventShow &&\n (shouldShow || this.preventHide)\n ) {\n this.state = {\n show: true,\n referencePos: this.getSelectionBoundingBox(),\n };\n\n this.emitUpdate();\n\n return;\n }\n\n // Checks if menu should be hidden.\n if (\n this.state?.show &&\n !this.preventHide &&\n (!shouldShow || this.preventShow || !this.editor.isEditable)\n ) {\n this.state.show = false;\n this.emitUpdate();\n\n return;\n }\n }\n\n destroy() {\n this.pmView.dom.removeEventListener(\"mousedown\", this.viewMousedownHandler);\n this.pmView.dom.removeEventListener(\"mouseup\", this.viewMouseupHandler);\n this.pmView.dom.removeEventListener(\"dragstart\", this.dragHandler);\n this.pmView.dom.removeEventListener(\"dragover\", this.dragHandler);\n\n this.pmView.dom.removeEventListener(\"focus\", this.focusHandler);\n this.pmView.dom.removeEventListener(\"blur\", this.blurHandler);\n\n document.removeEventListener(\"scroll\", this.scrollHandler);\n }\n\n getSelectionBoundingBox() {\n const { state } = this.pmView;\n const { selection } = state;\n\n // support for CellSelections\n const { ranges } = selection;\n const from = Math.min(...ranges.map((range) => range.$from.pos));\n const to = Math.max(...ranges.map((range) => range.$to.pos));\n\n if (isNodeSelection(selection)) {\n const node = this.pmView.nodeDOM(from) as HTMLElement;\n\n if (node) {\n return node.getBoundingClientRect();\n }\n }\n\n return posToDOMRect(this.pmView, from, to);\n }\n}\n\nexport const formattingToolbarPluginKey = new PluginKey(\n \"FormattingToolbarPlugin\"\n);\n\nexport class FormattingToolbarProsemirrorPlugin extends EventEmitter<any> {\n private view: FormattingToolbarView | undefined;\n public readonly plugin: Plugin;\n\n constructor(editor: BlockNoteEditor<any, any, any>) {\n super();\n this.plugin = new Plugin({\n key: formattingToolbarPluginKey,\n view: (editorView) => {\n this.view = new FormattingToolbarView(editor, editorView, (state) => {\n this.emit(\"update\", state);\n });\n return this.view;\n },\n });\n }\n\n public onUpdate(callback: (state: FormattingToolbarState) => void) {\n return this.on(\"update\", callback);\n }\n}\n","import { getMarkRange, posToDOMRect, Range } from \"@tiptap/core\";\nimport { EditorView } from \"@tiptap/pm/view\";\nimport { Mark } from \"prosemirror-model\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\n\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../schema\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition\";\nimport { EventEmitter } from \"../../util/EventEmitter\";\n\nexport type LinkToolbarState = UiElementPosition & {\n // The hovered link's URL, and the text it's displayed with in the\n // editor.\n url: string;\n text: string;\n};\n\nclass LinkToolbarView {\n public state?: LinkToolbarState;\n public emitUpdate: () => void;\n\n menuUpdateTimer: ReturnType<typeof setTimeout> | undefined;\n startMenuUpdateTimer: () => void;\n stopMenuUpdateTimer: () => void;\n\n mouseHoveredLinkMark: Mark | undefined;\n mouseHoveredLinkMarkRange: Range | undefined;\n\n keyboardHoveredLinkMark: Mark | undefined;\n keyboardHoveredLinkMarkRange: Range | undefined;\n\n linkMark: Mark | undefined;\n linkMarkRange: Range | undefined;\n\n constructor(\n private readonly editor: BlockNoteEditor<any, any, any>,\n private readonly pmView: EditorView,\n emitUpdate: (state: LinkToolbarState) => void\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized link toolbar\");\n }\n\n emitUpdate(this.state);\n };\n\n this.startMenuUpdateTimer = () => {\n this.menuUpdateTimer = setTimeout(() => {\n this.update();\n }, 250);\n };\n\n this.stopMenuUpdateTimer = () => {\n if (this.menuUpdateTimer) {\n clearTimeout(this.menuUpdateTimer);\n this.menuUpdateTimer = undefined;\n }\n\n return false;\n };\n\n this.pmView.dom.addEventListener(\"mouseover\", this.mouseOverHandler);\n document.addEventListener(\"click\", this.clickHandler, true);\n document.addEventListener(\"scroll\", this.scrollHandler);\n }\n\n mouseOverHandler = (event: MouseEvent) => {\n // Resets the link mark currently hovered by the mouse cursor.\n this.mouseHoveredLinkMark = undefined;\n this.mouseHoveredLinkMarkRange = undefined;\n\n this.stopMenuUpdateTimer();\n\n if (\n event.target instanceof HTMLAnchorElement &&\n event.target.nodeName === \"A\"\n ) {\n // Finds link mark at the hovered element's position to update mouseHoveredLinkMark and\n // mouseHoveredLinkMarkRange.\n const hoveredLinkElement = event.target;\n const posInHoveredLinkMark =\n this.pmView.posAtDOM(hoveredLinkElement, 0) + 1;\n const resolvedPosInHoveredLinkMark =\n this.pmView.state.doc.resolve(posInHoveredLinkMark);\n const marksAtPos = resolvedPosInHoveredLinkMark.marks();\n\n for (const mark of marksAtPos) {\n if (\n mark.type.name === this.pmView.state.schema.mark(\"link\").type.name\n ) {\n this.mouseHoveredLinkMark = mark;\n this.mouseHoveredLinkMarkRange =\n getMarkRange(resolvedPosInHoveredLinkMark, mark.type, mark.attrs) ||\n undefined;\n\n break;\n }\n }\n }\n\n this.startMenuUpdateTimer();\n\n return false;\n };\n\n clickHandler = (event: MouseEvent) => {\n const editorWrapper = this.pmView.dom.parentElement!;\n\n if (\n // Toolbar is open.\n this.linkMark &&\n // An element is clicked.\n event &&\n event.target &&\n // The clicked element is not the editor.\n !(\n editorWrapper === (event.target as Node) ||\n editorWrapper.contains(event.target as Node)\n )\n ) {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n }\n };\n\n scrollHandler = () => {\n if (this.linkMark !== undefined) {\n if (this.state?.show) {\n this.state.referencePos = posToDOMRect(\n this.pmView,\n this.linkMarkRange!.from,\n this.linkMarkRange!.to\n );\n this.emitUpdate();\n }\n }\n };\n\n editLink(url: string, text: string) {\n const tr = this.pmView.state.tr.insertText(\n text,\n this.linkMarkRange!.from,\n this.linkMarkRange!.to\n );\n tr.addMark(\n this.linkMarkRange!.from,\n this.linkMarkRange!.from + text.length,\n this.pmView.state.schema.mark(\"link\", { href: url })\n );\n this.pmView.dispatch(tr);\n this.pmView.focus();\n\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n }\n\n deleteLink() {\n this.pmView.dispatch(\n this.pmView.state.tr\n .removeMark(\n this.linkMarkRange!.from,\n this.linkMarkRange!.to,\n this.linkMark!.type\n )\n .setMeta(\"preventAutolink\", true)\n );\n this.pmView.focus();\n\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n }\n\n update() {\n if (!this.pmView.hasFocus()) {\n return;\n }\n\n // Saves the currently hovered link mark before it's updated.\n const prevLinkMark = this.linkMark;\n\n // Resets the currently hovered link mark.\n this.linkMark = undefined;\n this.linkMarkRange = undefined;\n\n // Resets the link mark currently hovered by the keyboard cursor.\n this.keyboardHoveredLinkMark = undefined;\n this.keyboardHoveredLinkMarkRange = undefined;\n\n // Finds link mark at the editor selection's position to update keyboardHoveredLinkMark and\n // keyboardHoveredLinkMarkRange.\n if (this.pmView.state.selection.empty) {\n const marksAtPos = this.pmView.state.selection.$from.marks();\n\n for (const mark of marksAtPos) {\n if (\n mark.type.name === this.pmView.state.schema.mark(\"link\").type.name\n ) {\n this.keyboardHoveredLinkMark = mark;\n this.keyboardHoveredLinkMarkRange =\n getMarkRange(\n this.pmView.state.selection.$from,\n mark.type,\n mark.attrs\n ) || undefined;\n\n break;\n }\n }\n }\n\n if (this.mouseHoveredLinkMark) {\n this.linkMark = this.mouseHoveredLinkMark;\n this.linkMarkRange = this.mouseHoveredLinkMarkRange;\n }\n\n // Keyboard cursor position takes precedence over mouse hovered link.\n if (this.keyboardHoveredLinkMark) {\n this.linkMark = this.keyboardHoveredLinkMark;\n this.linkMarkRange = this.keyboardHoveredLinkMarkRange;\n }\n\n if (this.linkMark && this.editor.isEditable) {\n this.state = {\n show: true,\n referencePos: posToDOMRect(\n this.pmView,\n this.linkMarkRange!.from,\n this.linkMarkRange!.to\n ),\n url: this.linkMark!.attrs.href,\n text: this.pmView.state.doc.textBetween(\n this.linkMarkRange!.from,\n this.linkMarkRange!.to\n ),\n };\n this.emitUpdate();\n\n return;\n }\n\n // Hides menu.\n if (\n this.state?.show &&\n prevLinkMark &&\n (!this.linkMark || !this.editor.isEditable)\n ) {\n this.state.show = false;\n this.emitUpdate();\n\n return;\n }\n }\n\n destroy() {\n this.pmView.dom.removeEventListener(\"mouseover\", this.mouseOverHandler);\n document.removeEventListener(\"scroll\", this.scrollHandler);\n document.removeEventListener(\"click\", this.clickHandler, true);\n }\n}\n\nexport const linkToolbarPluginKey = new PluginKey(\"LinkToolbarPlugin\");\n\nexport class LinkToolbarProsemirrorPlugin<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n> extends EventEmitter<any> {\n private view: LinkToolbarView | undefined;\n public readonly plugin: Plugin;\n\n constructor(editor: BlockNoteEditor<BSchema, I, S>) {\n super();\n this.plugin = new Plugin({\n key: linkToolbarPluginKey,\n view: (editorView) => {\n this.view = new LinkToolbarView(editor, editorView, (state) => {\n this.emit(\"update\", state);\n });\n return this.view;\n },\n });\n }\n\n public onUpdate(callback: (state: LinkToolbarState) => void) {\n return this.on(\"update\", callback);\n }\n\n /**\n * Edit the currently hovered link.\n */\n public editLink = (url: string, text: string) => {\n this.view!.editLink(url, text);\n };\n\n /**\n * Delete the currently hovered link.\n */\n public deleteLink = () => {\n this.view!.deleteLink();\n };\n\n /**\n * When hovering on/off links using the mouse cursor, the link toolbar will\n * open & close with a delay.\n *\n * This function starts the delay timer, and should be used for when the mouse\n * cursor enters the link toolbar.\n */\n public startHideTimer = () => {\n this.view!.startMenuUpdateTimer();\n };\n\n /**\n * When hovering on/off links using the mouse cursor, the link toolbar will\n * open & close with a delay.\n *\n * This function stops the delay timer, and should be used for when the mouse\n * cursor exits the link toolbar.\n */\n public stopHideTimer = () => {\n this.view!.stopMenuUpdateTimer();\n };\n}\n","import { findParentNode } from \"@tiptap/core\";\nimport { EditorState, Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet, EditorView } from \"prosemirror-view\";\n\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../schema\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition\";\nimport { EventEmitter } from \"../../util/EventEmitter\";\n\nconst findBlock = findParentNode((node) => node.type.name === \"blockContainer\");\n\nexport type SuggestionMenuState = UiElementPosition & {\n query: string;\n};\n\nclass SuggestionMenuView<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n> {\n private state?: SuggestionMenuState;\n public emitUpdate: (triggerCharacter: string) => void;\n\n pluginState: SuggestionPluginState;\n\n constructor(\n private readonly editor: BlockNoteEditor<BSchema, I, S>,\n emitUpdate: (menuName: string, state: SuggestionMenuState) => void\n ) {\n this.pluginState = undefined;\n\n this.emitUpdate = (menuName: string) => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized suggestions menu\");\n }\n\n emitUpdate(menuName, this.state);\n };\n\n document.addEventListener(\"scroll\", this.handleScroll);\n }\n\n handleScroll = () => {\n if (this.state?.show) {\n const decorationNode = document.querySelector(\n `[data-decoration-id=\"${this.pluginState!.decorationId}\"]`\n );\n this.state.referencePos = decorationNode!.getBoundingClientRect();\n this.emitUpdate(this.pluginState!.triggerCharacter!);\n }\n };\n\n update(view: EditorView, prevState: EditorState) {\n const prev: SuggestionPluginState =\n suggestionMenuPluginKey.getState(prevState);\n const next: SuggestionPluginState = suggestionMenuPluginKey.getState(\n view.state\n );\n\n // See how the state changed\n const started = prev === undefined && next !== undefined;\n const stopped = prev !== undefined && next === undefined;\n const changed = prev !== undefined && next !== undefined;\n\n // Cancel when suggestion isn't active\n if (!started && !changed && !stopped) {\n return;\n }\n\n this.pluginState = stopped ? prev : next;\n\n if (stopped || !this.editor.isEditable) {\n this.state!.show = false;\n this.emitUpdate(this.pluginState!.triggerCharacter);\n\n return;\n }\n\n const decorationNode = document.querySelector(\n `[data-decoration-id=\"${this.pluginState!.decorationId}\"]`\n );\n\n if (this.editor.isEditable) {\n this.state = {\n show: true,\n referencePos: decorationNode!.getBoundingClientRect(),\n query: this.pluginState!.query,\n };\n\n this.emitUpdate(this.pluginState!.triggerCharacter!);\n }\n }\n\n destroy() {\n document.removeEventListener(\"scroll\", this.handleScroll);\n }\n\n closeMenu = () => {\n this.editor._tiptapEditor.view.dispatch(\n this.editor._tiptapEditor.view.state.tr.setMeta(\n suggestionMenuPluginKey,\n null\n )\n );\n };\n\n clearQuery = () => {\n if (this.pluginState === undefined) {\n return;\n }\n\n this.editor._tiptapEditor\n .chain()\n .focus()\n .deleteRange({\n from:\n this.pluginState.queryStartPos! -\n (this.pluginState.fromUserInput\n ? this.pluginState.triggerCharacter!.length\n : 0),\n to: this.editor._tiptapEditor.state.selection.from,\n })\n .run();\n };\n}\n\ntype SuggestionPluginState =\n | {\n triggerCharacter: string;\n fromUserInput: boolean;\n queryStartPos: number;\n query: string;\n decorationId: string;\n }\n | undefined;\n\nexport const suggestionMenuPluginKey = new PluginKey(\"SuggestionMenuPlugin\");\n\n/**\n * A ProseMirror plugin for suggestions, designed to make '/'-commands possible as well as mentions.\n *\n * This is basically a simplified version of TipTap's [Suggestions](https://github.com/ueberdosis/tiptap/tree/db92a9b313c5993b723c85cd30256f1d4a0b65e1/packages/suggestion) plugin.\n *\n * This version is adapted from the aforementioned version in the following ways:\n * - This version supports generic items instead of only strings (to allow for more advanced filtering for example)\n * - This version hides some unnecessary complexity from the user of the plugin.\n * - This version handles key events differently\n */\nexport class SuggestionMenuProseMirrorPlugin<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n> extends EventEmitter<any> {\n private view: SuggestionMenuView<BSchema, I, S> | undefined;\n public readonly plugin: Plugin;\n\n private triggerCharacters: string[] = [];\n\n constructor(editor: BlockNoteEditor<BSchema, I, S>) {\n super();\n const triggerCharacters = this.triggerCharacters;\n this.plugin = new Plugin({\n key: suggestionMenuPluginKey,\n\n view: () => {\n this.view = new SuggestionMenuView<BSchema, I, S>(\n editor,\n (triggerCharacter, state) => {\n this.emit(`update ${triggerCharacter}`, state);\n }\n );\n return this.view;\n },\n\n state: {\n // Initialize the plugin's internal state.\n init(): SuggestionPluginState {\n return undefined;\n },\n\n // Apply changes to the plugin state from an editor transaction.\n apply(transaction, prev, _oldState, newState): SuggestionPluginState {\n // TODO: More clearly define which transactions should be ignored.\n if (transaction.getMeta(\"orderedListIndexing\") !== undefined) {\n return prev;\n }\n\n // Either contains the trigger character if the menu should be shown,\n // or null if it should be hidden.\n const suggestionPluginTransactionMeta: {\n triggerCharacter: string;\n fromUserInput?: boolean;\n } | null = transaction.getMeta(suggestionMenuPluginKey);\n\n // Only opens a menu of no menu is already open\n if (\n typeof suggestionPluginTransactionMeta === \"object\" &&\n suggestionPluginTransactionMeta !== null &&\n prev === undefined\n ) {\n return {\n triggerCharacter:\n suggestionPluginTransactionMeta.triggerCharacter,\n fromUserInput:\n suggestionPluginTransactionMeta.fromUserInput !== false,\n queryStartPos: newState.selection.from,\n query: \"\",\n decorationId: `id_${Math.floor(Math.random() * 0xffffffff)}`,\n };\n }\n\n // Checks if the menu is hidden, in which case it doesn't need to be hidden or updated.\n if (prev === undefined) {\n return prev;\n }\n\n // Checks if the menu should be hidden.\n if (\n // Highlighting text should hide the menu.\n newState.selection.from !== newState.selection.to ||\n // Transactions with plugin metadata should hide the menu.\n suggestionPluginTransactionMeta === null ||\n // Certain mouse events should hide the menu.\n // TODO: Change to global mousedown listener.\n transaction.getMeta(\"focus\") ||\n transaction.getMeta(\"blur\") ||\n transaction.getMeta(\"pointer\") ||\n // Moving the caret before the character which triggered the menu should hide it.\n (prev.triggerCharacter !== undefined &&\n newState.selection.from < prev.queryStartPos!)\n ) {\n return undefined;\n }\n\n const next = { ...prev };\n\n // Updates the current query.\n next.query = newState.doc.textBetween(\n prev.queryStartPos!,\n newState.selection.from\n );\n\n return next;\n },\n },\n\n props: {\n handleKeyDown(view, event) {\n const suggestionPluginState: SuggestionPluginState = (\n this as Plugin\n ).getState(view.state);\n\n if (\n triggerCharacters.includes(event.key) &&\n suggestionPluginState === undefined\n ) {\n event.preventDefault();\n\n view.dispatch(\n view.state.tr\n .insertText(event.key)\n .scrollIntoView()\n .setMeta(suggestionMenuPluginKey, {\n triggerCharacter: event.key,\n })\n );\n\n return true;\n }\n\n return false;\n },\n\n // Setup decorator on the currently active suggestion.\n decorations(state) {\n const suggestionPluginState: SuggestionPluginState = (\n this as Plugin\n ).getState(state);\n\n if (suggestionPluginState === undefined) {\n return null;\n }\n\n // If the menu was opened programmatically by another extension, it may not use a trigger character. In this\n // case, the decoration is set on the whole block instead, as the decoration range would otherwise be empty.\n if (!suggestionPluginState.fromUserInput) {\n const blockNode = findBlock(state.selection);\n if (blockNode) {\n return DecorationSet.create(state.doc, [\n Decoration.node(\n blockNode.pos,\n blockNode.pos + blockNode.node.nodeSize,\n {\n nodeName: \"span\",\n class: \"bn-suggestion-decorator\",\n \"data-decoration-id\": suggestionPluginState.decorationId,\n }\n ),\n ]);\n }\n }\n // Creates an inline decoration around the trigger character.\n return DecorationSet.create(state.doc, [\n Decoration.inline(\n suggestionPluginState.queryStartPos! -\n suggestionPluginState.triggerCharacter!.length,\n suggestionPluginState.queryStartPos!,\n {\n nodeName: \"span\",\n class: \"bn-suggestion-decorator\",\n \"data-decoration-id\": suggestionPluginState.decorationId,\n }\n ),\n ]);\n },\n },\n });\n }\n\n public onUpdate(\n triggerCharacter: string,\n callback: (state: SuggestionMenuState) => void\n ) {\n if (!this.triggerCharacters.includes(triggerCharacter)) {\n this.addTriggerCharacter(triggerCharacter);\n }\n // TODO: be able to remove the triggerCharacter\n return this.on(`update ${triggerCharacter}`, callback);\n }\n\n addTriggerCharacter = (triggerCharacter: string) => {\n this.triggerCharacters.push(triggerCharacter);\n };\n\n // TODO: Should this be called automatically when listeners are removed?\n removeTriggerCharacter = (triggerCharacter: string) => {\n this.triggerCharacters = this.triggerCharacters.filter(\n (c) => c !== triggerCharacter\n );\n };\n\n closeMenu = () => this.view!.closeMenu();\n\n clearQuery = () => this.view!.clearQuery();\n}\n\nexport function createSuggestionMenu<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(editor: BlockNoteEditor<BSchema, I, S>, triggerCharacter: string) {\n editor.suggestionMenus.addTriggerCharacter(triggerCharacter);\n}\n","import { Fragment, Node, ResolvedPos, Slice } from \"prosemirror-model\";\nimport { Selection } from \"prosemirror-state\";\nimport { Mappable } from \"prosemirror-transform\";\n\n/**\n * This class represents an editor selection which spans multiple nodes/blocks. It's currently only used to allow users\n * to drag multiple blocks at the same time. Expects the selection anchor and head to be between nodes, i.e. just before\n * the first target node and just after the last, and that anchor and head are at the same nesting level.\n *\n * Partially based on ProseMirror's NodeSelection implementation:\n * (https://github.com/ProseMirror/prosemirror-state/blob/master/src/selection.ts)\n * MultipleNodeSelection differs from NodeSelection in the following ways:\n * 1. Stores which nodes are included in the selection instead of just a single node.\n * 2. Already expects the selection to start just before the first target node and ends just after the last, while a\n * NodeSelection automatically sets both anchor and head to just before the single target node.\n */\nexport class MultipleNodeSelection extends Selection {\n nodes: Array<Node>;\n\n constructor($anchor: ResolvedPos, $head: ResolvedPos) {\n super($anchor, $head);\n\n // Parent is at the same nesting level as anchor/head since they are just before/ just after target nodes.\n const parentNode = $anchor.node();\n\n this.nodes = [];\n $anchor.doc.nodesBetween($anchor.pos, $head.pos, (node, _pos, parent) => {\n if (parent !== null && parent.eq(parentNode)) {\n this.nodes.push(node);\n return false;\n }\n return;\n });\n }\n\n static create(doc: Node, from: number, to = from): MultipleNodeSelection {\n return new MultipleNodeSelection(doc.resolve(from), doc.resolve(to));\n }\n\n content(): Slice {\n return new Slice(Fragment.from(this.nodes), 0, 0);\n }\n\n eq(selection: Selection): boolean {\n if (!(selection instanceof MultipleNodeSelection)) {\n return false;\n }\n\n if (this.nodes.length !== selection.nodes.length) {\n return false;\n }\n\n if (this.from !== selection.from || this.to !== selection.to) {\n return false;\n }\n\n for (let i = 0; i < this.nodes.length; i++) {\n if (!this.nodes[i].eq(selection.nodes[i])) {\n return false;\n }\n }\n\n return true;\n }\n\n map(doc: Node, mapping: Mappable): Selection {\n const fromResult = mapping.mapResult(this.from);\n const toResult = mapping.mapResult(this.to);\n\n if (toResult.deleted) {\n return Selection.near(doc.resolve(fromResult.pos));\n }\n\n if (fromResult.deleted) {\n return Selection.near(doc.resolve(toResult.pos));\n }\n\n return new MultipleNodeSelection(\n doc.resolve(fromResult.pos),\n doc.resolve(toResult.pos)\n );\n }\n\n toJSON(): any {\n return { type: \"node\", anchor: this.anchor, head: this.head };\n }\n}\n","import { PluginView } from \"@tiptap/pm/state\";\nimport { Node } from \"prosemirror-model\";\nimport { NodeSelection, Plugin, PluginKey, Selection } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\n\nimport { createExternalHTMLExporter } from \"../../api/exporters/html/externalHTMLExporter\";\nimport { createInternalHTMLSerializer } from \"../../api/exporters/html/internalHTMLSerializer\";\nimport { cleanHTMLToMarkdown } from \"../../api/exporters/markdown/markdownExporter\";\nimport { getBlockInfoFromPos } from \"../../api/getBlockInfoFromPos\";\nimport { Block } from \"../../blocks/defaultBlocks\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../schema\";\nimport { EventEmitter } from \"../../util/EventEmitter\";\nimport { suggestionMenuPluginKey } from \"../SuggestionMenu/SuggestionPlugin\";\nimport { MultipleNodeSelection } from \"./MultipleNodeSelection\";\n\nlet dragImageElement: Element | undefined;\n\nexport type SideMenuState<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n> = UiElementPosition & {\n // The block that the side menu is attached to.\n block: Block<BSchema, I, S>;\n};\n\nexport function getDraggableBlockFromCoords(\n coords: { left: number; top: number },\n view: EditorView\n) {\n if (!view.dom.isConnected) {\n // view is not connected to the DOM, this can cause posAtCoords to fail\n // (Cannot read properties of null (reading 'nearestDesc'), https://github.com/TypeCellOS/BlockNote/issues/123)\n return undefined;\n }\n\n const pos = view.posAtCoords(coords);\n if (!pos) {\n return undefined;\n }\n let node = view.domAtPos(pos.pos).node as HTMLElement;\n\n if (node === view.dom) {\n // mouse over root\n return undefined;\n }\n\n while (\n node &&\n node.parentNode &&\n node.parentNode !== view.dom &&\n !node.hasAttribute?.(\"data-id\")\n ) {\n node = node.parentNode as HTMLElement;\n }\n if (!node) {\n return undefined;\n }\n return { node, id: node.getAttribute(\"data-id\")! };\n}\n\nfunction blockPositionFromCoords(\n coords: { left: number; top: number },\n view: EditorView\n) {\n const block = getDraggableBlockFromCoords(coords, view);\n\n if (block && block.node.nodeType === 1) {\n // TODO: this uses undocumented PM APIs? do we need this / let's add docs?\n const docView = (view as any).docView;\n const desc = docView.nearestDesc(block.node, true);\n if (!desc || desc === docView) {\n return null;\n }\n return desc.posBefore;\n }\n return null;\n}\n\nfunction blockPositionsFromSelection(selection: Selection, doc: Node) {\n // Absolute positions just before the first block spanned by the selection, and just after the last block. Having the\n // selection start and end just before and just after the target blocks ensures no whitespace/line breaks are left\n // behind after dragging & dropping them.\n let beforeFirstBlockPos: number;\n let afterLastBlockPos: number;\n\n // Even the user starts dragging blocks but drops them in the same place, the selection will still be moved just\n // before & just after the blocks spanned by the selection, and therefore doesn't need to change if they try to drag\n // the same blocks again. If this happens, the anchor & head move out of the block content node they were originally\n // in. If the anchor should update but the head shouldn't and vice versa, it means the user selection is outside a\n // block content node, which should never happen.\n const selectionStartInBlockContent =\n doc.resolve(selection.from).node().type.spec.group === \"blockContent\";\n const selectionEndInBlockContent =\n doc.resolve(selection.to).node().type.spec.group === \"blockContent\";\n\n // Ensures that entire outermost nodes are selected if the selection spans multiple nesting levels.\n const minDepth = Math.min(selection.$anchor.depth, selection.$head.depth);\n\n if (selectionStartInBlockContent && selectionEndInBlockContent) {\n // Absolute positions at the start of the first block in the selection and at the end of the last block. User\n // selections will always start and end in block content nodes, but we want the start and end positions of their\n // parent block nodes, which is why minDepth - 1 is used.\n const startFirstBlockPos = selection.$from.start(minDepth - 1);\n const endLastBlockPos = selection.$to.end(minDepth - 1);\n\n // Shifting start and end positions by one moves them just outside the first and last selected blocks.\n beforeFirstBlockPos = doc.resolve(startFirstBlockPos - 1).pos;\n afterLastBlockPos = doc.resolve(endLastBlockPos + 1).pos;\n } else {\n beforeFirstBlockPos = selection.from;\n afterLastBlockPos = selection.to;\n }\n\n return { from: beforeFirstBlockPos, to: afterLastBlockPos };\n}\n\nfunction setDragImage(view: EditorView, from: number, to = from) {\n if (from === to) {\n // Moves to position to be just after the first (and only) selected block.\n to += view.state.doc.resolve(from + 1).node().nodeSize;\n }\n\n // Parent element is cloned to remove all unselected children without affecting the editor content.\n const parentClone = view.domAtPos(from).node.cloneNode(true) as Element;\n const parent = view.domAtPos(from).node as Element;\n\n const getElementIndex = (parentElement: Element, targetElement: Element) =>\n Array.prototype.indexOf.call(parentElement.children, targetElement);\n\n const firstSelectedBlockIndex = getElementIndex(\n parent,\n // Expects from position to be just before the first selected block.\n view.domAtPos(from + 1).node.parentElement!\n );\n const lastSelectedBlockIndex = getElementIndex(\n parent,\n // Expects to position to be just after the last selected block.\n view.domAtPos(to - 1).node.parentElement!\n );\n\n for (let i = parent.childElementCount - 1; i >= 0; i--) {\n if (i > lastSelectedBlockIndex || i < firstSelectedBlockIndex) {\n parentClone.removeChild(parentClone.children[i]);\n }\n }\n\n // dataTransfer.setDragImage(element) only works if element is attached to the DOM.\n unsetDragImage();\n dragImageElement = parentClone;\n\n // TODO: This is hacky, need a better way of assigning classes to the editor so that they can also be applied to the\n // drag preview.\n const classes = view.dom.className.split(\" \");\n const inheritedClasses = classes\n .filter(\n (className) =>\n className !== \"ProseMirror\" &&\n className !== \"bn-root\" &&\n className !== \"bn-editor\"\n )\n .join(\" \");\n\n dragImageElement.className =\n dragImageElement.className + \" bn-drag-preview \" + inheritedClasses;\n\n document.body.appendChild(dragImageElement);\n}\n\nfunction unsetDragImage() {\n if (dragImageElement !== undefined) {\n document.body.removeChild(dragImageElement);\n dragImageElement = undefined;\n }\n}\n\nfunction dragStart<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n e: { dataTransfer: DataTransfer | null; clientY: number },\n editor: BlockNoteEditor<BSchema, I, S>\n) {\n if (!e.dataTransfer) {\n return;\n }\n\n const view = editor.prosemirrorView;\n\n const editorBoundingBox = view.dom.getBoundingClientRect();\n\n const coords = {\n left: editorBoundingBox.left + editorBoundingBox.width / 2, // take middle of editor\n top: e.clientY,\n };\n\n const pos = blockPositionFromCoords(coords, view);\n if (pos != null) {\n const selection = view.state.selection;\n const doc = view.state.doc;\n\n const { from, to } = blockPositionsFromSelection(selection, doc);\n\n const draggedBlockInSelection = from <= pos && pos < to;\n const multipleBlocksSelected =\n selection.$anchor.node() !== selection.$head.node() ||\n selection instanceof MultipleNodeSelection;\n\n if (draggedBlockInSelection && multipleBlocksSelected) {\n view.dispatch(\n view.state.tr.setSelection(MultipleNodeSelection.create(doc, from, to))\n );\n setDragImage(view, from, to);\n } else {\n view.dispatch(\n view.state.tr.setSelection(NodeSelection.create(view.state.doc, pos))\n );\n setDragImage(view, pos);\n }\n\n const selectedSlice = view.state.selection.content();\n const schema = editor._tiptapEditor.schema;\n\n const internalHTMLSerializer = createInternalHTMLSerializer(schema, editor);\n const internalHTML = internalHTMLSerializer.serializeProseMirrorFragment(\n selectedSlice.content\n );\n\n const externalHTMLExporter = createExternalHTMLExporter(schema, editor);\n const externalHTML = externalHTMLExporter.exportProseMirrorFragment(\n selectedSlice.content\n );\n\n const plainText = cleanHTMLToMarkdown(externalHTML);\n\n e.dataTransfer.clearData();\n e.dataTransfer.setData(\"blocknote/html\", internalHTML);\n e.dataTransfer.setData(\"text/html\", externalHTML);\n e.dataTransfer.setData(\"text/plain\", plainText);\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setDragImage(dragImageElement!, 0, 0);\n view.dragging = { slice: selectedSlice, move: true };\n }\n}\n\nexport class SideMenuView<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n> implements PluginView\n{\n private state?: SideMenuState<BSchema, I, S>;\n private readonly emitUpdate: (state: SideMenuState<BSchema, I, S>) => void;\n\n // When true, the drag handle with be anchored at the same level as root elements\n // When false, the drag handle with be just to the left of the element\n // TODO: Is there any case where we want this to be false?\n private horizontalPosAnchoredAtRoot: boolean;\n private horizontalPosAnchor: number;\n\n private hoveredBlock: HTMLElement | undefined;\n\n // Used to check if currently dragged content comes from this editor instance.\n public isDragging = false;\n\n public menuFrozen = false;\n\n constructor(\n private readonly editor: BlockNoteEditor<BSchema, I, S>,\n private readonly pmView: EditorView,\n emitUpdate: (state: SideMenuState<BSchema, I, S>) => void\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized side menu\");\n }\n\n emitUpdate(this.state);\n };\n\n this.horizontalPosAnchoredAtRoot = true;\n this.horizontalPosAnchor = (\n this.pmView.dom.firstChild! as HTMLElement\n ).getBoundingClientRect().x;\n\n document.body.addEventListener(\"drop\", this.onDrop, true);\n document.body.addEventListener(\"dragover\", this.onDragOver);\n this.pmView.dom.addEventListener(\"dragstart\", this.onDragStart);\n\n // Shows or updates menu position whenever the cursor moves, if the menu isn't frozen.\n document.body.addEventListener(\"mousemove\", this.onMouseMove, true);\n\n // Makes menu scroll with the page.\n document.addEventListener(\"scroll\", this.onScroll);\n\n // Unfreezes the menu whenever the user clicks anywhere.\n document.body.addEventListener(\"mousedown\", this.onMouseDown, true);\n // Hides and unfreezes the menu whenever the user presses a key.\n document.body.addEventListener(\"keydown\", this.onKeyDown, true);\n }\n\n /**\n * Sets isDragging when dragging text.\n */\n onDragStart = () => {\n this.isDragging = true;\n };\n\n /**\n * If the event is outside the editor contents,\n * we dispatch a fake event, so that we can still drop the content\n * when dragging / dropping to the side of the editor\n */\n onDrop = (event: DragEvent) => {\n this.editor._tiptapEditor.commands.blur();\n\n if ((event as any).synthetic || !this.isDragging) {\n return;\n }\n\n const pos = this.pmView.posAtCoords({\n left: event.clientX,\n top: event.clientY,\n });\n\n this.isDragging = false;\n\n if (!pos || pos.inside === -1) {\n const evt = new Event(\"drop\", event) as any;\n const editorBoundingBox = (\n this.pmView.dom.firstChild! as HTMLElement\n ).getBoundingClientRect();\n evt.clientX = editorBoundingBox.left + editorBoundingBox.width / 2;\n evt.clientY = event.clientY;\n evt.dataTransfer = event.dataTransfer;\n evt.preventDefault = () => event.preventDefault();\n evt.synthetic = true; // prevent recursion\n // console.log(\"dispatch fake drop\");\n this.pmView.dom.dispatchEvent(evt);\n }\n };\n\n /**\n * If the event is outside the editor contents,\n * we dispatch a fake event, so that we can still drop the content\n * when dragging / dropping to the side of the editor\n */\n onDragOver = (event: DragEvent) => {\n if ((event as any).synthetic || !this.isDragging) {\n return;\n }\n const pos = this.pmView.posAtCoords({\n left: event.clientX,\n top: event.clientY,\n });\n\n if (!pos || pos.inside === -1) {\n const evt = new Event(\"dragover\", event) as any;\n const editorBoundingBox = (\n this.pmView.dom.firstChild! as HTMLElement\n ).getBoundingClientRect();\n evt.clientX = editorBoundingBox.left + editorBoundingBox.width / 2;\n evt.clientY = event.clientY;\n evt.dataTransfer = event.dataTransfer;\n evt.preventDefault = () => event.preventDefault();\n evt.synthetic = true; // prevent recursion\n // console.log(\"dispatch fake dragover\");\n this.pmView.dom.dispatchEvent(evt);\n }\n };\n\n onKeyDown = (_event: KeyboardEvent) => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate(this.state);\n }\n this.menuFrozen = false;\n };\n\n onMouseDown = (_event: MouseEvent) => {\n if (this.state && !this.state.show) {\n this.state.show = true;\n this.emitUpdate(this.state);\n }\n this.menuFrozen = false;\n };\n\n onMouseMove = (event: MouseEvent) => {\n if (this.menuFrozen) {\n return;\n }\n\n // Editor itself may have padding or other styling which affects\n // size/position, so we get the boundingRect of the first child (i.e. the\n // blockGroup that wraps all blocks in the editor) for more accurate side\n // menu placement.\n const editorBoundingBox = (\n this.pmView.dom.firstChild! as HTMLElement\n ).getBoundingClientRect();\n // We want the full area of the editor to check if the cursor is hovering\n // above it though.\n const editorOuterBoundingBox = this.pmView.dom.getBoundingClientRect();\n const cursorWithinEditor =\n event.clientX >= editorOuterBoundingBox.left &&\n event.clientX <= editorOuterBoundingBox.right &&\n event.clientY >= editorOuterBoundingBox.top &&\n event.clientY <= editorOuterBoundingBox.bottom;\n\n const editorWrapper = this.pmView.dom.parentElement!;\n\n // Doesn't update if the mouse hovers an element that's over the editor but\n // isn't a part of it or the side menu.\n if (\n // Cursor is within the editor area\n cursorWithinEditor &&\n // An element is hovered\n event &&\n event.target &&\n // Element is outside the editor\n !(\n editorWrapper === event.target ||\n editorWrapper.contains(event.target as HTMLElement)\n )\n ) {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate(this.state);\n }\n\n return;\n }\n\n this.horizontalPosAnchor = editorBoundingBox.x;\n\n // Gets block at mouse cursor's vertical position.\n const coords = {\n left: editorBoundingBox.left + editorBoundingBox.width / 2, // take middle of editor\n top: event.clientY,\n };\n const block = getDraggableBlockFromCoords(coords, this.pmView);\n\n // Closes the menu if the mouse cursor is beyond the editor vertically.\n if (!block || !this.editor.isEditable) {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate(this.state);\n }\n\n return;\n }\n\n // Doesn't update if the menu is already open and the mouse cursor is still hovering the same block.\n if (\n this.state?.show &&\n this.hoveredBlock?.hasAttribute(\"data-id\") &&\n this.hoveredBlock?.getAttribute(\"data-id\") === block.id\n ) {\n return;\n }\n\n this.hoveredBlock = block.node;\n\n // Gets the block's content node, which lets to ignore child blocks when determining the block menu's position.\n const blockContent = block.node.firstChild as HTMLElement;\n\n if (!blockContent) {\n return;\n }\n\n // Shows or updates elements.\n if (this.editor.isEditable) {\n const blockContentBoundingBox = blockContent.getBoundingClientRect();\n\n this.state = {\n show: true,\n referencePos: new DOMRect(\n this.horizontalPosAnchoredAtRoot\n ? this.horizontalPosAnchor\n : blockContentBoundingBox.x,\n blockContentBoundingBox.y,\n blockContentBoundingBox.width,\n blockContentBoundingBox.height\n ),\n block: this.editor.getBlock(\n this.hoveredBlock!.getAttribute(\"data-id\")!\n )!,\n };\n\n this.emitUpdate(this.state);\n }\n };\n\n onScroll = () => {\n if (this.state?.show) {\n const blockContent = this.hoveredBlock!.firstChild as HTMLElement;\n const blockContentBoundingBox = blockContent.getBoundingClientRect();\n\n this.state.referencePos = new DOMRect(\n this.horizontalPosAnchoredAtRoot\n ? this.horizontalPosAnchor\n : blockContentBoundingBox.x,\n blockContentBoundingBox.y,\n blockContentBoundingBox.width,\n blockContentBoundingBox.height\n );\n this.emitUpdate(this.state);\n }\n };\n\n destroy() {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate(this.state);\n }\n document.body.removeEventListener(\"mousemove\", this.onMouseMove, true);\n document.body.removeEventListener(\"dragover\", this.onDragOver);\n this.pmView.dom.removeEventListener(\"dragstart\", this.onDragStart);\n document.body.removeEventListener(\"drop\", this.onDrop, true);\n document.removeEventListener(\"scroll\", this.onScroll);\n document.body.removeEventListener(\"mousedown\", this.onMouseDown, true);\n document.body.removeEventListener(\"keydown\", this.onKeyDown, true);\n }\n\n addBlock() {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate(this.state);\n }\n\n this.menuFrozen = true;\n\n const blockContent = this.hoveredBlock!.firstChild! as HTMLElement;\n const blockContentBoundingBox = blockContent.getBoundingClientRect();\n\n const pos = this.pmView.posAtCoords({\n left: blockContentBoundingBox.left + blockContentBoundingBox.width / 2,\n top: blockContentBoundingBox.top + blockContentBoundingBox.height / 2,\n });\n if (!pos) {\n return;\n }\n\n const blockInfo = getBlockInfoFromPos(\n this.editor._tiptapEditor.state.doc,\n pos.pos\n );\n if (blockInfo === undefined) {\n return;\n }\n\n const { contentNode, startPos, endPos } = blockInfo;\n\n // Creates a new block if current one is not empty for the suggestion menu to open in.\n if (\n contentNode.type.spec.content !== \"inline*\" ||\n contentNode.textContent.length !== 0\n ) {\n const newBlockInsertionPos = endPos + 1;\n const newBlockContentPos = newBlockInsertionPos + 2;\n\n this.editor._tiptapEditor\n .chain()\n .BNCreateBlock(newBlockInsertionPos)\n // .BNUpdateBlock(newBlockContentPos, { type: \"paragraph\", props: {} })\n .setTextSelection(newBlockContentPos)\n .run();\n } else {\n this.editor._tiptapEditor.commands.setTextSelection(startPos + 1);\n }\n\n // Focuses and activates the suggestion menu.\n this.pmView.focus();\n this.pmView.dispatch(\n this.pmView.state.tr.scrollIntoView().setMeta(suggestionMenuPluginKey, {\n triggerCharacter: \"/\",\n fromUserInput: false,\n })\n );\n }\n}\n\nexport const sideMenuPluginKey = new PluginKey(\"SideMenuPlugin\");\n\nexport class SideMenuProsemirrorPlugin<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n> extends EventEmitter<any> {\n public view: SideMenuView<BSchema, I, S> | undefined;\n public readonly plugin: Plugin;\n\n constructor(private readonly editor: BlockNoteEditor<BSchema, I, S>) {\n super();\n this.plugin = new Plugin({\n key: sideMenuPluginKey,\n view: (editorView) => {\n this.view = new SideMenuView(editor, editorView, (state) => {\n this.emit(\"update\", state);\n });\n return this.view;\n },\n });\n }\n\n public onUpdate(callback: (state: SideMenuState<BSchema, I, S>) => void) {\n return this.on(\"update\", callback);\n }\n\n /**\n * If the block is empty, opens the slash menu. If the block has content,\n * creates a new block below and opens the slash menu in it.\n */\n addBlock = () => this.view!.addBlock();\n\n /**\n * Handles drag & drop events for blocks.\n */\n blockDragStart = (event: {\n dataTransfer: DataTransfer | null;\n clientY: number;\n }) => {\n this.view!.isDragging = true;\n dragStart(event, this.editor);\n };\n\n /**\n * Handles drag & drop events for blocks.\n */\n blockDragEnd = () => unsetDragImage();\n /**\n * Freezes the side menu. When frozen, the side menu will stay\n * attached to the same block regardless of which block is hovered by the\n * mouse cursor.\n */\n freezeMenu = () => (this.view!.menuFrozen = true);\n /**\n * Unfreezes the side menu. When frozen, the side menu will stay\n * attached to the same block regardless of which block is hovered by the\n * mouse cursor.\n */\n unfreezeMenu = () => (this.view!.menuFrozen = false);\n}\n","import { EditorState, Plugin, PluginKey } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\n\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport type {\n BlockFromConfig,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition\";\nimport { EventEmitter } from \"../../util/EventEmitter\";\nimport { DefaultBlockSchema } from \"../../blocks/defaultBlocks\";\n\nexport type ImagePanelState<\n I extends InlineContentSchema,\n S extends StyleSchema\n> = UiElementPosition & {\n // TODO: This typing is not quite right (children should be from BSchema)\n block: BlockFromConfig<DefaultBlockSchema[\"image\"], I, S>;\n};\n\nexport class ImagePanelView<\n I extends InlineContentSchema,\n S extends StyleSchema\n> {\n public state?: ImagePanelState<I, S>;\n public emitUpdate: () => void;\n\n public prevWasEditable: boolean | null = null;\n\n constructor(\n private readonly pluginKey: PluginKey,\n private readonly pmView: EditorView,\n emitUpdate: (state: ImagePanelState<I, S>) => void\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized image panel\");\n }\n\n emitUpdate(this.state);\n };\n\n pmView.dom.addEventListener(\"mousedown\", this.mouseDownHandler);\n\n pmView.dom.addEventListener(\"dragstart\", this.dragstartHandler);\n\n pmView.dom.addEventListener(\"blur\", this.blurHandler);\n\n document.addEventListener(\"scroll\", this.scrollHandler);\n }\n\n mouseDownHandler = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n // For dragging the whole editor.\n dragstartHandler = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n blurHandler = (event: FocusEvent) => {\n const editorWrapper = this.pmView.dom.parentElement!;\n\n // Checks if the focus is moving to an element outside the editor. If it is,\n // the panel is hidden.\n if (\n // An element is clicked.\n event &&\n event.relatedTarget &&\n // Element is inside the editor.\n (editorWrapper === (event.relatedTarget as Node) ||\n editorWrapper.contains(event.relatedTarget as Node))\n ) {\n return;\n }\n\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n scrollHandler = () => {\n if (this.state?.show) {\n const blockElement = document.querySelector(\n `[data-node-type=\"blockContainer\"][data-id=\"${this.state.block.id}\"]`\n )!;\n\n this.state.referencePos = blockElement.getBoundingClientRect();\n this.emitUpdate();\n }\n };\n\n update(view: EditorView, prevState: EditorState) {\n const pluginState: {\n block: BlockFromConfig<DefaultBlockSchema[\"image\"], I, S>;\n } = this.pluginKey.getState(view.state);\n\n if (!this.state?.show && pluginState.block) {\n const blockElement = document.querySelector(\n `[data-node-type=\"blockContainer\"][data-id=\"${pluginState.block.id}\"]`\n )!;\n\n this.state = {\n show: true,\n referencePos: blockElement.getBoundingClientRect(),\n block: pluginState.block,\n };\n\n this.emitUpdate();\n\n return;\n }\n\n if (\n !view.state.selection.eq(prevState.selection) ||\n !view.state.doc.eq(prevState.doc)\n ) {\n if (this.state?.show) {\n this.state.show = false;\n\n this.emitUpdate();\n }\n }\n }\n\n destroy() {\n this.pmView.dom.removeEventListener(\"mousedown\", this.mouseDownHandler);\n\n this.pmView.dom.removeEventListener(\"dragstart\", this.dragstartHandler);\n\n this.pmView.dom.removeEventListener(\"blur\", this.blurHandler);\n\n document.removeEventListener(\"scroll\", this.scrollHandler);\n }\n}\n\nconst imagePanelPluginKey = new PluginKey(\"ImagePanelPlugin\");\n\nexport class ImagePanelProsemirrorPlugin<\n I extends InlineContentSchema,\n S extends StyleSchema\n> extends EventEmitter<any> {\n private view: ImagePanelView<I, S> | undefined;\n public readonly plugin: Plugin;\n\n constructor(\n _editor: BlockNoteEditor<{ image: DefaultBlockSchema[\"image\"] }, I, S>\n ) {\n super();\n this.plugin = new Plugin<{\n block: BlockFromConfig<DefaultBlockSchema[\"image\"], I, S> | undefined;\n }>({\n key: imagePanelPluginKey,\n view: (editorView) => {\n this.view = new ImagePanelView(\n // editor,\n imagePanelPluginKey,\n editorView,\n (state) => {\n this.emit(\"update\", state);\n }\n );\n return this.view;\n },\n state: {\n init: () => {\n return {\n block: undefined,\n };\n },\n apply: (transaction) => {\n const block:\n | BlockFromConfig<DefaultBlockSchema[\"image\"], I, S>\n | undefined = transaction.getMeta(imagePanelPluginKey)?.block;\n\n return {\n block,\n };\n },\n },\n });\n }\n\n public onUpdate(callback: (state: ImagePanelState<I, S>) => void) {\n return this.on(\"update\", callback);\n }\n}\n","import { Plugin, PluginKey, PluginView } from \"prosemirror-state\";\nimport { Decoration, DecorationSet, EditorView } from \"prosemirror-view\";\nimport { nodeToBlock } from \"../../api/nodeConversions/nodeConversions\";\nimport { Block, DefaultBlockSchema } from \"../../blocks/defaultBlocks\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport {\n BlockFromConfigNoChildren,\n BlockSchemaWithBlock,\n InlineContentSchema,\n SpecificBlock,\n StyleSchema,\n} from \"../../schema\";\nimport { EventEmitter } from \"../../util/EventEmitter\";\nimport { getDraggableBlockFromCoords } from \"../SideMenu/SideMenuPlugin\";\n\nlet dragImageElement: HTMLElement | undefined;\n\nexport type TableHandlesState<\n I extends InlineContentSchema,\n S extends StyleSchema\n> = {\n show: boolean;\n referencePosCell: DOMRect;\n referencePosTable: DOMRect;\n\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], I, S>;\n colIndex: number;\n rowIndex: number;\n\n draggingState:\n | {\n draggedCellOrientation: \"row\" | \"col\";\n originalIndex: number;\n mousePos: number;\n }\n | undefined;\n};\n\nfunction setHiddenDragImage() {\n if (dragImageElement) {\n return;\n }\n\n dragImageElement = document.createElement(\"div\");\n dragImageElement.innerHTML = \"_\";\n dragImageElement.style.opacity = \"0\";\n dragImageElement.style.height = \"1px\";\n dragImageElement.style.width = \"1px\";\n document.body.appendChild(dragImageElement);\n}\n\nfunction unsetHiddenDragImage() {\n if (dragImageElement) {\n document.body.removeChild(dragImageElement);\n dragImageElement = undefined;\n }\n}\n\nfunction getChildIndex(node: Element) {\n return Array.prototype.indexOf.call(node.parentElement!.childNodes, node);\n}\n\n// Finds the DOM element corresponding to the table cell that the target element\n// is currently in. If the target element is not in a table cell, returns null.\nfunction domCellAround(target: Element | null): Element | null {\n while (target && target.nodeName !== \"TD\" && target.nodeName !== \"TH\") {\n target =\n target.classList && target.classList.contains(\"ProseMirror\")\n ? null\n : (target.parentNode as Element);\n }\n return target;\n}\n\n// Hides elements in the DOMwith the provided class names.\nfunction hideElementsWithClassNames(classNames: string[]) {\n classNames.forEach((className) => {\n const elementsToHide = document.getElementsByClassName(className);\n for (let i = 0; i < elementsToHide.length; i++) {\n (elementsToHide[i] as HTMLElement).style.visibility = \"hidden\";\n }\n });\n}\n\nexport class TableHandlesView<\n BSchema extends BlockSchemaWithBlock<\"table\", DefaultBlockSchema[\"table\"]>,\n I extends InlineContentSchema,\n S extends StyleSchema\n> implements PluginView\n{\n public state?: TableHandlesState<I, S>;\n public emitUpdate: () => void;\n\n public tableId: string | undefined;\n public tablePos: number | undefined;\n\n public menuFrozen = false;\n\n public prevWasEditable: boolean | null = null;\n\n constructor(\n private readonly editor: BlockNoteEditor<\n BlockSchemaWithBlock<\"table\", DefaultBlockSchema[\"table\"]>,\n I,\n S\n >,\n private readonly pmView: EditorView,\n emitUpdate: (state: TableHandlesState<I, S>) => void\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized image toolbar\");\n }\n\n emitUpdate(this.state);\n };\n\n pmView.dom.addEventListener(\"mousemove\", this.mouseMoveHandler);\n\n document.addEventListener(\"dragover\", this.dragOverHandler);\n document.addEventListener(\"drop\", this.dropHandler);\n\n document.addEventListener(\"scroll\", this.scrollHandler);\n }\n\n mouseMoveHandler = (event: MouseEvent) => {\n if (this.menuFrozen) {\n return;\n }\n\n const target = domCellAround(event.target as HTMLElement);\n\n if (!target || !this.editor.isEditable) {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n return;\n }\n\n const colIndex = getChildIndex(target);\n const rowIndex = getChildIndex(target.parentElement!);\n const cellRect = target.getBoundingClientRect();\n const tableRect =\n target.parentElement!.parentElement!.getBoundingClientRect();\n\n const blockEl = getDraggableBlockFromCoords(cellRect, this.pmView);\n if (!blockEl) {\n throw new Error(\n \"Found table cell element, but could not find surrounding blockContent element.\"\n );\n }\n this.tableId = blockEl.id;\n\n if (\n this.state !== undefined &&\n this.state.show &&\n this.tableId === blockEl.id &&\n this.state.rowIndex === rowIndex &&\n this.state.colIndex === colIndex\n ) {\n return;\n }\n\n let block: Block<any, any, any> | undefined = undefined;\n\n // Copied from `getBlock`. We don't use `getBlock` since we also need the PM\n // node for the table, so we would effectively be doing the same work twice.\n this.editor._tiptapEditor.state.doc.descendants((node, pos) => {\n if (typeof block !== \"undefined\") {\n return false;\n }\n\n if (node.type.name !== \"blockContainer\" || node.attrs.id !== blockEl.id) {\n return true;\n }\n\n block = nodeToBlock(\n node,\n this.editor.schema.blockSchema,\n this.editor.schema.inlineContentSchema,\n this.editor.schema.styleSchema,\n this.editor.blockCache\n );\n this.tablePos = pos + 1;\n\n return false;\n });\n\n this.state = {\n show: true,\n referencePosCell: cellRect,\n referencePosTable: tableRect,\n\n block: block! as SpecificBlock<BSchema, \"table\", I, S>,\n colIndex: colIndex,\n rowIndex: rowIndex,\n\n draggingState: undefined,\n };\n this.emitUpdate();\n\n return false;\n };\n\n dragOverHandler = (event: DragEvent) => {\n if (this.state?.draggingState === undefined) {\n return;\n }\n\n event.preventDefault();\n event.dataTransfer!.dropEffect = \"move\";\n\n hideElementsWithClassNames([\n \"column-resize-handle\",\n \"prosemirror-dropcursor-block\",\n \"prosemirror-dropcursor-inline\",\n ]);\n\n // The mouse cursor coordinates, bounded to the table's bounding box. The\n // bounding box is shrunk by 1px on each side to ensure that the bounded\n // coordinates are always inside a table cell.\n const boundedMouseCoords = {\n left: Math.min(\n Math.max(event.clientX, this.state.referencePosTable.left + 1),\n this.state.referencePosTable.right - 1\n ),\n top: Math.min(\n Math.max(event.clientY, this.state.referencePosTable.top + 1),\n this.state.referencePosTable.bottom - 1\n ),\n };\n\n // Gets the table cell element that the bounded mouse cursor coordinates lie\n // in.\n const tableCellElements = document\n .elementsFromPoint(boundedMouseCoords.left, boundedMouseCoords.top)\n .filter(\n (element) => element.tagName === \"TD\" || element.tagName === \"TH\"\n );\n if (tableCellElements.length === 0) {\n throw new Error(\n \"Could not find table cell element that the mouse cursor is hovering over.\"\n );\n }\n const tableCellElement = tableCellElements[0];\n\n let emitStateUpdate = false;\n\n // Gets current row and column index.\n const rowIndex = getChildIndex(tableCellElement.parentElement!);\n const colIndex = getChildIndex(tableCellElement);\n\n // Checks if the drop cursor needs to be updated. This affects decorations\n // only so it doesn't trigger a state update.\n const oldIndex =\n this.state.draggingState.draggedCellOrientation === \"row\"\n ? this.state.rowIndex\n : this.state.colIndex;\n const newIndex =\n this.state.draggingState.draggedCellOrientation === \"row\"\n ? rowIndex\n : colIndex;\n const dispatchDecorationsTransaction = newIndex !== oldIndex;\n\n // Checks if either the hovered cell has changed and updates the row and\n // column index. Also updates the reference DOMRect.\n if (this.state.rowIndex !== rowIndex || this.state.colIndex !== colIndex) {\n this.state.rowIndex = rowIndex;\n this.state.colIndex = colIndex;\n\n this.state.referencePosCell = tableCellElement.getBoundingClientRect();\n\n emitStateUpdate = true;\n }\n\n // Checks if the mouse cursor position along the axis that the user is\n // dragging on has changed and updates it.\n const mousePos =\n this.state.draggingState.draggedCellOrientation === \"row\"\n ? boundedMouseCoords.top\n : boundedMouseCoords.left;\n if (this.state.draggingState.mousePos !== mousePos) {\n this.state.draggingState.mousePos = mousePos;\n\n emitStateUpdate = true;\n }\n\n // Emits a state update if any of the fields have changed.\n if (emitStateUpdate) {\n this.emitUpdate();\n }\n\n // Dispatches a dummy transaction to force a decorations update if\n // necessary.\n if (dispatchDecorationsTransaction) {\n this.pmView.dispatch(\n this.pmView.state.tr.setMeta(tableHandlesPluginKey, true)\n );\n }\n };\n\n dropHandler = (event: DragEvent) => {\n if (this.state === undefined || this.state.draggingState === undefined) {\n return;\n }\n\n event.preventDefault();\n\n const rows = this.state.block.content.rows;\n\n if (this.state.draggingState.draggedCellOrientation === \"row\") {\n const rowToMove = rows[this.state.draggingState.originalIndex];\n rows.splice(this.state.draggingState.originalIndex, 1);\n rows.splice(this.state.rowIndex, 0, rowToMove);\n } else {\n const cellsToMove = rows.map(\n (row) => row.cells[this.state!.draggingState!.originalIndex]\n );\n rows.forEach((row, rowIndex) => {\n row.cells.splice(this.state!.draggingState!.originalIndex, 1);\n row.cells.splice(this.state!.colIndex, 0, cellsToMove[rowIndex]);\n });\n }\n\n this.editor.updateBlock(this.state.block, {\n type: \"table\",\n content: {\n type: \"tableContent\",\n rows: rows,\n },\n });\n };\n\n scrollHandler = () => {\n if (this.state?.show) {\n const tableElement = document.querySelector(\n `[data-node-type=\"blockContainer\"][data-id=\"${this.tableId}\"] table`\n )!;\n const cellElement = tableElement.querySelector(\n `tr:nth-child(${this.state.rowIndex + 1}) > td:nth-child(${\n this.state.colIndex + 1\n })`\n )!;\n\n this.state.referencePosTable = tableElement.getBoundingClientRect();\n this.state.referencePosCell = cellElement.getBoundingClientRect();\n this.emitUpdate();\n }\n };\n\n destroy() {\n this.pmView.dom.removeEventListener(\"mousedown\", this.mouseMoveHandler);\n\n document.removeEventListener(\"dragover\", this.dragOverHandler);\n document.removeEventListener(\"drop\", this.dropHandler);\n\n document.removeEventListener(\"scroll\", this.scrollHandler);\n }\n}\n\nexport const tableHandlesPluginKey = new PluginKey(\"TableHandlesPlugin\");\n\nexport class TableHandlesProsemirrorPlugin<\n I extends InlineContentSchema,\n S extends StyleSchema\n> extends EventEmitter<any> {\n private view:\n | TableHandlesView<\n BlockSchemaWithBlock<\"table\", DefaultBlockSchema[\"table\"]>,\n I,\n S\n >\n | undefined;\n public readonly plugin: Plugin;\n\n constructor(\n private readonly editor: BlockNoteEditor<\n BlockSchemaWithBlock<\"table\", DefaultBlockSchema[\"table\"]>,\n I,\n S\n >\n ) {\n super();\n this.plugin = new Plugin({\n key: tableHandlesPluginKey,\n view: (editorView) => {\n this.view = new TableHandlesView(editor, editorView, (state) => {\n this.emit(\"update\", state);\n });\n return this.view;\n },\n // We use decorations to render the drop cursor when dragging a table row\n // or column. The decorations are updated in the `dragOverHandler` method.\n props: {\n decorations: (state) => {\n if (\n this.view === undefined ||\n this.view.state === undefined ||\n this.view.state.draggingState === undefined ||\n this.view.tablePos === undefined\n ) {\n return;\n }\n\n const newIndex =\n this.view.state.draggingState.draggedCellOrientation === \"row\"\n ? this.view.state.rowIndex\n : this.view.state.colIndex;\n\n const decorations: Decoration[] = [];\n\n if (newIndex === this.view.state.draggingState.originalIndex) {\n return DecorationSet.create(state.doc, decorations);\n }\n\n // Gets the table to show the drop cursor in.\n const tableResolvedPos = state.doc.resolve(this.view.tablePos + 1);\n const tableNode = tableResolvedPos.node();\n\n if (this.view.state.draggingState.draggedCellOrientation === \"row\") {\n // Gets the row at the new index.\n const rowResolvedPos = state.doc.resolve(\n tableResolvedPos.posAtIndex(newIndex) + 1\n );\n const rowNode = rowResolvedPos.node();\n\n // Iterates over all cells in the row.\n for (let i = 0; i < rowNode.childCount; i++) {\n // Gets each cell in the row.\n const cellResolvedPos = state.doc.resolve(\n rowResolvedPos.posAtIndex(i) + 1\n );\n const cellNode = cellResolvedPos.node();\n\n // Creates a decoration at the start or end of each cell,\n // depending on whether the new index is before or after the\n // original index.\n const decorationPos =\n cellResolvedPos.pos +\n (newIndex > this.view.state.draggingState.originalIndex\n ? cellNode.nodeSize - 2\n : 0);\n decorations.push(\n // The widget is a small bar which spans the width of the cell.\n Decoration.widget(decorationPos, () => {\n const widget = document.createElement(\"div\");\n widget.className = \"bn-table-drop-cursor\";\n widget.style.left = \"0\";\n widget.style.right = \"0\";\n // This is only necessary because the drop indicator's height\n // is an even number of pixels, whereas the border between\n // table cells is an odd number of pixels. So this makes the\n // positioning slightly more consistent regardless of where\n // the row is being dropped.\n if (\n newIndex > this.view!.state!.draggingState!.originalIndex\n ) {\n widget.style.bottom = \"-2px\";\n } else {\n widget.style.top = \"-3px\";\n }\n widget.style.height = \"4px\";\n\n return widget;\n })\n );\n }\n } else {\n // Iterates over all rows in the table.\n for (let i = 0; i < tableNode.childCount; i++) {\n // Gets each row in the table.\n const rowResolvedPos = state.doc.resolve(\n tableResolvedPos.posAtIndex(i) + 1\n );\n\n // Gets the cell at the new index in the row.\n const cellResolvedPos = state.doc.resolve(\n rowResolvedPos.posAtIndex(newIndex) + 1\n );\n const cellNode = cellResolvedPos.node();\n\n // Creates a decoration at the start or end of each cell,\n // depending on whether the new index is before or after the\n // original index.\n const decorationPos =\n cellResolvedPos.pos +\n (newIndex > this.view.state.draggingState.originalIndex\n ? cellNode.nodeSize - 2\n : 0);\n decorations.push(\n // The widget is a small bar which spans the height of the cell.\n Decoration.widget(decorationPos, () => {\n const widget = document.createElement(\"div\");\n widget.className = \"bn-table-drop-cursor\";\n widget.style.top = \"0\";\n widget.style.bottom = \"0\";\n // This is only necessary because the drop indicator's width\n // is an even number of pixels, whereas the border between\n // table cells is an odd number of pixels. So this makes the\n // positioning slightly more consistent regardless of where\n // the column is being dropped.\n if (\n newIndex > this.view!.state!.draggingState!.originalIndex\n ) {\n widget.style.right = \"-2px\";\n } else {\n widget.style.left = \"-3px\";\n }\n widget.style.width = \"4px\";\n\n return widget;\n })\n );\n }\n }\n\n return DecorationSet.create(state.doc, decorations);\n },\n },\n });\n }\n\n public onUpdate(callback: (state: TableHandlesState<I, S>) => void) {\n return this.on(\"update\", callback);\n }\n\n /**\n * Callback that should be set on the `dragStart` event for whichever element\n * is used as the column drag handle.\n */\n colDragStart = (event: {\n dataTransfer: DataTransfer | null;\n clientX: number;\n }) => {\n if (this.view!.state === undefined) {\n throw new Error(\n \"Attempted to drag table column, but no table block was hovered prior.\"\n );\n }\n\n this.view!.state.draggingState = {\n draggedCellOrientation: \"col\",\n originalIndex: this.view!.state.colIndex,\n mousePos: event.clientX,\n };\n this.view!.emitUpdate();\n\n this.editor._tiptapEditor.view.dispatch(\n this.editor._tiptapEditor.state.tr.setMeta(tableHandlesPluginKey, {\n draggedCellOrientation:\n this.view!.state.draggingState.draggedCellOrientation,\n originalIndex: this.view!.state.colIndex,\n newIndex: this.view!.state.colIndex,\n tablePos: this.view!.tablePos,\n })\n );\n\n setHiddenDragImage();\n event.dataTransfer!.setDragImage(dragImageElement!, 0, 0);\n event.dataTransfer!.effectAllowed = \"move\";\n };\n\n /**\n * Callback that should be set on the `dragStart` event for whichever element\n * is used as the row drag handle.\n */\n rowDragStart = (event: {\n dataTransfer: DataTransfer | null;\n clientY: number;\n }) => {\n if (this.view!.state === undefined) {\n throw new Error(\n \"Attempted to drag table row, but no table block was hovered prior.\"\n );\n }\n\n this.view!.state.draggingState = {\n draggedCellOrientation: \"row\",\n originalIndex: this.view!.state.rowIndex,\n mousePos: event.clientY,\n };\n this.view!.emitUpdate();\n\n this.editor._tiptapEditor.view.dispatch(\n this.editor._tiptapEditor.state.tr.setMeta(tableHandlesPluginKey, {\n draggedCellOrientation:\n this.view!.state.draggingState.draggedCellOrientation,\n originalIndex: this.view!.state.rowIndex,\n newIndex: this.view!.state.rowIndex,\n tablePos: this.view!.tablePos,\n })\n );\n\n setHiddenDragImage();\n event.dataTransfer!.setDragImage(dragImageElement!, 0, 0);\n event.dataTransfer!.effectAllowed = \"copyMove\";\n };\n\n /**\n * Callback that should be set on the `dragEnd` event for both the element\n * used as the row drag handle, and the one used as the column drag handle.\n */\n dragEnd = () => {\n if (this.view!.state === undefined) {\n throw new Error(\n \"Attempted to drag table row, but no table block was hovered prior.\"\n );\n }\n\n this.view!.state.draggingState = undefined;\n this.view!.emitUpdate();\n\n this.editor._tiptapEditor.view.dispatch(\n this.editor._tiptapEditor.state.tr.setMeta(tableHandlesPluginKey, null)\n );\n\n unsetHiddenDragImage();\n };\n\n /**\n * Freezes the drag handles. When frozen, they will stay attached to the same\n * cell regardless of which cell is hovered by the mouse cursor.\n */\n freezeHandles = () => {\n this.view!.menuFrozen = true;\n };\n\n /**\n * Unfreezes the drag handles. When frozen, they will stay attached to the\n * same cell regardless of which cell is hovered by the mouse cursor.\n */\n unfreezeHandles = () => {\n this.view!.menuFrozen = false;\n };\n}\n","import { Extension } from \"@tiptap/core\";\nimport { NodeSelection, Plugin } from \"prosemirror-state\";\nimport { Node } from \"prosemirror-model\";\n\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../schema\";\nimport { createExternalHTMLExporter } from \"./html/externalHTMLExporter\";\nimport { createInternalHTMLSerializer } from \"./html/internalHTMLSerializer\";\nimport { cleanHTMLToMarkdown } from \"./markdown/markdownExporter\";\nimport { EditorView } from \"prosemirror-view\";\n\nfunction selectedFragmentToHTML<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n view: EditorView,\n editor: BlockNoteEditor<BSchema, I, S>\n): {\n internalHTML: string;\n externalHTML: string;\n plainText: string;\n} {\n const selectedFragment = view.state.selection.content().content;\n\n const internalHTMLSerializer = createInternalHTMLSerializer(\n view.state.schema,\n editor\n );\n const internalHTML =\n internalHTMLSerializer.serializeProseMirrorFragment(selectedFragment);\n\n const externalHTMLExporter = createExternalHTMLExporter(\n view.state.schema,\n editor\n );\n const externalHTML =\n externalHTMLExporter.exportProseMirrorFragment(selectedFragment);\n\n const plainText = cleanHTMLToMarkdown(externalHTML);\n\n return { internalHTML, externalHTML, plainText };\n}\n\nexport const createCopyToClipboardExtension = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n editor: BlockNoteEditor<BSchema, I, S>\n) =>\n Extension.create<{ editor: BlockNoteEditor<BSchema, I, S> }, undefined>({\n name: \"copyToClipboard\",\n addProseMirrorPlugins() {\n return [\n new Plugin({\n props: {\n handleDOMEvents: {\n copy(view, event) {\n // Stops the default browser copy behaviour.\n event.preventDefault();\n event.clipboardData!.clearData();\n\n // Checks if a `blockContent` node is being copied and expands\n // the selection to the parent `blockContainer` node. This is\n // for the use-case in which only a block without content is\n // selected, e.g. an image block.\n if (\n \"node\" in view.state.selection &&\n (view.state.selection.node as Node).type.spec.group ===\n \"blockContent\"\n ) {\n view.dispatch(\n view.state.tr.setSelection(\n new NodeSelection(\n view.state.doc.resolve(view.state.selection.from - 1)\n )\n )\n );\n }\n\n const { internalHTML, externalHTML, plainText } =\n selectedFragmentToHTML(view, editor);\n\n // TODO: Writing to other MIME types not working in Safari for\n // some reason.\n event.clipboardData!.setData(\"blocknote/html\", internalHTML);\n event.clipboardData!.setData(\"text/html\", externalHTML);\n event.clipboardData!.setData(\"text/plain\", plainText);\n\n // Prevent default PM handler to be called\n return true;\n },\n // This is for the use-case in which only a block without content\n // is selected, e.g. an image block, and dragged (not using the\n // drag handle).\n dragstart(view, event) {\n // Checks if a `NodeSelection` is active.\n if (!(\"node\" in view.state.selection)) {\n return;\n }\n\n // Checks if a `blockContent` node is being dragged.\n if (\n (view.state.selection.node as Node).type.spec.group !==\n \"blockContent\"\n ) {\n return;\n }\n\n // Expands the selection to the parent `blockContainer` node.\n view.dispatch(\n view.state.tr.setSelection(\n new NodeSelection(\n view.state.doc.resolve(view.state.selection.from - 1)\n )\n )\n );\n\n // Stops the default browser drag start behaviour.\n event.preventDefault();\n event.dataTransfer!.clearData();\n\n const { internalHTML, externalHTML, plainText } =\n selectedFragmentToHTML(view, editor);\n\n // TODO: Writing to other MIME types not working in Safari for\n // some reason.\n event.dataTransfer!.setData(\"blocknote/html\", internalHTML);\n event.dataTransfer!.setData(\"text/html\", externalHTML);\n event.dataTransfer!.setData(\"text/plain\", plainText);\n\n // Prevent default PM handler to be called\n return true;\n },\n },\n },\n }),\n ];\n },\n });\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin } from \"prosemirror-state\";\n\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../schema\";\nimport { nestedListsToBlockNoteStructure } from \"./html/util/nestedLists\";\n\nconst acceptedMIMETypes = [\n \"blocknote/html\",\n \"text/html\",\n \"text/plain\",\n] as const;\n\nexport const createPasteFromClipboardExtension = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n editor: BlockNoteEditor<BSchema, I, S>\n) =>\n Extension.create<{ editor: BlockNoteEditor<BSchema, I, S> }, undefined>({\n name: \"pasteFromClipboard\",\n addProseMirrorPlugins() {\n return [\n new Plugin({\n props: {\n handleDOMEvents: {\n paste(_view, event) {\n event.preventDefault();\n let format: (typeof acceptedMIMETypes)[number] | null = null;\n\n for (const mimeType of acceptedMIMETypes) {\n if (event.clipboardData!.types.includes(mimeType)) {\n format = mimeType;\n break;\n }\n }\n\n if (format !== null) {\n let data = event.clipboardData!.getData(format);\n if (format === \"text/html\") {\n const htmlNode = nestedListsToBlockNoteStructure(\n data.trim()\n );\n\n data = htmlNode.innerHTML;\n }\n editor._tiptapEditor.view.pasteHTML(data);\n }\n\n return true;\n },\n },\n },\n }),\n ];\n },\n });\n","import { Extension } from \"@tiptap/core\";\nimport { defaultProps } from \"../../blocks/defaultProps\";\n\nexport const BackgroundColorExtension = Extension.create({\n name: \"blockBackgroundColor\",\n\n addGlobalAttributes() {\n return [\n {\n types: [\"blockContainer\"],\n attributes: {\n backgroundColor: {\n default: defaultProps.backgroundColor.default,\n parseHTML: (element) =>\n element.hasAttribute(\"data-background-color\")\n ? element.getAttribute(\"data-background-color\")\n : defaultProps.backgroundColor.default,\n renderHTML: (attributes) =>\n attributes.backgroundColor !==\n defaultProps.backgroundColor.default && {\n \"data-background-color\": attributes.backgroundColor,\n },\n },\n },\n },\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet } from \"prosemirror-view\";\n\nconst PLUGIN_KEY = new PluginKey(`blocknote-placeholder`);\n\n/**\n * This is a modified version of the tiptap\n * placeholder plugin, that also sets hasAnchorClass\n *\n * It does not set a data-placeholder (text is currently done in css)\n *\n */\nexport interface PlaceholderOptions {\n placeholders: Record<string | \"default\", string>;\n}\n\nexport const Placeholder = Extension.create<PlaceholderOptions>({\n name: \"placeholder\",\n\n addOptions() {\n return {\n placeholders: {\n default: \"Enter text or type '/' for commands\",\n heading: \"Heading\",\n bulletListItem: \"List\",\n numberedListItem: \"List\",\n },\n };\n },\n\n addProseMirrorPlugins() {\n const placeholders = this.options.placeholders;\n return [\n new Plugin({\n key: PLUGIN_KEY,\n view: () => {\n const styleEl = document.createElement(\"style\");\n document.head.appendChild(styleEl);\n const styleSheet = styleEl.sheet!;\n\n const getBaseSelector = (additionalSelectors = \"\") =>\n `.bn-block-content${additionalSelectors} .bn-inline-content:has(> .ProseMirror-trailingBreak):before`;\n\n const getSelector = (\n blockType: string | \"default\",\n mustBeFocused = true\n ) => {\n const mustBeFocusedSelector = mustBeFocused\n ? `[data-is-empty-and-focused]`\n : ``;\n\n if (blockType === \"default\") {\n return getBaseSelector(mustBeFocusedSelector);\n }\n\n const blockTypeSelector = `[data-content-type=\"${blockType}\"]`;\n return getBaseSelector(mustBeFocusedSelector + blockTypeSelector);\n };\n\n for (const [blockType, placeholder] of Object.entries(placeholders)) {\n const mustBeFocused = blockType === \"default\";\n\n styleSheet.insertRule(\n `${getSelector(\n blockType,\n mustBeFocused\n )}{ content: ${JSON.stringify(placeholder)}; }`\n );\n\n // For some reason, the placeholders which show when the block is focused\n // take priority over ones which show depending on block type, so we need\n // to make sure the block specific ones are also used when the block is\n // focused.\n if (!mustBeFocused) {\n styleSheet.insertRule(\n `${getSelector(blockType, true)}{ content: ${JSON.stringify(\n placeholder\n )}; }`\n );\n }\n }\n\n return {\n destroy: () => {\n document.head.removeChild(styleEl);\n },\n };\n },\n props: {\n // TODO: maybe also add placeholder for empty document (\"e.g.: start writing..\")\n decorations: (state) => {\n const { doc, selection } = state;\n\n const active = this.editor.isEditable;\n\n if (!active) {\n return;\n }\n\n if (!selection.empty) {\n return;\n }\n\n const $pos = selection.$anchor;\n const node = $pos.parent;\n\n if (node.content.size > 0) {\n return null;\n }\n\n const before = $pos.before();\n\n const dec = Decoration.node(before, before + node.nodeSize, {\n \"data-is-empty-and-focused\": \"true\",\n });\n\n return DecorationSet.create(doc, [dec]);\n },\n },\n }),\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\n\nexport const TextAlignmentExtension = Extension.create({\n name: \"textAlignment\",\n\n addGlobalAttributes() {\n return [\n {\n // Attribute is applied to block content instead of container so that child blocks don't inherit the text\n // alignment styling.\n types: [\"paragraph\", \"heading\", \"bulletListItem\", \"numberedListItem\"],\n attributes: {\n textAlignment: {\n default: \"left\",\n parseHTML: (element) => {\n return element.getAttribute(\"data-text-alignment\");\n },\n renderHTML: (attributes) =>\n attributes.textAlignment !== \"left\" && {\n \"data-text-alignment\": attributes.textAlignment,\n },\n },\n },\n },\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { defaultProps } from \"../../blocks/defaultProps\";\n\nexport const TextColorExtension = Extension.create({\n name: \"blockTextColor\",\n\n addGlobalAttributes() {\n return [\n {\n types: [\"blockContainer\"],\n attributes: {\n textColor: {\n default: defaultProps.textColor.default,\n parseHTML: (element) =>\n element.hasAttribute(\"data-text-color\")\n ? element.getAttribute(\"data-text-color\")\n : defaultProps.textColor.default,\n renderHTML: (attributes) =>\n attributes.textColor !== defaultProps.textColor.default && {\n \"data-text-color\": attributes.textColor,\n },\n },\n },\n },\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\n\n// based on https://github.com/ueberdosis/tiptap/blob/40a9404c94c7fef7900610c195536384781ae101/demos/src/Experiments/TrailingNode/Vue/trailing-node.ts\n\n/**\n * Extension based on:\n * - https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap-extensions/src/extensions/TrailingNode.js\n * - https://github.com/remirror/remirror/blob/e0f1bec4a1e8073ce8f5500d62193e52321155b9/packages/prosemirror-trailing-node/src/trailing-node-plugin.ts\n */\n\nexport interface TrailingNodeOptions {\n node: string;\n}\n\n/**\n * Add a trailing node to the document so the user can always click at the bottom of the document and start typing\n */\nexport const TrailingNode = Extension.create<TrailingNodeOptions>({\n name: \"trailingNode\",\n\n addProseMirrorPlugins() {\n const plugin = new PluginKey(this.name);\n // const disabledNodes = Object.entries(this.editor.schema.nodes)\n // .map(([, value]) => value)\n // .filter((node) => this.options.notAfter.includes(node.name));\n\n return [\n new Plugin({\n key: plugin,\n appendTransaction: (_, __, state) => {\n const { doc, tr, schema } = state;\n const shouldInsertNodeAtEnd = plugin.getState(state);\n const endPosition = doc.content.size - 2;\n const type = schema.nodes[\"blockContainer\"];\n const contentType = schema.nodes[\"paragraph\"];\n if (!shouldInsertNodeAtEnd) {\n return;\n }\n\n return tr.insert(\n endPosition,\n type.create(undefined, contentType.create())\n );\n },\n state: {\n init: (_, _state) => {\n // (maybe fix): use same logic as apply() here\n // so it works when initializing\n },\n apply: (tr, value) => {\n if (!tr.docChanged) {\n return value;\n }\n\n let lastNode = tr.doc.lastChild;\n\n if (!lastNode || lastNode.type.name !== \"blockGroup\") {\n throw new Error(\"Expected blockGroup\");\n }\n\n lastNode = lastNode.lastChild;\n\n if (!lastNode || lastNode.type.name !== \"blockContainer\") {\n throw new Error(\"Expected blockContainer\");\n }\n\n const lastContentNode = lastNode.firstChild;\n\n if (!lastContentNode) {\n throw new Error(\"Expected blockContent\");\n }\n\n // If last node is not empty (size > 4) or it doesn't contain\n // inline content, we need to add a trailing node.\n return (\n lastNode.nodeSize > 4 ||\n lastContentNode.type.spec.content !== \"inline*\"\n );\n },\n },\n }),\n ];\n },\n});\n","import { Plugin, PluginKey } from \"prosemirror-state\";\n\nconst PLUGIN_KEY = new PluginKey(\"non-editable-block\");\n// Prevent typing for blocks without inline content, as this would otherwise\n// convert them into paragraph blocks.\nexport const NonEditableBlockPlugin = () => {\n return new Plugin({\n key: PLUGIN_KEY,\n props: {\n handleKeyDown: (view, event) => {\n // Checks for node selection\n if (\"node\" in view.state.selection) {\n // Checks if key input will insert a character - we want to block this\n // as it will convert the block into a paragraph.\n if (\n event.key.length === 1 &&\n !event.ctrlKey &&\n !event.altKey &&\n !event.metaKey &&\n !event.shiftKey\n ) {\n event.preventDefault();\n }\n }\n },\n },\n });\n};\n","import { findChildren } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet } from \"prosemirror-view\";\n\nconst PLUGIN_KEY = new PluginKey(`previous-blocks`);\n\nconst nodeAttributes: Record<string, string> = {\n // Numbered List Items\n index: \"index\",\n // Headings\n level: \"level\",\n // All Blocks\n type: \"type\",\n depth: \"depth\",\n \"depth-change\": \"depth-change\",\n};\n\n/**\n * This plugin tracks transformation of Block node attributes, so we can support CSS transitions.\n *\n * Problem it solves: ProseMirror recreates the DOM when transactions happen. So when a transaction changes a Node attribute,\n * it results in a completely new DOM element. This means CSS transitions don't work.\n *\n * Solution: When attributes change on a node, this plugin sets a data-* attribute with the \"previous\" value. This way we can still use CSS transitions. (See block.module.css)\n */\nexport const PreviousBlockTypePlugin = () => {\n let timeout: any;\n return new Plugin({\n key: PLUGIN_KEY,\n view(_editorView) {\n return {\n update: async (view, _prevState) => {\n if (this.key?.getState(view.state).updatedBlocks.size > 0) {\n // use setTimeout 0 to clear the decorations so that at least\n // for one DOM-render the decorations have been applied\n timeout = setTimeout(() => {\n view.dispatch(\n view.state.tr.setMeta(PLUGIN_KEY, { clearUpdate: true })\n );\n }, 0);\n }\n },\n destroy: () => {\n if (timeout) {\n clearTimeout(timeout);\n }\n },\n };\n },\n state: {\n init() {\n return {\n // Block attributes, by block ID, from just before the previous transaction.\n prevTransactionOldBlockAttrs: {} as any,\n // Block attributes, by block ID, from just before the current transaction.\n currentTransactionOldBlockAttrs: {} as any,\n // Set of IDs of blocks whose attributes changed from the current transaction.\n updatedBlocks: new Set<string>(),\n };\n },\n\n apply(transaction, prev, oldState, newState) {\n prev.currentTransactionOldBlockAttrs = {};\n prev.updatedBlocks.clear();\n\n if (!transaction.docChanged || oldState.doc.eq(newState.doc)) {\n return prev;\n }\n\n // TODO: Instead of iterating through the entire document, only check nodes affected by the transactions. Will\n // also probably require checking nodes affected by the previous transaction too.\n // We didn't get this to work yet:\n // const transform = combineTransactionSteps(oldState.doc, [transaction]);\n // // const { mapping } = transform;\n // const changes = getChangedRanges(transform);\n //\n // changes.forEach(({ oldRange, newRange }) => {\n // const oldNodes = findChildrenInRange(\n // oldState.doc,\n // oldRange,\n // (node) => node.attrs.id\n // );\n //\n // const newNodes = findChildrenInRange(\n // newState.doc,\n // newRange,\n // (node) => node.attrs.id\n // );\n\n const currentTransactionOriginalOldBlockAttrs = {} as any;\n\n const oldNodes = findChildren(oldState.doc, (node) => node.attrs.id);\n const oldNodesById = new Map(\n oldNodes.map((node) => [node.node.attrs.id, node])\n );\n const newNodes = findChildren(newState.doc, (node) => node.attrs.id);\n\n // Traverses all block containers in the new editor state.\n for (const node of newNodes) {\n const oldNode = oldNodesById.get(node.node.attrs.id);\n\n const oldContentNode = oldNode?.node.firstChild;\n const newContentNode = node.node.firstChild;\n\n if (oldNode && oldContentNode && newContentNode) {\n const newAttrs = {\n index: newContentNode.attrs.index,\n level: newContentNode.attrs.level,\n type: newContentNode.type.name,\n depth: newState.doc.resolve(node.pos).depth,\n };\n\n let oldAttrs = {\n index: oldContentNode.attrs.index,\n level: oldContentNode.attrs.level,\n type: oldContentNode.type.name,\n depth: oldState.doc.resolve(oldNode.pos).depth,\n };\n\n currentTransactionOriginalOldBlockAttrs[node.node.attrs.id] =\n oldAttrs;\n\n // Whenever a transaction is appended by the OrderedListItemIndexPlugin, it's given the metadata:\n // { \"orderedListIndexing\": true }\n // These appended transactions happen immediately after any transaction which causes ordered list item\n // indices to require updating, including those which trigger animations. Therefore, these animations are\n // immediately overridden when the PreviousBlockTypePlugin processes the appended transaction, despite only\n // the listItemIndex attribute changing. To solve this, oldAttrs must be edited for transactions with the\n // \"orderedListIndexing\" metadata, so the correct animation can be re-triggered.\n if (transaction.getMeta(\"numberedListIndexing\")) {\n // If the block existed before the transaction, gets the attributes from before the previous transaction\n // (i.e. the transaction that caused list item indices to need updating).\n if (node.node.attrs.id in prev.prevTransactionOldBlockAttrs) {\n oldAttrs =\n prev.prevTransactionOldBlockAttrs[node.node.attrs.id];\n }\n\n // Stops list item indices themselves being animated (looks smoother), unless the block's content type is\n // changing from a numbered list item to something else.\n if (newAttrs.type === \"numberedListItem\") {\n oldAttrs.index = newAttrs.index;\n }\n }\n\n prev.currentTransactionOldBlockAttrs[node.node.attrs.id] = oldAttrs;\n\n // TODO: faster deep equal?\n if (JSON.stringify(oldAttrs) !== JSON.stringify(newAttrs)) {\n (oldAttrs as any)[\"depth-change\"] =\n oldAttrs.depth - newAttrs.depth;\n\n // for debugging:\n // console.log(\n // \"id:\",\n // node.node.attrs.id,\n // \"previousBlockTypePlugin changes detected, oldAttrs\",\n // oldAttrs,\n // \"new\",\n // newAttrs\n // );\n\n prev.updatedBlocks.add(node.node.attrs.id);\n }\n }\n }\n\n prev.prevTransactionOldBlockAttrs =\n currentTransactionOriginalOldBlockAttrs;\n\n return prev;\n },\n },\n props: {\n decorations(state) {\n const pluginState = (this as Plugin).getState(state);\n if (pluginState.updatedBlocks.size === 0) {\n return undefined;\n }\n\n const decorations: Decoration[] = [];\n\n state.doc.descendants((node, pos) => {\n if (!node.attrs.id) {\n return;\n }\n\n if (!pluginState.updatedBlocks.has(node.attrs.id)) {\n return;\n }\n\n const prevAttrs =\n pluginState.currentTransactionOldBlockAttrs[node.attrs.id];\n const decorationAttrs: any = {};\n\n for (const [nodeAttr, val] of Object.entries(prevAttrs)) {\n decorationAttrs[\"data-prev-\" + nodeAttributes[nodeAttr]] =\n val || \"none\";\n }\n\n // for debugging:\n // console.log(\n // \"previousBlockTypePlugin committing decorations\",\n // decorationAttrs\n // );\n\n const decoration = Decoration.node(pos, pos + node.nodeSize, {\n ...decorationAttrs,\n });\n\n decorations.push(decoration);\n });\n\n return DecorationSet.create(state.doc, decorations);\n },\n },\n });\n};\n","import { Node } from \"@tiptap/core\";\nimport { Fragment, Node as PMNode, Slice } from \"prosemirror-model\";\nimport { NodeSelection, TextSelection } from \"prosemirror-state\";\n\nimport { getBlockInfoFromPos } from \"../api/getBlockInfoFromPos\";\nimport {\n blockToNode,\n inlineContentToNodes,\n tableContentToNodes,\n} from \"../api/nodeConversions/nodeConversions\";\nimport { PartialBlock } from \"../blocks/defaultBlocks\";\nimport type { BlockNoteEditor } from \"../editor/BlockNoteEditor\";\nimport { NonEditableBlockPlugin } from \"../extensions/NonEditableBlocks/NonEditableBlockPlugin\";\nimport { PreviousBlockTypePlugin } from \"../extensions/PreviousBlockType/PreviousBlockTypePlugin\";\nimport {\n BlockNoteDOMAttributes,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../schema\";\nimport { mergeCSSClasses } from \"../util/browser\";\nimport { UnreachableCaseError } from \"../util/typescript\";\n\n// Object containing all possible block attributes.\nconst BlockAttributes: Record<string, string> = {\n blockColor: \"data-block-color\",\n blockStyle: \"data-block-style\",\n id: \"data-id\",\n depth: \"data-depth\",\n depthChange: \"data-depth-change\",\n};\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n block: {\n BNCreateBlock: (pos: number) => ReturnType;\n BNDeleteBlock: (posInBlock: number) => ReturnType;\n BNMergeBlocks: (posBetweenBlocks: number) => ReturnType;\n BNSplitBlock: (posInBlock: number, keepType: boolean) => ReturnType;\n BNUpdateBlock: <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n >(\n posInBlock: number,\n block: PartialBlock<BSchema, I, S>\n ) => ReturnType;\n BNCreateOrUpdateBlock: <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n >(\n posInBlock: number,\n block: PartialBlock<BSchema, I, S>\n ) => ReturnType;\n };\n }\n}\n\n/**\n * The main \"Block node\" documents consist of\n */\nexport const BlockContainer = Node.create<{\n domAttributes?: BlockNoteDOMAttributes;\n editor: BlockNoteEditor<BlockSchema, InlineContentSchema, StyleSchema>;\n}>({\n name: \"blockContainer\",\n group: \"blockContainer\",\n // A block always contains content, and optionally a blockGroup which contains nested blocks\n content: \"blockContent blockGroup?\",\n // Ensures content-specific keyboard handlers trigger first.\n priority: 50,\n defining: true,\n\n parseHTML() {\n return [\n {\n tag: \"div\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const attrs: Record<string, string> = {};\n for (const [nodeAttr, HTMLAttr] of Object.entries(BlockAttributes)) {\n if (element.getAttribute(HTMLAttr)) {\n attrs[nodeAttr] = element.getAttribute(HTMLAttr)!;\n }\n }\n\n if (element.getAttribute(\"data-node-type\") === \"blockContainer\") {\n return attrs;\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n const blockOuter = document.createElement(\"div\");\n blockOuter.className = \"bn-block-outer\";\n blockOuter.setAttribute(\"data-node-type\", \"blockOuter\");\n for (const [attribute, value] of Object.entries(HTMLAttributes)) {\n if (attribute !== \"class\") {\n blockOuter.setAttribute(attribute, value);\n }\n }\n\n const blockHTMLAttributes = {\n ...(this.options.domAttributes?.block || {}),\n ...HTMLAttributes,\n };\n const block = document.createElement(\"div\");\n block.className = mergeCSSClasses(\"bn-block\", blockHTMLAttributes.class);\n block.setAttribute(\"data-node-type\", this.name);\n for (const [attribute, value] of Object.entries(blockHTMLAttributes)) {\n if (attribute !== \"class\") {\n block.setAttribute(attribute, value);\n }\n }\n\n blockOuter.appendChild(block);\n\n return {\n dom: blockOuter,\n contentDOM: block,\n };\n },\n\n addCommands() {\n return {\n // Creates a new text block at a given position.\n BNCreateBlock:\n (pos) =>\n ({ state, dispatch }) => {\n const newBlock =\n state.schema.nodes[\"blockContainer\"].createAndFill()!;\n\n if (dispatch) {\n state.tr.insert(pos, newBlock);\n }\n\n return true;\n },\n // Deletes a block at a given position.\n BNDeleteBlock:\n (posInBlock) =>\n ({ state, dispatch }) => {\n const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);\n if (blockInfo === undefined) {\n return false;\n }\n\n const { startPos, endPos } = blockInfo;\n\n if (dispatch) {\n state.tr.deleteRange(startPos, endPos);\n }\n\n return true;\n },\n // Updates a block at a given position.\n BNUpdateBlock:\n (posInBlock, block) =>\n ({ state, dispatch }) => {\n const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);\n if (blockInfo === undefined) {\n return false;\n }\n\n const { startPos, endPos, node, contentNode } = blockInfo;\n\n if (dispatch) {\n // Adds blockGroup node with child blocks if necessary.\n if (block.children !== undefined) {\n const childNodes = [];\n\n // Creates ProseMirror nodes for each child block, including their descendants.\n for (const child of block.children) {\n childNodes.push(\n blockToNode(\n child,\n state.schema,\n this.options.editor.schema.styleSchema\n )\n );\n }\n\n // Checks if a blockGroup node already exists.\n if (node.childCount === 2) {\n // Replaces all child nodes in the existing blockGroup with the ones created earlier.\n state.tr.replace(\n startPos + contentNode.nodeSize + 1,\n endPos - 1,\n new Slice(Fragment.from(childNodes), 0, 0)\n );\n } else {\n // Inserts a new blockGroup containing the child nodes created earlier.\n state.tr.insert(\n startPos + contentNode.nodeSize,\n state.schema.nodes[\"blockGroup\"].create({}, childNodes)\n );\n }\n }\n\n const oldType = contentNode.type.name;\n const newType = block.type || oldType;\n\n // The code below determines the new content of the block.\n // or \"keep\" to keep as-is\n let content: PMNode[] | \"keep\" = \"keep\";\n\n // Has there been any custom content provided?\n if (block.content) {\n if (typeof block.content === \"string\") {\n // Adds a single text node with no marks to the content.\n content = [state.schema.text(block.content)];\n } else if (Array.isArray(block.content)) {\n // Adds a text node with the provided styles converted into marks to the content,\n // for each InlineContent object.\n content = inlineContentToNodes(\n block.content,\n state.schema,\n this.options.editor.schema.styleSchema\n );\n } else if (block.content.type === \"tableContent\") {\n content = tableContentToNodes(\n block.content,\n state.schema,\n this.options.editor.schema.styleSchema\n );\n } else {\n throw new UnreachableCaseError(block.content.type);\n }\n } else {\n // no custom content has been provided, use existing content IF possible\n\n // Since some block types contain inline content and others don't,\n // we either need to call setNodeMarkup to just update type &\n // attributes, or replaceWith to replace the whole blockContent.\n const oldContentType = state.schema.nodes[oldType].spec.content;\n const newContentType = state.schema.nodes[newType].spec.content;\n\n if (oldContentType === \"\") {\n // keep old content, because it's empty anyway and should be compatible with\n // any newContentType\n } else if (newContentType !== oldContentType) {\n // the content type changed, replace the previous content\n content = [];\n } else {\n // keep old content, because the content type is the same and should be compatible\n }\n }\n\n // Now, changes the blockContent node type and adds the provided props\n // as attributes. Also preserves all existing attributes that are\n // compatible with the new type.\n //\n // Use either setNodeMarkup or replaceWith depending on whether the\n // content is being replaced or not.\n if (content === \"keep\") {\n // use setNodeMarkup to only update the type and attributes\n state.tr.setNodeMarkup(\n startPos,\n block.type === undefined\n ? undefined\n : state.schema.nodes[block.type],\n {\n ...contentNode.attrs,\n ...block.props,\n }\n );\n } else {\n // use replaceWith to replace the content and the block itself\n // also reset the selection since replacing the block content\n // sets it to the next block.\n state.tr\n .replaceWith(\n startPos,\n endPos,\n state.schema.nodes[newType].create(\n {\n ...contentNode.attrs,\n ...block.props,\n },\n content\n )\n )\n // If the node doesn't contain editable content, we want to\n // select the whole node. But if it does have editable content,\n // we want to set the selection to the start of it.\n .setSelection(\n state.schema.nodes[newType].spec.content === \"\"\n ? new NodeSelection(state.tr.doc.resolve(startPos))\n : state.schema.nodes[newType].spec.content === \"inline*\"\n ? new TextSelection(state.tr.doc.resolve(startPos))\n : // Need to offset the position as we have to get through the\n // `tableRow` and `tableCell` nodes to get to the\n // `tableParagraph` node we want to set the selection in.\n new TextSelection(state.tr.doc.resolve(startPos + 4))\n );\n }\n\n // Adds all provided props as attributes to the parent blockContainer node too, and also preserves existing\n // attributes.\n state.tr.setNodeMarkup(startPos - 1, undefined, {\n ...node.attrs,\n ...block.props,\n });\n }\n\n return true;\n },\n // Appends the text contents of a block to the nearest previous block, given a position between them. Children of\n // the merged block are moved out of it first, rather than also being merged.\n //\n // In the example below, the position passed into the function is between Block1 and Block2.\n //\n // Block1\n // Block2\n // Block3\n // Block4\n // Block5\n //\n // Becomes:\n //\n // Block1\n // Block2Block3\n // Block4\n // Block5\n BNMergeBlocks:\n (posBetweenBlocks) =>\n ({ state, dispatch }) => {\n const nextNodeIsBlock =\n state.doc.resolve(posBetweenBlocks + 1).node().type.name ===\n \"blockContainer\";\n const prevNodeIsBlock =\n state.doc.resolve(posBetweenBlocks - 1).node().type.name ===\n \"blockContainer\";\n\n if (!nextNodeIsBlock || !prevNodeIsBlock) {\n return false;\n }\n\n const nextBlockInfo = getBlockInfoFromPos(\n state.doc,\n posBetweenBlocks + 1\n );\n\n const { node, contentNode, startPos, endPos, depth } = nextBlockInfo!;\n\n // Removes a level of nesting all children of the next block by 1 level, if it contains both content and block\n // group nodes.\n if (node.childCount === 2) {\n const childBlocksStart = state.doc.resolve(\n startPos + contentNode.nodeSize + 1\n );\n const childBlocksEnd = state.doc.resolve(endPos - 1);\n const childBlocksRange =\n childBlocksStart.blockRange(childBlocksEnd);\n\n // Moves the block group node inside the block into the block group node that the current block is in.\n if (dispatch) {\n state.tr.lift(childBlocksRange!, depth - 1);\n }\n }\n\n let prevBlockEndPos = posBetweenBlocks - 1;\n let prevBlockInfo = getBlockInfoFromPos(state.doc, prevBlockEndPos);\n\n // Finds the nearest previous block, regardless of nesting level.\n while (prevBlockInfo!.numChildBlocks > 0) {\n prevBlockEndPos--;\n prevBlockInfo = getBlockInfoFromPos(state.doc, prevBlockEndPos);\n if (prevBlockInfo === undefined) {\n return false;\n }\n }\n\n // Deletes next block and adds its text content to the nearest previous block.\n\n if (dispatch) {\n dispatch(\n state.tr\n .deleteRange(startPos, startPos + contentNode.nodeSize)\n .replace(\n prevBlockEndPos - 1,\n startPos,\n new Slice(contentNode.content, 0, 0)\n )\n .scrollIntoView()\n );\n\n state.tr.setSelection(\n new TextSelection(state.doc.resolve(prevBlockEndPos - 1))\n );\n }\n\n return true;\n },\n // Splits a block at a given position. Content after the position is moved to a new block below, at the same\n // nesting level.\n BNSplitBlock:\n (posInBlock, keepType) =>\n ({ state, dispatch }) => {\n const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);\n if (blockInfo === undefined) {\n return false;\n }\n\n const { contentNode, contentType, startPos, endPos, depth } =\n blockInfo;\n\n const originalBlockContent = state.doc.cut(startPos + 1, posInBlock);\n const newBlockContent = state.doc.cut(posInBlock, endPos - 1);\n\n const newBlock =\n state.schema.nodes[\"blockContainer\"].createAndFill()!;\n\n const newBlockInsertionPos = endPos + 1;\n const newBlockContentPos = newBlockInsertionPos + 2;\n\n if (dispatch) {\n // Creates a new block. Since the schema requires it to have a content node, a paragraph node is created\n // automatically, spanning newBlockContentPos to newBlockContentPos + 1.\n state.tr.insert(newBlockInsertionPos, newBlock);\n\n // Replaces the content of the newly created block's content node. Doesn't replace the whole content node so\n // its type doesn't change.\n state.tr.replace(\n newBlockContentPos,\n newBlockContentPos + 1,\n newBlockContent.content.size > 0\n ? new Slice(\n Fragment.from(newBlockContent),\n depth + 2,\n depth + 2\n )\n : undefined\n );\n\n // Changes the type of the content node. The range doesn't matter as long as both from and to positions are\n // within the content node.\n if (keepType) {\n state.tr.setBlockType(\n newBlockContentPos,\n newBlockContentPos,\n state.schema.node(contentType).type,\n contentNode.attrs\n );\n }\n\n // Sets the selection to the start of the new block's content node.\n state.tr.setSelection(\n new TextSelection(state.doc.resolve(newBlockContentPos))\n );\n\n // Replaces the content of the original block's content node. Doesn't replace the whole content node so its\n // type doesn't change.\n state.tr.replace(\n startPos + 1,\n endPos - 1,\n originalBlockContent.content.size > 0\n ? new Slice(\n Fragment.from(originalBlockContent),\n depth + 2,\n depth + 2\n )\n : undefined\n );\n }\n\n return true;\n },\n };\n },\n\n addProseMirrorPlugins() {\n return [PreviousBlockTypePlugin(), NonEditableBlockPlugin()];\n },\n\n addKeyboardShortcuts() {\n // handleBackspace is partially adapted from https://github.com/ueberdosis/tiptap/blob/ed56337470efb4fd277128ab7ef792b37cfae992/packages/core/src/extensions/keymap.ts\n const handleBackspace = () =>\n this.editor.commands.first(({ commands }) => [\n // Deletes the selection if it's not empty.\n () => commands.deleteSelection(),\n // Undoes an input rule if one was triggered in the last editor state change.\n () => commands.undoInputRule(),\n // Reverts block content type to a paragraph if the selection is at the start of the block.\n () =>\n commands.command(({ state }) => {\n const { contentType, startPos } = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n )!;\n\n const selectionAtBlockStart = state.selection.from === startPos + 1;\n const isParagraph = contentType.name === \"paragraph\";\n\n if (selectionAtBlockStart && !isParagraph) {\n return commands.BNUpdateBlock(state.selection.from, {\n type: \"paragraph\",\n props: {},\n });\n }\n\n return false;\n }),\n // Removes a level of nesting if the block is indented if the selection is at the start of the block.\n () =>\n commands.command(({ state }) => {\n const { startPos } = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n )!;\n\n const selectionAtBlockStart = state.selection.from === startPos + 1;\n\n if (selectionAtBlockStart) {\n return commands.liftListItem(\"blockContainer\");\n }\n\n return false;\n }),\n // Merges block with the previous one if it isn't indented, isn't the first block in the doc, and the selection\n // is at the start of the block.\n () =>\n commands.command(({ state }) => {\n const { depth, startPos } = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n )!;\n\n const selectionAtBlockStart = state.selection.from === startPos + 1;\n const selectionEmpty = state.selection.empty;\n const blockAtDocStart = startPos === 2;\n\n const posBetweenBlocks = startPos - 1;\n\n if (\n !blockAtDocStart &&\n selectionAtBlockStart &&\n selectionEmpty &&\n depth === 2\n ) {\n return commands.BNMergeBlocks(posBetweenBlocks);\n }\n\n return false;\n }),\n ]);\n\n const handleDelete = () =>\n this.editor.commands.first(({ commands }) => [\n // Deletes the selection if it's not empty.\n () => commands.deleteSelection(),\n // Merges block with the next one (at the same nesting level or lower),\n // if one exists, the block has no children, and the selection is at the\n // end of the block.\n () =>\n commands.command(({ state }) => {\n const { node, depth, endPos } = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n )!;\n\n const blockAtDocEnd = endPos === state.doc.nodeSize - 4;\n const selectionAtBlockEnd = state.selection.from === endPos - 1;\n const selectionEmpty = state.selection.empty;\n const hasChildBlocks = node.childCount === 2;\n\n if (\n !blockAtDocEnd &&\n selectionAtBlockEnd &&\n selectionEmpty &&\n !hasChildBlocks\n ) {\n let oldDepth = depth;\n let newPos = endPos + 2;\n let newDepth = state.doc.resolve(newPos).depth;\n\n while (newDepth < oldDepth) {\n oldDepth = newDepth;\n newPos += 2;\n newDepth = state.doc.resolve(newPos).depth;\n }\n\n return commands.BNMergeBlocks(newPos - 1);\n }\n\n return false;\n }),\n ]);\n\n const handleEnter = () =>\n this.editor.commands.first(({ commands }) => [\n // Removes a level of nesting if the block is empty & indented, while the selection is also empty & at the start\n // of the block.\n () =>\n commands.command(({ state }) => {\n const { node, depth } = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n )!;\n\n const selectionAtBlockStart =\n state.selection.$anchor.parentOffset === 0;\n const selectionEmpty =\n state.selection.anchor === state.selection.head;\n const blockEmpty = node.textContent.length === 0;\n const blockIndented = depth > 2;\n\n if (\n selectionAtBlockStart &&\n selectionEmpty &&\n blockEmpty &&\n blockIndented\n ) {\n return commands.liftListItem(\"blockContainer\");\n }\n\n return false;\n }),\n // Creates a new block and moves the selection to it if the current one is empty, while the selection is also\n // empty & at the start of the block.\n () =>\n commands.command(({ state, chain }) => {\n const { node, endPos } = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n )!;\n\n const selectionAtBlockStart =\n state.selection.$anchor.parentOffset === 0;\n const selectionEmpty =\n state.selection.anchor === state.selection.head;\n const blockEmpty = node.textContent.length === 0;\n\n if (selectionAtBlockStart && selectionEmpty && blockEmpty) {\n const newBlockInsertionPos = endPos + 1;\n const newBlockContentPos = newBlockInsertionPos + 2;\n\n chain()\n .BNCreateBlock(newBlockInsertionPos)\n .setTextSelection(newBlockContentPos)\n .run();\n\n return true;\n }\n\n return false;\n }),\n // Splits the current block, moving content inside that's after the cursor to a new text block below. Also\n // deletes the selection beforehand, if it's not empty.\n () =>\n commands.command(({ state, chain }) => {\n const { node } = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n )!;\n\n const selectionAtBlockStart =\n state.selection.$anchor.parentOffset === 0;\n const blockEmpty = node.textContent.length === 0;\n\n if (!blockEmpty) {\n chain()\n .deleteSelection()\n .BNSplitBlock(state.selection.from, selectionAtBlockStart)\n .run();\n\n return true;\n }\n\n return false;\n }),\n ]);\n\n return {\n Backspace: handleBackspace,\n Delete: handleDelete,\n Enter: handleEnter,\n // Always returning true for tab key presses ensures they're not captured by the browser. Otherwise, they blur the\n // editor since the browser will try to use tab for keyboard navigation.\n Tab: () => {\n this.editor.commands.sinkListItem(\"blockContainer\");\n return true;\n },\n \"Shift-Tab\": () => {\n this.editor.commands.liftListItem(\"blockContainer\");\n return true;\n },\n };\n },\n});\n","import { Node } from \"@tiptap/core\";\nimport { BlockNoteDOMAttributes } from \"../schema\";\nimport { mergeCSSClasses } from \"../util/browser\";\n\nexport const BlockGroup = Node.create<{\n domAttributes?: BlockNoteDOMAttributes;\n}>({\n name: \"blockGroup\",\n group: \"blockGroup\",\n content: \"blockContainer+\",\n\n parseHTML() {\n return [\n {\n tag: \"div\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n if (element.getAttribute(\"data-node-type\") === \"blockGroup\") {\n // Null means the element matches, but we don't want to add any attributes to the node.\n return null;\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n const blockGroupHTMLAttributes = {\n ...(this.options.domAttributes?.blockGroup || {}),\n ...HTMLAttributes,\n };\n const blockGroup = document.createElement(\"div\");\n blockGroup.className = mergeCSSClasses(\n \"bn-block-group\",\n blockGroupHTMLAttributes.class\n );\n blockGroup.setAttribute(\"data-node-type\", \"blockGroup\");\n for (const [attribute, value] of Object.entries(blockGroupHTMLAttributes)) {\n if (attribute !== \"class\") {\n blockGroup.setAttribute(attribute, value);\n }\n }\n\n return {\n dom: blockGroup,\n contentDOM: blockGroup,\n };\n },\n});\n","import {Node} from \"@tiptap/core\";\n\nexport const Doc = Node.create({\n name: \"doc\",\n topNode: true,\n content: \"blockGroup\",\n});\n","import { Extensions, extensions } from \"@tiptap/core\";\n\nimport type { BlockNoteEditor } from \"./BlockNoteEditor\";\n\nimport Collaboration from \"@tiptap/extension-collaboration\";\nimport CollaborationCursor from \"@tiptap/extension-collaboration-cursor\";\nimport { Dropcursor } from \"@tiptap/extension-dropcursor\";\nimport { Gapcursor } from \"@tiptap/extension-gapcursor\";\nimport { HardBreak } from \"@tiptap/extension-hard-break\";\nimport { History } from \"@tiptap/extension-history\";\nimport { Link } from \"@tiptap/extension-link\";\nimport { Text } from \"@tiptap/extension-text\";\nimport * as Y from \"yjs\";\nimport { createCopyToClipboardExtension } from \"../api/exporters/copyExtension\";\nimport { createPasteFromClipboardExtension } from \"../api/parsers/pasteExtension\";\nimport { BackgroundColorExtension } from \"../extensions/BackgroundColor/BackgroundColorExtension\";\nimport { Placeholder } from \"../extensions/Placeholder/PlaceholderExtension\";\nimport { TextAlignmentExtension } from \"../extensions/TextAlignment/TextAlignmentExtension\";\nimport { TextColorExtension } from \"../extensions/TextColor/TextColorExtension\";\nimport { TrailingNode } from \"../extensions/TrailingNode/TrailingNodeExtension\";\nimport UniqueID from \"../extensions/UniqueID/UniqueID\";\nimport { BlockContainer, BlockGroup, Doc } from \"../pm-nodes\";\nimport {\n BlockNoteDOMAttributes,\n BlockSchema,\n BlockSpecs,\n InlineContentSchema,\n InlineContentSpecs,\n StyleSchema,\n StyleSpecs,\n} from \"../schema\";\n\n/**\n * Get all the Tiptap extensions BlockNote is configured with by default\n */\nexport const getBlockNoteExtensions = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(opts: {\n editor: BlockNoteEditor<BSchema, I, S>;\n placeholders?: Record<string | \"default\", string>;\n domAttributes: Partial<BlockNoteDOMAttributes>;\n blockSchema: BSchema;\n blockSpecs: BlockSpecs;\n inlineContentSpecs: InlineContentSpecs;\n styleSpecs: StyleSpecs;\n collaboration?: {\n fragment: Y.XmlFragment;\n user: {\n name: string;\n color: string;\n };\n provider: any;\n renderCursor?: (user: any) => HTMLElement;\n };\n}) => {\n const ret: Extensions = [\n extensions.ClipboardTextSerializer,\n extensions.Commands,\n extensions.Editable,\n extensions.FocusEvents,\n extensions.Tabindex,\n\n // DevTools,\n Gapcursor,\n\n // DropCursor,\n Placeholder.configure({\n // TODO: This shorthand is kind of ugly\n ...(opts.placeholders !== undefined\n ? { placeholders: opts.placeholders }\n : {}),\n }),\n UniqueID.configure({\n types: [\"blockContainer\"],\n }),\n HardBreak,\n // Comments,\n\n // basics:\n Text,\n\n // marks:\n Link,\n ...Object.values(opts.styleSpecs).map((styleSpec) => {\n return styleSpec.implementation.mark;\n }),\n\n TextColorExtension,\n\n BackgroundColorExtension,\n TextAlignmentExtension,\n\n // nodes\n Doc,\n BlockContainer.configure({\n editor: opts.editor as any,\n domAttributes: opts.domAttributes,\n }),\n BlockGroup.configure({\n domAttributes: opts.domAttributes,\n }),\n ...Object.values(opts.inlineContentSpecs)\n .filter((a) => a.config !== \"link\" && a.config !== \"text\")\n .map((inlineContentSpec) => {\n return inlineContentSpec.implementation!.node.configure({\n editor: opts.editor as any,\n });\n }),\n\n ...Object.values(opts.blockSpecs).flatMap((blockSpec) => {\n return [\n // dependent nodes (e.g.: tablecell / row)\n ...(blockSpec.implementation.requiredExtensions || []).map((ext) =>\n ext.configure({\n editor: opts.editor,\n domAttributes: opts.domAttributes,\n })\n ),\n // the actual node itself\n blockSpec.implementation.node.configure({\n editor: opts.editor,\n domAttributes: opts.domAttributes,\n }),\n ];\n }),\n createCopyToClipboardExtension(opts.editor),\n createPasteFromClipboardExtension(opts.editor),\n\n Dropcursor.configure({ width: 5, color: \"#ddeeff\" }),\n // This needs to be at the bottom of this list, because Key events (such as enter, when selecting a /command),\n // should be handled before Enter handlers in other components like splitListItem\n TrailingNode,\n ];\n\n if (opts.collaboration) {\n ret.push(\n Collaboration.configure({\n fragment: opts.collaboration.fragment,\n })\n );\n if (opts.collaboration.provider?.awareness) {\n const defaultRender = (user: { color: string; name: string }) => {\n const cursor = document.createElement(\"span\");\n\n cursor.classList.add(\"collaboration-cursor__caret\");\n cursor.setAttribute(\"style\", `border-color: ${user.color}`);\n\n const label = document.createElement(\"span\");\n\n label.classList.add(\"collaboration-cursor__label\");\n label.setAttribute(\"style\", `background-color: ${user.color}`);\n label.insertBefore(document.createTextNode(user.name), null);\n\n const nonbreakingSpace1 = document.createTextNode(\"\\u2060\");\n const nonbreakingSpace2 = document.createTextNode(\"\\u2060\");\n cursor.insertBefore(nonbreakingSpace1, null);\n cursor.insertBefore(label, null);\n cursor.insertBefore(nonbreakingSpace2, null);\n return cursor;\n };\n ret.push(\n CollaborationCursor.configure({\n user: opts.collaboration.user,\n render: opts.collaboration.renderCursor || defaultRender,\n provider: opts.collaboration.provider,\n })\n );\n }\n } else {\n // disable history extension when collaboration is enabled as Yjs takes care of undo / redo\n ret.push(History);\n }\n\n return ret;\n};\n","import { Fragment, Slice } from \"@tiptap/pm/model\";\nimport { EditorView } from \"@tiptap/pm/view\";\n\n// helper function to remove a child from a fragment\nfunction removeChild(node: Fragment, n: number) {\n const children: any[] = [];\n node.forEach((child, _, i) => {\n if (i !== n) {\n children.push(child);\n }\n });\n return Fragment.from(children);\n}\n\n/**\n * fix for https://github.com/ProseMirror/prosemirror/issues/1430#issuecomment-1822570821\n *\n * Without this fix, pasting two paragraphs would cause the second one to be indented in the other\n * this fix wraps every element in the slice in it's own blockContainer, to prevent Prosemirror from nesting the\n * elements on paste.\n *\n * The exception is when we encounter blockGroups with listitems, because those actually should be nested\n */\nexport function transformPasted(slice: Slice, view: EditorView) {\n let f = Fragment.from(slice.content);\n for (let i = 0; i < f.childCount; i++) {\n if (f.child(i).type.spec.group === \"blockContent\") {\n const content = [f.child(i)];\n\n // when there is a blockGroup with lists, it should be nested in the new blockcontainer\n // (if we remove this if-block, the nesting bug will be fixed, but lists won't be nested correctly)\n if (\n i + 1 < f.childCount &&\n f.child(i + 1).type.spec.group === \"blockGroup\"\n ) {\n const nestedChild = f\n .child(i + 1)\n .child(0)\n .child(0);\n\n if (\n nestedChild.type.name === \"bulletListItem\" ||\n nestedChild.type.name === \"numberedListItem\"\n ) {\n content.push(f.child(i + 1));\n f = removeChild(f, i + 1);\n }\n }\n const container = view.state.schema.nodes.blockContainer.create(\n undefined,\n content\n );\n f = f.replaceChild(i, container);\n }\n }\n\n return new Slice(f, slice.openStart, slice.openEnd);\n}\n","import {\n defaultBlockSpecs,\n defaultInlineContentSpecs,\n defaultStyleSpecs,\n} from \"../blocks/defaultBlocks\";\nimport {\n BlockSchema,\n BlockSchemaFromSpecs,\n BlockSpecs,\n InlineContentSchema,\n InlineContentSchemaFromSpecs,\n InlineContentSpecs,\n StyleSchema,\n StyleSchemaFromSpecs,\n StyleSpecs,\n getBlockSchemaFromSpecs,\n getInlineContentSchemaFromSpecs,\n getStyleSchemaFromSpecs,\n} from \"../schema\";\nimport type {\n BlockNoDefaults,\n PartialBlockNoDefaults,\n} from \"../schema/blocks/types\";\nimport type { BlockNoteEditor } from \"./BlockNoteEditor\";\n\nexport class BlockNoteSchema<\n BSchema extends BlockSchema,\n ISchema extends InlineContentSchema,\n SSchema extends StyleSchema\n> {\n public readonly blockSpecs: BlockSpecs;\n public readonly inlineContentSpecs: InlineContentSpecs;\n public readonly styleSpecs: StyleSpecs;\n\n public readonly blockSchema: BSchema;\n public readonly inlineContentSchema: ISchema;\n public readonly styleSchema: SSchema;\n\n // Helper so that you can use typeof schema.BlockNoteEditor\n public readonly BlockNoteEditor: BlockNoteEditor<BSchema, ISchema, SSchema> =\n \"only for types\" as any;\n\n public readonly Block: BlockNoDefaults<BSchema, ISchema, SSchema> =\n \"only for types\" as any;\n\n public readonly PartialBlock: PartialBlockNoDefaults<\n BSchema,\n ISchema,\n SSchema\n > = \"only for types\" as any;\n\n public static create<\n BSpecs extends BlockSpecs = typeof defaultBlockSpecs,\n ISpecs extends InlineContentSpecs = typeof defaultInlineContentSpecs,\n SSpecs extends StyleSpecs = typeof defaultStyleSpecs\n >(options?: {\n /**\n * A list of custom block types that should be available in the editor.\n */\n blockSpecs?: BSpecs;\n /**\n * A list of custom InlineContent types that should be available in the editor.\n */\n inlineContentSpecs?: ISpecs;\n /**\n * A list of custom Styles that should be available in the editor.\n */\n styleSpecs?: SSpecs;\n }) {\n return new BlockNoteSchema<\n BlockSchemaFromSpecs<BSpecs>,\n InlineContentSchemaFromSpecs<ISpecs>,\n StyleSchemaFromSpecs<SSpecs>\n >(options);\n // as BlockNoteSchema<\n // BlockSchemaFromSpecs<BSpecs>,\n // InlineContentSchemaFromSpecs<ISpecs>,\n // StyleSchemaFromSpecs<SSpecs>\n // >;\n }\n\n constructor(opts?: {\n blockSpecs?: BlockSpecs;\n inlineContentSpecs?: InlineContentSpecs;\n styleSpecs?: StyleSpecs;\n }) {\n this.blockSpecs = opts?.blockSpecs || defaultBlockSpecs;\n this.inlineContentSpecs =\n opts?.inlineContentSpecs || defaultInlineContentSpecs;\n this.styleSpecs = opts?.styleSpecs || defaultStyleSpecs;\n\n this.blockSchema = getBlockSchemaFromSpecs(this.blockSpecs) as any;\n this.inlineContentSchema = getInlineContentSchemaFromSpecs(\n this.inlineContentSpecs\n ) as any;\n this.styleSchema = getStyleSchemaFromSpecs(this.styleSpecs) as any;\n }\n}\n","import { EditorOptions, createDocument } from \"@tiptap/core\";\n// import \"./blocknote.css\";\nimport { Editor as TiptapEditor } from \"@tiptap/core\";\nimport { Node } from \"@tiptap/pm/model\";\nimport { EditorView } from \"@tiptap/pm/view\";\nimport { EditorState } from \"prosemirror-state\";\n\nimport { blockToNode } from \"../api/nodeConversions/nodeConversions\";\nimport { PartialBlock } from \"../blocks/defaultBlocks\";\nimport { StyleSchema } from \"../schema\";\n\nexport type BlockNoteTipTapEditorOptions = Partial<\n Omit<EditorOptions, \"content\">\n> & {\n content: PartialBlock<any, any, any>[];\n};\n\n/**\n * Custom Editor class that extends TiptapEditor and separates\n * the creation of the view from the constructor.\n */\n// @ts-ignore\nexport class BlockNoteTipTapEditor extends TiptapEditor {\n private _state: EditorState;\n\n constructor(options: BlockNoteTipTapEditorOptions, styleSchema: StyleSchema) {\n // possible fix for next.js server side rendering\n // const d = globalThis.document;\n // const w = globalThis.window;\n // if (!globalThis.document) {\n // globalThis.document = {\n // createElement: () => {},\n // };\n // }\n // if (!globalThis.window) {\n // globalThis.window = {\n // setTimeout: () => {},\n // };\n // }\n // options.injectCSS = false\n super({ ...options, content: undefined });\n\n // try {\n // globalThis.window = w;\n // } catch(e) {}\n // try {\n // globalThis.document = d;\n // } catch(e) {}\n\n // This is a hack to make \"initial content detection\" by y-prosemirror (and also tiptap isEmpty)\n // properly detect whether or not the document has changed.\n // We change the doc.createAndFill function to make sure the initial block id is set, instead of null\n const schema = this.schema;\n let cache: any;\n const oldCreateAndFill = schema.nodes.doc.createAndFill;\n (schema.nodes.doc as any).createAndFill = (...args: any) => {\n if (cache) {\n return cache;\n }\n const ret = oldCreateAndFill.apply(schema.nodes.doc, args);\n\n // create a copy that we can mutate (otherwise, assigning attrs is not safe and corrupts the pm state)\n const jsonNode = JSON.parse(JSON.stringify(ret!.toJSON()));\n jsonNode.content[0].content[0].attrs.id = \"initialBlockId\";\n\n cache = Node.fromJSON(schema, jsonNode);\n return cache;\n };\n\n let doc: Node;\n\n try {\n const pmNodes = options?.content.map((b) =>\n blockToNode(b, this.schema, styleSchema).toJSON()\n );\n doc = createDocument(\n {\n type: \"doc\",\n content: [\n {\n type: \"blockGroup\",\n content: pmNodes,\n },\n ],\n },\n this.schema,\n this.options.parseOptions\n );\n } catch (e) {\n console.error(\n \"Error creating document from blocks passed as `initialContent`. Caused by exception: \",\n e\n );\n throw new Error(\n \"Error creating document from blocks passed as `initialContent`:\\n\" +\n +JSON.stringify(options.content)\n );\n }\n\n // Create state immediately, so that it's available independently from the View,\n // the way Prosemirror \"intends it to be\". This also makes sure that we can access\n // the state before the view is created / mounted.\n this._state = EditorState.create({\n doc,\n schema: this.schema,\n // selection: selection || undefined,\n });\n }\n\n get state() {\n if (this.view) {\n this._state = this.view.state;\n }\n return this._state;\n }\n\n createView() {\n // no-op\n // Disable default call to `createView` in the Editor constructor.\n // We should call `createView` manually only when a DOM element is available\n }\n\n /**\n * Replace the default `createView` method with a custom one - which we call on mount\n */\n private createViewAlternative() {\n // Without queueMicrotask, custom IC / styles will give a React FlushSync error\n queueMicrotask(() => {\n this.view = new EditorView(this.options.element, {\n ...this.options.editorProps,\n // @ts-ignore\n dispatchTransaction: this.dispatchTransaction.bind(this),\n state: this.state,\n });\n\n // `editor.view` is not yet available at this time.\n // Therefore we will add all plugins and node views directly afterwards.\n const newState = this.state.reconfigure({\n plugins: this.extensionManager.plugins,\n });\n\n this.view.updateState(newState);\n\n this.createNodeViews();\n });\n }\n\n /**\n * Mounts / unmounts the editor to a dom element\n *\n * @param element DOM element to mount to, ur null / undefined to destroy\n */\n public mount = (element?: HTMLElement | null) => {\n if (!element) {\n this.destroy();\n } else {\n this.options.element = element;\n // @ts-ignore\n this.createViewAlternative();\n }\n };\n}\n","import { EditorOptions, Extension } from \"@tiptap/core\";\nimport { Node } from \"prosemirror-model\";\n// import \"./blocknote.css\";\nimport * as Y from \"yjs\";\nimport {\n insertBlocks,\n insertContentAt,\n removeBlocks,\n replaceBlocks,\n updateBlock,\n} from \"../api/blockManipulation/blockManipulation\";\nimport { createExternalHTMLExporter } from \"../api/exporters/html/externalHTMLExporter\";\nimport { blocksToMarkdown } from \"../api/exporters/markdown/markdownExporter\";\nimport { getBlockInfoFromPos } from \"../api/getBlockInfoFromPos\";\nimport {\n inlineContentToNodes,\n nodeToBlock,\n} from \"../api/nodeConversions/nodeConversions\";\nimport { getNodeById } from \"../api/nodeUtil\";\nimport { HTMLToBlocks } from \"../api/parsers/html/parseHTML\";\nimport { markdownToBlocks } from \"../api/parsers/markdown/parseMarkdown\";\nimport {\n Block,\n DefaultBlockSchema,\n DefaultInlineContentSchema,\n DefaultStyleSchema,\n PartialBlock,\n} from \"../blocks/defaultBlocks\";\nimport { FormattingToolbarProsemirrorPlugin } from \"../extensions/FormattingToolbar/FormattingToolbarPlugin\";\nimport { LinkToolbarProsemirrorPlugin } from \"../extensions/LinkToolbar/LinkToolbarPlugin\";\nimport { SideMenuProsemirrorPlugin } from \"../extensions/SideMenu/SideMenuPlugin\";\nimport { SuggestionMenuProseMirrorPlugin } from \"../extensions/SuggestionMenu/SuggestionPlugin\";\nimport { ImagePanelProsemirrorPlugin } from \"../extensions/ImagePanel/ImageToolbarPlugin\";\nimport { TableHandlesProsemirrorPlugin } from \"../extensions/TableHandles/TableHandlesPlugin\";\nimport { UniqueID } from \"../extensions/UniqueID/UniqueID\";\nimport {\n BlockIdentifier,\n BlockNoteDOMAttributes,\n BlockSchema,\n BlockSpecs,\n InlineContentSchema,\n InlineContentSpecs,\n PartialInlineContent,\n StyleSchema,\n StyleSpecs,\n Styles,\n} from \"../schema\";\nimport { mergeCSSClasses } from \"../util/browser\";\nimport { NoInfer, UnreachableCaseError } from \"../util/typescript\";\n\nimport { getBlockNoteExtensions } from \"./BlockNoteExtensions\";\nimport { TextCursorPosition } from \"./cursorPositionTypes\";\n\nimport { Selection } from \"./selectionTypes\";\nimport { transformPasted } from \"./transformPasted\";\n\nimport { checkDefaultBlockTypeInSchema } from \"../blocks/defaultBlockTypeGuards\";\nimport { BlockNoteSchema } from \"./BlockNoteSchema\";\nimport {\n BlockNoteTipTapEditor,\n BlockNoteTipTapEditorOptions,\n} from \"./BlockNoteTipTapEditor\";\n\n// CSS\nimport \"./Block.css\";\nimport \"./editor.css\";\n\nexport type BlockNoteEditorOptions<\n BSchema extends BlockSchema,\n ISchema extends InlineContentSchema,\n SSchema extends StyleSchema\n> = {\n // TODO: Figure out if enableBlockNoteExtensions/disableHistoryExtension are needed and document them.\n enableBlockNoteExtensions: boolean;\n\n placeholders: Record<string | \"default\", string>;\n\n /**\n * An object containing attributes that should be added to HTML elements of the editor.\n *\n * @example { editor: { class: \"my-editor-class\" } }\n */\n domAttributes: Partial<BlockNoteDOMAttributes>;\n\n /**\n * The content that should be in the editor when it's created, represented as an array of partial block objects.\n */\n initialContent: PartialBlock<\n NoInfer<BSchema>,\n NoInfer<ISchema>,\n NoInfer<SSchema>\n >[];\n /**\n * Use default BlockNote font and reset the styles of <p> <li> <h1> elements etc., that are used in BlockNote.\n *\n * @default true\n */\n defaultStyles: boolean;\n\n schema: BlockNoteSchema<BSchema, ISchema, SSchema>;\n\n /**\n * A custom function to handle file uploads.\n * @param file The file that should be uploaded.\n * @returns The URL of the uploaded file.\n */\n uploadFile: (file: File) => Promise<string>;\n\n /**\n * When enabled, allows for collaboration between multiple users.\n */\n collaboration: {\n /**\n * The Yjs XML fragment that's used for collaboration.\n */\n fragment: Y.XmlFragment;\n /**\n * The user info for the current user that's shown to other collaborators.\n */\n user: {\n name: string;\n color: string;\n };\n /**\n * A Yjs provider (used for awareness / cursor information)\n */\n provider: any;\n /**\n * Optional function to customize how cursors of users are rendered\n */\n renderCursor?: (user: any) => HTMLElement;\n };\n\n // tiptap options, undocumented\n _tiptapOptions: Partial<EditorOptions>;\n};\n\nconst blockNoteTipTapOptions = {\n enableInputRules: true,\n enablePasteRules: true,\n enableCoreExtensions: false,\n};\n\nexport class BlockNoteEditor<\n BSchema extends BlockSchema = DefaultBlockSchema,\n ISchema extends InlineContentSchema = DefaultInlineContentSchema,\n SSchema extends StyleSchema = DefaultStyleSchema\n> {\n public readonly _tiptapEditor: BlockNoteTipTapEditor & {\n contentComponent: any;\n };\n public blockCache = new WeakMap<Node, Block<any, any, any>>();\n public readonly schema: BlockNoteSchema<BSchema, ISchema, SSchema>;\n\n public readonly blockImplementations: BlockSpecs;\n public readonly inlineContentImplementations: InlineContentSpecs;\n public readonly styleImplementations: StyleSpecs;\n\n public readonly formattingToolbar: FormattingToolbarProsemirrorPlugin;\n public readonly linkToolbar: LinkToolbarProsemirrorPlugin<\n BSchema,\n ISchema,\n SSchema\n >;\n public readonly sideMenu: SideMenuProsemirrorPlugin<\n BSchema,\n ISchema,\n SSchema\n >;\n public readonly suggestionMenus: SuggestionMenuProseMirrorPlugin<\n BSchema,\n ISchema,\n SSchema\n >;\n public readonly imagePanel?: ImagePanelProsemirrorPlugin<ISchema, SSchema>;\n public readonly tableHandles?: TableHandlesProsemirrorPlugin<\n ISchema,\n SSchema\n >;\n\n public readonly uploadFile: ((file: File) => Promise<string>) | undefined;\n\n public static create<\n BSchema extends BlockSchema = DefaultBlockSchema,\n ISchema extends InlineContentSchema = DefaultInlineContentSchema,\n SSchema extends StyleSchema = DefaultStyleSchema\n >(options: Partial<BlockNoteEditorOptions<BSchema, ISchema, SSchema>> = {}) {\n return new BlockNoteEditor<BSchema, ISchema, SSchema>(options);\n }\n\n private constructor(\n private readonly options: Partial<BlockNoteEditorOptions<any, any, any>>\n ) {\n const anyOpts = options as any;\n if (anyOpts.onEditorContentChange) {\n throw new Error(\n \"onEditorContentChange initialization option is deprecated, use <BlockNoteView onChange={...} />, the useEditorChange(...) hook, or editor.onChange(...)\"\n );\n }\n\n if (anyOpts.onTextCursorPositionChange) {\n throw new Error(\n \"onTextCursorPositionChange initialization option is deprecated, use <BlockNoteView onSelectionChange={...} />, the useEditorSelectionChange(...) hook, or editor.onSelectionChange(...)\"\n );\n }\n\n if (anyOpts.onEditorReady) {\n throw new Error(\n \"onEditorReady is deprecated. Editor is immediately ready for use after creation.\"\n );\n }\n\n if (anyOpts.editable) {\n throw new Error(\n \"editable initialization option is deprecated, use <BlockNoteView editable={true/false} />, or alternatively editor.isEditable = true/false\"\n );\n }\n\n // apply defaults\n const newOptions = {\n defaultStyles: true,\n schema: options.schema || BlockNoteSchema.create(),\n ...options,\n };\n\n // @ts-ignore\n this.schema = newOptions.schema;\n this.blockImplementations = newOptions.schema.blockSpecs;\n this.inlineContentImplementations = newOptions.schema.inlineContentSpecs;\n this.styleImplementations = newOptions.schema.styleSpecs;\n\n this.formattingToolbar = new FormattingToolbarProsemirrorPlugin(this);\n this.linkToolbar = new LinkToolbarProsemirrorPlugin(this);\n this.sideMenu = new SideMenuProsemirrorPlugin(this);\n this.suggestionMenus = new SuggestionMenuProseMirrorPlugin(this);\n if (checkDefaultBlockTypeInSchema(\"image\", this)) {\n // Type guards only work on `const`s? Not working for `this`\n this.imagePanel = new ImagePanelProsemirrorPlugin(this as any);\n }\n if (checkDefaultBlockTypeInSchema(\"table\", this)) {\n this.tableHandles = new TableHandlesProsemirrorPlugin(this as any);\n }\n\n const extensions = getBlockNoteExtensions({\n editor: this,\n placeholders: newOptions.placeholders,\n domAttributes: newOptions.domAttributes || {},\n blockSchema: this.schema.blockSchema,\n blockSpecs: this.schema.blockSpecs,\n styleSpecs: this.schema.styleSpecs,\n inlineContentSpecs: this.schema.inlineContentSpecs,\n collaboration: newOptions.collaboration,\n });\n\n const blockNoteUIExtension = Extension.create({\n name: \"BlockNoteUIExtension\",\n\n addProseMirrorPlugins: () => {\n return [\n this.formattingToolbar.plugin,\n this.linkToolbar.plugin,\n this.sideMenu.plugin,\n this.suggestionMenus.plugin,\n ...(this.imagePanel ? [this.imagePanel.plugin] : []),\n ...(this.tableHandles ? [this.tableHandles.plugin] : []),\n ];\n },\n });\n extensions.push(blockNoteUIExtension);\n\n this.uploadFile = newOptions.uploadFile;\n\n if (newOptions.collaboration && newOptions.initialContent) {\n console.warn(\n \"When using Collaboration, initialContent might cause conflicts, because changes should come from the collaboration provider\"\n );\n }\n\n const initialContent =\n newOptions.initialContent ||\n (options.collaboration\n ? [\n {\n type: \"paragraph\",\n id: \"initialBlockId\",\n },\n ]\n : [\n {\n type: \"paragraph\",\n id: UniqueID.options.generateID(),\n },\n ]);\n\n if (!Array.isArray(initialContent) || initialContent.length === 0) {\n throw new Error(\n \"initialContent must be a non-empty array of blocks, received: \" +\n initialContent\n );\n }\n\n const tiptapOptions: BlockNoteTipTapEditorOptions = {\n ...blockNoteTipTapOptions,\n ...newOptions._tiptapOptions,\n content: initialContent,\n extensions:\n newOptions.enableBlockNoteExtensions === false\n ? newOptions._tiptapOptions?.extensions || []\n : [...(newOptions._tiptapOptions?.extensions || []), ...extensions],\n editorProps: {\n ...newOptions._tiptapOptions?.editorProps,\n attributes: {\n ...newOptions._tiptapOptions?.editorProps?.attributes,\n ...newOptions.domAttributes?.editor,\n class: mergeCSSClasses(\n \"bn-editor\",\n newOptions.defaultStyles ? \"bn-default-styles\" : \"\",\n newOptions.domAttributes?.editor?.class || \"\"\n ),\n },\n transformPasted,\n },\n };\n\n this._tiptapEditor = new BlockNoteTipTapEditor(\n tiptapOptions,\n this.schema.styleSchema\n ) as BlockNoteTipTapEditor & {\n contentComponent: any;\n };\n }\n\n /**\n * Mount the editor to a parent DOM element. Call mount(undefined) to clean up\n *\n * @warning Not needed for React, use BlockNoteView to take care of this\n */\n public mount(parentElement?: HTMLElement | null) {\n this._tiptapEditor.mount(parentElement);\n }\n\n public get prosemirrorView() {\n return this._tiptapEditor.view;\n }\n\n public get domElement() {\n return this._tiptapEditor.view.dom as HTMLDivElement;\n }\n\n public isFocused() {\n return this._tiptapEditor.view.hasFocus();\n }\n\n public focus() {\n this._tiptapEditor.view.focus();\n }\n\n /**\n * @deprecated, use `editor.document` instead\n */\n public get topLevelBlocks(): Block<BSchema, ISchema, SSchema>[] {\n return this.topLevelBlocks;\n }\n\n /**\n * Gets a snapshot of all top-level (non-nested) blocks in the editor.\n * @returns A snapshot of all top-level (non-nested) blocks in the editor.\n */\n public get document(): Block<BSchema, ISchema, SSchema>[] {\n const blocks: Block<BSchema, ISchema, SSchema>[] = [];\n\n this._tiptapEditor.state.doc.firstChild!.descendants((node) => {\n blocks.push(\n nodeToBlock(\n node,\n this.schema.blockSchema,\n this.schema.inlineContentSchema,\n this.schema.styleSchema,\n this.blockCache\n )\n );\n\n return false;\n });\n\n return blocks;\n }\n\n /**\n * Gets a snapshot of an existing block from the editor.\n * @param blockIdentifier The identifier of an existing block that should be retrieved.\n * @returns The block that matches the identifier, or `undefined` if no matching block was found.\n */\n public getBlock(\n blockIdentifier: BlockIdentifier\n ): Block<BSchema, ISchema, SSchema> | undefined {\n const id =\n typeof blockIdentifier === \"string\"\n ? blockIdentifier\n : blockIdentifier.id;\n let newBlock: Block<BSchema, ISchema, SSchema> | undefined = undefined;\n\n this._tiptapEditor.state.doc.firstChild!.descendants((node) => {\n if (typeof newBlock !== \"undefined\") {\n return false;\n }\n\n if (node.type.name !== \"blockContainer\" || node.attrs.id !== id) {\n return true;\n }\n\n newBlock = nodeToBlock(\n node,\n this.schema.blockSchema,\n this.schema.inlineContentSchema,\n this.schema.styleSchema,\n this.blockCache\n );\n\n return false;\n });\n\n return newBlock;\n }\n\n /**\n * Traverses all blocks in the editor depth-first, and executes a callback for each.\n * @param callback The callback to execute for each block. Returning `false` stops the traversal.\n * @param reverse Whether the blocks should be traversed in reverse order.\n */\n public forEachBlock(\n callback: (block: Block<BSchema, ISchema, SSchema>) => boolean,\n reverse = false\n ): void {\n const blocks = this.document.slice();\n\n if (reverse) {\n blocks.reverse();\n }\n\n function traverseBlockArray(\n blockArray: Block<BSchema, ISchema, SSchema>[]\n ): boolean {\n for (const block of blockArray) {\n if (!callback(block)) {\n return false;\n }\n\n const children = reverse\n ? block.children.slice().reverse()\n : block.children;\n\n if (!traverseBlockArray(children)) {\n return false;\n }\n }\n\n return true;\n }\n\n traverseBlockArray(blocks);\n }\n\n /**\n * Executes a callback whenever the editor's contents change.\n * @param callback The callback to execute.\n */\n public onEditorContentChange(callback: () => void) {\n this._tiptapEditor.on(\"update\", callback);\n }\n\n /**\n * Executes a callback whenever the editor's selection changes.\n * @param callback The callback to execute.\n */\n public onEditorSelectionChange(callback: () => void) {\n this._tiptapEditor.on(\"selectionUpdate\", callback);\n }\n\n /**\n * Gets a snapshot of the current text cursor position.\n * @returns A snapshot of the current text cursor position.\n */\n public getTextCursorPosition(): TextCursorPosition<\n BSchema,\n ISchema,\n SSchema\n > {\n const { node, depth, startPos, endPos } = getBlockInfoFromPos(\n this._tiptapEditor.state.doc,\n this._tiptapEditor.state.selection.from\n )!;\n\n // Index of the current blockContainer node relative to its parent blockGroup.\n const nodeIndex = this._tiptapEditor.state.doc\n .resolve(endPos)\n .index(depth - 1);\n // Number of the parent blockGroup's child blockContainer nodes.\n const numNodes = this._tiptapEditor.state.doc\n .resolve(endPos + 1)\n .node().childCount;\n\n // Gets previous blockContainer node at the same nesting level, if the current node isn't the first child.\n let prevNode: Node | undefined = undefined;\n if (nodeIndex > 0) {\n prevNode = this._tiptapEditor.state.doc.resolve(startPos - 2).node();\n }\n\n // Gets next blockContainer node at the same nesting level, if the current node isn't the last child.\n let nextNode: Node | undefined = undefined;\n if (nodeIndex < numNodes - 1) {\n nextNode = this._tiptapEditor.state.doc.resolve(endPos + 2).node();\n }\n\n return {\n block: nodeToBlock(\n node,\n this.schema.blockSchema,\n this.schema.inlineContentSchema,\n this.schema.styleSchema,\n this.blockCache\n ),\n prevBlock:\n prevNode === undefined\n ? undefined\n : nodeToBlock(\n prevNode,\n this.schema.blockSchema,\n this.schema.inlineContentSchema,\n this.schema.styleSchema,\n this.blockCache\n ),\n nextBlock:\n nextNode === undefined\n ? undefined\n : nodeToBlock(\n nextNode,\n this.schema.blockSchema,\n this.schema.inlineContentSchema,\n this.schema.styleSchema,\n this.blockCache\n ),\n };\n }\n\n /**\n * Sets the text cursor position to the start or end of an existing block. Throws an error if the target block could\n * not be found.\n * @param targetBlock The identifier of an existing block that the text cursor should be moved to.\n * @param placement Whether the text cursor should be placed at the start or end of the block.\n */\n public setTextCursorPosition(\n targetBlock: BlockIdentifier,\n placement: \"start\" | \"end\" = \"start\"\n ) {\n const id = typeof targetBlock === \"string\" ? targetBlock : targetBlock.id;\n\n const { posBeforeNode } = getNodeById(id, this._tiptapEditor.state.doc);\n const { startPos, contentNode } = getBlockInfoFromPos(\n this._tiptapEditor.state.doc,\n posBeforeNode + 2\n )!;\n\n const contentType: \"none\" | \"inline\" | \"table\" =\n this.schema.blockSchema[contentNode.type.name]!.content;\n\n if (contentType === \"none\") {\n this._tiptapEditor.commands.setNodeSelection(startPos);\n return;\n }\n\n if (contentType === \"inline\") {\n if (placement === \"start\") {\n this._tiptapEditor.commands.setTextSelection(startPos + 1);\n } else {\n this._tiptapEditor.commands.setTextSelection(\n startPos + contentNode.nodeSize - 1\n );\n }\n } else if (contentType === \"table\") {\n if (placement === \"start\") {\n // Need to offset the position as we have to get through the `tableRow`\n // and `tableCell` nodes to get to the `tableParagraph` node we want to\n // set the selection in.\n this._tiptapEditor.commands.setTextSelection(startPos + 4);\n } else {\n this._tiptapEditor.commands.setTextSelection(\n startPos + contentNode.nodeSize - 4\n );\n }\n } else {\n throw new UnreachableCaseError(contentType);\n }\n }\n\n /**\n * Gets a snapshot of the current selection.\n */\n public getSelection(): Selection<BSchema, ISchema, SSchema> | undefined {\n // Either the TipTap selection is empty, or it's a node selection. In either\n // case, it only spans one block, so we return undefined.\n if (\n this._tiptapEditor.state.selection.from ===\n this._tiptapEditor.state.selection.to ||\n \"node\" in this._tiptapEditor.state.selection\n ) {\n return undefined;\n }\n\n const blocks: Block<BSchema, ISchema, SSchema>[] = [];\n\n // TODO: This adds all child blocks to the same array. Needs to find min\n // depth and only add blocks at that depth.\n this._tiptapEditor.state.doc.descendants((node, pos) => {\n if (node.type.spec.group !== \"blockContent\") {\n return true;\n }\n\n if (\n pos + node.nodeSize < this._tiptapEditor.state.selection.from ||\n pos > this._tiptapEditor.state.selection.to\n ) {\n return true;\n }\n\n blocks.push(\n nodeToBlock(\n this._tiptapEditor.state.doc.resolve(pos).node(),\n this.schema.blockSchema,\n this.schema.inlineContentSchema,\n this.schema.styleSchema,\n this.blockCache\n )\n );\n\n return false;\n });\n\n return { blocks: blocks };\n }\n\n /**\n * Checks if the editor is currently editable, or if it's locked.\n * @returns True if the editor is editable, false otherwise.\n */\n public get isEditable(): boolean {\n return this._tiptapEditor.isEditable;\n }\n\n /**\n * Makes the editor editable or locks it, depending on the argument passed.\n * @param editable True to make the editor editable, or false to lock it.\n */\n public set isEditable(editable: boolean) {\n if (this._tiptapEditor.options.editable !== editable) {\n this._tiptapEditor.setEditable(editable);\n }\n }\n\n /**\n * Inserts new blocks into the editor. If a block's `id` is undefined, BlockNote generates one automatically. Throws an\n * error if the reference block could not be found.\n * @param blocksToInsert An array of partial blocks that should be inserted.\n * @param referenceBlock An identifier for an existing block, at which the new blocks should be inserted.\n * @param placement Whether the blocks should be inserted just before, just after, or nested inside the\n * `referenceBlock`. Inserts the blocks at the start of the existing block's children if \"nested\" is used.\n */\n public insertBlocks(\n blocksToInsert: PartialBlock<BSchema, ISchema, SSchema>[],\n referenceBlock: BlockIdentifier,\n placement: \"before\" | \"after\" | \"nested\" = \"before\"\n ) {\n return insertBlocks(blocksToInsert, referenceBlock, placement, this);\n }\n\n /**\n * Updates an existing block in the editor. Since updatedBlock is a PartialBlock object, some fields might not be\n * defined. These undefined fields are kept as-is from the existing block. Throws an error if the block to update could\n * not be found.\n * @param blockToUpdate The block that should be updated.\n * @param update A partial block which defines how the existing block should be changed.\n */\n public updateBlock(\n blockToUpdate: BlockIdentifier,\n update: PartialBlock<BSchema, ISchema, SSchema>\n ) {\n return updateBlock(blockToUpdate, update, this);\n }\n\n /**\n * Removes existing blocks from the editor. Throws an error if any of the blocks could not be found.\n * @param blocksToRemove An array of identifiers for existing blocks that should be removed.\n */\n public removeBlocks(blocksToRemove: BlockIdentifier[]) {\n return removeBlocks(blocksToRemove, this);\n }\n\n /**\n * Replaces existing blocks in the editor with new blocks. If the blocks that should be removed are not adjacent or\n * are at different nesting levels, `blocksToInsert` will be inserted at the position of the first block in\n * `blocksToRemove`. Throws an error if any of the blocks to remove could not be found.\n * @param blocksToRemove An array of blocks that should be replaced.\n * @param blocksToInsert An array of partial blocks to replace the old ones with.\n */\n public replaceBlocks(\n blocksToRemove: BlockIdentifier[],\n blocksToInsert: PartialBlock<BSchema, ISchema, SSchema>[]\n ) {\n return replaceBlocks(blocksToRemove, blocksToInsert, this);\n }\n\n /**\n * Insert a piece of content at the current cursor position.\n *\n * @param content can be a string, or array of partial inline content elements\n */\n public insertInlineContent(content: PartialInlineContent<ISchema, SSchema>) {\n const nodes = inlineContentToNodes(\n content,\n this._tiptapEditor.schema,\n this.schema.styleSchema\n );\n\n insertContentAt(\n {\n from: this._tiptapEditor.state.selection.from,\n to: this._tiptapEditor.state.selection.to,\n },\n nodes,\n this\n );\n }\n\n /**\n * Gets the active text styles at the text cursor position or at the end of the current selection if it's active.\n */\n public getActiveStyles() {\n const styles: Styles<SSchema> = {};\n const marks = this._tiptapEditor.state.selection.$to.marks();\n\n for (const mark of marks) {\n const config = this.schema.styleSchema[mark.type.name];\n if (!config) {\n console.warn(\"mark not found in styleschema\", mark.type.name);\n continue;\n }\n if (config.propSchema === \"boolean\") {\n (styles as any)[config.type] = true;\n } else {\n (styles as any)[config.type] = mark.attrs.stringValue;\n }\n }\n\n return styles;\n }\n\n /**\n * Adds styles to the currently selected content.\n * @param styles The styles to add.\n */\n public addStyles(styles: Styles<SSchema>) {\n this._tiptapEditor.view.focus();\n\n for (const [style, value] of Object.entries(styles)) {\n const config = this.schema.styleSchema[style];\n if (!config) {\n throw new Error(`style ${style} not found in styleSchema`);\n }\n if (config.propSchema === \"boolean\") {\n this._tiptapEditor.commands.setMark(style);\n } else if (config.propSchema === \"string\") {\n this._tiptapEditor.commands.setMark(style, { stringValue: value });\n } else {\n throw new UnreachableCaseError(config.propSchema);\n }\n }\n }\n\n /**\n * Removes styles from the currently selected content.\n * @param styles The styles to remove.\n */\n public removeStyles(styles: Styles<SSchema>) {\n this._tiptapEditor.view.focus();\n\n for (const style of Object.keys(styles)) {\n this._tiptapEditor.commands.unsetMark(style);\n }\n }\n\n /**\n * Toggles styles on the currently selected content.\n * @param styles The styles to toggle.\n */\n public toggleStyles(styles: Styles<SSchema>) {\n this._tiptapEditor.view.focus();\n\n for (const [style, value] of Object.entries(styles)) {\n const config = this.schema.styleSchema[style];\n if (!config) {\n throw new Error(`style ${style} not found in styleSchema`);\n }\n if (config.propSchema === \"boolean\") {\n this._tiptapEditor.commands.toggleMark(style);\n } else if (config.propSchema === \"string\") {\n this._tiptapEditor.commands.toggleMark(style, { stringValue: value });\n } else {\n throw new UnreachableCaseError(config.propSchema);\n }\n }\n }\n\n /**\n * Gets the currently selected text.\n */\n public getSelectedText() {\n return this._tiptapEditor.state.doc.textBetween(\n this._tiptapEditor.state.selection.from,\n this._tiptapEditor.state.selection.to\n );\n }\n\n /**\n * Gets the URL of the last link in the current selection, or `undefined` if there are no links in the selection.\n */\n public getSelectedLinkUrl() {\n return this._tiptapEditor.getAttributes(\"link\").href as string | undefined;\n }\n\n /**\n * Creates a new link to replace the selected content.\n * @param url The link URL.\n * @param text The text to display the link with.\n */\n public createLink(url: string, text?: string) {\n if (url === \"\") {\n return;\n }\n\n const { from, to } = this._tiptapEditor.state.selection;\n\n if (!text) {\n text = this._tiptapEditor.state.doc.textBetween(from, to);\n }\n\n const mark = this._tiptapEditor.schema.mark(\"link\", { href: url });\n\n this._tiptapEditor.view.dispatch(\n this._tiptapEditor.view.state.tr\n .insertText(text, from, to)\n .addMark(from, from + text.length, mark)\n );\n }\n\n /**\n * Checks if the block containing the text cursor can be nested.\n */\n public canNestBlock() {\n const { startPos, depth } = getBlockInfoFromPos(\n this._tiptapEditor.state.doc,\n this._tiptapEditor.state.selection.from\n )!;\n\n return this._tiptapEditor.state.doc.resolve(startPos).index(depth - 1) > 0;\n }\n\n /**\n * Nests the block containing the text cursor into the block above it.\n */\n public nestBlock() {\n this._tiptapEditor.commands.sinkListItem(\"blockContainer\");\n }\n\n /**\n * Checks if the block containing the text cursor is nested.\n */\n public canUnnestBlock() {\n const { depth } = getBlockInfoFromPos(\n this._tiptapEditor.state.doc,\n this._tiptapEditor.state.selection.from\n )!;\n\n return depth > 2;\n }\n\n /**\n * Lifts the block containing the text cursor out of its parent.\n */\n public unnestBlock() {\n this._tiptapEditor.commands.liftListItem(\"blockContainer\");\n }\n\n // TODO: Fix when implementing HTML/Markdown import & export\n /**\n * Serializes blocks into an HTML string. To better conform to HTML standards, children of blocks which aren't list\n * items are un-nested in the output HTML.\n * @param blocks An array of blocks that should be serialized into HTML.\n * @returns The blocks, serialized as an HTML string.\n */\n public async blocksToHTMLLossy(\n blocks: Block<BSchema, ISchema, SSchema>[] = this.document\n ): Promise<string> {\n const exporter = createExternalHTMLExporter(\n this._tiptapEditor.schema,\n this\n );\n return exporter.exportBlocks(blocks);\n }\n\n /**\n * Parses blocks from an HTML string. Tries to create `Block` objects out of any HTML block-level elements, and\n * `InlineNode` objects from any HTML inline elements, though not all element types are recognized. If BlockNote\n * doesn't recognize an HTML element's tag, it will parse it as a paragraph or plain text.\n * @param html The HTML string to parse blocks from.\n * @returns The blocks parsed from the HTML string.\n */\n public async tryParseHTMLToBlocks(\n html: string\n ): Promise<Block<BSchema, ISchema, SSchema>[]> {\n return HTMLToBlocks(\n html,\n this.schema.blockSchema,\n this.schema.inlineContentSchema,\n this.schema.styleSchema,\n this._tiptapEditor.schema\n );\n }\n\n /**\n * Serializes blocks into a Markdown string. The output is simplified as Markdown does not support all features of\n * BlockNote - children of blocks which aren't list items are un-nested and certain styles are removed.\n * @param blocks An array of blocks that should be serialized into Markdown.\n * @returns The blocks, serialized as a Markdown string.\n */\n public async blocksToMarkdownLossy(\n blocks: Block<BSchema, ISchema, SSchema>[] = this.document\n ): Promise<string> {\n return blocksToMarkdown(blocks, this._tiptapEditor.schema, this);\n }\n\n /**\n * Creates a list of blocks from a Markdown string. Tries to create `Block` and `InlineNode` objects based on\n * Markdown syntax, though not all symbols are recognized. If BlockNote doesn't recognize a symbol, it will parse it\n * as text.\n * @param markdown The Markdown string to parse blocks from.\n * @returns The blocks parsed from the Markdown string.\n */\n public async tryParseMarkdownToBlocks(\n markdown: string\n ): Promise<Block<BSchema, ISchema, SSchema>[]> {\n return markdownToBlocks(\n markdown,\n this.schema.blockSchema,\n this.schema.inlineContentSchema,\n this.schema.styleSchema,\n this._tiptapEditor.schema\n );\n }\n\n /**\n * Updates the user info for the current user that's shown to other collaborators.\n */\n public updateCollaborationUserInfo(user: { name: string; color: string }) {\n if (!this.options.collaboration) {\n throw new Error(\n \"Cannot update collaboration user info when collaboration is disabled.\"\n );\n }\n this._tiptapEditor.commands.updateUser(user);\n }\n\n /**\n * A callback function that runs whenever the editor's contents change.\n *\n * @param callback The callback to execute.\n * @returns A function to remove the callback.\n */\n public onChange(\n callback: (editor: BlockNoteEditor<BSchema, ISchema, SSchema>) => void\n ) {\n const cb = () => {\n callback(this);\n };\n\n this._tiptapEditor.on(\"update\", cb);\n\n return () => {\n this._tiptapEditor.off(\"update\", cb);\n };\n }\n\n /**\n * A callback function that runs whenever the text cursor position or selection changes.\n *\n * @param callback The callback to execute.\n * @returns A function to remove the callback.\n */\n public onSelectionChange(\n callback: (editor: BlockNoteEditor<BSchema, ISchema, SSchema>) => void\n ) {\n const cb = () => {\n callback(this);\n };\n\n this._tiptapEditor.on(\"selectionUpdate\", cb);\n\n return () => {\n this._tiptapEditor.off(\"selectionUpdate\", cb);\n };\n }\n}\n","import { Block, PartialBlock } from \"../../blocks/defaultBlocks\";\nimport { checkDefaultBlockTypeInSchema } from \"../../blocks/defaultBlockTypeGuards\";\nimport { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport {\n BlockSchema,\n InlineContentSchema,\n isStyledTextInlineContent,\n StyleSchema,\n} from \"../../schema\";\nimport { formatKeyboardShortcut } from \"../../util/browser\";\nimport { DefaultSuggestionItem } from \"./DefaultSuggestionItem\";\n\n// Sets the editor's text cursor position to the next content editable block,\n// so either a block with inline content or a table. The last block is always a\n// paragraph, so this function won't try to set the cursor position past the\n// last block.\nfunction setSelectionToNextContentEditableBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(editor: BlockNoteEditor<BSchema, I, S>) {\n let block = editor.getTextCursorPosition().block;\n let contentType = editor.schema.blockSchema[block.type].content;\n\n while (contentType === \"none\") {\n block = editor.getTextCursorPosition().nextBlock!;\n contentType = editor.schema.blockSchema[block.type].content as\n | \"inline\"\n | \"table\"\n | \"none\";\n editor.setTextCursorPosition(block, \"end\");\n }\n}\n\n// Checks if the current block is empty or only contains a slash, and if so,\n// updates the current block instead of inserting a new one below. If the new\n// block doesn't contain editable content, the cursor is moved to the next block\n// that does.\nexport function insertOrUpdateBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n block: PartialBlock<BSchema, I, S>\n): Block<BSchema, I, S> {\n const currentBlock = editor.getTextCursorPosition().block;\n\n if (currentBlock.content === undefined) {\n throw new Error(\"Slash Menu open in a block that doesn't contain content.\");\n }\n\n if (\n Array.isArray(currentBlock.content) &&\n ((currentBlock.content.length === 1 &&\n isStyledTextInlineContent(currentBlock.content[0]) &&\n currentBlock.content[0].type === \"text\" &&\n currentBlock.content[0].text === \"/\") ||\n currentBlock.content.length === 0)\n ) {\n editor.updateBlock(currentBlock, block);\n } else {\n editor.insertBlocks([block], currentBlock, \"after\");\n editor.setTextCursorPosition(\n editor.getTextCursorPosition().nextBlock!,\n \"end\"\n );\n }\n\n const insertedBlock = editor.getTextCursorPosition().block;\n setSelectionToNextContentEditableBlock(editor);\n\n return insertedBlock;\n}\n\nexport function getDefaultSlashMenuItems<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(editor: BlockNoteEditor<BSchema, I, S>) {\n const items: DefaultSuggestionItem[] = [];\n\n if (checkDefaultBlockTypeInSchema(\"heading\", editor)) {\n items.push(\n {\n title: \"Heading 1\",\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: 1 },\n });\n },\n subtext: \"Used for a top-level heading\",\n badge: formatKeyboardShortcut(\"Mod-Alt-1\"),\n aliases: [\"h\", \"heading1\", \"h1\"],\n group: \"Headings\",\n },\n {\n title: \"Heading 2\",\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: 2 },\n });\n },\n subtext: \"Used for key sections\",\n badge: formatKeyboardShortcut(\"Mod-Alt-2\"),\n aliases: [\"h2\", \"heading2\", \"subheading\"],\n group: \"Headings\",\n },\n {\n title: \"Heading 3\",\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: 3 },\n });\n },\n subtext: \"Used for subsections and group headings\",\n badge: formatKeyboardShortcut(\"Mod-Alt-3\"),\n aliases: [\"h3\", \"heading3\", \"subheading\"],\n group: \"Headings\",\n }\n );\n }\n\n if (checkDefaultBlockTypeInSchema(\"numberedListItem\", editor)) {\n items.push({\n title: \"Numbered List\",\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"numberedListItem\",\n });\n },\n subtext: \"Used to display a numbered list\",\n badge: formatKeyboardShortcut(\"Mod-Shift-7\"),\n aliases: [\"ol\", \"li\", \"list\", \"numberedlist\", \"numbered list\"],\n group: \"Basic blocks\",\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"bulletListItem\", editor)) {\n items.push({\n title: \"Bullet List\",\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"bulletListItem\",\n });\n },\n subtext: \"Used to display an unordered list\",\n badge: formatKeyboardShortcut(\"Mod-Shift-8\"),\n aliases: [\"ul\", \"li\", \"list\", \"bulletlist\", \"bullet list\"],\n group: \"Basic blocks\",\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"paragraph\", editor)) {\n items.push({\n title: \"Paragraph\",\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"paragraph\",\n });\n },\n subtext: \"Used for the body of your document\",\n badge: formatKeyboardShortcut(\"Mod-Alt-0\"),\n aliases: [\"p\", \"paragraph\"],\n group: \"Basic blocks\",\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"table\", editor)) {\n items.push({\n title: \"Table\",\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"table\",\n content: {\n type: \"tableContent\",\n rows: [\n {\n cells: [\"\", \"\", \"\"],\n },\n {\n cells: [\"\", \"\", \"\"],\n },\n ],\n },\n });\n },\n subtext: \"Used for for tables\",\n aliases: [\"table\"],\n group: \"Advanced\",\n badge: undefined,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"image\", editor)) {\n items.push({\n title: \"Image\",\n onItemClick: () => {\n const insertedBlock = insertOrUpdateBlock(editor, {\n type: \"image\",\n });\n\n // Immediately open the image toolbar\n editor.prosemirrorView.dispatch(\n editor._tiptapEditor.state.tr.setMeta(editor.imagePanel!.plugin, {\n block: insertedBlock,\n })\n );\n },\n subtext: \"Insert an image\",\n aliases: [\n \"image\",\n \"imageUpload\",\n \"upload\",\n \"img\",\n \"picture\",\n \"media\",\n \"url\",\n \"drive\",\n \"dropbox\",\n ],\n group: \"Media\",\n });\n }\n\n return items;\n}\n\nexport function filterSuggestionItems<\n T extends { title: string; aliases?: readonly string[] }\n>(items: T[], query: string) {\n return items.filter(\n ({ title, aliases }) =>\n title.toLowerCase().startsWith(query.toLowerCase()) ||\n (aliases &&\n aliases.filter((alias) =>\n alias.toLowerCase().startsWith(query.toLowerCase())\n ).length !== 0)\n );\n}\n","import { Block, PartialBlock } from \"../../blocks/defaultBlocks\";\nimport UniqueID from \"../../extensions/UniqueID/UniqueID\";\nimport { BlockSchema, TableContent } from \"../../schema/blocks/types\";\nimport {\n InlineContent,\n InlineContentSchema,\n PartialInlineContent,\n StyledText,\n isPartialLinkInlineContent,\n isStyledTextInlineContent,\n} from \"../../schema/inlineContent/types\";\nimport { StyleSchema } from \"../../schema/styles/types\";\n\nfunction textShorthandToStyledText(\n content: string | StyledText<any>[] = \"\"\n): StyledText<any>[] {\n if (typeof content === \"string\") {\n return [\n {\n type: \"text\",\n text: content,\n styles: {},\n },\n ];\n }\n return content;\n}\n\nfunction partialContentToInlineContent(\n content: PartialInlineContent<any, any> | TableContent<any> | undefined\n): InlineContent<any, any>[] | TableContent<any> | undefined {\n if (typeof content === \"string\") {\n return textShorthandToStyledText(content);\n }\n\n if (Array.isArray(content)) {\n return content.flatMap((partialContent) => {\n if (typeof partialContent === \"string\") {\n return textShorthandToStyledText(partialContent);\n } else if (isPartialLinkInlineContent(partialContent)) {\n return {\n ...partialContent,\n content: textShorthandToStyledText(partialContent.content),\n };\n } else if (isStyledTextInlineContent(partialContent)) {\n return partialContent;\n } else {\n // custom inline content\n\n return {\n props: {},\n ...partialContent,\n content: partialContentToInlineContent(partialContent.content),\n } as any;\n }\n });\n }\n\n return content;\n}\n\nexport function partialBlocksToBlocksForTesting<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n schema: BSchema,\n partialBlocks: Array<PartialBlock<BSchema, I, S>>\n): Array<Block<BSchema, I, S>> {\n return partialBlocks.map((partialBlock) =>\n partialBlockToBlockForTesting(schema, partialBlock)\n );\n}\n\nexport function partialBlockToBlockForTesting<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n schema: BSchema,\n partialBlock: PartialBlock<BSchema, I, S>\n): Block<BSchema, I, S> {\n const withDefaults: Block<BSchema, I, S> = {\n id: \"\",\n type: partialBlock.type!,\n props: {} as any,\n content:\n schema[partialBlock.type!].content === \"inline\" ? [] : (undefined as any),\n children: [] as any,\n ...partialBlock,\n };\n\n Object.entries(schema[partialBlock.type!].propSchema).forEach(\n ([propKey, propValue]) => {\n if (withDefaults.props[propKey] === undefined) {\n (withDefaults.props as any)[propKey] = propValue.default;\n }\n }\n );\n\n return {\n ...withDefaults,\n content: partialContentToInlineContent(withDefaults.content),\n children: withDefaults.children.map((c) => {\n return partialBlockToBlockForTesting(schema, c);\n }),\n } as any;\n}\n\nexport function addIdsToBlock(block: PartialBlock<any, any, any>) {\n if (!block.id) {\n block.id = UniqueID.options.generateID();\n }\n if (block.children) {\n addIdsToBlocks(block.children);\n }\n}\n\nexport function addIdsToBlocks(blocks: PartialBlock<any, any, any>[]) {\n for (const block of blocks) {\n addIdsToBlock(block);\n }\n}\n"],"names":["removeDuplicates","array","by","seen","item","key","findDuplicates","items","filtered","el","index","UniqueID","Extension","testOptions","v4","element","attributes","dragSourceElement","transformPasted","Plugin","PluginKey","transactions","oldState","newState","docChanges","transaction","filterTransactions","tr","_a","_b","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","getBlockInfo","blockContainer","contentNode","contentType","numChildBlocks","getBlockInfoFromPos","doc","outerBlockGroupEndPos","$pos","maxDepth","depth","startPos","endPos","isLinkInlineContent","content","isPartialLinkInlineContent","isStyledTextInlineContent","UnreachableCaseError","val","styledTextToNodes","styledText","schema","styleSchema","marks","style","value","config","text","linkToNodes","link","linkMark","styledTextArrayToNodes","nodes","inlineContentToNodes","blockContent","blockOrInlineContentToContentNode","tableContentToNodes","tableContent","rowNodes","row","columnNodes","cell","pNode","textNodes","cellNode","rowNode","block","type","blockToNode","children","child","groupNode","contentNodeToTableContent","inlineContentSchema","ret","contentNodeToInlineContent","currentContent","nodeToCustomInlineContent","styles","mark","props","icConfig","attr","propSchema","nodeToBlock","blockSchema","blockCache","cachedBlock","blockInfo","blockSpec","blockConfig","i","options","serializeNodeInner","serializer","editor","toExternalHTML","dom","contentDOM","DOMSerializer","blockContentNode","blockGroupNode","impl","serializeProseMirrorFragment","internalHTML","parent","simplifyBlocks","listItemBlockTypes","simplifyBlocksHelper","tree","blockGroup","numChildElements","activeList","isListItemBlock","listItemBlockType","numElementsRemoved","fromDom","listItemElement","numElementsAdded","createExternalHTMLExporter","unified","rehypeParse","rehypeStringify","blocks","createInternalHTMLSerializer","uploadToTmpFilesDotOrg_DEV_ONLY","file","body","isAppleOS","formatKeyboardShortcut","shortcut","mergeCSSClasses","classes","c","isSafari","createDefaultBlockDOMOutputSpec","blockName","htmlTag","blockContentHTMLAttributes","inlineContentHTMLAttributes","attribute","inlineContent","defaultBlockToHTML","toDOM","renderSpec","defaultProps","inheritedProps","camelToDataKebab","str","propsToAttributes","tiptapAttributes","name","_spec","spec","asNumber","getBlockFromPos","getPos","tipTapEditor","blockIdentifier","wrapInBlockStructure","blockType","blockProps","domAttributes","prop","createStronglyTypedTiptapNode","Node","createInternalBlockSpec","implementation","createBlockSpecFromStronglyTypedTiptapNode","requiredExtensions","getBlockSchemaFromSpecs","specs","getParseRules","customParseFunction","rules","createBlockSpec","blockImplementation","div","blockContentDOMAttributes","output","addInlineContentAttributes","inlineContentType","inlineContentProps","addInlineContentKeyboardShortcuts","resolvedPos","createInternalInlineContentSpec","createInlineContentSpecFromTipTapNode","getInlineContentSchemaFromSpecs","getInlineContentParseRules","htmlElement","createInlineContentSpec","inlineContentConfig","inlineContentImplementation","stylePropsToAttributes","addStyleAttributes","styleType","styleValue","createInternalStyleSpec","createStyleSpecFromTipTapMark","getStyleSchemaFromSpecs","getStyleParseRules","createStyleSpec","styleConfig","styleImplementation","Mark","renderResult","BackgroundColorMark","HTMLAttributes","BackgroundColor","TextColorMark","TextColor","getCurrentBlockContentType","headingPropSchema","HeadingBlockContent","parsed","level","InputRule","state","chain","range","Heading","imagePropSchema","textAlignmentToAlignItems","textAlignment","minWidth","Image","wrapper","addImageButton","addImageButtonIcon","addImageButtonText","imageAndCaptionWrapper","imageWrapper","image","leftResizeHandle","rightResizeHandle","caption","handleEditorUpdate","selection","selectedBlock","resizeParams","windowMouseMoveHandler","newWidth","windowMouseUpHandler","addImageButtonMouseDownHandler","addImageButtonClickHandler","imageMouseEnterHandler","imageMouseLeaveHandler","leftResizeHandleMouseDownHandler","rightResizeHandleMouseDownHandler","figure","img","figcaption","handleEnter","selectionEmpty","commands","bulletListItemPropSchema","BulletListItemBlockContent","BulletListItem","PLUGIN_KEY","NumberedListIndexingPlugin","_transactions","_oldState","modified","newIndex","isFirstBlockInDoc","prevBlockInfo","prevBlockContentNode","prevBlockIndex","numberedListItemPropSchema","NumberedListItemBlockContent","NumberedListItem","paragraphPropSchema","ParagraphBlockContent","Paragraph","TableExtension","columnResizing","tableEditing","selectionIsEmpty","selectionIsAtStartOfNode","selectionIsInTableParagraphNode","extension","context","callOrReturn","getExtensionField","tablePropSchema","TableBlockContent","TableParagraph","mergeAttributes","Table","TableHeader","TableCell","TableRow","defaultBlockSpecs","defaultBlockSchema","defaultStyleSpecs","Bold","Italic","Underline","Strike","Code","defaultStyleSchema","defaultInlineContentSpecs","defaultInlineContentSchema","checkDefaultBlockTypeInSchema","checkBlockIsDefaultType","checkBlockTypeHasDefaultProp","checkBlockHasDefaultProp","getNodeById","targetNode","posBeforeNode","insertBlocks","blocksToInsert","referenceBlock","placement","ttEditor","nodesToInsert","insertedBlocks","updateBlock","blockToUpdate","update","blockContainerNode","removeBlocksWithCallback","blocksToRemove","callback","idsOfBlocksToRemove","removedBlocks","removedSize","oldDocSize","newDocSize","notFoundIds","removeBlocks","replaceBlocks","idOfFirstBlock","insertContentAt","position","from","to","isOnlyTextContent","isOnlyBlockContent","selectionToInsertionEnd","removeUnderlines","removeUnderlinesHelper","cleanHTMLToMarkdown","cleanHTMLString","rehypeRemark","remarkGfm","remarkStringify","blocksToMarkdown","externalHTML","getChildIndex","isWhitespaceNode","liftNestedListsToParent","parentListItem","siblingsAfter","sibling","siblingContainer","createGroups","listItem","_detachedDoc","detachedDoc","nestedListsToBlockNoteStructure","elementOrHTML","HTMLToBlocks","html","icSchema","pmSchema","htmlNode","parentNode","DOMParser","code","properties","result","markdownToBlocks","markdown","htmlString","remarkParse","remarkRehype","defaultHandlers","EventEmitter","__publicField","fn","args","callbacks","FormattingToolbarView","pmView","emitUpdate","editorWrapper","composing","isSame","ranges","shouldShow","isNodeSelection","posToDOMRect","formattingToolbarPluginKey","FormattingToolbarProsemirrorPlugin","editorView","LinkToolbarView","hoveredLinkElement","posInHoveredLinkMark","resolvedPosInHoveredLinkMark","marksAtPos","getMarkRange","url","prevLinkMark","linkToolbarPluginKey","LinkToolbarProsemirrorPlugin","findBlock","findParentNode","SuggestionMenuView","decorationNode","suggestionMenuPluginKey","menuName","prevState","prev","next","started","stopped","SuggestionMenuProseMirrorPlugin","triggerCharacter","triggerCharacters","suggestionPluginTransactionMeta","suggestionPluginState","blockNode","DecorationSet","Decoration","createSuggestionMenu","MultipleNodeSelection","Selection","$anchor","$head","_pos","fromResult","toResult","dragImageElement","getDraggableBlockFromCoords","coords","blockPositionFromCoords","docView","desc","blockPositionsFromSelection","beforeFirstBlockPos","afterLastBlockPos","selectionStartInBlockContent","selectionEndInBlockContent","minDepth","startFirstBlockPos","endLastBlockPos","setDragImage","parentClone","getElementIndex","parentElement","targetElement","firstSelectedBlockIndex","lastSelectedBlockIndex","unsetDragImage","inheritedClasses","className","dragStart","e","editorBoundingBox","draggedBlockInSelection","multipleBlocksSelected","NodeSelection","selectedSlice","plainText","SideMenuView","evt","_event","editorOuterBoundingBox","cursorWithinEditor","_c","_d","_e","blockContentBoundingBox","newBlockInsertionPos","newBlockContentPos","sideMenuPluginKey","SideMenuProsemirrorPlugin","ImagePanelView","pluginKey","blockElement","pluginState","imagePanelPluginKey","ImagePanelProsemirrorPlugin","_editor","setHiddenDragImage","unsetHiddenDragImage","domCellAround","target","hideElementsWithClassNames","classNames","elementsToHide","TableHandlesView","colIndex","rowIndex","cellRect","tableRect","blockEl","boundedMouseCoords","tableCellElements","tableCellElement","emitStateUpdate","oldIndex","dispatchDecorationsTransaction","mousePos","tableHandlesPluginKey","rows","rowToMove","cellsToMove","tableElement","cellElement","TableHandlesProsemirrorPlugin","decorations","tableResolvedPos","tableNode","rowResolvedPos","cellResolvedPos","decorationPos","widget","selectedFragmentToHTML","selectedFragment","createCopyToClipboardExtension","acceptedMIMETypes","createPasteFromClipboardExtension","_view","format","mimeType","data","BackgroundColorExtension","Placeholder","placeholders","styleEl","styleSheet","getBaseSelector","additionalSelectors","getSelector","mustBeFocused","mustBeFocusedSelector","blockTypeSelector","placeholder","before","dec","TextAlignmentExtension","TextColorExtension","TrailingNode","plugin","_","__","shouldInsertNodeAtEnd","endPosition","_state","lastNode","lastContentNode","NonEditableBlockPlugin","nodeAttributes","PreviousBlockTypePlugin","timeout","_editorView","_prevState","currentTransactionOriginalOldBlockAttrs","oldNodes","findChildren","oldNodesById","oldNode","oldContentNode","newContentNode","newAttrs","oldAttrs","prevAttrs","decorationAttrs","nodeAttr","decoration","BlockAttributes","BlockContainer","attrs","HTMLAttr","blockOuter","blockHTMLAttributes","dispatch","newBlock","posInBlock","childNodes","oldType","newType","oldContentType","newContentType","TextSelection","posBetweenBlocks","nextNodeIsBlock","prevNodeIsBlock","nextBlockInfo","childBlocksStart","childBlocksEnd","childBlocksRange","prevBlockEndPos","keepType","originalBlockContent","newBlockContent","selectionAtBlockStart","isParagraph","blockAtDocStart","blockAtDocEnd","selectionAtBlockEnd","hasChildBlocks","oldDepth","newPos","newDepth","blockEmpty","blockIndented","BlockGroup","blockGroupHTMLAttributes","Doc","getBlockNoteExtensions","opts","extensions","Gapcursor","HardBreak","Text","Link","styleSpec","a","inlineContentSpec","ext","Dropcursor","Collaboration","defaultRender","user","cursor","label","nonbreakingSpace1","nonbreakingSpace2","CollaborationCursor","History","removeChild","n","f","nestedChild","container","BlockNoteSchema","BlockNoteTipTapEditor","TiptapEditor","cache","oldCreateAndFill","pmNodes","b","createDocument","EditorState","EditorView","blockNoteTipTapOptions","BlockNoteEditor","anyOpts","newOptions","blockNoteUIExtension","initialContent","tiptapOptions","_f","_h","_g","reverse","traverseBlockArray","blockArray","nodeIndex","numNodes","prevNode","nextNode","targetBlock","editable","cb","setSelectionToNextContentEditableBlock","insertOrUpdateBlock","currentBlock","insertedBlock","getDefaultSlashMenuItems","filterSuggestionItems","query","title","aliases","alias","textShorthandToStyledText","partialContentToInlineContent","partialContent","partialBlocksToBlocksForTesting","partialBlocks","partialBlock","partialBlockToBlockForTesting","withDefaults","propKey","propValue","addIdsToBlock","addIdsToBlocks"],"mappings":"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"}
1
+ {"version":3,"file":"blocknote.umd.cjs","sources":["../src/extensions/UniqueID/UniqueID.ts","../src/api/getBlockInfoFromPos.ts","../src/schema/inlineContent/types.ts","../src/util/typescript.ts","../src/api/nodeConversions/nodeConversions.ts","../src/api/exporters/html/util/sharedHTMLConversion.ts","../src/api/exporters/html/util/simplifyBlocksRehypePlugin.ts","../src/api/exporters/html/externalHTMLExporter.ts","../src/api/exporters/html/internalHTMLSerializer.ts","../src/blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts","../src/util/browser.ts","../src/blocks/defaultBlockHelpers.ts","../src/blocks/defaultProps.ts","../src/util/string.ts","../src/schema/blocks/internal.ts","../src/schema/blocks/createSpec.ts","../src/schema/inlineContent/internal.ts","../src/schema/inlineContent/createSpec.ts","../src/schema/styles/internal.ts","../src/schema/styles/createSpec.ts","../src/extensions/BackgroundColor/BackgroundColorMark.ts","../src/extensions/TextColor/TextColorMark.ts","../src/api/getCurrentBlockContentType.ts","../src/blocks/HeadingBlockContent/HeadingBlockContent.ts","../src/blocks/ImageBlockContent/ImageBlockContent.ts","../src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts","../src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts","../src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts","../src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts","../src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts","../src/blocks/TableBlockContent/TableExtension.ts","../src/blocks/TableBlockContent/TableBlockContent.ts","../src/blocks/defaultBlocks.ts","../src/blocks/defaultBlockTypeGuards.ts","../src/api/nodeUtil.ts","../src/api/blockManipulation/blockManipulation.ts","../src/api/exporters/markdown/removeUnderlinesRehypePlugin.ts","../src/api/exporters/markdown/markdownExporter.ts","../src/api/parsers/html/util/nestedLists.ts","../src/api/parsers/html/parseHTML.ts","../src/api/parsers/markdown/parseMarkdown.ts","../src/util/EventEmitter.ts","../src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts","../src/extensions/LinkToolbar/LinkToolbarPlugin.ts","../src/extensions/SuggestionMenu/SuggestionPlugin.ts","../src/extensions/SideMenu/MultipleNodeSelection.ts","../src/extensions/SideMenu/SideMenuPlugin.ts","../src/extensions/ImagePanel/ImageToolbarPlugin.ts","../src/extensions/TableHandles/TableHandlesPlugin.ts","../src/api/exporters/copyExtension.ts","../src/api/parsers/pasteExtension.ts","../src/extensions/BackgroundColor/BackgroundColorExtension.ts","../src/extensions/Placeholder/PlaceholderExtension.ts","../src/extensions/TextAlignment/TextAlignmentExtension.ts","../src/extensions/TextColor/TextColorExtension.ts","../src/extensions/TrailingNode/TrailingNodeExtension.ts","../src/extensions/NonEditableBlocks/NonEditableBlockPlugin.ts","../src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts","../src/pm-nodes/BlockContainer.ts","../src/pm-nodes/BlockGroup.ts","../src/pm-nodes/Doc.ts","../src/editor/BlockNoteExtensions.ts","../src/editor/transformPasted.ts","../src/editor/BlockNoteSchema.ts","../src/editor/BlockNoteTipTapEditor.ts","../src/editor/BlockNoteEditor.ts","../src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts","../src/api/testUtil/partialBlockTestUtil.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 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 [`data-${this.options.attributeName}`]:\n attributes[this.options.attributeName],\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 // console.log(\"appendTransaction\");\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) => {\n let _a, _b;\n return !((_b = (_a = this.options).filterTransaction) === null ||\n _b === void 0\n ? void 0\n : _b.call(_a, tr));\n });\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 newNodes.forEach(({ node, pos }) => {\n let _a;\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 =\n (_a = tr.doc.nodeAt(pos)) === null || _a === void 0\n ? void 0\n : _a.attrs[attributeName];\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 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`\n // so we can do some checks before\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 dragSourceElement = null;\n transformPasted = true;\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, NodeType } from \"prosemirror-model\";\n\nexport type BlockInfoWithoutPositions = {\n id: string;\n node: Node;\n contentNode: Node;\n contentType: NodeType;\n numChildBlocks: number;\n};\n\nexport type BlockInfo = BlockInfoWithoutPositions & {\n startPos: number;\n endPos: number;\n depth: number;\n};\n\n/**\n * Helper function for `getBlockInfoFromPos`, returns information regarding\n * provided blockContainer node.\n * @param blockContainer The blockContainer node to retrieve info for.\n */\nexport function getBlockInfo(blockContainer: Node): BlockInfoWithoutPositions {\n const id = blockContainer.attrs[\"id\"];\n const contentNode = blockContainer.firstChild!;\n const contentType = contentNode.type;\n const numChildBlocks =\n blockContainer.childCount === 2 ? blockContainer.lastChild!.childCount : 0;\n\n return {\n id,\n node: blockContainer,\n contentNode,\n contentType,\n numChildBlocks,\n };\n}\n\n/**\n * Retrieves information regarding the nearest blockContainer node in a\n * ProseMirror doc, relative to a position.\n * @param doc The ProseMirror doc.\n * @param pos An integer position.\n * @returns A BlockInfo object for the nearest blockContainer node.\n */\nexport function getBlockInfoFromPos(doc: Node, pos: number): BlockInfo {\n // If the position is outside the outer block group, we need to move it to the\n // nearest block. This happens when the collaboration plugin is active, where\n // the selection is placed at the very end of the doc.\n const outerBlockGroupStartPos = 1;\n const outerBlockGroupEndPos = doc.nodeSize - 2;\n if (pos <= outerBlockGroupStartPos) {\n pos = outerBlockGroupStartPos + 1;\n\n while (\n doc.resolve(pos).parent.type.name !== \"blockContainer\" &&\n pos < outerBlockGroupEndPos\n ) {\n pos++;\n }\n } else if (pos >= outerBlockGroupEndPos) {\n pos = outerBlockGroupEndPos - 1;\n\n while (\n doc.resolve(pos).parent.type.name !== \"blockContainer\" &&\n pos > outerBlockGroupStartPos\n ) {\n pos--;\n }\n }\n\n // This gets triggered when a node selection on a block is active, i.e. when\n // you drag and drop a block.\n if (doc.resolve(pos).parent.type.name === \"blockGroup\") {\n pos++;\n }\n\n const $pos = doc.resolve(pos);\n\n const maxDepth = $pos.depth;\n let node = $pos.node(maxDepth);\n let depth = maxDepth;\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n if (depth < 0) {\n throw new Error(\n \"Could not find blockContainer node. This can only happen if the underlying BlockNote schema has been edited.\"\n );\n }\n\n if (node.type.name === \"blockContainer\") {\n break;\n }\n\n depth -= 1;\n node = $pos.node(depth);\n }\n\n const { id, contentNode, contentType, numChildBlocks } = getBlockInfo(node);\n\n const startPos = $pos.start(depth);\n const endPos = $pos.end(depth);\n\n return {\n id,\n node,\n contentNode,\n contentType,\n numChildBlocks,\n startPos,\n endPos,\n depth,\n };\n}\n","import { Node } from \"@tiptap/core\";\nimport { PropSchema, Props } from \"../propTypes\";\nimport { StyleSchema, Styles } from \"../styles/types\";\n\nexport type CustomInlineContentConfig = {\n type: string;\n content: \"styled\" | \"none\"; // | \"plain\"\n readonly propSchema: PropSchema;\n // content: \"inline\" | \"none\" | \"table\";\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 node: Node;\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","export class UnreachableCaseError extends Error {\n constructor(val: never) {\n super(`Unreachable case: ${val}`);\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 { Mark, Node, Schema } from \"@tiptap/pm/model\";\n\nimport UniqueID from \"../../extensions/UniqueID/UniqueID\";\nimport type {\n BlockSchema,\n CustomInlineContentConfig,\n CustomInlineContentFromConfig,\n InlineContent,\n InlineContentFromConfig,\n InlineContentSchema,\n PartialCustomInlineContentFromConfig,\n PartialInlineContent,\n PartialLink,\n PartialTableContent,\n StyleSchema,\n StyledText,\n Styles,\n TableContent,\n} from \"../../schema\";\nimport { getBlockInfo } from \"../getBlockInfoFromPos\";\n\nimport type { Block, PartialBlock } from \"../../blocks/defaultBlocks\";\nimport {\n isLinkInlineContent,\n isPartialLinkInlineContent,\n isStyledTextInlineContent,\n} from \"../../schema/inlineContent/types\";\nimport { UnreachableCaseError } from \"../../util/typescript\";\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): 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 marks.push(schema.mark(style));\n } else if (config.propSchema === \"string\") {\n marks.push(schema.mark(style, { stringValue: value }));\n } else {\n throw new UnreachableCaseError(config.propSchema);\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\"].create();\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): 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 )\n );\n return nodes;\n }\n\n for (const styledText of content) {\n nodes.push(...styledTextToNodes(styledText, schema, styleSchema));\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 styleSchema: S\n): Node[] {\n const nodes: Node[] = [];\n\n for (const content of blockContent) {\n if (typeof content === \"string\") {\n nodes.push(...styledTextArrayToNodes(content, schema, styleSchema));\n } else if (isPartialLinkInlineContent(content)) {\n nodes.push(...linkToNodes(content, schema, styleSchema));\n } else if (isStyledTextInlineContent(content)) {\n nodes.push(...styledTextArrayToNodes([content], schema, styleSchema));\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\n): Node[] {\n const rowNodes: Node[] = [];\n\n for (const row of tableContent.rows) {\n const columnNodes: Node[] = [];\n for (const cell of row.cells) {\n let pNode: Node;\n if (!cell) {\n pNode = schema.nodes[\"tableParagraph\"].create({});\n } else if (typeof cell === \"string\") {\n pNode = schema.nodes[\"tableParagraph\"].create({}, schema.text(cell));\n } else {\n const textNodes = inlineContentToNodes(cell, schema, styleSchema);\n pNode = schema.nodes[\"tableParagraph\"].create({}, textNodes);\n }\n\n const cellNode = schema.nodes[\"tableCell\"].create({}, pNode);\n columnNodes.push(cellNode);\n }\n const rowNode = schema.nodes[\"tableRow\"].create({}, 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].create(block.props);\n } else if (typeof block.content === \"string\") {\n contentNode = schema.nodes[type].create(\n block.props,\n schema.text(block.content)\n );\n } else if (Array.isArray(block.content)) {\n const nodes = inlineContentToNodes(block.content, schema, styleSchema);\n contentNode = schema.nodes[type].create(block.props, nodes);\n } else if (block.content.type === \"tableContent\") {\n const nodes = tableContentToNodes(block.content, schema, styleSchema);\n contentNode = schema.nodes[type].create(block.props, nodes);\n } else {\n throw new UnreachableCaseError(block.content.type);\n }\n return contentNode;\n}\n/**\n * Converts a BlockNote block to a TipTap node.\n */\nexport function blockToNode(\n block: PartialBlock<any, any, any>,\n schema: Schema,\n styleSchema: StyleSchema\n) {\n let id = block.id;\n\n if (id === undefined) {\n id = UniqueID.options.generateID();\n }\n\n const contentNode = blockOrInlineContentToContentNode(\n block,\n schema,\n styleSchema\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 groupNode = schema.nodes[\"blockGroup\"].create({}, children);\n\n return schema.nodes[\"blockContainer\"].create(\n {\n id: id,\n ...block.props,\n },\n children.length > 0 ? [contentNode, groupNode] : contentNode\n );\n}\n\n/**\n * Converts an internal (prosemirror) table node contentto a BlockNote Tablecontent\n */\nfunction 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 rows: [],\n };\n\n contentNode.content.forEach((rowNode) => {\n const row: TableContent<I, S>[\"rows\"][0] = {\n cells: [],\n };\n\n rowNode.content.forEach((cellNode) => {\n row.cells.push(\n contentNodeToInlineContent(\n cellNode.firstChild!,\n inlineContentSchema,\n styleSchema\n )\n );\n });\n\n ret.rows.push(row);\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 (\n node.type.name !== \"link\" &&\n node.type.name !== \"text\" &&\n inlineContentSchema[node.type.name]\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 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].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 TipTap node to a BlockNote block.\n */\nexport function nodeToBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n node: Node,\n blockSchema: BSchema,\n inlineContentSchema: I,\n styleSchema: S,\n blockCache?: WeakMap<Node, Block<BSchema, I, S>>\n): Block<BSchema, I, S> {\n if (node.type.name !== \"blockContainer\") {\n throw Error(\n \"Node must be of type blockContainer, but is of type\" +\n node.type.name +\n \".\"\n );\n }\n\n const cachedBlock = blockCache?.get(node);\n\n if (cachedBlock) {\n return cachedBlock;\n }\n\n const blockInfo = getBlockInfo(node);\n\n let id = blockInfo.id;\n\n // Only used for blocks converted from other formats.\n if (id === null) {\n id = UniqueID.options.generateID();\n }\n\n const props: any = {};\n for (const [attr, value] of Object.entries({\n ...node.attrs,\n ...blockInfo.contentNode.attrs,\n })) {\n const blockSpec = blockSchema[blockInfo.contentType.name];\n\n if (!blockSpec) {\n throw Error(\n \"Block is of an unrecognized type: \" + blockInfo.contentType.name\n );\n }\n\n const propSchema = blockSpec.propSchema;\n\n if (attr in propSchema) {\n props[attr] = value;\n }\n }\n\n const blockConfig = blockSchema[blockInfo.contentType.name];\n\n const children: Block<BSchema, I, S>[] = [];\n for (let i = 0; i < blockInfo.numChildBlocks; i++) {\n children.push(\n nodeToBlock(\n node.lastChild!.child(i),\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 content = contentNodeToInlineContent(\n blockInfo.contentNode,\n inlineContentSchema,\n styleSchema\n );\n } else if (blockConfig.content === \"table\") {\n content = contentNodeToTableContent(\n blockInfo.contentNode,\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","import { DOMSerializer, Fragment, Node } from \"prosemirror-model\";\n\nimport type { BlockNoteEditor } from \"../../../../editor/BlockNoteEditor\";\nimport {\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../../../schema\";\nimport { nodeToBlock } from \"../../../nodeConversions/nodeConversions\";\n\nfunction doc(options: { document?: Document }) {\n return options.document || window.document;\n}\n\n// Used to implement `serializeNodeInner` for the `internalHTMLSerializer` and\n// `externalHTMLExporter`. Changes how the content of `blockContainer` nodes is\n// serialized vs the default `DOMSerializer` implementation. For the\n// `blockContent` node, the `toInternalHTML` or `toExternalHTML` function of its\n// corresponding block is used for serialization instead of the node's\n// `renderHTML` method.\nexport const serializeNodeInner = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n node: Node,\n options: { document?: Document },\n serializer: DOMSerializer,\n editor: BlockNoteEditor<BSchema, I, S>,\n toExternalHTML: boolean\n) => {\n if (!serializer.nodes[node.type.name]) {\n throw new Error(\"Serializer is missing a node type: \" + node.type.name);\n }\n\n const { dom, contentDOM } = DOMSerializer.renderSpec(\n doc(options),\n serializer.nodes[node.type.name](node)\n );\n\n if (contentDOM) {\n if (node.isLeaf) {\n throw new RangeError(\"Content hole not allowed in a leaf node spec\");\n }\n\n // Handles converting `blockContainer` nodes to HTML.\n if (node.type.name === \"blockContainer\") {\n const blockContentNode =\n node.childCount > 0 &&\n node.firstChild!.type.spec.group === \"blockContent\"\n ? node.firstChild!\n : undefined;\n const blockGroupNode =\n node.childCount > 0 && node.lastChild!.type.spec.group === \"blockGroup\"\n ? node.lastChild!\n : undefined;\n\n // Converts `blockContent` node using the custom `blockSpec`'s\n // `toExternalHTML` or `toInternalHTML` function.\n // Note: While `blockContainer` nodes should always contain a\n // `blockContent` node according to the schema, PM Fragments don't always\n // conform to the schema. This is unintuitive but important as it occurs\n // when copying only nested blocks.\n if (blockContentNode !== undefined) {\n const impl =\n editor.blockImplementations[blockContentNode.type.name]\n .implementation;\n const toHTML = toExternalHTML\n ? impl.toExternalHTML\n : impl.toInternalHTML;\n const blockContent = toHTML(\n nodeToBlock(\n node,\n editor.schema.blockSchema,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n editor.blockCache\n ),\n editor as any\n );\n\n // Converts inline nodes in the `blockContent` node's content to HTML\n // using their `renderHTML` methods.\n if (blockContent.contentDOM !== undefined) {\n if (node.isLeaf) {\n throw new RangeError(\n \"Content hole not allowed in a leaf node spec\"\n );\n }\n\n blockContent.contentDOM.appendChild(\n serializer.serializeFragment(blockContentNode.content, options)\n );\n }\n\n contentDOM.appendChild(blockContent.dom);\n }\n\n // Converts `blockGroup` node to HTML using its `renderHTML` method.\n if (blockGroupNode !== undefined) {\n serializer.serializeFragment(\n Fragment.from(blockGroupNode),\n options,\n contentDOM\n );\n }\n } else {\n // Converts the node normally, i.e. using its `renderHTML method`.\n serializer.serializeFragment(node.content, options, contentDOM);\n }\n }\n\n return dom as HTMLElement;\n};\n\n// Used to implement `serializeProseMirrorFragment` for the\n// `internalHTMLSerializer` and `externalHTMLExporter`. Does basically the same\n// thing as `serializer.serializeFragment`, but takes fewer arguments and\n// returns a string instead, to make it easier to use.\nexport const serializeProseMirrorFragment = (\n fragment: Fragment,\n serializer: DOMSerializer\n) => {\n const internalHTML = serializer.serializeFragment(fragment);\n const parent = document.createElement(\"div\");\n parent.appendChild(internalHTML);\n\n return parent.innerHTML;\n};\n","import { Element as HASTElement, Parent as HASTParent } from \"hast\";\nimport { fromDom } from \"hast-util-from-dom\";\n\ntype SimplifyBlocksOptions = {\n orderedListItemBlockTypes: Set<string>;\n unorderedListItemBlockTypes: Set<string>;\n};\n\n/**\n * Rehype plugin which converts the HTML output string rendered by BlockNote into a simplified structure which better\n * follows HTML standards. It does several things:\n * - Removes all block related div elements, leaving only the actual content inside the block.\n * - Lifts nested blocks to a higher level for all block types that don't represent list items.\n * - Wraps blocks which represent list items in corresponding ul/ol HTML elements and restructures them to comply\n * with HTML list structure.\n * @param options Options for specifying which block types represent ordered and unordered list items.\n */\nexport function simplifyBlocks(options: SimplifyBlocksOptions) {\n const listItemBlockTypes = new Set<string>([\n ...options.orderedListItemBlockTypes,\n ...options.unorderedListItemBlockTypes,\n ]);\n\n const simplifyBlocksHelper = (tree: HASTParent) => {\n // Checks whether blocks in the tree are wrapped by a parent `blockGroup`\n // element, in which case the `blockGroup`'s children are lifted out, and it\n // is removed.\n if (\n tree.children.length === 1 &&\n (tree.children[0] as HASTElement).properties?.[\"dataNodeType\"] ===\n \"blockGroup\"\n ) {\n const blockGroup = tree.children[0] as HASTElement;\n tree.children.pop();\n tree.children.push(...blockGroup.children);\n }\n\n let numChildElements = tree.children.length;\n let activeList: HASTElement | undefined;\n\n for (let i = 0; i < numChildElements; i++) {\n const blockOuter = tree.children[i] as HASTElement;\n const blockContainer = blockOuter.children[0] as HASTElement;\n const blockContent = blockContainer.children[0] as HASTElement;\n const blockGroup =\n blockContainer.children.length === 2\n ? (blockContainer.children[1] as HASTElement)\n : null;\n\n const isListItemBlock = listItemBlockTypes.has(\n blockContent.properties![\"dataContentType\"] as string\n );\n\n const listItemBlockType = isListItemBlock\n ? options.orderedListItemBlockTypes.has(\n blockContent.properties![\"dataContentType\"] as string\n )\n ? \"ol\"\n : \"ul\"\n : null;\n\n // Plugin runs recursively to process nested blocks.\n if (blockGroup !== null) {\n simplifyBlocksHelper(blockGroup);\n }\n\n // Checks that there is an active list, but the block can't be added to it as it's of a different type.\n if (activeList && activeList.tagName !== listItemBlockType) {\n // Blocks that were copied into the list are removed and the list is inserted in their place.\n tree.children.splice(\n i - activeList.children.length,\n activeList.children.length,\n activeList\n );\n\n // Updates the current index and number of child elements.\n const numElementsRemoved = activeList.children.length - 1;\n i -= numElementsRemoved;\n numChildElements -= numElementsRemoved;\n\n activeList = undefined;\n }\n\n // Checks if the block represents a list item.\n if (isListItemBlock) {\n // Checks if a list isn't already active. We don't have to check if the block and the list are of the same\n // type as this was already done earlier.\n if (!activeList) {\n // Creates a new list element to represent an active list.\n activeList = fromDom(\n document.createElement(listItemBlockType!)\n ) as HASTElement;\n }\n\n // Creates a new list item element to represent the block.\n const listItemElement = fromDom(\n document.createElement(\"li\")\n ) as HASTElement;\n\n // Adds only the content inside the block to the active list.\n listItemElement.children.push(blockContent.children[0]);\n // Nested blocks have already been processed in the recursive function call, so the resulting elements are\n // also added to the active list.\n if (blockGroup !== null) {\n listItemElement.children.push(...blockGroup.children);\n }\n\n // Adds the list item representing the block to the active list.\n activeList.children.push(listItemElement);\n } else if (blockGroup !== null) {\n // Lifts all children out of the current block, as only list items should allow nesting.\n tree.children.splice(i + 1, 0, ...blockGroup.children);\n // Replaces the block with only the content inside it.\n tree.children[i] = blockContent.children[0];\n\n // Updates the current index and number of child elements.\n const numElementsAdded = blockGroup.children.length;\n i += numElementsAdded;\n numChildElements += numElementsAdded;\n } else {\n // Replaces the block with only the content inside it.\n tree.children[i] = blockContent.children[0];\n }\n }\n\n // Since the active list is only inserted after encountering a block which can't be added to it, there are cases\n // where it remains un-inserted after processing all blocks, which are handled here.\n if (activeList) {\n tree.children.splice(\n numChildElements - activeList.children.length,\n activeList.children.length,\n activeList\n );\n }\n };\n\n return simplifyBlocksHelper;\n}\n","import { DOMSerializer, Fragment, Node, Schema } from \"prosemirror-model\";\nimport rehypeParse from \"rehype-parse\";\nimport rehypeStringify from \"rehype-stringify\";\nimport { unified } from \"unified\";\n\nimport { PartialBlock } from \"../../../blocks/defaultBlocks\";\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../../schema\";\nimport { blockToNode } from \"../../nodeConversions/nodeConversions\";\nimport {\n serializeNodeInner,\n serializeProseMirrorFragment,\n} from \"./util/sharedHTMLConversion\";\nimport { simplifyBlocks } from \"./util/simplifyBlocksRehypePlugin\";\n\n// Used to export BlockNote blocks and ProseMirror nodes to HTML for use outside\n// the editor. Blocks are exported using the `toExternalHTML` method in their\n// `blockSpec`, or `toInternalHTML` if `toExternalHTML` is not defined.\n//\n// The HTML created by this serializer is different to what's rendered by the\n// editor to the DOM. This also means that data is likely to be lost when\n// converting back to original blocks. The differences in the output HTML are:\n// 1. It doesn't include the `blockGroup` and `blockContainer` wrappers meaning\n// that nesting is not preserved for non-list-item blocks.\n// 2. `li` items in the output HTML are wrapped in `ul` or `ol` elements.\n// 3. While nesting for list items is preserved, other types of blocks nested\n// inside a list are un-nested and a new list is created after them.\n// 4. The HTML is wrapped in a single `div` element.\n//\n// The serializer has 2 main methods:\n// `exportBlocks`: Exports an array of blocks to HTML.\n// `exportFragment`: Exports a ProseMirror fragment to HTML. This is mostly\n// useful if you want to export a selection which may not start/end at the\n// start/end of a block.\nexport interface ExternalHTMLExporter<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n> {\n exportBlocks: (blocks: PartialBlock<BSchema, I, S>[]) => string;\n exportProseMirrorFragment: (fragment: Fragment) => string;\n}\n\nexport const createExternalHTMLExporter = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n schema: Schema,\n editor: BlockNoteEditor<BSchema, I, S>\n): ExternalHTMLExporter<BSchema, I, S> => {\n const serializer = DOMSerializer.fromSchema(schema) as DOMSerializer & {\n serializeNodeInner: (\n node: Node,\n options: { document?: Document }\n ) => HTMLElement;\n // TODO: Should not be async, but is since we're using a rehype plugin to\n // convert internal HTML to external HTML.\n exportProseMirrorFragment: (fragment: Fragment) => string;\n exportBlocks: (blocks: PartialBlock<BSchema, I, S>[]) => string;\n };\n\n serializer.serializeNodeInner = (\n node: Node,\n options: { document?: Document }\n ) => serializeNodeInner(node, options, serializer, editor, true);\n\n // Like the `internalHTMLSerializer`, also uses `serializeProseMirrorFragment`\n // but additionally runs it through the `simplifyBlocks` rehype plugin to\n // convert the internal HTML to external.\n serializer.exportProseMirrorFragment = (fragment) => {\n const externalHTML = unified()\n .use(rehypeParse, { fragment: true })\n .use(simplifyBlocks, {\n orderedListItemBlockTypes: new Set<string>([\"numberedListItem\"]),\n unorderedListItemBlockTypes: new Set<string>([\"bulletListItem\"]),\n })\n .use(rehypeStringify)\n .processSync(serializeProseMirrorFragment(fragment, serializer));\n\n return externalHTML.value as string;\n };\n\n serializer.exportBlocks = (blocks: PartialBlock<BSchema, I, S>[]) => {\n const nodes = blocks.map((block) =>\n blockToNode(block, schema, editor.schema.styleSchema)\n );\n const blockGroup = schema.nodes[\"blockGroup\"].create(null, nodes);\n\n return serializer.exportProseMirrorFragment(Fragment.from(blockGroup));\n };\n\n return serializer;\n};\n","import { DOMSerializer, Fragment, Node, Schema } from \"prosemirror-model\";\nimport { PartialBlock } from \"../../../blocks/defaultBlocks\";\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../../schema\";\nimport { blockToNode } from \"../../nodeConversions/nodeConversions\";\nimport {\n serializeNodeInner,\n serializeProseMirrorFragment,\n} from \"./util/sharedHTMLConversion\";\n\n// Used to serialize BlockNote blocks and ProseMirror nodes to HTML without\n// losing data. Blocks are exported using the `toInternalHTML` method in their\n// `blockSpec`.\n//\n// The HTML created by this serializer is the same as what's rendered by the\n// editor to the DOM. This means that it retains the same structure as the\n// editor, including the `blockGroup` and `blockContainer` wrappers. This also\n// means that it can be converted back to the original blocks without any data\n// loss.\n//\n// The serializer has 2 main methods:\n// `serializeFragment`: Serializes a ProseMirror fragment to HTML. This is\n// mostly useful if you want to serialize a selection which may not start/end at\n// the start/end of a block.\n// `serializeBlocks`: Serializes an array of blocks to HTML.\nexport interface InternalHTMLSerializer<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n> {\n // TODO: Ideally we would expand the BlockNote API to support partial\n // selections so we don't need this.\n serializeProseMirrorFragment: (fragment: Fragment) => string;\n serializeBlocks: (blocks: PartialBlock<BSchema, I, S>[]) => string;\n}\n\nexport const createInternalHTMLSerializer = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n schema: Schema,\n editor: BlockNoteEditor<BSchema, I, S>\n): InternalHTMLSerializer<BSchema, I, S> => {\n const serializer = DOMSerializer.fromSchema(schema) as DOMSerializer & {\n serializeNodeInner: (\n node: Node,\n options: { document?: Document }\n ) => HTMLElement;\n serializeBlocks: (blocks: PartialBlock<BSchema, I, S>[]) => string;\n serializeProseMirrorFragment: (\n fragment: Fragment,\n options?: { document?: Document | undefined } | undefined,\n target?: HTMLElement | DocumentFragment | undefined\n ) => string;\n };\n\n serializer.serializeNodeInner = (\n node: Node,\n options: { document?: Document }\n ) => serializeNodeInner(node, options, serializer, editor, false);\n\n serializer.serializeProseMirrorFragment = (fragment: Fragment) =>\n serializeProseMirrorFragment(fragment, serializer);\n\n serializer.serializeBlocks = (blocks: PartialBlock<BSchema, I, S>[]) => {\n const nodes = blocks.map((block) =>\n blockToNode(block, schema, editor.schema.styleSchema)\n );\n const blockGroup = schema.nodes[\"blockGroup\"].create(null, nodes);\n\n return serializer.serializeProseMirrorFragment(Fragment.from(blockGroup));\n };\n\n return serializer;\n};\n","/**\n * Uploads a file to tmpfiles.org and returns the URL to the uploaded file.\n *\n * @warning This function should only be used for development purposes, replace with your own backend!\n */\nexport const uploadToTmpFilesDotOrg_DEV_ONLY = async (\n file: File\n): Promise<string> => {\n const body = new FormData();\n body.append(\"file\", file);\n\n const ret = await fetch(\"https://tmpfiles.org/api/v1/upload\", {\n method: \"POST\",\n body: body,\n });\n return (await ret.json()).data.url.replace(\n \"tmpfiles.org/\",\n \"tmpfiles.org/dl/\"\n );\n};\n","export const isAppleOS = () =>\n typeof navigator !== \"undefined\" &&\n (/Mac/.test(navigator.platform) ||\n (/AppleWebKit/.test(navigator.userAgent) &&\n /Mobile\\/\\w+/.test(navigator.userAgent)));\n\nexport function formatKeyboardShortcut(shortcut: string) {\n if (isAppleOS()) {\n return shortcut.replace(\"Mod\", \"⌘\");\n } else {\n return shortcut.replace(\"Mod\", \"Ctrl\");\n }\n}\n\nexport function mergeCSSClasses(...classes: string[]) {\n return classes.filter((c) => c).join(\" \");\n}\n\nexport const isSafari = () =>\n /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n","import { blockToNode } from \"../api/nodeConversions/nodeConversions\";\nimport type { BlockNoteEditor } from \"../editor/BlockNoteEditor\";\nimport type {\n BlockNoDefaults,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../schema\";\nimport { mergeCSSClasses } from \"../util/browser\";\n\n// Function that creates a ProseMirror `DOMOutputSpec` for a default block.\n// Since all default blocks have the same structure (`blockContent` div with a\n// `inlineContent` element inside), this function only needs the block's name\n// for the `data-content-type` attribute of the `blockContent` element and the\n// HTML tag of the `inlineContent` element, as well as any HTML attributes to\n// add to those.\nexport function createDefaultBlockDOMOutputSpec(\n blockName: string,\n htmlTag: string,\n blockContentHTMLAttributes: Record<string, string>,\n inlineContentHTMLAttributes: Record<string, string>\n) {\n const blockContent = document.createElement(\"div\");\n blockContent.className = mergeCSSClasses(\n \"bn-block-content\",\n blockContentHTMLAttributes.class\n );\n blockContent.setAttribute(\"data-content-type\", blockName);\n for (const [attribute, value] of Object.entries(blockContentHTMLAttributes)) {\n if (attribute !== \"class\") {\n blockContent.setAttribute(attribute, value);\n }\n }\n\n const inlineContent = document.createElement(htmlTag);\n inlineContent.className = mergeCSSClasses(\n \"bn-inline-content\",\n inlineContentHTMLAttributes.class\n );\n for (const [attribute, value] of Object.entries(\n inlineContentHTMLAttributes\n )) {\n if (attribute !== \"class\") {\n inlineContent.setAttribute(attribute, value);\n }\n }\n\n blockContent.appendChild(inlineContent);\n\n return {\n dom: blockContent,\n contentDOM: inlineContent,\n };\n}\n\n// Function used to convert default blocks to HTML. It uses the corresponding\n// node's `renderHTML` method to do the conversion by using a default\n// `DOMSerializer`.\nexport const defaultBlockToHTML = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n block: BlockNoDefaults<BSchema, I, S>,\n editor: BlockNoteEditor<BSchema, I, S>\n): {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n} => {\n const node = blockToNode(\n block,\n editor._tiptapEditor.schema,\n editor.schema.styleSchema\n ).firstChild!;\n const toDOM = editor._tiptapEditor.schema.nodes[node.type.name].spec.toDOM;\n\n if (toDOM === undefined) {\n throw new Error(\n \"This block has no default HTML serialization as its corresponding TipTap node doesn't implement `renderHTML`.\"\n );\n }\n\n const renderSpec = toDOM(node);\n\n if (typeof renderSpec !== \"object\" || !(\"dom\" in renderSpec)) {\n throw new Error(\n \"Cannot use this block's default HTML serialization as its corresponding TipTap node's `renderHTML` function does not return an object with the `dom` property.\"\n );\n }\n\n return renderSpec as {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n};\n","import type { Props, PropSchema } from \"../schema\";\n\n// TODO: this system should probably be moved / refactored.\n// The dependency from schema on this file doesn't make sense\n\nexport const defaultProps = {\n backgroundColor: {\n default: \"default\" as const,\n },\n textColor: {\n default: \"default\" as const,\n },\n textAlignment: {\n default: \"left\" as const,\n values: [\"left\", \"center\", \"right\", \"justify\"] as const,\n },\n} satisfies PropSchema;\n\nexport type DefaultProps = Props<typeof defaultProps>;\n\n// Default props which are set on `blockContainer` nodes rather than\n// `blockContent` nodes. Ensures that they are not redundantly added to\n// a custom block's TipTap node attributes.\nexport const inheritedProps = [\"backgroundColor\", \"textColor\"];\n","export function camelToDataKebab(str: string): string {\n return \"data-\" + str.replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase();\n}\n","import {\n Attribute,\n Attributes,\n Editor,\n Extension,\n Node,\n NodeConfig,\n} from \"@tiptap/core\";\nimport { defaultBlockToHTML } from \"../../blocks/defaultBlockHelpers\";\nimport { inheritedProps } from \"../../blocks/defaultProps\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport { mergeCSSClasses } from \"../../util/browser\";\nimport { camelToDataKebab } from \"../../util/string\";\nimport { InlineContentSchema } from \"../inlineContent/types\";\nimport { PropSchema, Props } from \"../propTypes\";\nimport { StyleSchema } from \"../styles/types\";\nimport {\n BlockConfig,\n BlockSchemaFromSpecs,\n BlockSchemaWithBlock,\n BlockSpec,\n BlockSpecs,\n SpecificBlock,\n TiptapBlockImplementation,\n} from \"./types\";\n\n// Function that uses the 'propSchema' of a blockConfig to create a TipTap\n// node's `addAttributes` property.\n// TODO: extract function\nexport function propsToAttributes(propSchema: PropSchema): Attributes {\n const tiptapAttributes: Record<string, Attribute> = {};\n\n Object.entries(propSchema)\n .filter(([name, _spec]) => !inheritedProps.includes(name))\n .forEach(([name, spec]) => {\n tiptapAttributes[name] = {\n default: spec.default,\n keepOnSplit: true,\n // Props are displayed in kebab-case as HTML attributes. If a prop's\n // value is the same as its default, we don't display an HTML\n // attribute for it.\n parseHTML: (element) => {\n const value = element.getAttribute(camelToDataKebab(name));\n\n if (value === null) {\n return null;\n }\n\n if (typeof spec.default === \"boolean\") {\n if (value === \"true\") {\n return true;\n }\n\n if (value === \"false\") {\n return false;\n }\n\n return null;\n }\n\n if (typeof spec.default === \"number\") {\n const asNumber = parseFloat(value);\n const isNumeric =\n !Number.isNaN(asNumber) && Number.isFinite(asNumber);\n\n if (isNumeric) {\n return asNumber;\n }\n\n return null;\n }\n\n return value;\n },\n renderHTML: (attributes) =>\n attributes[name] !== spec.default\n ? {\n [camelToDataKebab(name)]: attributes[name],\n }\n : {},\n };\n });\n\n return tiptapAttributes;\n}\n\n// Used to figure out which block should be rendered. This block is then used to\n// create the node view.\nexport function getBlockFromPos<\n BType extends string,\n Config extends BlockConfig,\n BSchema extends BlockSchemaWithBlock<BType, Config>,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n getPos: (() => number) | boolean,\n editor: BlockNoteEditor<BSchema, I, S>,\n tipTapEditor: Editor,\n type: BType\n) {\n // Gets position of the node\n if (typeof getPos === \"boolean\") {\n throw new Error(\n \"Cannot find node position as getPos is a boolean, not a function.\"\n );\n }\n const pos = getPos();\n // Gets parent blockContainer node\n const blockContainer = tipTapEditor.state.doc.resolve(pos!).node();\n // Gets block identifier\n const blockIdentifier = blockContainer.attrs.id;\n // Gets the block\n const block = editor.getBlock(blockIdentifier)! as SpecificBlock<\n BSchema,\n BType,\n I,\n S\n >;\n if (block.type !== type) {\n throw new Error(\"Block type does not match\");\n }\n\n return block;\n}\n\n// Function that wraps the `dom` element returned from 'blockConfig.render' in a\n// `blockContent` div, which contains the block type and props as HTML\n// attributes. If `blockConfig.render` also returns a `contentDOM`, it also adds\n// an `inlineContent` class to it.\nexport function wrapInBlockStructure<\n BType extends string,\n PSchema extends PropSchema\n>(\n element: {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n destroy?: () => void;\n },\n blockType: BType,\n blockProps: Props<PSchema>,\n propSchema: PSchema,\n domAttributes?: Record<string, string>\n): {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n destroy?: () => void;\n} {\n // Creates `blockContent` element\n const blockContent = document.createElement(\"div\");\n\n // Adds custom HTML attributes\n if (domAttributes !== undefined) {\n for (const [attr, value] of Object.entries(domAttributes)) {\n if (attr !== \"class\") {\n blockContent.setAttribute(attr, value);\n }\n }\n }\n // Sets blockContent class\n blockContent.className = mergeCSSClasses(\n \"bn-block-content\",\n domAttributes?.class || \"\"\n );\n // Sets content type attribute\n blockContent.setAttribute(\"data-content-type\", blockType);\n // Adds props as HTML attributes in kebab-case with \"data-\" prefix. Skips props\n // which are already added as HTML attributes to the parent `blockContent`\n // element (inheritedProps) and props set to their default values.\n for (const [prop, value] of Object.entries(blockProps)) {\n if (!inheritedProps.includes(prop) && value !== propSchema[prop].default) {\n blockContent.setAttribute(camelToDataKebab(prop), value);\n }\n }\n\n blockContent.appendChild(element.dom);\n\n if (element.contentDOM !== undefined) {\n element.contentDOM.className = mergeCSSClasses(\n \"bn-inline-content\",\n element.contentDOM.className\n );\n element.contentDOM.setAttribute(\"data-editable\", \"\");\n }\n\n return {\n ...element,\n dom: blockContent,\n };\n}\n\n// Helper type to keep track of the `name` and `content` properties after calling Node.create.\ntype StronglyTypedTipTapNode<\n Name extends string,\n Content extends \"inline*\" | \"tableRow+\" | \"\"\n> = Node & { name: Name; config: { content: Content } };\n\nexport function createStronglyTypedTiptapNode<\n Name extends string,\n Content extends \"inline*\" | \"tableRow+\" | \"\"\n>(config: NodeConfig & { name: Name; content: Content }) {\n return Node.create(config) as StronglyTypedTipTapNode<Name, Content>; // force re-typing (should be safe as it's type-checked from the config)\n}\n\n// This helper function helps to instantiate a blockspec with a\n// config and implementation that conform to the type of Config\nexport function createInternalBlockSpec<T extends BlockConfig>(\n config: T,\n implementation: TiptapBlockImplementation<\n T,\n any,\n InlineContentSchema,\n StyleSchema\n >\n) {\n return {\n config,\n implementation,\n } satisfies BlockSpec<T, any, InlineContentSchema, StyleSchema>;\n}\n\nexport function createBlockSpecFromStronglyTypedTiptapNode<\n T extends Node,\n P extends PropSchema\n>(node: T, propSchema: P, requiredExtensions?: Array<Extension | Node>) {\n return createInternalBlockSpec(\n {\n type: node.name as T[\"name\"],\n content: (node.config.content === \"inline*\"\n ? \"inline\"\n : node.config.content === \"tableRow+\"\n ? \"table\"\n : \"none\") as T[\"config\"][\"content\"] extends \"inline*\"\n ? \"inline\"\n : T[\"config\"][\"content\"] extends \"tableRow+\"\n ? \"table\"\n : \"none\",\n propSchema,\n },\n {\n node,\n requiredExtensions,\n toInternalHTML: defaultBlockToHTML,\n toExternalHTML: defaultBlockToHTML,\n // parse: () => undefined, // parse rules are in node already\n }\n );\n}\n\nexport function getBlockSchemaFromSpecs<T extends BlockSpecs>(specs: T) {\n return Object.fromEntries(\n Object.entries(specs).map(([key, value]) => [key, value.config])\n ) as BlockSchemaFromSpecs<T>;\n}\n","import { ParseRule } from \"@tiptap/pm/model\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport { InlineContentSchema } from \"../inlineContent/types\";\nimport { StyleSchema } from \"../styles/types\";\nimport {\n createInternalBlockSpec,\n createStronglyTypedTiptapNode,\n getBlockFromPos,\n propsToAttributes,\n wrapInBlockStructure,\n} from \"./internal\";\nimport {\n BlockConfig,\n BlockFromConfig,\n BlockSchemaWithBlock,\n PartialBlockFromConfig,\n} from \"./types\";\n\n// restrict content to \"inline\" and \"none\" only\nexport type CustomBlockConfig = BlockConfig & {\n content: \"inline\" | \"none\";\n};\n\nexport type CustomBlockImplementation<\n T extends CustomBlockConfig,\n I extends InlineContentSchema,\n S extends StyleSchema\n> = {\n render: (\n /**\n * The custom block to render\n */\n block: BlockFromConfig<T, I, S>,\n /**\n * The BlockNote editor instance\n * This is typed generically. If you want an editor with your custom schema, you need to\n * cast it manually, e.g.: `const e = editor as BlockNoteEditor<typeof mySchema>;`\n */\n editor: BlockNoteEditor<BlockSchemaWithBlock<T[\"type\"], T>, I, S>\n // (note) if we want to fix the manual cast, we need to prevent circular references and separate block definition and render implementations\n // or allow manually passing <BSchema>, but that's not possible without passing the other generics because Typescript doesn't support partial inferred generics\n ) => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n destroy?: () => void;\n };\n // Exports block to external HTML. If not defined, the output will be the same\n // as `render(...).dom`. Used to create clipboard data when pasting outside\n // BlockNote.\n // TODO: Maybe can return undefined to ignore when serializing?\n toExternalHTML?: (\n block: BlockFromConfig<T, I, S>,\n editor: BlockNoteEditor<BlockSchemaWithBlock<T[\"type\"], T>, I, S>\n ) => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n\n parse?: (\n el: HTMLElement\n ) => PartialBlockFromConfig<T, I, S>[\"props\"] | undefined;\n};\n\n// Function that uses the 'parse' function of a blockConfig to create a\n// TipTap node's `parseHTML` property. This is only used for parsing content\n// from the clipboard.\nexport function getParseRules(\n config: BlockConfig,\n customParseFunction: CustomBlockImplementation<any, any, any>[\"parse\"]\n) {\n const rules: ParseRule[] = [\n {\n tag: \"[data-content-type=\" + config.type + \"]\",\n contentElement: \"[data-editable]\",\n },\n ];\n\n if (customParseFunction) {\n rules.push({\n tag: \"*\",\n getAttrs(node: string | HTMLElement) {\n if (typeof node === \"string\") {\n return false;\n }\n\n const props = customParseFunction?.(node);\n\n if (props === undefined) {\n return false;\n }\n\n return props;\n },\n });\n }\n // getContent(node, schema) {\n // const block = blockConfig.parse?.(node as HTMLElement);\n //\n // if (block !== undefined && block.content !== undefined) {\n // return Fragment.from(\n // typeof block.content === \"string\"\n // ? schema.text(block.content)\n // : inlineContentToNodes(block.content, schema)\n // );\n // }\n //\n // return Fragment.empty;\n // },\n // });\n // }\n\n return rules;\n}\n\n// A function to create custom block for API consumers\n// we want to hide the tiptap node from API consumers and provide a simpler API surface instead\nexport function createBlockSpec<\n T extends CustomBlockConfig,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(blockConfig: T, blockImplementation: CustomBlockImplementation<T, I, S>) {\n const node = createStronglyTypedTiptapNode({\n name: blockConfig.type as T[\"type\"],\n content: (blockConfig.content === \"inline\"\n ? \"inline*\"\n : \"\") as T[\"content\"] extends \"inline\" ? \"inline*\" : \"\",\n group: \"blockContent\",\n selectable: true,\n\n addAttributes() {\n return propsToAttributes(blockConfig.propSchema);\n },\n\n parseHTML() {\n return getParseRules(blockConfig, blockImplementation.parse);\n },\n\n renderHTML() {\n // renderHTML is not really used, as we always use a nodeView, and we use toExternalHTML / toInternalHTML for serialization\n // There's an edge case when this gets called nevertheless; before the nodeviews have been mounted\n // this is why we implement it with a temporary placeholder\n const div = document.createElement(\"div\");\n div.setAttribute(\"data-tmp-placeholder\", \"true\");\n return {\n dom: div,\n };\n },\n\n addNodeView() {\n return ({ getPos }) => {\n // Gets the BlockNote editor instance\n const editor = this.options.editor;\n // Gets the block\n const block = getBlockFromPos(\n getPos,\n editor,\n this.editor,\n blockConfig.type\n );\n // Gets the custom HTML attributes for `blockContent` nodes\n const blockContentDOMAttributes =\n this.options.domAttributes?.blockContent || {};\n\n const output = blockImplementation.render(block as any, editor);\n\n return wrapInBlockStructure(\n output,\n block.type,\n block.props,\n blockConfig.propSchema,\n blockContentDOMAttributes\n );\n };\n },\n });\n\n if (node.name !== blockConfig.type) {\n throw new Error(\n \"Node name does not match block type. This is a bug in BlockNote.\"\n );\n }\n\n return createInternalBlockSpec(blockConfig, {\n node,\n toInternalHTML: (block, editor) => {\n const blockContentDOMAttributes =\n node.options.domAttributes?.blockContent || {};\n\n const output = blockImplementation.render(block as any, editor as any);\n\n return wrapInBlockStructure(\n output,\n block.type,\n block.props,\n blockConfig.propSchema,\n blockContentDOMAttributes\n );\n },\n toExternalHTML: (block, editor) => {\n const blockContentDOMAttributes =\n node.options.domAttributes?.blockContent || {};\n\n let output = blockImplementation.toExternalHTML?.(\n block as any,\n editor as any\n );\n if (output === undefined) {\n output = blockImplementation.render(block as any, editor as any);\n }\n\n return wrapInBlockStructure(\n output,\n block.type,\n block.props,\n blockConfig.propSchema,\n blockContentDOMAttributes\n );\n },\n });\n}\n","import { KeyboardShortcutCommand, Node } from \"@tiptap/core\";\n\nimport { camelToDataKebab } from \"../../util/string\";\nimport { PropSchema, Props } from \"../propTypes\";\nimport {\n CustomInlineContentConfig,\n InlineContentConfig,\n InlineContentImplementation,\n InlineContentSchemaFromSpecs,\n InlineContentSpec,\n InlineContentSpecs,\n} from \"./types\";\n\n// Function that adds necessary classes and attributes to the `dom` element\n// returned from a custom inline content's 'render' function, to ensure no data\n// is lost on internal copy & paste.\nexport function addInlineContentAttributes<\n IType extends string,\n PSchema extends PropSchema\n>(\n element: {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n },\n inlineContentType: IType,\n inlineContentProps: Props<PSchema>,\n propSchema: PSchema\n): {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n} {\n // Sets content type attribute\n element.dom.setAttribute(\"data-inline-content-type\", inlineContentType);\n // Adds props as HTML attributes in kebab-case with \"data-\" prefix. Skips props\n // set to their default values.\n Object.entries(inlineContentProps)\n .filter(([prop, value]) => value !== propSchema[prop].default)\n .map(([prop, value]) => {\n return [camelToDataKebab(prop), value];\n })\n .forEach(([prop, value]) => element.dom.setAttribute(prop, value));\n\n if (element.contentDOM !== undefined) {\n element.contentDOM.setAttribute(\"data-editable\", \"\");\n }\n\n return element;\n}\n\n// see https://github.com/TypeCellOS/BlockNote/pull/435\nexport function addInlineContentKeyboardShortcuts<\n T extends CustomInlineContentConfig\n>(\n config: T\n): {\n [p: string]: KeyboardShortcutCommand;\n} {\n return {\n Backspace: ({ editor }) => {\n const resolvedPos = editor.state.selection.$from;\n\n return (\n editor.state.selection.empty &&\n resolvedPos.node().type.name === config.type &&\n resolvedPos.parentOffset === 0\n );\n },\n };\n}\n\n// This helper function helps to instantiate a InlineContentSpec with a\n// config and implementation that conform to the type of Config\nexport function createInternalInlineContentSpec<T extends InlineContentConfig>(\n config: T,\n implementation: InlineContentImplementation<T>\n) {\n return {\n config,\n implementation,\n } satisfies InlineContentSpec<T>;\n}\n\nexport function createInlineContentSpecFromTipTapNode<\n T extends Node,\n P extends PropSchema\n>(node: T, propSchema: P) {\n return createInternalInlineContentSpec(\n {\n type: node.name as T[\"name\"],\n propSchema,\n content: node.config.content === \"inline*\" ? \"styled\" : \"none\",\n },\n {\n node,\n }\n );\n}\n\nexport function getInlineContentSchemaFromSpecs<T extends InlineContentSpecs>(\n specs: T\n) {\n return Object.fromEntries(\n Object.entries(specs).map(([key, value]) => [key, value.config])\n ) as InlineContentSchemaFromSpecs<T>;\n}\n","import { Node } from \"@tiptap/core\";\nimport { ParseRule } from \"@tiptap/pm/model\";\nimport { nodeToCustomInlineContent } from \"../../api/nodeConversions/nodeConversions\";\nimport { propsToAttributes } from \"../blocks/internal\";\nimport { Props } from \"../propTypes\";\nimport { StyleSchema } from \"../styles/types\";\nimport {\n addInlineContentAttributes,\n addInlineContentKeyboardShortcuts,\n createInlineContentSpecFromTipTapNode,\n} from \"./internal\";\nimport {\n CustomInlineContentConfig,\n InlineContentConfig,\n InlineContentFromConfig,\n InlineContentSpec,\n} from \"./types\";\n\n// TODO: support serialization\n\nexport type CustomInlineContentImplementation<\n T extends InlineContentConfig,\n // B extends BlockSchema,\n // I extends InlineContentSchema,\n S extends StyleSchema\n> = {\n render: (\n /**\n * The custom inline content to render\n */\n inlineContent: InlineContentFromConfig<T, S>\n /**\n * The BlockNote editor instance\n * This is typed generically. If you want an editor with your custom schema, you need to\n * cast it manually, e.g.: `const e = editor as BlockNoteEditor<typeof mySchema>;`\n */\n // editor: BlockNoteEditor<B, I, S>\n // (note) if we want to fix the manual cast, we need to prevent circular references and separate block definition and render implementations\n // or allow manually passing <BSchema>, but that's not possible without passing the other generics because Typescript doesn't support partial inferred generics\n ) => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n // destroy?: () => void;\n };\n};\n\nexport function getInlineContentParseRules(\n config: CustomInlineContentConfig\n): ParseRule[] {\n return [\n {\n tag: `[data-inline-content-type=\"${config.type}\"]`,\n contentElement: (element) => {\n const htmlElement = element as HTMLElement;\n\n if (htmlElement.matches(\"[data-editable]\")) {\n return htmlElement;\n }\n\n return htmlElement.querySelector(\"[data-editable]\") || htmlElement;\n },\n },\n ];\n}\n\nexport function createInlineContentSpec<\n T extends CustomInlineContentConfig,\n S extends StyleSchema\n>(\n inlineContentConfig: T,\n inlineContentImplementation: CustomInlineContentImplementation<T, S>\n): InlineContentSpec<T> {\n const node = Node.create({\n name: inlineContentConfig.type,\n inline: true,\n group: \"inline\",\n selectable: inlineContentConfig.content === \"styled\",\n atom: inlineContentConfig.content === \"none\",\n content: (inlineContentConfig.content === \"styled\"\n ? \"inline*\"\n : \"\") as T[\"content\"] extends \"styled\" ? \"inline*\" : \"\",\n\n addAttributes() {\n return propsToAttributes(inlineContentConfig.propSchema);\n },\n\n addKeyboardShortcuts() {\n return addInlineContentKeyboardShortcuts(inlineContentConfig);\n },\n\n parseHTML() {\n return getInlineContentParseRules(inlineContentConfig);\n },\n\n renderHTML({ node }) {\n const editor = this.options.editor;\n\n const output = inlineContentImplementation.render(\n nodeToCustomInlineContent(\n node,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema\n ) as any as InlineContentFromConfig<T, S> // TODO: fix cast\n );\n\n return addInlineContentAttributes(\n output,\n inlineContentConfig.type,\n node.attrs as Props<T[\"propSchema\"]>,\n inlineContentConfig.propSchema\n );\n },\n });\n\n return createInlineContentSpecFromTipTapNode(\n node,\n inlineContentConfig.propSchema\n ) as InlineContentSpec<T>; // TODO: fix cast\n}\n","import { Attributes, Mark } from \"@tiptap/core\";\nimport {\n StyleConfig,\n StyleImplementation,\n StylePropSchema,\n StyleSchemaFromSpecs,\n StyleSpec,\n StyleSpecs,\n} from \"./types\";\n\nexport function stylePropsToAttributes(\n propSchema: StylePropSchema\n): Attributes {\n if (propSchema === \"boolean\") {\n return {};\n }\n return {\n stringValue: {\n default: undefined,\n keepOnSplit: true,\n parseHTML: (element) => element.getAttribute(\"data-value\"),\n renderHTML: (attributes) =>\n attributes.stringValue !== undefined\n ? {\n \"data-value\": attributes.stringValue,\n }\n : {},\n },\n };\n}\n\n// Function that adds necessary classes and attributes to the `dom` element\n// returned from a custom style's 'render' function, to ensure no data is lost\n// on internal copy & paste.\nexport function addStyleAttributes<\n SType extends string,\n PSchema extends StylePropSchema\n>(\n element: {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n },\n styleType: SType,\n styleValue: PSchema extends \"boolean\" ? undefined : string,\n propSchema: PSchema\n): {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n} {\n // Sets content type attribute\n element.dom.setAttribute(\"data-style-type\", styleType);\n // Adds style value as an HTML attribute in kebab-case with \"data-\" prefix, if\n // the style takes a string value.\n if (propSchema === \"string\") {\n element.dom.setAttribute(\"data-value\", styleValue as string);\n }\n\n if (element.contentDOM !== undefined) {\n element.contentDOM.setAttribute(\"data-editable\", \"\");\n }\n\n return element;\n}\n\n// This helper function helps to instantiate a stylespec with a\n// config and implementation that conform to the type of Config\nexport function createInternalStyleSpec<T extends StyleConfig>(\n config: T,\n implementation: StyleImplementation\n) {\n return {\n config,\n implementation,\n } satisfies StyleSpec<T>;\n}\n\nexport function createStyleSpecFromTipTapMark<\n T extends Mark,\n P extends StylePropSchema\n>(mark: T, propSchema: P) {\n return createInternalStyleSpec(\n {\n type: mark.name as T[\"name\"],\n propSchema,\n },\n {\n mark,\n }\n );\n}\n\nexport function getStyleSchemaFromSpecs<T extends StyleSpecs>(specs: T) {\n return Object.fromEntries(\n Object.entries(specs).map(([key, value]) => [key, value.config])\n ) as StyleSchemaFromSpecs<T>;\n}\n","import { Mark } from \"@tiptap/core\";\nimport { ParseRule } from \"@tiptap/pm/model\";\nimport {\n addStyleAttributes,\n createInternalStyleSpec,\n stylePropsToAttributes,\n} from \"./internal\";\nimport { StyleConfig, StyleSpec } from \"./types\";\nimport {UnreachableCaseError} from \"../../util/typescript\";\n\nexport type CustomStyleImplementation<T extends StyleConfig> = {\n render: T[\"propSchema\"] extends \"boolean\"\n ? () => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n }\n : (value: string) => {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n};\n\n// TODO: support serialization\n\nexport function getStyleParseRules(config: StyleConfig): ParseRule[] {\n return [\n {\n tag: `[data-style-type=\"${config.type}\"]`,\n contentElement: (element) => {\n const htmlElement = element as HTMLElement;\n\n if (htmlElement.matches(\"[data-editable]\")) {\n return htmlElement;\n }\n\n return htmlElement.querySelector(\"[data-editable]\") || htmlElement;\n },\n },\n ];\n}\n\nexport function createStyleSpec<T extends StyleConfig>(\n styleConfig: T,\n styleImplementation: CustomStyleImplementation<T>\n): StyleSpec<T> {\n const mark = Mark.create({\n name: styleConfig.type,\n\n addAttributes() {\n return stylePropsToAttributes(styleConfig.propSchema);\n },\n\n parseHTML() {\n return getStyleParseRules(styleConfig);\n },\n\n renderHTML({ mark }) {\n let renderResult: {\n dom: HTMLElement;\n contentDOM?: HTMLElement;\n };\n\n if (styleConfig.propSchema === \"boolean\") {\n // @ts-ignore not sure why this is complaining\n renderResult = styleImplementation.render();\n } else if (styleConfig.propSchema === \"string\") {\n renderResult = styleImplementation.render(mark.attrs.stringValue);\n } else {\n throw new UnreachableCaseError(styleConfig.propSchema);\n }\n\n // const renderResult = styleImplementation.render();\n return addStyleAttributes(\n renderResult,\n styleConfig.type,\n mark.attrs.stringValue,\n styleConfig.propSchema\n );\n },\n });\n\n return createInternalStyleSpec(styleConfig, {\n mark,\n });\n}\n","import { Mark } from \"@tiptap/core\";\nimport { createStyleSpecFromTipTapMark } from \"../../schema\";\n\nconst BackgroundColorMark = Mark.create({\n name: \"backgroundColor\",\n\n addAttributes() {\n return {\n stringValue: {\n default: undefined,\n parseHTML: (element) => element.getAttribute(\"data-background-color\"),\n renderHTML: (attributes) => ({\n \"data-background-color\": attributes.stringValue,\n }),\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"span\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n if (element.hasAttribute(\"data-background-color\")) {\n return {\n stringValue: element.getAttribute(\"data-background-color\"),\n };\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"span\", HTMLAttributes, 0];\n },\n});\n\nexport const BackgroundColor = createStyleSpecFromTipTapMark(\n BackgroundColorMark,\n \"string\"\n);\n","import { Mark } from \"@tiptap/core\";\nimport { createStyleSpecFromTipTapMark } from \"../../schema\";\n\nconst TextColorMark = Mark.create({\n name: \"textColor\",\n\n addAttributes() {\n return {\n stringValue: {\n default: undefined,\n parseHTML: (element) => element.getAttribute(\"data-text-color\"),\n renderHTML: (attributes) => ({\n \"data-text-color\": attributes.stringValue,\n }),\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: \"span\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n if (element.hasAttribute(\"data-text-color\")) {\n return { stringValue: element.getAttribute(\"data-text-color\") };\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"span\", HTMLAttributes, 0];\n },\n});\n\nexport const TextColor = createStyleSpecFromTipTapMark(TextColorMark, \"string\");\n","import { Editor } from \"@tiptap/core\";\nimport { getBlockInfoFromPos } from \"./getBlockInfoFromPos\";\n\n// Used to get the content type of the block that the text cursor is in. This is\n// a band-aid fix to prevent input rules and keyboard shortcuts from triggering\n// in tables, but really those should be extended to work with block selections.\nexport const getCurrentBlockContentType = (editor: Editor) => {\n const { contentType } = getBlockInfoFromPos(\n editor.state.doc,\n editor.state.selection.from\n );\n\n return contentType.spec.content;\n};\n","import { InputRule } from \"@tiptap/core\";\nimport {\n PropSchema,\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../schema\";\nimport { createDefaultBlockDOMOutputSpec } from \"../defaultBlockHelpers\";\nimport { defaultProps } from \"../defaultProps\";\nimport { getCurrentBlockContentType } from \"../../api/getCurrentBlockContentType\";\n\nexport const headingPropSchema = {\n ...defaultProps,\n level: { default: 1, values: [1, 2, 3] as const },\n} satisfies PropSchema;\n\nconst HeadingBlockContent = createStronglyTypedTiptapNode({\n name: \"heading\",\n content: \"inline*\",\n group: \"blockContent\",\n addAttributes() {\n return {\n level: {\n default: 1,\n // instead of \"level\" attributes, use \"data-level\"\n parseHTML: (element) => {\n const attr = element.getAttribute(\"data-level\")!;\n const parsed = parseInt(attr);\n if (isFinite(parsed)) {\n return parsed;\n }\n return undefined;\n },\n renderHTML: (attributes) => {\n return {\n \"data-level\": (attributes.level as number).toString(),\n };\n },\n },\n };\n },\n\n addInputRules() {\n return [\n ...[1, 2, 3].map((level) => {\n // Creates a heading of appropriate level when starting with \"#\", \"##\", or \"###\".\n return new InputRule({\n find: new RegExp(`^(#{${level}})\\\\s$`),\n handler: ({ state, chain, range }) => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return;\n }\n\n chain()\n .BNUpdateBlock(state.selection.from, {\n type: \"heading\",\n props: {\n level: level as any,\n },\n })\n // Removes the \"#\" character(s) used to set the heading.\n .deleteRange({ from: range.from, to: range.to });\n },\n });\n }),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n \"Mod-Alt-1\": () => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return true;\n }\n\n return this.editor.commands.BNUpdateBlock(\n this.editor.state.selection.anchor,\n {\n type: \"heading\",\n props: {\n level: 1 as any,\n },\n }\n );\n },\n \"Mod-Alt-2\": () => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return true;\n }\n\n return this.editor.commands.BNUpdateBlock(\n this.editor.state.selection.anchor,\n {\n type: \"heading\",\n props: {\n level: 2 as any,\n },\n }\n );\n },\n \"Mod-Alt-3\": () => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return true;\n }\n\n return this.editor.commands.BNUpdateBlock(\n this.editor.state.selection.anchor,\n {\n type: \"heading\",\n props: {\n level: 3 as any,\n },\n }\n );\n },\n };\n },\n parseHTML() {\n return [\n {\n tag: \"div[data-content-type=\" + this.name + \"]\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n return {\n level: element.getAttribute(\"data-level\"),\n };\n },\n },\n {\n tag: \"h1\",\n attrs: { level: 1 },\n node: \"heading\",\n },\n {\n tag: \"h2\",\n attrs: { level: 2 },\n node: \"heading\",\n },\n {\n tag: \"h3\",\n attrs: { level: 3 },\n node: \"heading\",\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n `h${node.attrs.level}`,\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {}\n );\n },\n});\n\nexport const Heading = createBlockSpecFromStronglyTypedTiptapNode(\n HeadingBlockContent,\n headingPropSchema\n);\n","import type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\n\nimport {\n BlockFromConfig,\n BlockSchemaWithBlock,\n CustomBlockConfig,\n InlineContentSchema,\n PropSchema,\n StyleSchema,\n createBlockSpec,\n} from \"../../schema\";\nimport { defaultProps } from \"../defaultProps\";\n\nexport const imagePropSchema = {\n textAlignment: defaultProps.textAlignment,\n backgroundColor: defaultProps.backgroundColor,\n // Image url.\n url: {\n default: \"\" as const,\n },\n // Image caption.\n caption: {\n default: \"\" as const,\n },\n // Image width in px.\n width: {\n default: 512 as const,\n },\n} satisfies PropSchema;\n\n// Converts text alignment prop values to the flexbox `align-items` values.\nconst textAlignmentToAlignItems = (\n textAlignment: \"left\" | \"center\" | \"right\" | \"justify\"\n): \"flex-start\" | \"center\" | \"flex-end\" => {\n switch (textAlignment) {\n case \"left\":\n return \"flex-start\";\n case \"center\":\n return \"center\";\n case \"right\":\n return \"flex-end\";\n default:\n return \"flex-start\";\n }\n};\n\n// Min image width in px.\nconst minWidth = 64;\n\nconst blockConfig = {\n type: \"image\" as const,\n propSchema: imagePropSchema,\n content: \"none\",\n} satisfies CustomBlockConfig;\n\nexport const renderImage = (\n block: BlockFromConfig<typeof blockConfig, InlineContentSchema, StyleSchema>,\n editor: BlockNoteEditor<BlockSchemaWithBlock<\"image\", typeof blockConfig>>\n) => {\n // Wrapper element to set the image alignment, contains both image/image\n // upload dashboard and caption.\n const wrapper = document.createElement(\"div\");\n wrapper.className = \"bn-image-block-content-wrapper\";\n wrapper.style.alignItems = textAlignmentToAlignItems(\n block.props.textAlignment\n );\n\n // Button element that acts as a placeholder for images with no src.\n const addImageButton = document.createElement(\"div\");\n addImageButton.className = \"bn-add-image-button\";\n\n // Icon for the add image button.\n const addImageButtonIcon = document.createElement(\"div\");\n addImageButtonIcon.className = \"bn-add-image-button-icon\";\n\n // Text for the add image button.\n const addImageButtonText = document.createElement(\"p\");\n addImageButtonText.className = \"bn-add-image-button-text\";\n addImageButtonText.innerText = \"Add Image\";\n\n // Wrapper element for the image, resize handles and caption.\n const imageAndCaptionWrapper = document.createElement(\"div\");\n imageAndCaptionWrapper.className = \"bn-image-and-caption-wrapper\";\n\n // Wrapper element for the image and resize handles.\n const imageWrapper = document.createElement(\"div\");\n imageWrapper.className = \"bn-image-wrapper\";\n\n // Image element.\n const image = document.createElement(\"img\");\n image.className = \"bn-image\";\n image.src = block.props.url;\n image.alt = \"placeholder\";\n image.contentEditable = \"false\";\n image.draggable = false;\n image.style.width = `${Math.min(\n block.props.width,\n editor.domElement.firstElementChild!.clientWidth\n )}px`;\n\n // Resize handle elements.\n const leftResizeHandle = document.createElement(\"div\");\n leftResizeHandle.className = \"bn-image-resize-handle\";\n leftResizeHandle.style.left = \"4px\";\n const rightResizeHandle = document.createElement(\"div\");\n rightResizeHandle.className = \"bn-image-resize-handle\";\n rightResizeHandle.style.right = \"4px\";\n\n // Caption element.\n const caption = document.createElement(\"p\");\n caption.className = \"bn-image-caption\";\n caption.innerText = block.props.caption;\n caption.style.padding = block.props.caption ? \"4px\" : \"\";\n\n // Adds a light blue outline to selected image blocks.\n const handleEditorUpdate = () => {\n const selection = editor.getSelection()?.blocks || [];\n const currentBlock = editor.getTextCursorPosition().block;\n\n const isSelected =\n [currentBlock, ...selection].find(\n (selectedBlock) => selectedBlock.id === block.id\n ) !== undefined;\n\n if (isSelected) {\n addImageButton.style.outline = \"4px solid rgb(100, 160, 255)\";\n imageAndCaptionWrapper.style.outline = \"4px solid rgb(100, 160, 255)\";\n } else {\n addImageButton.style.outline = \"\";\n imageAndCaptionWrapper.style.outline = \"\";\n }\n };\n editor.onEditorContentChange(handleEditorUpdate);\n editor.onEditorSelectionChange(handleEditorUpdate);\n\n // Temporary parameters set when the user begins resizing the image, used to\n // calculate the new width of the image.\n let resizeParams:\n | {\n handleUsed: \"left\" | \"right\";\n initialWidth: number;\n initialClientX: number;\n }\n | undefined;\n\n // Updates the image width with an updated width depending on the cursor X\n // offset from when the resize began, and which resize handle is being used.\n const windowMouseMoveHandler = (event: MouseEvent) => {\n if (!resizeParams) {\n if (\n !editor.isEditable &&\n imageWrapper.contains(leftResizeHandle) &&\n imageWrapper.contains(rightResizeHandle)\n ) {\n imageWrapper.removeChild(leftResizeHandle);\n imageWrapper.removeChild(rightResizeHandle);\n }\n\n return;\n }\n\n let newWidth: number;\n\n if (textAlignmentToAlignItems(block.props.textAlignment) === \"center\") {\n if (resizeParams.handleUsed === \"left\") {\n newWidth =\n resizeParams.initialWidth +\n (resizeParams.initialClientX - event.clientX) * 2;\n } else {\n newWidth =\n resizeParams.initialWidth +\n (event.clientX - resizeParams.initialClientX) * 2;\n }\n } else {\n if (resizeParams.handleUsed === \"left\") {\n newWidth =\n resizeParams.initialWidth +\n resizeParams.initialClientX -\n event.clientX;\n } else {\n newWidth =\n resizeParams.initialWidth +\n event.clientX -\n resizeParams.initialClientX;\n }\n }\n\n // Ensures the image is not wider than the editor and not smaller than a\n // predetermined minimum width.\n if (newWidth < minWidth) {\n image.style.width = `${minWidth}px`;\n } else if (newWidth > editor.domElement.firstElementChild!.clientWidth) {\n image.style.width = `${\n editor.domElement.firstElementChild!.clientWidth\n }px`;\n } else {\n image.style.width = `${newWidth}px`;\n }\n };\n // Stops mouse movements from resizing the image and updates the block's\n // `width` prop to the new value.\n const windowMouseUpHandler = (event: MouseEvent) => {\n // Hides the drag handles if the cursor is no longer over the image.\n if (\n (!event.target ||\n !imageWrapper.contains(event.target as Node) ||\n !editor.isEditable) &&\n imageWrapper.contains(leftResizeHandle) &&\n imageWrapper.contains(rightResizeHandle)\n ) {\n imageWrapper.removeChild(leftResizeHandle);\n imageWrapper.removeChild(rightResizeHandle);\n }\n\n if (!resizeParams) {\n return;\n }\n\n resizeParams = undefined;\n\n editor.updateBlock(block, {\n type: \"image\",\n props: {\n // Removes \"px\" from the end of the width string and converts to float.\n width: parseFloat(image.style.width.slice(0, -2)) as any,\n },\n });\n };\n\n // Prevents focus from moving to the button.\n const addImageButtonMouseDownHandler = (event: MouseEvent) => {\n event.preventDefault();\n };\n // Opens the image toolbar.\n const addImageButtonClickHandler = () => {\n editor._tiptapEditor.view.dispatch(\n editor._tiptapEditor.state.tr.setMeta(editor.imagePanel!.plugin, {\n block: block,\n })\n );\n };\n\n // Shows the resize handles when hovering over the image with the cursor.\n const imageMouseEnterHandler = () => {\n if (editor.isEditable) {\n imageWrapper.appendChild(leftResizeHandle);\n imageWrapper.appendChild(rightResizeHandle);\n }\n };\n // Hides the resize handles when the cursor leaves the image, unless the\n // cursor moves to one of the resize handles.\n const imageMouseLeaveHandler = (event: MouseEvent) => {\n if (\n event.relatedTarget === leftResizeHandle ||\n event.relatedTarget === rightResizeHandle\n ) {\n return;\n }\n\n if (resizeParams) {\n return;\n }\n\n if (\n editor.isEditable &&\n imageWrapper.contains(leftResizeHandle) &&\n imageWrapper.contains(rightResizeHandle)\n ) {\n imageWrapper.removeChild(leftResizeHandle);\n imageWrapper.removeChild(rightResizeHandle);\n }\n };\n\n // Sets the resize params, allowing the user to begin resizing the image by\n // moving the cursor left or right.\n const leftResizeHandleMouseDownHandler = (event: MouseEvent) => {\n event.preventDefault();\n\n imageWrapper.appendChild(leftResizeHandle);\n imageWrapper.appendChild(rightResizeHandle);\n\n resizeParams = {\n handleUsed: \"left\",\n initialWidth: block.props.width,\n initialClientX: event.clientX,\n };\n };\n const rightResizeHandleMouseDownHandler = (event: MouseEvent) => {\n event.preventDefault();\n\n imageWrapper.appendChild(leftResizeHandle);\n imageWrapper.appendChild(rightResizeHandle);\n\n resizeParams = {\n handleUsed: \"right\",\n initialWidth: block.props.width,\n initialClientX: event.clientX,\n };\n };\n\n addImageButton.appendChild(addImageButtonIcon);\n addImageButton.appendChild(addImageButtonText);\n\n imageAndCaptionWrapper.appendChild(imageWrapper);\n imageWrapper.appendChild(image);\n imageAndCaptionWrapper.appendChild(caption);\n\n if (block.props.url === \"\") {\n wrapper.appendChild(addImageButton);\n } else {\n wrapper.appendChild(imageAndCaptionWrapper);\n }\n\n window.addEventListener(\"mousemove\", windowMouseMoveHandler);\n window.addEventListener(\"mouseup\", windowMouseUpHandler);\n addImageButton.addEventListener(\"mousedown\", addImageButtonMouseDownHandler);\n addImageButton.addEventListener(\"click\", addImageButtonClickHandler);\n image.addEventListener(\"mouseenter\", imageMouseEnterHandler);\n image.addEventListener(\"mouseleave\", imageMouseLeaveHandler);\n leftResizeHandle.addEventListener(\n \"mousedown\",\n leftResizeHandleMouseDownHandler\n );\n rightResizeHandle.addEventListener(\n \"mousedown\",\n rightResizeHandleMouseDownHandler\n );\n\n return {\n dom: wrapper,\n destroy: () => {\n window.removeEventListener(\"mousemove\", windowMouseMoveHandler);\n window.removeEventListener(\"mouseup\", windowMouseUpHandler);\n addImageButton.removeEventListener(\n \"mousedown\",\n addImageButtonMouseDownHandler\n );\n addImageButton.removeEventListener(\"click\", addImageButtonClickHandler);\n leftResizeHandle.removeEventListener(\n \"mousedown\",\n leftResizeHandleMouseDownHandler\n );\n rightResizeHandle.removeEventListener(\n \"mousedown\",\n rightResizeHandleMouseDownHandler\n );\n },\n };\n};\n\nexport const Image = createBlockSpec(\n {\n type: \"image\" as const,\n propSchema: imagePropSchema,\n content: \"none\",\n },\n {\n render: renderImage,\n toExternalHTML: (block) => {\n if (block.props.url === \"\") {\n const div = document.createElement(\"p\");\n div.innerHTML = \"Add Image\";\n\n return {\n dom: div,\n };\n }\n\n const figure = document.createElement(\"figure\");\n\n const img = document.createElement(\"img\");\n img.src = block.props.url;\n figure.appendChild(img);\n\n if (block.props.caption !== \"\") {\n const figcaption = document.createElement(\"figcaption\");\n figcaption.innerHTML = block.props.caption;\n figure.appendChild(figcaption);\n }\n\n return {\n dom: figure,\n };\n },\n parse: (element: HTMLElement) => {\n if (element.tagName === \"FIGURE\") {\n const img = element.querySelector(\"img\");\n const caption = element.querySelector(\"figcaption\");\n return {\n url: img?.getAttribute(\"src\") || \"\",\n caption:\n caption?.textContent || img?.getAttribute(\"alt\") || undefined,\n };\n } else if (element.tagName === \"IMG\") {\n return {\n url: element.getAttribute(\"src\") || \"\",\n caption: element.getAttribute(\"alt\") || undefined,\n };\n }\n\n return undefined;\n },\n }\n);\n","import { Editor } from \"@tiptap/core\";\nimport { getBlockInfoFromPos } from \"../../api/getBlockInfoFromPos\";\n\nexport const handleEnter = (editor: Editor) => {\n const { node, contentType } = getBlockInfoFromPos(\n editor.state.doc,\n editor.state.selection.from\n )!;\n\n const selectionEmpty =\n editor.state.selection.anchor === editor.state.selection.head;\n\n if (\n !(\n contentType.name === \"bulletListItem\" ||\n contentType.name === \"numberedListItem\"\n ) ||\n !selectionEmpty\n ) {\n return false;\n }\n\n return editor.commands.first(({ state, chain, commands }) => [\n () =>\n // Changes list item block to a text block if the content is empty.\n commands.command(() => {\n if (node.textContent.length === 0) {\n return commands.BNUpdateBlock(state.selection.from, {\n type: \"paragraph\",\n props: {},\n });\n }\n\n return false;\n }),\n\n () =>\n // Splits the current block, moving content inside that's after the cursor to a new block of the same type\n // below.\n commands.command(() => {\n if (node.textContent.length > 0) {\n chain()\n .deleteSelection()\n .BNSplitBlock(state.selection.from, true)\n .run();\n\n return true;\n }\n\n return false;\n }),\n ]);\n};\n","import { InputRule } from \"@tiptap/core\";\nimport {\n PropSchema,\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../../schema\";\nimport { createDefaultBlockDOMOutputSpec } from \"../../defaultBlockHelpers\";\nimport { defaultProps } from \"../../defaultProps\";\nimport { handleEnter } from \"../ListItemKeyboardShortcuts\";\nimport { getCurrentBlockContentType } from \"../../../api/getCurrentBlockContentType\";\n\nexport const bulletListItemPropSchema = {\n ...defaultProps,\n} satisfies PropSchema;\n\nconst BulletListItemBlockContent = createStronglyTypedTiptapNode({\n name: \"bulletListItem\",\n content: \"inline*\",\n group: \"blockContent\",\n addInputRules() {\n return [\n // Creates an unordered list when starting with \"-\", \"+\", or \"*\".\n new InputRule({\n find: new RegExp(`^[-+*]\\\\s$`),\n handler: ({ state, chain, range }) => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return;\n }\n\n chain()\n .BNUpdateBlock(state.selection.from, {\n type: \"bulletListItem\",\n props: {},\n })\n // Removes the \"-\", \"+\", or \"*\" character used to set the list.\n .deleteRange({ from: range.from, to: range.to });\n },\n }),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n Enter: () => handleEnter(this.editor),\n \"Mod-Shift-8\": () => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return true;\n }\n\n return this.editor.commands.BNUpdateBlock(\n this.editor.state.selection.anchor,\n {\n type: \"bulletListItem\",\n props: {},\n }\n );\n },\n };\n },\n\n parseHTML() {\n return [\n // Case for regular HTML list structure.\n {\n tag: \"div[data-content-type=\" + this.name + \"]\", // TODO: remove if we can't come up with test case that needs this\n },\n {\n tag: \"li\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const parent = element.parentElement;\n\n if (parent === null) {\n return false;\n }\n\n if (\n parent.tagName === \"UL\" ||\n (parent.tagName === \"DIV\" && parent.parentElement!.tagName === \"UL\")\n ) {\n return {};\n }\n\n return false;\n },\n node: \"bulletListItem\",\n },\n // Case for BlockNote list structure.\n {\n tag: \"p\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const parent = element.parentElement;\n\n if (parent === null) {\n return false;\n }\n\n if (parent.getAttribute(\"data-content-type\") === \"bulletListItem\") {\n return {};\n }\n\n return false;\n },\n priority: 300,\n node: \"bulletListItem\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n // We use a <p> tag, because for <li> tags we'd need a <ul> element to put\n // them in to be semantically correct, which we can't have due to the\n // schema.\n \"p\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {}\n );\n },\n});\n\nexport const BulletListItem = createBlockSpecFromStronglyTypedTiptapNode(\n BulletListItemBlockContent,\n bulletListItemPropSchema\n);\n","import { Plugin, PluginKey } from \"prosemirror-state\";\nimport { getBlockInfoFromPos } from \"../../../api/getBlockInfoFromPos\";\n\n// ProseMirror Plugin which automatically assigns indices to ordered list items per nesting level.\nconst PLUGIN_KEY = new PluginKey(`numbered-list-indexing`);\nexport const NumberedListIndexingPlugin = () => {\n return new Plugin({\n key: PLUGIN_KEY,\n appendTransaction: (_transactions, _oldState, newState) => {\n const tr = newState.tr;\n tr.setMeta(\"numberedListIndexing\", true);\n\n let modified = false;\n\n // Traverses each node the doc using DFS, so blocks which are on the same nesting level will be traversed in the\n // same order they appear. This means the index of each list item block can be calculated by incrementing the\n // index of the previous list item block.\n newState.doc.descendants((node, pos) => {\n if (\n node.type.name === \"blockContainer\" &&\n node.firstChild!.type.name === \"numberedListItem\"\n ) {\n let newIndex = \"1\";\n const isFirstBlockInDoc = pos === 1;\n\n const blockInfo = getBlockInfoFromPos(tr.doc, pos + 1)!;\n if (blockInfo === undefined) {\n return;\n }\n\n // Checks if this block is the start of a new ordered list, i.e. if it's the first block in the document, the\n // first block in its nesting level, or the previous block is not an ordered list item.\n if (!isFirstBlockInDoc) {\n const prevBlockInfo = getBlockInfoFromPos(tr.doc, pos - 2)!;\n if (prevBlockInfo === undefined) {\n return;\n }\n\n const isFirstBlockInNestingLevel =\n blockInfo.depth !== prevBlockInfo.depth;\n\n if (!isFirstBlockInNestingLevel) {\n const prevBlockContentNode = prevBlockInfo.contentNode;\n const prevBlockContentType = prevBlockInfo.contentType;\n\n const isPrevBlockOrderedListItem =\n prevBlockContentType.name === \"numberedListItem\";\n\n if (isPrevBlockOrderedListItem) {\n const prevBlockIndex = prevBlockContentNode.attrs[\"index\"];\n\n newIndex = (parseInt(prevBlockIndex) + 1).toString();\n }\n }\n }\n\n const contentNode = blockInfo.contentNode;\n const index = contentNode.attrs[\"index\"];\n\n if (index !== newIndex) {\n modified = true;\n\n tr.setNodeMarkup(pos + 1, undefined, {\n index: newIndex,\n });\n }\n }\n });\n\n return modified ? tr : null;\n },\n });\n};\n","import { InputRule } from \"@tiptap/core\";\nimport {\n PropSchema,\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../../schema\";\nimport { createDefaultBlockDOMOutputSpec } from \"../../defaultBlockHelpers\";\nimport { defaultProps } from \"../../defaultProps\";\nimport { handleEnter } from \"../ListItemKeyboardShortcuts\";\nimport { NumberedListIndexingPlugin } from \"./NumberedListIndexingPlugin\";\nimport { getCurrentBlockContentType } from \"../../../api/getCurrentBlockContentType\";\n\nexport const numberedListItemPropSchema = {\n ...defaultProps,\n} satisfies PropSchema;\n\nconst NumberedListItemBlockContent = createStronglyTypedTiptapNode({\n name: \"numberedListItem\",\n content: \"inline*\",\n group: \"blockContent\",\n addAttributes() {\n return {\n index: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-index\"),\n renderHTML: (attributes) => {\n return {\n \"data-index\": attributes.index,\n };\n },\n },\n };\n },\n\n addInputRules() {\n return [\n // Creates an ordered list when starting with \"1.\".\n new InputRule({\n find: new RegExp(`^1\\\\.\\\\s$`),\n handler: ({ state, chain, range }) => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return;\n }\n\n chain()\n .BNUpdateBlock(state.selection.from, {\n type: \"numberedListItem\",\n props: {},\n })\n // Removes the \"1.\" characters used to set the list.\n .deleteRange({ from: range.from, to: range.to });\n },\n }),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n Enter: () => handleEnter(this.editor),\n \"Mod-Shift-7\": () => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return true;\n }\n\n return this.editor.commands.BNUpdateBlock(\n this.editor.state.selection.anchor,\n {\n type: \"numberedListItem\",\n props: {},\n }\n );\n },\n };\n },\n\n addProseMirrorPlugins() {\n return [NumberedListIndexingPlugin()];\n },\n\n parseHTML() {\n return [\n {\n tag: \"div[data-content-type=\" + this.name + \"]\", // TODO: remove if we can't come up with test case that needs this\n },\n // Case for regular HTML list structure.\n // (e.g.: when pasting from other apps)\n {\n tag: \"li\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const parent = element.parentElement;\n\n if (parent === null) {\n return false;\n }\n\n if (\n parent.tagName === \"OL\" ||\n (parent.tagName === \"DIV\" && parent.parentElement!.tagName === \"OL\")\n ) {\n return {};\n }\n\n return false;\n },\n node: \"numberedListItem\",\n },\n // Case for BlockNote list structure.\n // (e.g.: when pasting from blocknote)\n {\n tag: \"p\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const parent = element.parentElement;\n\n if (parent === null) {\n return false;\n }\n\n if (parent.getAttribute(\"data-content-type\") === \"numberedListItem\") {\n return {};\n }\n\n return false;\n },\n priority: 300,\n node: \"numberedListItem\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n // We use a <p> tag, because for <li> tags we'd need an <ol> element to\n // put them in to be semantically correct, which we can't have due to the\n // schema.\n \"p\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {}\n );\n },\n});\n\nexport const NumberedListItem = createBlockSpecFromStronglyTypedTiptapNode(\n NumberedListItemBlockContent,\n numberedListItemPropSchema\n);\n","import {\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../schema\";\nimport { createDefaultBlockDOMOutputSpec } from \"../defaultBlockHelpers\";\nimport { defaultProps } from \"../defaultProps\";\nimport { handleEnter } from \"../ListItemBlockContent/ListItemKeyboardShortcuts\";\nimport { getCurrentBlockContentType } from \"../../api/getCurrentBlockContentType\";\n\nexport const paragraphPropSchema = {\n ...defaultProps,\n};\n\nexport const ParagraphBlockContent = createStronglyTypedTiptapNode({\n name: \"paragraph\",\n content: \"inline*\",\n group: \"blockContent\",\n\n addKeyboardShortcuts() {\n return {\n Enter: () => handleEnter(this.editor),\n \"Mod-Alt-0\": () => {\n if (getCurrentBlockContentType(this.editor) !== \"inline*\") {\n return true;\n }\n\n return this.editor.commands.BNUpdateBlock(\n this.editor.state.selection.anchor,\n {\n type: \"paragraph\",\n props: {},\n }\n );\n },\n };\n },\n\n parseHTML() {\n return [\n { tag: \"div[data-content-type=\" + this.name + \"]\" },\n {\n tag: \"p\",\n priority: 200,\n node: \"paragraph\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n \"p\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {}\n );\n },\n});\n\nexport const Paragraph = createBlockSpecFromStronglyTypedTiptapNode(\n ParagraphBlockContent,\n paragraphPropSchema\n);\n","import { callOrReturn, Extension, getExtensionField } from \"@tiptap/core\";\nimport { columnResizing, tableEditing } from \"prosemirror-tables\";\n\nexport const TableExtension = Extension.create({\n name: \"BlockNoteTableExtension\",\n\n addProseMirrorPlugins: () => {\n return [\n columnResizing({\n cellMinWidth: 100,\n }),\n tableEditing(),\n ];\n },\n\n addKeyboardShortcuts() {\n return {\n // Makes enter create a new line within the cell.\n Enter: () => {\n if (\n this.editor.state.selection.empty &&\n this.editor.state.selection.$head.parent.type.name ===\n \"tableParagraph\"\n ) {\n this.editor.commands.setHardBreak();\n\n return true;\n }\n\n return false;\n },\n // Ensures that backspace won't delete the table if the text cursor is at\n // the start of a cell and the selection is empty.\n Backspace: () => {\n const selection = this.editor.state.selection;\n const selectionIsEmpty = selection.empty;\n const selectionIsAtStartOfNode = selection.$head.parentOffset === 0;\n const selectionIsInTableParagraphNode =\n selection.$head.node().type.name === \"tableParagraph\";\n\n return (\n selectionIsEmpty &&\n selectionIsAtStartOfNode &&\n selectionIsInTableParagraphNode\n );\n },\n };\n },\n\n extendNodeSchema(extension) {\n const context = {\n name: extension.name,\n options: extension.options,\n storage: extension.storage,\n };\n\n return {\n tableRole: callOrReturn(\n getExtensionField(extension, \"tableRole\", context)\n ),\n };\n },\n});\n","import { mergeAttributes, Node } from \"@tiptap/core\";\nimport { TableCell } from \"@tiptap/extension-table-cell\";\nimport { TableHeader } from \"@tiptap/extension-table-header\";\nimport { TableRow } from \"@tiptap/extension-table-row\";\nimport {\n createBlockSpecFromStronglyTypedTiptapNode,\n createStronglyTypedTiptapNode,\n} from \"../../schema\";\nimport { createDefaultBlockDOMOutputSpec } from \"../defaultBlockHelpers\";\nimport { defaultProps } from \"../defaultProps\";\nimport { TableExtension } from \"./TableExtension\";\n\nexport const tablePropSchema = {\n ...defaultProps,\n};\n\nexport const TableBlockContent = createStronglyTypedTiptapNode({\n name: \"table\",\n content: \"tableRow+\",\n group: \"blockContent\",\n tableRole: \"table\",\n\n isolating: true,\n\n parseHTML() {\n return [{ tag: \"table\" }];\n },\n\n renderHTML({ HTMLAttributes }) {\n return createDefaultBlockDOMOutputSpec(\n this.name,\n \"table\",\n {\n ...(this.options.domAttributes?.blockContent || {}),\n ...HTMLAttributes,\n },\n this.options.domAttributes?.inlineContent || {}\n );\n },\n});\n\nconst TableParagraph = Node.create({\n name: \"tableParagraph\",\n group: \"tableContent\",\n content: \"inline*\",\n\n parseHTML() {\n return [{ tag: \"p\" }];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"p\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),\n 0,\n ];\n },\n});\n\nexport const Table = createBlockSpecFromStronglyTypedTiptapNode(\n TableBlockContent,\n tablePropSchema,\n [\n TableExtension,\n TableParagraph,\n TableHeader.extend({\n content: \"tableContent\",\n }),\n TableCell.extend({\n content: \"tableContent\",\n }),\n TableRow,\n ]\n);\n","import Bold from \"@tiptap/extension-bold\";\nimport Code from \"@tiptap/extension-code\";\nimport Italic from \"@tiptap/extension-italic\";\nimport Strike from \"@tiptap/extension-strike\";\nimport Underline from \"@tiptap/extension-underline\";\nimport { BackgroundColor } from \"../extensions/BackgroundColor/BackgroundColorMark\";\nimport { TextColor } from \"../extensions/TextColor/TextColorMark\";\nimport {\n BlockNoDefaults,\n BlockSchema,\n BlockSpecs,\n InlineContentSchema,\n InlineContentSpecs,\n PartialBlockNoDefaults,\n StyleSchema,\n StyleSpecs,\n createStyleSpecFromTipTapMark,\n getBlockSchemaFromSpecs,\n getInlineContentSchemaFromSpecs,\n getStyleSchemaFromSpecs,\n} from \"../schema\";\nimport { Heading } from \"./HeadingBlockContent/HeadingBlockContent\";\nimport { Image } from \"./ImageBlockContent/ImageBlockContent\";\nimport { BulletListItem } from \"./ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent\";\nimport { NumberedListItem } from \"./ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent\";\nimport { Paragraph } from \"./ParagraphBlockContent/ParagraphBlockContent\";\nimport { Table } from \"./TableBlockContent/TableBlockContent\";\n\nexport const defaultBlockSpecs = {\n paragraph: Paragraph,\n heading: Heading,\n bulletListItem: BulletListItem,\n numberedListItem: NumberedListItem,\n image: Image,\n table: Table,\n} satisfies BlockSpecs;\n\nexport const defaultBlockSchema = getBlockSchemaFromSpecs(defaultBlockSpecs);\n\n// underscore is used that in case a user overrides DefaultBlockSchema,\n// they can still access the original default block schema\nexport type _DefaultBlockSchema = typeof defaultBlockSchema;\nexport type DefaultBlockSchema = _DefaultBlockSchema;\n\nexport const defaultStyleSpecs = {\n bold: createStyleSpecFromTipTapMark(Bold, \"boolean\"),\n italic: createStyleSpecFromTipTapMark(Italic, \"boolean\"),\n underline: createStyleSpecFromTipTapMark(Underline, \"boolean\"),\n strike: createStyleSpecFromTipTapMark(Strike, \"boolean\"),\n code: createStyleSpecFromTipTapMark(Code, \"boolean\"),\n textColor: TextColor,\n backgroundColor: BackgroundColor,\n} satisfies StyleSpecs;\n\nexport const defaultStyleSchema = getStyleSchemaFromSpecs(defaultStyleSpecs);\n\n// underscore is used that in case a user overrides DefaultStyleSchema,\n// they can still access the original default style schema\nexport type _DefaultStyleSchema = typeof defaultStyleSchema;\nexport type DefaultStyleSchema = _DefaultStyleSchema;\n\nexport const defaultInlineContentSpecs = {\n text: { config: \"text\", implementation: {} as any },\n link: { config: \"link\", implementation: {} as any },\n} satisfies InlineContentSpecs;\n\nexport const defaultInlineContentSchema = getInlineContentSchemaFromSpecs(\n defaultInlineContentSpecs\n);\n\n// underscore is used that in case a user overrides DefaultInlineContentSchema,\n// they can still access the original default inline content schema\nexport type _DefaultInlineContentSchema = typeof defaultInlineContentSchema;\nexport type DefaultInlineContentSchema = _DefaultInlineContentSchema;\n\nexport type PartialBlock<\n BSchema extends BlockSchema = DefaultBlockSchema,\n I extends InlineContentSchema = DefaultInlineContentSchema,\n S extends StyleSchema = DefaultStyleSchema\n> = PartialBlockNoDefaults<BSchema, I, S>;\n\nexport type Block<\n BSchema extends BlockSchema = DefaultBlockSchema,\n I extends InlineContentSchema = DefaultInlineContentSchema,\n S extends StyleSchema = DefaultStyleSchema\n> = BlockNoDefaults<BSchema, I, S>;\n","import type { BlockNoteEditor } from \"../editor/BlockNoteEditor\";\nimport { BlockFromConfig, InlineContentSchema, StyleSchema } from \"../schema\";\nimport { Block, DefaultBlockSchema, defaultBlockSchema } from \"./defaultBlocks\";\nimport { defaultProps } from \"./defaultProps\";\n\nexport function checkDefaultBlockTypeInSchema<\n BlockType extends keyof DefaultBlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n blockType: BlockType,\n editor: BlockNoteEditor<any, I, S>\n): editor is BlockNoteEditor<{ Type: DefaultBlockSchema[BlockType] }, I, S> {\n return (\n blockType in editor.schema.blockSchema &&\n editor.schema.blockSchema[blockType] === defaultBlockSchema[blockType]\n );\n}\n\nexport function checkBlockIsDefaultType<\n BlockType extends keyof DefaultBlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n blockType: BlockType,\n block: Block<any, I, S>,\n editor: BlockNoteEditor<any, I, S>\n): block is BlockFromConfig<DefaultBlockSchema[BlockType], I, S> {\n return (\n block.type === blockType &&\n block.type in editor.schema.blockSchema &&\n checkDefaultBlockTypeInSchema(block.type, editor)\n );\n}\n\nexport function checkBlockTypeHasDefaultProp<\n Prop extends keyof typeof defaultProps,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n prop: Prop,\n blockType: string,\n editor: BlockNoteEditor<any, I, S>\n): editor is BlockNoteEditor<\n {\n [BT in string]: {\n type: BT;\n propSchema: {\n [P in Prop]: (typeof defaultProps)[P];\n };\n content: \"table\" | \"inline\" | \"none\";\n };\n },\n I,\n S\n> {\n return (\n blockType in editor.schema.blockSchema &&\n prop in editor.schema.blockSchema[blockType].propSchema &&\n editor.schema.blockSchema[blockType].propSchema[prop] === defaultProps[prop]\n );\n}\n\nexport function checkBlockHasDefaultProp<\n Prop extends keyof typeof defaultProps,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n prop: Prop,\n block: Block<any, I, S>,\n editor: BlockNoteEditor<any, I, S>\n): block is BlockFromConfig<\n {\n type: string;\n propSchema: {\n [P in Prop]: (typeof defaultProps)[P];\n };\n content: \"table\" | \"inline\" | \"none\";\n },\n I,\n S\n> {\n return checkBlockTypeHasDefaultProp(prop, block.type, editor);\n}\n","import { Node } from \"prosemirror-model\";\n\n/**\n * Get a TipTap node by id\n */\nexport function getNodeById(\n id: string,\n doc: Node\n): { node: Node; posBeforeNode: number } {\n let targetNode: Node | undefined = undefined;\n let posBeforeNode: number | undefined = undefined;\n\n doc.firstChild!.descendants((node, pos) => {\n // Skips traversing nodes after node with target ID has been found.\n if (targetNode) {\n return false;\n }\n\n // Keeps traversing nodes if block with target ID has not been found.\n if (node.type.name !== \"blockContainer\" || node.attrs.id !== id) {\n return true;\n }\n\n targetNode = node;\n posBeforeNode = pos + 1;\n\n return false;\n });\n\n if (targetNode === undefined || posBeforeNode === undefined) {\n throw Error(\"Could not find block in the editor with matching ID.\");\n }\n\n return {\n node: targetNode,\n posBeforeNode: posBeforeNode,\n };\n}\n","import { Node } from \"prosemirror-model\";\n\nimport { selectionToInsertionEnd } from \"@tiptap/core\";\nimport { Transaction } from \"prosemirror-state\";\nimport { Block, PartialBlock } from \"../../blocks/defaultBlocks\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport {\n BlockIdentifier,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema\";\nimport { blockToNode, nodeToBlock } from \"../nodeConversions/nodeConversions\";\nimport { getNodeById } from \"../nodeUtil\";\n\nexport function insertBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n blocksToInsert: PartialBlock<BSchema, I, S>[],\n referenceBlock: BlockIdentifier,\n placement: \"before\" | \"after\" | \"nested\" = \"before\",\n editor: BlockNoteEditor<BSchema, I, S>\n): Block<BSchema, I, S>[] {\n const ttEditor = editor._tiptapEditor;\n\n const id =\n typeof referenceBlock === \"string\" ? referenceBlock : referenceBlock.id;\n\n const nodesToInsert: Node[] = [];\n for (const blockSpec of blocksToInsert) {\n nodesToInsert.push(\n blockToNode(blockSpec, ttEditor.schema, editor.schema.styleSchema)\n );\n }\n\n const { node, posBeforeNode } = getNodeById(id, ttEditor.state.doc);\n\n if (placement === \"before\") {\n ttEditor.view.dispatch(\n ttEditor.state.tr.insert(posBeforeNode, nodesToInsert)\n );\n }\n\n if (placement === \"after\") {\n ttEditor.view.dispatch(\n ttEditor.state.tr.insert(posBeforeNode + node.nodeSize, nodesToInsert)\n );\n }\n\n if (placement === \"nested\") {\n // Case if block doesn't already have children.\n if (node.childCount < 2) {\n const blockGroupNode = ttEditor.state.schema.nodes[\"blockGroup\"].create(\n {},\n nodesToInsert\n );\n\n ttEditor.view.dispatch(\n ttEditor.state.tr.insert(\n posBeforeNode + node.firstChild!.nodeSize + 1,\n blockGroupNode\n )\n );\n }\n }\n\n // Now that the `PartialBlock`s have been converted to nodes, we can\n // re-convert them into full `Block`s.\n const insertedBlocks: Block<BSchema, I, S>[] = [];\n for (const node of nodesToInsert) {\n insertedBlocks.push(\n nodeToBlock(\n node,\n editor.schema.blockSchema,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n editor.blockCache\n )\n );\n }\n\n return insertedBlocks;\n}\n\nexport function updateBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n blockToUpdate: BlockIdentifier,\n update: PartialBlock<BSchema, I, S>,\n editor: BlockNoteEditor<BSchema, I, S>\n): Block<BSchema, I, S> {\n const ttEditor = editor._tiptapEditor;\n\n const id =\n typeof blockToUpdate === \"string\" ? blockToUpdate : blockToUpdate.id;\n const { posBeforeNode } = getNodeById(id, ttEditor.state.doc);\n\n ttEditor.commands.BNUpdateBlock(posBeforeNode + 1, update);\n\n const blockContainerNode = ttEditor.state.doc\n .resolve(posBeforeNode + 1)\n .node();\n\n return nodeToBlock(\n blockContainerNode,\n editor.schema.blockSchema,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n editor.blockCache\n );\n}\n\nfunction removeBlocksWithCallback<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n blocksToRemove: BlockIdentifier[],\n editor: BlockNoteEditor<BSchema, I, S>,\n // Should return new removedSize.\n callback?: (\n node: Node,\n pos: number,\n tr: Transaction,\n removedSize: number\n ) => number\n): Block<BSchema, I, S>[] {\n const ttEditor = editor._tiptapEditor;\n const tr = ttEditor.state.tr;\n\n const idsOfBlocksToRemove = new Set<string>(\n blocksToRemove.map((block) =>\n typeof block === \"string\" ? block : block.id\n )\n );\n const removedBlocks: Block<BSchema, I, S>[] = [];\n let removedSize = 0;\n\n ttEditor.state.doc.descendants((node, pos) => {\n // Skips traversing nodes after all target blocks have been removed.\n if (idsOfBlocksToRemove.size === 0) {\n return false;\n }\n\n // Keeps traversing nodes if block with target ID has not been found.\n if (\n node.type.name !== \"blockContainer\" ||\n !idsOfBlocksToRemove.has(node.attrs.id)\n ) {\n return true;\n }\n\n // Saves the block that is being deleted.\n removedBlocks.push(\n nodeToBlock(\n node,\n editor.schema.blockSchema,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n editor.blockCache\n )\n );\n idsOfBlocksToRemove.delete(node.attrs.id);\n\n // Removes the block and calculates the change in document size.\n removedSize = callback?.(node, pos, tr, removedSize) || removedSize;\n const oldDocSize = tr.doc.nodeSize;\n tr.delete(pos - removedSize - 1, pos - removedSize + node.nodeSize + 1);\n const newDocSize = tr.doc.nodeSize;\n removedSize += oldDocSize - newDocSize;\n\n return false;\n });\n\n // Throws an error if now all blocks could be found.\n if (idsOfBlocksToRemove.size > 0) {\n const notFoundIds = [...idsOfBlocksToRemove].join(\"\\n\");\n\n throw Error(\n \"Blocks with the following IDs could not be found in the editor: \" +\n notFoundIds\n );\n }\n\n ttEditor.view.dispatch(tr);\n\n return removedBlocks;\n}\n\nexport function removeBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n blocksToRemove: BlockIdentifier[],\n editor: BlockNoteEditor<BSchema, I, S>\n): Block<BSchema, I, S>[] {\n return removeBlocksWithCallback(blocksToRemove, editor);\n}\n\nexport function replaceBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n blocksToRemove: BlockIdentifier[],\n blocksToInsert: PartialBlock<BSchema, I, S>[],\n editor: BlockNoteEditor<BSchema, I, S>\n): {\n insertedBlocks: Block<BSchema, I, S>[];\n removedBlocks: Block<BSchema, I, S>[];\n} {\n const ttEditor = editor._tiptapEditor;\n\n const nodesToInsert: Node[] = [];\n for (const block of blocksToInsert) {\n nodesToInsert.push(\n blockToNode(block, ttEditor.schema, editor.schema.styleSchema)\n );\n }\n\n const idOfFirstBlock =\n typeof blocksToRemove[0] === \"string\"\n ? blocksToRemove[0]\n : blocksToRemove[0].id;\n const removedBlocks = removeBlocksWithCallback(\n blocksToRemove,\n editor,\n (node, pos, tr, removedSize) => {\n if (node.attrs.id === idOfFirstBlock) {\n const oldDocSize = tr.doc.nodeSize;\n tr.insert(pos, nodesToInsert);\n const newDocSize = tr.doc.nodeSize;\n\n return removedSize + oldDocSize - newDocSize;\n }\n\n return removedSize;\n }\n );\n\n // Now that the `PartialBlock`s have been converted to nodes, we can\n // re-convert them into full `Block`s.\n const insertedBlocks: Block<BSchema, I, S>[] = [];\n for (const node of nodesToInsert) {\n insertedBlocks.push(\n nodeToBlock(\n node,\n editor.schema.blockSchema,\n editor.schema.inlineContentSchema,\n editor.schema.styleSchema,\n editor.blockCache\n )\n );\n }\n\n return { insertedBlocks, removedBlocks };\n}\n\n// similar to tiptap insertContentAt\nexport function insertContentAt<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n position: any,\n nodes: Node[],\n editor: BlockNoteEditor<BSchema, I, S>,\n options: {\n updateSelection: boolean;\n } = { updateSelection: true }\n) {\n const ttEditor = editor._tiptapEditor;\n const tr = ttEditor.state.tr;\n\n // don’t dispatch an empty fragment because this can lead to strange errors\n // if (content.toString() === \"<>\") {\n // return true;\n // }\n\n let { from, to } =\n typeof position === \"number\"\n ? { from: position, to: position }\n : { from: position.from, to: position.to };\n\n let isOnlyTextContent = true;\n let isOnlyBlockContent = true;\n // const nodes = isFragment(content) ? content : [content];\n\n let text = \"\";\n\n nodes.forEach((node) => {\n // check if added node is valid\n node.check();\n\n if (isOnlyTextContent && node.isText && node.marks.length === 0) {\n text += node.text;\n } else {\n isOnlyTextContent = false;\n }\n\n isOnlyBlockContent = isOnlyBlockContent ? node.isBlock : false;\n });\n\n // check if we can replace the wrapping node by\n // the newly inserted content\n // example:\n // replace an empty paragraph by an inserted image\n // instead of inserting the image below the paragraph\n if (from === to && isOnlyBlockContent) {\n const { parent } = tr.doc.resolve(from);\n const isEmptyTextBlock =\n parent.isTextblock && !parent.type.spec.code && !parent.childCount;\n\n if (isEmptyTextBlock) {\n from -= 1;\n to += 1;\n }\n }\n\n // if there is only plain text we have to use `insertText`\n // because this will keep the current marks\n if (isOnlyTextContent) {\n // if value is string, we can use it directly\n // otherwise if it is an array, we have to join it\n // if (Array.isArray(value)) {\n // tr.insertText(value.map((v) => v.text || \"\").join(\"\"), from, to);\n // } else if (typeof value === \"object\" && !!value && !!value.text) {\n // tr.insertText(value.text, from, to);\n // } else {\n // tr.insertText(value as string, from, to);\n // }\n tr.insertText(text, from, to);\n } else {\n tr.replaceWith(from, to, nodes);\n }\n\n // set cursor at end of inserted content\n if (options.updateSelection) {\n selectionToInsertionEnd(tr, tr.steps.length - 1, -1);\n }\n\n ttEditor.view.dispatch(tr);\n\n return true;\n}\n","import { Element as HASTElement, Parent as HASTParent } from \"hast\";\n\n/**\n * Rehype plugin which removes <u> tags. Used to remove underlines before converting HTML to markdown, as Markdown\n * doesn't support underlines.\n */\nexport function removeUnderlines() {\n const removeUnderlinesHelper = (tree: HASTParent) => {\n let numChildElements = tree.children.length;\n\n for (let i = 0; i < numChildElements; i++) {\n const node = tree.children[i];\n\n if (node.type === \"element\") {\n // Recursively removes underlines from child elements.\n removeUnderlinesHelper(node);\n\n if ((node as HASTElement).tagName === \"u\") {\n // Lifts child nodes outside underline element, deletes the underline element, and updates current index &\n // the number of child elements.\n if (node.children.length > 0) {\n tree.children.splice(i, 1, ...node.children);\n\n const numElementsAdded = node.children.length - 1;\n numChildElements += numElementsAdded;\n i += numElementsAdded;\n } else {\n tree.children.splice(i, 1);\n\n numChildElements--;\n i--;\n }\n }\n }\n }\n };\n\n return removeUnderlinesHelper;\n}\n","import { Schema } from \"prosemirror-model\";\nimport rehypeParse from \"rehype-parse\";\nimport rehypeRemark from \"rehype-remark\";\nimport remarkGfm from \"remark-gfm\";\nimport remarkStringify from \"remark-stringify\";\nimport { unified } from \"unified\";\nimport { Block } from \"../../../blocks/defaultBlocks\";\nimport type { BlockNoteEditor } from \"../../../editor/BlockNoteEditor\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../../schema\";\nimport { createExternalHTMLExporter } from \"../html/externalHTMLExporter\";\nimport { removeUnderlines } from \"./removeUnderlinesRehypePlugin\";\n\nexport function cleanHTMLToMarkdown(cleanHTMLString: string) {\n const markdownString = unified()\n .use(rehypeParse, { fragment: true })\n .use(removeUnderlines)\n .use(rehypeRemark)\n .use(remarkGfm)\n .use(remarkStringify)\n .processSync(cleanHTMLString);\n\n return markdownString.value as string;\n}\n\nexport function blocksToMarkdown<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n blocks: Block<BSchema, I, S>[],\n schema: Schema,\n editor: BlockNoteEditor<BSchema, I, S>\n): string {\n const exporter = createExternalHTMLExporter(schema, editor);\n const externalHTML = exporter.exportBlocks(blocks);\n\n return cleanHTMLToMarkdown(externalHTML);\n}\n","function getChildIndex(node: Element) {\n return Array.prototype.indexOf.call(node.parentElement!.childNodes, node);\n}\n\nfunction isWhitespaceNode(node: Node) {\n return node.nodeType === 3 && !/\\S/.test(node.nodeValue || \"\");\n}\n\n/**\n * Step 1, Turns:\n *\n * <ul>\n * <li>item</li>\n * <li>\n * <ul>\n * <li>...</li>\n * <li>...</li>\n * </ul>\n * </li>\n *\n * Into:\n * <ul>\n * <li>item</li>\n * <ul>\n * <li>...</li>\n * <li>...</li>\n * </ul>\n * </ul>\n *\n */\nfunction liftNestedListsToParent(element: HTMLElement) {\n element.querySelectorAll(\"li > ul, li > ol\").forEach((list) => {\n const index = getChildIndex(list);\n const parentListItem = list.parentElement!;\n const siblingsAfter = Array.from(parentListItem.childNodes).slice(\n index + 1\n );\n list.remove();\n siblingsAfter.forEach((sibling) => {\n sibling.remove();\n });\n\n parentListItem.insertAdjacentElement(\"afterend\", list);\n\n siblingsAfter.reverse().forEach((sibling) => {\n if (isWhitespaceNode(sibling)) {\n return;\n }\n const siblingContainer = document.createElement(\"li\");\n siblingContainer.append(sibling);\n list.insertAdjacentElement(\"afterend\", siblingContainer);\n });\n if (parentListItem.childNodes.length === 0) {\n parentListItem.remove();\n }\n });\n}\n\n/**\n * Step 2, Turns (output of liftNestedListsToParent):\n *\n * <li>item</li>\n * <ul>\n * <li>...</li>\n * <li>...</li>\n * </ul>\n *\n * Into:\n * <div>\n * <li>item</li>\n * <div data-node-type=\"blockGroup\">\n * <ul>\n * <li>...</li>\n * <li>...</li>\n * </ul>\n * </div>\n * </div>\n *\n * This resulting format is parsed\n */\nfunction createGroups(element: HTMLElement) {\n element.querySelectorAll(\"li + ul, li + ol\").forEach((list) => {\n const listItem = list.previousElementSibling as HTMLElement;\n const blockContainer = document.createElement(\"div\");\n\n listItem.insertAdjacentElement(\"afterend\", blockContainer);\n blockContainer.append(listItem);\n\n const blockGroup = document.createElement(\"div\");\n blockGroup.setAttribute(\"data-node-type\", \"blockGroup\");\n blockContainer.append(blockGroup);\n\n while (\n blockContainer.nextElementSibling?.nodeName === \"UL\" ||\n blockContainer.nextElementSibling?.nodeName === \"OL\"\n ) {\n blockGroup.append(blockContainer.nextElementSibling);\n }\n });\n}\n\n// prevent XSS, similar to https://github.com/ProseMirror/prosemirror-view/blob/1251b2b412656a2a06263e4187574beb43651273/src/clipboard.ts#L204\n// https://github.com/TypeCellOS/BlockNote/issues/601\nlet _detachedDoc: Document | null = null;\nfunction detachedDoc() {\n return (\n _detachedDoc ||\n (_detachedDoc = document.implementation.createHTMLDocument(\"title\"))\n );\n}\n\nexport function nestedListsToBlockNoteStructure(\n elementOrHTML: HTMLElement | string\n) {\n if (typeof elementOrHTML === \"string\") {\n const element = detachedDoc().createElement(\"div\");\n element.innerHTML = elementOrHTML;\n elementOrHTML = element;\n }\n liftNestedListsToParent(elementOrHTML);\n createGroups(elementOrHTML);\n return elementOrHTML;\n}\n","import { DOMParser, Schema } from \"prosemirror-model\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../../schema\";\n\nimport { Block } from \"../../../blocks/defaultBlocks\";\nimport { nodeToBlock } from \"../../nodeConversions/nodeConversions\";\nimport { nestedListsToBlockNoteStructure } from \"./util/nestedLists\";\nexport async function HTMLToBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n html: string,\n blockSchema: BSchema,\n icSchema: I,\n styleSchema: S,\n pmSchema: Schema\n): Promise<Block<BSchema, I, S>[]> {\n const htmlNode = nestedListsToBlockNoteStructure(html);\n const parser = DOMParser.fromSchema(pmSchema);\n\n // Other approach might be to use\n // const doc = pmSchema.nodes[\"doc\"].createAndFill()!;\n // and context: doc.resolve(3),\n\n const parentNode = parser.parse(htmlNode, {\n topNode: pmSchema.nodes[\"blockGroup\"].create(),\n });\n\n const blocks: Block<BSchema, I, S>[] = [];\n\n for (let i = 0; i < parentNode.childCount; i++) {\n blocks.push(\n nodeToBlock(parentNode.child(i), blockSchema, icSchema, styleSchema)\n );\n }\n\n return blocks;\n}\n","import { Schema } from \"prosemirror-model\";\nimport rehypeStringify from \"rehype-stringify\";\nimport remarkGfm from \"remark-gfm\";\nimport remarkParse from \"remark-parse\";\nimport remarkRehype, { defaultHandlers } from \"remark-rehype\";\nimport { unified } from \"unified\";\nimport { Block } from \"../../../blocks/defaultBlocks\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../../schema\";\nimport { HTMLToBlocks } from \"../html/parseHTML\";\n\n// modified version of https://github.com/syntax-tree/mdast-util-to-hast/blob/main/lib/handlers/code.js\n// that outputs a data-language attribute instead of a CSS class (e.g.: language-typescript)\nfunction code(state: any, node: any) {\n const value = node.value ? node.value + \"\\n\" : \"\";\n /** @type {Properties} */\n const properties: any = {};\n\n if (node.lang) {\n // changed line\n properties[\"data-language\"] = node.lang;\n }\n\n // Create `<code>`.\n /** @type {Element} */\n let result: any = {\n type: \"element\",\n tagName: \"code\",\n properties,\n children: [{ type: \"text\", value }],\n };\n\n if (node.meta) {\n result.data = { meta: node.meta };\n }\n\n state.patch(node, result);\n result = state.applyData(node, result);\n\n // Create `<pre>`.\n result = {\n type: \"element\",\n tagName: \"pre\",\n properties: {},\n children: [result],\n };\n state.patch(node, result);\n return result;\n}\n\nexport function markdownToBlocks<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n markdown: string,\n blockSchema: BSchema,\n icSchema: I,\n styleSchema: S,\n pmSchema: Schema\n): Promise<Block<BSchema, I, S>[]> {\n const htmlString = unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkRehype, {\n handlers: {\n ...(defaultHandlers as any),\n code,\n },\n })\n .use(rehypeStringify)\n .processSync(markdown);\n\n return HTMLToBlocks(\n htmlString.value as string,\n blockSchema,\n icSchema,\n styleSchema,\n pmSchema\n );\n}\n","// from https://raw.githubusercontent.com/ueberdosis/tiptap/develop/packages/core/src/EventEmitter.ts (MIT)\n\ntype StringKeyOf<T> = Extract<keyof T, string>;\ntype CallbackType<\n T extends Record<string, any>,\n EventName extends StringKeyOf<T>\n> = T[EventName] extends any[] ? T[EventName] : [T[EventName]];\ntype CallbackFunction<\n T extends Record<string, any>,\n EventName extends StringKeyOf<T>\n> = (...props: CallbackType<T, EventName>) => any;\n\nexport class EventEmitter<T extends Record<string, any>> {\n // eslint-disable-next-line @typescript-eslint/ban-types\n private callbacks: { [key: string]: Function[] } = {};\n\n public on<EventName extends StringKeyOf<T>>(\n event: EventName,\n fn: CallbackFunction<T, EventName>\n ) {\n if (!this.callbacks[event]) {\n this.callbacks[event] = [];\n }\n\n this.callbacks[event].push(fn);\n\n return () => this.off(event, fn);\n }\n\n protected emit<EventName extends StringKeyOf<T>>(\n event: EventName,\n ...args: CallbackType<T, EventName>\n ) {\n const callbacks = this.callbacks[event];\n\n if (callbacks) {\n callbacks.forEach((callback) => callback.apply(this, args));\n }\n }\n\n public off<EventName extends StringKeyOf<T>>(\n event: EventName,\n fn?: CallbackFunction<T, EventName>\n ) {\n const callbacks = this.callbacks[event];\n\n if (callbacks) {\n if (fn) {\n this.callbacks[event] = callbacks.filter((callback) => callback !== fn);\n } else {\n delete this.callbacks[event];\n }\n }\n }\n\n protected removeAllListeners(): void {\n this.callbacks = {};\n }\n}\n","import { isNodeSelection, posToDOMRect } from \"@tiptap/core\";\nimport { EditorState, Plugin, PluginKey } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\n\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../schema\";\nimport { EventEmitter } from \"../../util/EventEmitter\";\n\nexport type FormattingToolbarState = UiElementPosition;\n\nexport class FormattingToolbarView {\n public state?: FormattingToolbarState;\n public emitUpdate: () => void;\n\n public preventHide = false;\n public preventShow = false;\n public prevWasEditable: boolean | null = null;\n\n public shouldShow: (props: {\n view: EditorView;\n state: EditorState;\n from: number;\n to: number;\n }) => boolean = ({ state }) => !state.selection.empty;\n\n constructor(\n private readonly editor: BlockNoteEditor<\n BlockSchema,\n InlineContentSchema,\n StyleSchema\n >,\n private readonly pmView: EditorView,\n emitUpdate: (state: FormattingToolbarState) => void\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\n \"Attempting to update uninitialized formatting toolbar\"\n );\n }\n\n emitUpdate(this.state);\n };\n\n pmView.dom.addEventListener(\"mousedown\", this.viewMousedownHandler);\n pmView.dom.addEventListener(\"mouseup\", this.viewMouseupHandler);\n pmView.dom.addEventListener(\"dragstart\", this.dragHandler);\n pmView.dom.addEventListener(\"dragover\", this.dragHandler);\n\n pmView.dom.addEventListener(\"focus\", this.focusHandler);\n pmView.dom.addEventListener(\"blur\", this.blurHandler);\n\n document.addEventListener(\"scroll\", this.scrollHandler);\n }\n\n viewMousedownHandler = () => {\n this.preventShow = true;\n };\n\n viewMouseupHandler = () => {\n this.preventShow = false;\n setTimeout(() => this.update(this.pmView));\n };\n\n // For dragging the whole editor.\n dragHandler = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n focusHandler = () => {\n // we use `setTimeout` to make sure `selection` is already updated\n setTimeout(() => this.update(this.pmView));\n };\n\n blurHandler = (event: FocusEvent) => {\n if (this.preventHide) {\n this.preventHide = false;\n\n return;\n }\n\n const editorWrapper = this.pmView.dom.parentElement!;\n\n // Checks if the focus is moving to an element outside the editor. If it is,\n // the toolbar is hidden.\n if (\n // An element is clicked.\n event &&\n event.relatedTarget &&\n // Element is inside the editor.\n (editorWrapper === (event.relatedTarget as Node) ||\n editorWrapper.contains(event.relatedTarget as Node))\n ) {\n return;\n }\n\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n scrollHandler = () => {\n if (this.state?.show) {\n this.state.referencePos = this.getSelectionBoundingBox();\n this.emitUpdate();\n }\n };\n\n update(view: EditorView, oldState?: EditorState) {\n const { state, composing } = view;\n const { doc, selection } = state;\n const isSame =\n oldState && oldState.doc.eq(doc) && oldState.selection.eq(selection);\n\n if (\n (this.prevWasEditable === null ||\n this.prevWasEditable === this.editor.isEditable) &&\n (composing || isSame)\n ) {\n return;\n }\n\n this.prevWasEditable = this.editor.isEditable;\n\n // support for CellSelections\n const { ranges } = selection;\n const from = Math.min(...ranges.map((range) => range.$from.pos));\n const to = Math.max(...ranges.map((range) => range.$to.pos));\n\n const shouldShow = this.shouldShow?.({\n view,\n state,\n from,\n to,\n });\n\n // Checks if menu should be shown/updated.\n if (\n this.editor.isEditable &&\n !this.preventShow &&\n (shouldShow || this.preventHide)\n ) {\n this.state = {\n show: true,\n referencePos: this.getSelectionBoundingBox(),\n };\n\n this.emitUpdate();\n\n return;\n }\n\n // Checks if menu should be hidden.\n if (\n this.state?.show &&\n !this.preventHide &&\n (!shouldShow || this.preventShow || !this.editor.isEditable)\n ) {\n this.state.show = false;\n this.emitUpdate();\n\n return;\n }\n }\n\n destroy() {\n this.pmView.dom.removeEventListener(\"mousedown\", this.viewMousedownHandler);\n this.pmView.dom.removeEventListener(\"mouseup\", this.viewMouseupHandler);\n this.pmView.dom.removeEventListener(\"dragstart\", this.dragHandler);\n this.pmView.dom.removeEventListener(\"dragover\", this.dragHandler);\n\n this.pmView.dom.removeEventListener(\"focus\", this.focusHandler);\n this.pmView.dom.removeEventListener(\"blur\", this.blurHandler);\n\n document.removeEventListener(\"scroll\", this.scrollHandler);\n }\n\n getSelectionBoundingBox() {\n const { state } = this.pmView;\n const { selection } = state;\n\n // support for CellSelections\n const { ranges } = selection;\n const from = Math.min(...ranges.map((range) => range.$from.pos));\n const to = Math.max(...ranges.map((range) => range.$to.pos));\n\n if (isNodeSelection(selection)) {\n const node = this.pmView.nodeDOM(from) as HTMLElement;\n\n if (node) {\n return node.getBoundingClientRect();\n }\n }\n\n return posToDOMRect(this.pmView, from, to);\n }\n}\n\nexport const formattingToolbarPluginKey = new PluginKey(\n \"FormattingToolbarPlugin\"\n);\n\nexport class FormattingToolbarProsemirrorPlugin extends EventEmitter<any> {\n private view: FormattingToolbarView | undefined;\n public readonly plugin: Plugin;\n\n constructor(editor: BlockNoteEditor<any, any, any>) {\n super();\n this.plugin = new Plugin({\n key: formattingToolbarPluginKey,\n view: (editorView) => {\n this.view = new FormattingToolbarView(editor, editorView, (state) => {\n this.emit(\"update\", state);\n });\n return this.view;\n },\n });\n }\n\n public onUpdate(callback: (state: FormattingToolbarState) => void) {\n return this.on(\"update\", callback);\n }\n}\n","import { getMarkRange, posToDOMRect, Range } from \"@tiptap/core\";\nimport { EditorView } from \"@tiptap/pm/view\";\nimport { Mark } from \"prosemirror-model\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\n\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../schema\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition\";\nimport { EventEmitter } from \"../../util/EventEmitter\";\n\nexport type LinkToolbarState = UiElementPosition & {\n // The hovered link's URL, and the text it's displayed with in the\n // editor.\n url: string;\n text: string;\n};\n\nclass LinkToolbarView {\n public state?: LinkToolbarState;\n public emitUpdate: () => void;\n\n menuUpdateTimer: ReturnType<typeof setTimeout> | undefined;\n startMenuUpdateTimer: () => void;\n stopMenuUpdateTimer: () => void;\n\n mouseHoveredLinkMark: Mark | undefined;\n mouseHoveredLinkMarkRange: Range | undefined;\n\n keyboardHoveredLinkMark: Mark | undefined;\n keyboardHoveredLinkMarkRange: Range | undefined;\n\n linkMark: Mark | undefined;\n linkMarkRange: Range | undefined;\n\n constructor(\n private readonly editor: BlockNoteEditor<any, any, any>,\n private readonly pmView: EditorView,\n emitUpdate: (state: LinkToolbarState) => void\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized link toolbar\");\n }\n\n emitUpdate(this.state);\n };\n\n this.startMenuUpdateTimer = () => {\n this.menuUpdateTimer = setTimeout(() => {\n this.update();\n }, 250);\n };\n\n this.stopMenuUpdateTimer = () => {\n if (this.menuUpdateTimer) {\n clearTimeout(this.menuUpdateTimer);\n this.menuUpdateTimer = undefined;\n }\n\n return false;\n };\n\n this.pmView.dom.addEventListener(\"mouseover\", this.mouseOverHandler);\n document.addEventListener(\"click\", this.clickHandler, true);\n document.addEventListener(\"scroll\", this.scrollHandler);\n }\n\n mouseOverHandler = (event: MouseEvent) => {\n // Resets the link mark currently hovered by the mouse cursor.\n this.mouseHoveredLinkMark = undefined;\n this.mouseHoveredLinkMarkRange = undefined;\n\n this.stopMenuUpdateTimer();\n\n if (\n event.target instanceof HTMLAnchorElement &&\n event.target.nodeName === \"A\"\n ) {\n // Finds link mark at the hovered element's position to update mouseHoveredLinkMark and\n // mouseHoveredLinkMarkRange.\n const hoveredLinkElement = event.target;\n const posInHoveredLinkMark =\n this.pmView.posAtDOM(hoveredLinkElement, 0) + 1;\n const resolvedPosInHoveredLinkMark =\n this.pmView.state.doc.resolve(posInHoveredLinkMark);\n const marksAtPos = resolvedPosInHoveredLinkMark.marks();\n\n for (const mark of marksAtPos) {\n if (\n mark.type.name === this.pmView.state.schema.mark(\"link\").type.name\n ) {\n this.mouseHoveredLinkMark = mark;\n this.mouseHoveredLinkMarkRange =\n getMarkRange(resolvedPosInHoveredLinkMark, mark.type, mark.attrs) ||\n undefined;\n\n break;\n }\n }\n }\n\n this.startMenuUpdateTimer();\n\n return false;\n };\n\n clickHandler = (event: MouseEvent) => {\n const editorWrapper = this.pmView.dom.parentElement!;\n\n if (\n // Toolbar is open.\n this.linkMark &&\n // An element is clicked.\n event &&\n event.target &&\n // The clicked element is not the editor.\n !(\n editorWrapper === (event.target as Node) ||\n editorWrapper.contains(event.target as Node)\n )\n ) {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n }\n };\n\n scrollHandler = () => {\n if (this.linkMark !== undefined) {\n if (this.state?.show) {\n this.state.referencePos = posToDOMRect(\n this.pmView,\n this.linkMarkRange!.from,\n this.linkMarkRange!.to\n );\n this.emitUpdate();\n }\n }\n };\n\n editLink(url: string, text: string) {\n const tr = this.pmView.state.tr.insertText(\n text,\n this.linkMarkRange!.from,\n this.linkMarkRange!.to\n );\n tr.addMark(\n this.linkMarkRange!.from,\n this.linkMarkRange!.from + text.length,\n this.pmView.state.schema.mark(\"link\", { href: url })\n );\n this.pmView.dispatch(tr);\n this.pmView.focus();\n\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n }\n\n deleteLink() {\n this.pmView.dispatch(\n this.pmView.state.tr\n .removeMark(\n this.linkMarkRange!.from,\n this.linkMarkRange!.to,\n this.linkMark!.type\n )\n .setMeta(\"preventAutolink\", true)\n );\n this.pmView.focus();\n\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n }\n\n update() {\n if (!this.pmView.hasFocus()) {\n return;\n }\n\n // Saves the currently hovered link mark before it's updated.\n const prevLinkMark = this.linkMark;\n\n // Resets the currently hovered link mark.\n this.linkMark = undefined;\n this.linkMarkRange = undefined;\n\n // Resets the link mark currently hovered by the keyboard cursor.\n this.keyboardHoveredLinkMark = undefined;\n this.keyboardHoveredLinkMarkRange = undefined;\n\n // Finds link mark at the editor selection's position to update keyboardHoveredLinkMark and\n // keyboardHoveredLinkMarkRange.\n if (this.pmView.state.selection.empty) {\n const marksAtPos = this.pmView.state.selection.$from.marks();\n\n for (const mark of marksAtPos) {\n if (\n mark.type.name === this.pmView.state.schema.mark(\"link\").type.name\n ) {\n this.keyboardHoveredLinkMark = mark;\n this.keyboardHoveredLinkMarkRange =\n getMarkRange(\n this.pmView.state.selection.$from,\n mark.type,\n mark.attrs\n ) || undefined;\n\n break;\n }\n }\n }\n\n if (this.mouseHoveredLinkMark) {\n this.linkMark = this.mouseHoveredLinkMark;\n this.linkMarkRange = this.mouseHoveredLinkMarkRange;\n }\n\n // Keyboard cursor position takes precedence over mouse hovered link.\n if (this.keyboardHoveredLinkMark) {\n this.linkMark = this.keyboardHoveredLinkMark;\n this.linkMarkRange = this.keyboardHoveredLinkMarkRange;\n }\n\n if (this.linkMark && this.editor.isEditable) {\n this.state = {\n show: true,\n referencePos: posToDOMRect(\n this.pmView,\n this.linkMarkRange!.from,\n this.linkMarkRange!.to\n ),\n url: this.linkMark!.attrs.href,\n text: this.pmView.state.doc.textBetween(\n this.linkMarkRange!.from,\n this.linkMarkRange!.to\n ),\n };\n this.emitUpdate();\n\n return;\n }\n\n // Hides menu.\n if (\n this.state?.show &&\n prevLinkMark &&\n (!this.linkMark || !this.editor.isEditable)\n ) {\n this.state.show = false;\n this.emitUpdate();\n\n return;\n }\n }\n\n destroy() {\n this.pmView.dom.removeEventListener(\"mouseover\", this.mouseOverHandler);\n document.removeEventListener(\"scroll\", this.scrollHandler);\n document.removeEventListener(\"click\", this.clickHandler, true);\n }\n}\n\nexport const linkToolbarPluginKey = new PluginKey(\"LinkToolbarPlugin\");\n\nexport class LinkToolbarProsemirrorPlugin<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n> extends EventEmitter<any> {\n private view: LinkToolbarView | undefined;\n public readonly plugin: Plugin;\n\n constructor(editor: BlockNoteEditor<BSchema, I, S>) {\n super();\n this.plugin = new Plugin({\n key: linkToolbarPluginKey,\n view: (editorView) => {\n this.view = new LinkToolbarView(editor, editorView, (state) => {\n this.emit(\"update\", state);\n });\n return this.view;\n },\n });\n }\n\n public onUpdate(callback: (state: LinkToolbarState) => void) {\n return this.on(\"update\", callback);\n }\n\n /**\n * Edit the currently hovered link.\n */\n public editLink = (url: string, text: string) => {\n this.view!.editLink(url, text);\n };\n\n /**\n * Delete the currently hovered link.\n */\n public deleteLink = () => {\n this.view!.deleteLink();\n };\n\n /**\n * When hovering on/off links using the mouse cursor, the link toolbar will\n * open & close with a delay.\n *\n * This function starts the delay timer, and should be used for when the mouse\n * cursor enters the link toolbar.\n */\n public startHideTimer = () => {\n this.view!.startMenuUpdateTimer();\n };\n\n /**\n * When hovering on/off links using the mouse cursor, the link toolbar will\n * open & close with a delay.\n *\n * This function stops the delay timer, and should be used for when the mouse\n * cursor exits the link toolbar.\n */\n public stopHideTimer = () => {\n this.view!.stopMenuUpdateTimer();\n };\n}\n","import { findParentNode } from \"@tiptap/core\";\nimport { EditorState, Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet, EditorView } from \"prosemirror-view\";\n\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../schema\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition\";\nimport { EventEmitter } from \"../../util/EventEmitter\";\n\nconst findBlock = findParentNode((node) => node.type.name === \"blockContainer\");\n\nexport type SuggestionMenuState = UiElementPosition & {\n query: string;\n};\n\nclass SuggestionMenuView<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n> {\n private state?: SuggestionMenuState;\n public emitUpdate: (triggerCharacter: string) => void;\n\n pluginState: SuggestionPluginState;\n\n constructor(\n private readonly editor: BlockNoteEditor<BSchema, I, S>,\n emitUpdate: (menuName: string, state: SuggestionMenuState) => void\n ) {\n this.pluginState = undefined;\n\n this.emitUpdate = (menuName: string) => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized suggestions menu\");\n }\n\n emitUpdate(menuName, this.state);\n };\n\n document.addEventListener(\"scroll\", this.handleScroll);\n }\n\n handleScroll = () => {\n if (this.state?.show) {\n const decorationNode = document.querySelector(\n `[data-decoration-id=\"${this.pluginState!.decorationId}\"]`\n );\n this.state.referencePos = decorationNode!.getBoundingClientRect();\n this.emitUpdate(this.pluginState!.triggerCharacter!);\n }\n };\n\n update(view: EditorView, prevState: EditorState) {\n const prev: SuggestionPluginState =\n suggestionMenuPluginKey.getState(prevState);\n const next: SuggestionPluginState = suggestionMenuPluginKey.getState(\n view.state\n );\n\n // See how the state changed\n const started = prev === undefined && next !== undefined;\n const stopped = prev !== undefined && next === undefined;\n const changed = prev !== undefined && next !== undefined;\n\n // Cancel when suggestion isn't active\n if (!started && !changed && !stopped) {\n return;\n }\n\n this.pluginState = stopped ? prev : next;\n\n if (stopped || !this.editor.isEditable) {\n this.state!.show = false;\n this.emitUpdate(this.pluginState!.triggerCharacter);\n\n return;\n }\n\n const decorationNode = document.querySelector(\n `[data-decoration-id=\"${this.pluginState!.decorationId}\"]`\n );\n\n if (this.editor.isEditable) {\n this.state = {\n show: true,\n referencePos: decorationNode!.getBoundingClientRect(),\n query: this.pluginState!.query,\n };\n\n this.emitUpdate(this.pluginState!.triggerCharacter!);\n }\n }\n\n destroy() {\n document.removeEventListener(\"scroll\", this.handleScroll);\n }\n\n closeMenu = () => {\n this.editor._tiptapEditor.view.dispatch(\n this.editor._tiptapEditor.view.state.tr.setMeta(\n suggestionMenuPluginKey,\n null\n )\n );\n };\n\n clearQuery = () => {\n if (this.pluginState === undefined) {\n return;\n }\n\n this.editor._tiptapEditor\n .chain()\n .focus()\n .deleteRange({\n from:\n this.pluginState.queryStartPos! -\n (this.pluginState.fromUserInput\n ? this.pluginState.triggerCharacter!.length\n : 0),\n to: this.editor._tiptapEditor.state.selection.from,\n })\n .run();\n };\n}\n\ntype SuggestionPluginState =\n | {\n triggerCharacter: string;\n fromUserInput: boolean;\n queryStartPos: number;\n query: string;\n decorationId: string;\n }\n | undefined;\n\nexport const suggestionMenuPluginKey = new PluginKey(\"SuggestionMenuPlugin\");\n\n/**\n * A ProseMirror plugin for suggestions, designed to make '/'-commands possible as well as mentions.\n *\n * This is basically a simplified version of TipTap's [Suggestions](https://github.com/ueberdosis/tiptap/tree/db92a9b313c5993b723c85cd30256f1d4a0b65e1/packages/suggestion) plugin.\n *\n * This version is adapted from the aforementioned version in the following ways:\n * - This version supports generic items instead of only strings (to allow for more advanced filtering for example)\n * - This version hides some unnecessary complexity from the user of the plugin.\n * - This version handles key events differently\n */\nexport class SuggestionMenuProseMirrorPlugin<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n> extends EventEmitter<any> {\n private view: SuggestionMenuView<BSchema, I, S> | undefined;\n public readonly plugin: Plugin;\n\n private triggerCharacters: string[] = [];\n\n constructor(editor: BlockNoteEditor<BSchema, I, S>) {\n super();\n const triggerCharacters = this.triggerCharacters;\n this.plugin = new Plugin({\n key: suggestionMenuPluginKey,\n\n view: () => {\n this.view = new SuggestionMenuView<BSchema, I, S>(\n editor,\n (triggerCharacter, state) => {\n this.emit(`update ${triggerCharacter}`, state);\n }\n );\n return this.view;\n },\n\n state: {\n // Initialize the plugin's internal state.\n init(): SuggestionPluginState {\n return undefined;\n },\n\n // Apply changes to the plugin state from an editor transaction.\n apply(transaction, prev, _oldState, newState): SuggestionPluginState {\n // TODO: More clearly define which transactions should be ignored.\n if (transaction.getMeta(\"orderedListIndexing\") !== undefined) {\n return prev;\n }\n\n // Either contains the trigger character if the menu should be shown,\n // or null if it should be hidden.\n const suggestionPluginTransactionMeta: {\n triggerCharacter: string;\n fromUserInput?: boolean;\n } | null = transaction.getMeta(suggestionMenuPluginKey);\n\n // Only opens a menu of no menu is already open\n if (\n typeof suggestionPluginTransactionMeta === \"object\" &&\n suggestionPluginTransactionMeta !== null &&\n prev === undefined\n ) {\n return {\n triggerCharacter:\n suggestionPluginTransactionMeta.triggerCharacter,\n fromUserInput:\n suggestionPluginTransactionMeta.fromUserInput !== false,\n queryStartPos: newState.selection.from,\n query: \"\",\n decorationId: `id_${Math.floor(Math.random() * 0xffffffff)}`,\n };\n }\n\n // Checks if the menu is hidden, in which case it doesn't need to be hidden or updated.\n if (prev === undefined) {\n return prev;\n }\n\n // Checks if the menu should be hidden.\n if (\n // Highlighting text should hide the menu.\n newState.selection.from !== newState.selection.to ||\n // Transactions with plugin metadata should hide the menu.\n suggestionPluginTransactionMeta === null ||\n // Certain mouse events should hide the menu.\n // TODO: Change to global mousedown listener.\n transaction.getMeta(\"focus\") ||\n transaction.getMeta(\"blur\") ||\n transaction.getMeta(\"pointer\") ||\n // Moving the caret before the character which triggered the menu should hide it.\n (prev.triggerCharacter !== undefined &&\n newState.selection.from < prev.queryStartPos!)\n ) {\n return undefined;\n }\n\n const next = { ...prev };\n\n // Updates the current query.\n next.query = newState.doc.textBetween(\n prev.queryStartPos!,\n newState.selection.from\n );\n\n return next;\n },\n },\n\n props: {\n handleTextInput(view, _from, _to, text) {\n const suggestionPluginState: SuggestionPluginState = (\n this as Plugin\n ).getState(view.state);\n\n if (\n triggerCharacters.includes(text) &&\n suggestionPluginState === undefined\n ) {\n view.dispatch(\n view.state.tr\n .insertText(text)\n .scrollIntoView()\n .setMeta(suggestionMenuPluginKey, {\n triggerCharacter: text,\n })\n );\n\n return true;\n }\n return false;\n },\n\n // Setup decorator on the currently active suggestion.\n decorations(state) {\n const suggestionPluginState: SuggestionPluginState = (\n this as Plugin\n ).getState(state);\n\n if (suggestionPluginState === undefined) {\n return null;\n }\n\n // If the menu was opened programmatically by another extension, it may not use a trigger character. In this\n // case, the decoration is set on the whole block instead, as the decoration range would otherwise be empty.\n if (!suggestionPluginState.fromUserInput) {\n const blockNode = findBlock(state.selection);\n if (blockNode) {\n return DecorationSet.create(state.doc, [\n Decoration.node(\n blockNode.pos,\n blockNode.pos + blockNode.node.nodeSize,\n {\n nodeName: \"span\",\n class: \"bn-suggestion-decorator\",\n \"data-decoration-id\": suggestionPluginState.decorationId,\n }\n ),\n ]);\n }\n }\n // Creates an inline decoration around the trigger character.\n return DecorationSet.create(state.doc, [\n Decoration.inline(\n suggestionPluginState.queryStartPos! -\n suggestionPluginState.triggerCharacter!.length,\n suggestionPluginState.queryStartPos!,\n {\n nodeName: \"span\",\n class: \"bn-suggestion-decorator\",\n \"data-decoration-id\": suggestionPluginState.decorationId,\n }\n ),\n ]);\n },\n },\n });\n }\n\n public onUpdate(\n triggerCharacter: string,\n callback: (state: SuggestionMenuState) => void\n ) {\n if (!this.triggerCharacters.includes(triggerCharacter)) {\n this.addTriggerCharacter(triggerCharacter);\n }\n // TODO: be able to remove the triggerCharacter\n return this.on(`update ${triggerCharacter}`, callback);\n }\n\n addTriggerCharacter = (triggerCharacter: string) => {\n this.triggerCharacters.push(triggerCharacter);\n };\n\n // TODO: Should this be called automatically when listeners are removed?\n removeTriggerCharacter = (triggerCharacter: string) => {\n this.triggerCharacters = this.triggerCharacters.filter(\n (c) => c !== triggerCharacter\n );\n };\n\n closeMenu = () => this.view!.closeMenu();\n\n clearQuery = () => this.view!.clearQuery();\n}\n\nexport function createSuggestionMenu<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(editor: BlockNoteEditor<BSchema, I, S>, triggerCharacter: string) {\n editor.suggestionMenus.addTriggerCharacter(triggerCharacter);\n}\n","import { Fragment, Node, ResolvedPos, Slice } from \"prosemirror-model\";\nimport { Selection } from \"prosemirror-state\";\nimport { Mappable } from \"prosemirror-transform\";\n\n/**\n * This class represents an editor selection which spans multiple nodes/blocks. It's currently only used to allow users\n * to drag multiple blocks at the same time. Expects the selection anchor and head to be between nodes, i.e. just before\n * the first target node and just after the last, and that anchor and head are at the same nesting level.\n *\n * Partially based on ProseMirror's NodeSelection implementation:\n * (https://github.com/ProseMirror/prosemirror-state/blob/master/src/selection.ts)\n * MultipleNodeSelection differs from NodeSelection in the following ways:\n * 1. Stores which nodes are included in the selection instead of just a single node.\n * 2. Already expects the selection to start just before the first target node and ends just after the last, while a\n * NodeSelection automatically sets both anchor and head to just before the single target node.\n */\nexport class MultipleNodeSelection extends Selection {\n nodes: Array<Node>;\n\n constructor($anchor: ResolvedPos, $head: ResolvedPos) {\n super($anchor, $head);\n\n // Parent is at the same nesting level as anchor/head since they are just before/ just after target nodes.\n const parentNode = $anchor.node();\n\n this.nodes = [];\n $anchor.doc.nodesBetween($anchor.pos, $head.pos, (node, _pos, parent) => {\n if (parent !== null && parent.eq(parentNode)) {\n this.nodes.push(node);\n return false;\n }\n return;\n });\n }\n\n static create(doc: Node, from: number, to = from): MultipleNodeSelection {\n return new MultipleNodeSelection(doc.resolve(from), doc.resolve(to));\n }\n\n content(): Slice {\n return new Slice(Fragment.from(this.nodes), 0, 0);\n }\n\n eq(selection: Selection): boolean {\n if (!(selection instanceof MultipleNodeSelection)) {\n return false;\n }\n\n if (this.nodes.length !== selection.nodes.length) {\n return false;\n }\n\n if (this.from !== selection.from || this.to !== selection.to) {\n return false;\n }\n\n for (let i = 0; i < this.nodes.length; i++) {\n if (!this.nodes[i].eq(selection.nodes[i])) {\n return false;\n }\n }\n\n return true;\n }\n\n map(doc: Node, mapping: Mappable): Selection {\n const fromResult = mapping.mapResult(this.from);\n const toResult = mapping.mapResult(this.to);\n\n if (toResult.deleted) {\n return Selection.near(doc.resolve(fromResult.pos));\n }\n\n if (fromResult.deleted) {\n return Selection.near(doc.resolve(toResult.pos));\n }\n\n return new MultipleNodeSelection(\n doc.resolve(fromResult.pos),\n doc.resolve(toResult.pos)\n );\n }\n\n toJSON(): any {\n return { type: \"node\", anchor: this.anchor, head: this.head };\n }\n}\n","import { PluginView } from \"@tiptap/pm/state\";\nimport { Node } from \"prosemirror-model\";\nimport { NodeSelection, Plugin, PluginKey, Selection } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\n\nimport { createExternalHTMLExporter } from \"../../api/exporters/html/externalHTMLExporter\";\nimport { createInternalHTMLSerializer } from \"../../api/exporters/html/internalHTMLSerializer\";\nimport { cleanHTMLToMarkdown } from \"../../api/exporters/markdown/markdownExporter\";\nimport { getBlockInfoFromPos } from \"../../api/getBlockInfoFromPos\";\nimport { Block } from \"../../blocks/defaultBlocks\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../schema\";\nimport { EventEmitter } from \"../../util/EventEmitter\";\nimport { suggestionMenuPluginKey } from \"../SuggestionMenu/SuggestionPlugin\";\nimport { MultipleNodeSelection } from \"./MultipleNodeSelection\";\n\nlet dragImageElement: Element | undefined;\n\nexport type SideMenuState<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n> = UiElementPosition & {\n // The block that the side menu is attached to.\n block: Block<BSchema, I, S>;\n};\n\nexport function getDraggableBlockFromCoords(\n coords: { left: number; top: number },\n view: EditorView\n) {\n if (!view.dom.isConnected) {\n // view is not connected to the DOM, this can cause posAtCoords to fail\n // (Cannot read properties of null (reading 'nearestDesc'), https://github.com/TypeCellOS/BlockNote/issues/123)\n return undefined;\n }\n\n const pos = view.posAtCoords(coords);\n if (!pos) {\n return undefined;\n }\n let node = view.domAtPos(pos.pos).node as HTMLElement;\n\n if (node === view.dom) {\n // mouse over root\n return undefined;\n }\n\n while (\n node &&\n node.parentNode &&\n node.parentNode !== view.dom &&\n !node.hasAttribute?.(\"data-id\")\n ) {\n node = node.parentNode as HTMLElement;\n }\n if (!node) {\n return undefined;\n }\n return { node, id: node.getAttribute(\"data-id\")! };\n}\n\nfunction blockPositionFromCoords(\n coords: { left: number; top: number },\n view: EditorView\n) {\n const block = getDraggableBlockFromCoords(coords, view);\n\n if (block && block.node.nodeType === 1) {\n // TODO: this uses undocumented PM APIs? do we need this / let's add docs?\n const docView = (view as any).docView;\n const desc = docView.nearestDesc(block.node, true);\n if (!desc || desc === docView) {\n return null;\n }\n return desc.posBefore;\n }\n return null;\n}\n\nfunction blockPositionsFromSelection(selection: Selection, doc: Node) {\n // Absolute positions just before the first block spanned by the selection, and just after the last block. Having the\n // selection start and end just before and just after the target blocks ensures no whitespace/line breaks are left\n // behind after dragging & dropping them.\n let beforeFirstBlockPos: number;\n let afterLastBlockPos: number;\n\n // Even the user starts dragging blocks but drops them in the same place, the selection will still be moved just\n // before & just after the blocks spanned by the selection, and therefore doesn't need to change if they try to drag\n // the same blocks again. If this happens, the anchor & head move out of the block content node they were originally\n // in. If the anchor should update but the head shouldn't and vice versa, it means the user selection is outside a\n // block content node, which should never happen.\n const selectionStartInBlockContent =\n doc.resolve(selection.from).node().type.spec.group === \"blockContent\";\n const selectionEndInBlockContent =\n doc.resolve(selection.to).node().type.spec.group === \"blockContent\";\n\n // Ensures that entire outermost nodes are selected if the selection spans multiple nesting levels.\n const minDepth = Math.min(selection.$anchor.depth, selection.$head.depth);\n\n if (selectionStartInBlockContent && selectionEndInBlockContent) {\n // Absolute positions at the start of the first block in the selection and at the end of the last block. User\n // selections will always start and end in block content nodes, but we want the start and end positions of their\n // parent block nodes, which is why minDepth - 1 is used.\n const startFirstBlockPos = selection.$from.start(minDepth - 1);\n const endLastBlockPos = selection.$to.end(minDepth - 1);\n\n // Shifting start and end positions by one moves them just outside the first and last selected blocks.\n beforeFirstBlockPos = doc.resolve(startFirstBlockPos - 1).pos;\n afterLastBlockPos = doc.resolve(endLastBlockPos + 1).pos;\n } else {\n beforeFirstBlockPos = selection.from;\n afterLastBlockPos = selection.to;\n }\n\n return { from: beforeFirstBlockPos, to: afterLastBlockPos };\n}\n\nfunction setDragImage(view: EditorView, from: number, to = from) {\n if (from === to) {\n // Moves to position to be just after the first (and only) selected block.\n to += view.state.doc.resolve(from + 1).node().nodeSize;\n }\n\n // Parent element is cloned to remove all unselected children without affecting the editor content.\n const parentClone = view.domAtPos(from).node.cloneNode(true) as Element;\n const parent = view.domAtPos(from).node as Element;\n\n const getElementIndex = (parentElement: Element, targetElement: Element) =>\n Array.prototype.indexOf.call(parentElement.children, targetElement);\n\n const firstSelectedBlockIndex = getElementIndex(\n parent,\n // Expects from position to be just before the first selected block.\n view.domAtPos(from + 1).node.parentElement!\n );\n const lastSelectedBlockIndex = getElementIndex(\n parent,\n // Expects to position to be just after the last selected block.\n view.domAtPos(to - 1).node.parentElement!\n );\n\n for (let i = parent.childElementCount - 1; i >= 0; i--) {\n if (i > lastSelectedBlockIndex || i < firstSelectedBlockIndex) {\n parentClone.removeChild(parentClone.children[i]);\n }\n }\n\n // dataTransfer.setDragImage(element) only works if element is attached to the DOM.\n unsetDragImage();\n dragImageElement = parentClone;\n\n // TODO: This is hacky, need a better way of assigning classes to the editor so that they can also be applied to the\n // drag preview.\n const classes = view.dom.className.split(\" \");\n const inheritedClasses = classes\n .filter(\n (className) =>\n className !== \"ProseMirror\" &&\n className !== \"bn-root\" &&\n className !== \"bn-editor\"\n )\n .join(\" \");\n\n dragImageElement.className =\n dragImageElement.className + \" bn-drag-preview \" + inheritedClasses;\n\n document.body.appendChild(dragImageElement);\n}\n\nfunction unsetDragImage() {\n if (dragImageElement !== undefined) {\n document.body.removeChild(dragImageElement);\n dragImageElement = undefined;\n }\n}\n\nfunction dragStart<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n e: { dataTransfer: DataTransfer | null; clientY: number },\n editor: BlockNoteEditor<BSchema, I, S>\n) {\n if (!e.dataTransfer) {\n return;\n }\n\n const view = editor.prosemirrorView;\n\n const editorBoundingBox = view.dom.getBoundingClientRect();\n\n const coords = {\n left: editorBoundingBox.left + editorBoundingBox.width / 2, // take middle of editor\n top: e.clientY,\n };\n\n const pos = blockPositionFromCoords(coords, view);\n if (pos != null) {\n const selection = view.state.selection;\n const doc = view.state.doc;\n\n const { from, to } = blockPositionsFromSelection(selection, doc);\n\n const draggedBlockInSelection = from <= pos && pos < to;\n const multipleBlocksSelected =\n selection.$anchor.node() !== selection.$head.node() ||\n selection instanceof MultipleNodeSelection;\n\n if (draggedBlockInSelection && multipleBlocksSelected) {\n view.dispatch(\n view.state.tr.setSelection(MultipleNodeSelection.create(doc, from, to))\n );\n setDragImage(view, from, to);\n } else {\n view.dispatch(\n view.state.tr.setSelection(NodeSelection.create(view.state.doc, pos))\n );\n setDragImage(view, pos);\n }\n\n const selectedSlice = view.state.selection.content();\n const schema = editor._tiptapEditor.schema;\n\n const internalHTMLSerializer = createInternalHTMLSerializer(schema, editor);\n const internalHTML = internalHTMLSerializer.serializeProseMirrorFragment(\n selectedSlice.content\n );\n\n const externalHTMLExporter = createExternalHTMLExporter(schema, editor);\n const externalHTML = externalHTMLExporter.exportProseMirrorFragment(\n selectedSlice.content\n );\n\n const plainText = cleanHTMLToMarkdown(externalHTML);\n\n e.dataTransfer.clearData();\n e.dataTransfer.setData(\"blocknote/html\", internalHTML);\n e.dataTransfer.setData(\"text/html\", externalHTML);\n e.dataTransfer.setData(\"text/plain\", plainText);\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setDragImage(dragImageElement!, 0, 0);\n view.dragging = { slice: selectedSlice, move: true };\n }\n}\n\nexport class SideMenuView<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n> implements PluginView\n{\n private state?: SideMenuState<BSchema, I, S>;\n private readonly emitUpdate: (state: SideMenuState<BSchema, I, S>) => void;\n\n // When true, the drag handle with be anchored at the same level as root elements\n // When false, the drag handle with be just to the left of the element\n // TODO: Is there any case where we want this to be false?\n private horizontalPosAnchoredAtRoot: boolean;\n private horizontalPosAnchor: number;\n\n private hoveredBlock: HTMLElement | undefined;\n\n // Used to check if currently dragged content comes from this editor instance.\n public isDragging = false;\n\n public menuFrozen = false;\n\n constructor(\n private readonly editor: BlockNoteEditor<BSchema, I, S>,\n private readonly pmView: EditorView,\n emitUpdate: (state: SideMenuState<BSchema, I, S>) => void\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized side menu\");\n }\n\n emitUpdate(this.state);\n };\n\n this.horizontalPosAnchoredAtRoot = true;\n this.horizontalPosAnchor = (\n this.pmView.dom.firstChild! as HTMLElement\n ).getBoundingClientRect().x;\n\n document.body.addEventListener(\"drop\", this.onDrop, true);\n document.body.addEventListener(\"dragover\", this.onDragOver);\n this.pmView.dom.addEventListener(\"dragstart\", this.onDragStart);\n\n // Shows or updates menu position whenever the cursor moves, if the menu isn't frozen.\n document.body.addEventListener(\"mousemove\", this.onMouseMove, true);\n\n // Makes menu scroll with the page.\n document.addEventListener(\"scroll\", this.onScroll);\n\n // Unfreezes the menu whenever the user clicks anywhere.\n document.body.addEventListener(\"mousedown\", this.onMouseDown, true);\n // Hides and unfreezes the menu whenever the user presses a key.\n document.body.addEventListener(\"keydown\", this.onKeyDown, true);\n }\n\n /**\n * Sets isDragging when dragging text.\n */\n onDragStart = () => {\n this.isDragging = true;\n };\n\n /**\n * If the event is outside the editor contents,\n * we dispatch a fake event, so that we can still drop the content\n * when dragging / dropping to the side of the editor\n */\n onDrop = (event: DragEvent) => {\n this.editor._tiptapEditor.commands.blur();\n\n if ((event as any).synthetic || !this.isDragging) {\n return;\n }\n\n const pos = this.pmView.posAtCoords({\n left: event.clientX,\n top: event.clientY,\n });\n\n this.isDragging = false;\n\n if (!pos || pos.inside === -1) {\n const evt = new Event(\"drop\", event) as any;\n const editorBoundingBox = (\n this.pmView.dom.firstChild! as HTMLElement\n ).getBoundingClientRect();\n evt.clientX = editorBoundingBox.left + editorBoundingBox.width / 2;\n evt.clientY = event.clientY;\n evt.dataTransfer = event.dataTransfer;\n evt.preventDefault = () => event.preventDefault();\n evt.synthetic = true; // prevent recursion\n // console.log(\"dispatch fake drop\");\n this.pmView.dom.dispatchEvent(evt);\n }\n };\n\n /**\n * If the event is outside the editor contents,\n * we dispatch a fake event, so that we can still drop the content\n * when dragging / dropping to the side of the editor\n */\n onDragOver = (event: DragEvent) => {\n if ((event as any).synthetic || !this.isDragging) {\n return;\n }\n const pos = this.pmView.posAtCoords({\n left: event.clientX,\n top: event.clientY,\n });\n\n if (!pos || pos.inside === -1) {\n const evt = new Event(\"dragover\", event) as any;\n const editorBoundingBox = (\n this.pmView.dom.firstChild! as HTMLElement\n ).getBoundingClientRect();\n evt.clientX = editorBoundingBox.left + editorBoundingBox.width / 2;\n evt.clientY = event.clientY;\n evt.dataTransfer = event.dataTransfer;\n evt.preventDefault = () => event.preventDefault();\n evt.synthetic = true; // prevent recursion\n // console.log(\"dispatch fake dragover\");\n this.pmView.dom.dispatchEvent(evt);\n }\n };\n\n onKeyDown = (_event: KeyboardEvent) => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate(this.state);\n }\n this.menuFrozen = false;\n };\n\n onMouseDown = (_event: MouseEvent) => {\n if (this.state && !this.state.show) {\n this.state.show = true;\n this.emitUpdate(this.state);\n }\n this.menuFrozen = false;\n };\n\n onMouseMove = (event: MouseEvent) => {\n if (this.menuFrozen) {\n return;\n }\n\n // Editor itself may have padding or other styling which affects\n // size/position, so we get the boundingRect of the first child (i.e. the\n // blockGroup that wraps all blocks in the editor) for more accurate side\n // menu placement.\n const editorBoundingBox = (\n this.pmView.dom.firstChild! as HTMLElement\n ).getBoundingClientRect();\n // We want the full area of the editor to check if the cursor is hovering\n // above it though.\n const editorOuterBoundingBox = this.pmView.dom.getBoundingClientRect();\n const cursorWithinEditor =\n event.clientX >= editorOuterBoundingBox.left &&\n event.clientX <= editorOuterBoundingBox.right &&\n event.clientY >= editorOuterBoundingBox.top &&\n event.clientY <= editorOuterBoundingBox.bottom;\n\n const editorWrapper = this.pmView.dom.parentElement!;\n\n // Doesn't update if the mouse hovers an element that's over the editor but\n // isn't a part of it or the side menu.\n if (\n // Cursor is within the editor area\n cursorWithinEditor &&\n // An element is hovered\n event &&\n event.target &&\n // Element is outside the editor\n !(\n editorWrapper === event.target ||\n editorWrapper.contains(event.target as HTMLElement)\n )\n ) {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate(this.state);\n }\n\n return;\n }\n\n this.horizontalPosAnchor = editorBoundingBox.x;\n\n // Gets block at mouse cursor's vertical position.\n const coords = {\n left: editorBoundingBox.left + editorBoundingBox.width / 2, // take middle of editor\n top: event.clientY,\n };\n const block = getDraggableBlockFromCoords(coords, this.pmView);\n\n // Closes the menu if the mouse cursor is beyond the editor vertically.\n if (!block || !this.editor.isEditable) {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate(this.state);\n }\n\n return;\n }\n\n // Doesn't update if the menu is already open and the mouse cursor is still hovering the same block.\n if (\n this.state?.show &&\n this.hoveredBlock?.hasAttribute(\"data-id\") &&\n this.hoveredBlock?.getAttribute(\"data-id\") === block.id\n ) {\n return;\n }\n\n this.hoveredBlock = block.node;\n\n // Gets the block's content node, which lets to ignore child blocks when determining the block menu's position.\n const blockContent = block.node.firstChild as HTMLElement;\n\n if (!blockContent) {\n return;\n }\n\n // Shows or updates elements.\n if (this.editor.isEditable) {\n const blockContentBoundingBox = blockContent.getBoundingClientRect();\n\n this.state = {\n show: true,\n referencePos: new DOMRect(\n this.horizontalPosAnchoredAtRoot\n ? this.horizontalPosAnchor\n : blockContentBoundingBox.x,\n blockContentBoundingBox.y,\n blockContentBoundingBox.width,\n blockContentBoundingBox.height\n ),\n block: this.editor.getBlock(\n this.hoveredBlock!.getAttribute(\"data-id\")!\n )!,\n };\n\n this.emitUpdate(this.state);\n }\n };\n\n onScroll = () => {\n if (this.state?.show) {\n const blockContent = this.hoveredBlock!.firstChild as HTMLElement;\n const blockContentBoundingBox = blockContent.getBoundingClientRect();\n\n this.state.referencePos = new DOMRect(\n this.horizontalPosAnchoredAtRoot\n ? this.horizontalPosAnchor\n : blockContentBoundingBox.x,\n blockContentBoundingBox.y,\n blockContentBoundingBox.width,\n blockContentBoundingBox.height\n );\n this.emitUpdate(this.state);\n }\n };\n\n destroy() {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate(this.state);\n }\n document.body.removeEventListener(\"mousemove\", this.onMouseMove, true);\n document.body.removeEventListener(\"dragover\", this.onDragOver);\n this.pmView.dom.removeEventListener(\"dragstart\", this.onDragStart);\n document.body.removeEventListener(\"drop\", this.onDrop, true);\n document.removeEventListener(\"scroll\", this.onScroll);\n document.body.removeEventListener(\"mousedown\", this.onMouseDown, true);\n document.body.removeEventListener(\"keydown\", this.onKeyDown, true);\n }\n\n addBlock() {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate(this.state);\n }\n\n this.menuFrozen = true;\n\n const blockContent = this.hoveredBlock!.firstChild! as HTMLElement;\n const blockContentBoundingBox = blockContent.getBoundingClientRect();\n\n const pos = this.pmView.posAtCoords({\n left: blockContentBoundingBox.left + blockContentBoundingBox.width / 2,\n top: blockContentBoundingBox.top + blockContentBoundingBox.height / 2,\n });\n if (!pos) {\n return;\n }\n\n const blockInfo = getBlockInfoFromPos(\n this.editor._tiptapEditor.state.doc,\n pos.pos\n );\n if (blockInfo === undefined) {\n return;\n }\n\n const { contentNode, startPos, endPos } = blockInfo;\n\n // Creates a new block if current one is not empty for the suggestion menu to open in.\n if (\n contentNode.type.spec.content !== \"inline*\" ||\n contentNode.textContent.length !== 0\n ) {\n const newBlockInsertionPos = endPos + 1;\n const newBlockContentPos = newBlockInsertionPos + 2;\n\n this.editor._tiptapEditor\n .chain()\n .BNCreateBlock(newBlockInsertionPos)\n // .BNUpdateBlock(newBlockContentPos, { type: \"paragraph\", props: {} })\n .setTextSelection(newBlockContentPos)\n .run();\n } else {\n this.editor._tiptapEditor.commands.setTextSelection(startPos + 1);\n }\n\n // Focuses and activates the suggestion menu.\n this.pmView.focus();\n this.pmView.dispatch(\n this.pmView.state.tr.scrollIntoView().setMeta(suggestionMenuPluginKey, {\n triggerCharacter: \"/\",\n fromUserInput: false,\n })\n );\n }\n}\n\nexport const sideMenuPluginKey = new PluginKey(\"SideMenuPlugin\");\n\nexport class SideMenuProsemirrorPlugin<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n> extends EventEmitter<any> {\n public view: SideMenuView<BSchema, I, S> | undefined;\n public readonly plugin: Plugin;\n\n constructor(private readonly editor: BlockNoteEditor<BSchema, I, S>) {\n super();\n this.plugin = new Plugin({\n key: sideMenuPluginKey,\n view: (editorView) => {\n this.view = new SideMenuView(editor, editorView, (state) => {\n this.emit(\"update\", state);\n });\n return this.view;\n },\n });\n }\n\n public onUpdate(callback: (state: SideMenuState<BSchema, I, S>) => void) {\n return this.on(\"update\", callback);\n }\n\n /**\n * If the block is empty, opens the slash menu. If the block has content,\n * creates a new block below and opens the slash menu in it.\n */\n addBlock = () => this.view!.addBlock();\n\n /**\n * Handles drag & drop events for blocks.\n */\n blockDragStart = (event: {\n dataTransfer: DataTransfer | null;\n clientY: number;\n }) => {\n this.view!.isDragging = true;\n dragStart(event, this.editor);\n };\n\n /**\n * Handles drag & drop events for blocks.\n */\n blockDragEnd = () => unsetDragImage();\n /**\n * Freezes the side menu. When frozen, the side menu will stay\n * attached to the same block regardless of which block is hovered by the\n * mouse cursor.\n */\n freezeMenu = () => (this.view!.menuFrozen = true);\n /**\n * Unfreezes the side menu. When frozen, the side menu will stay\n * attached to the same block regardless of which block is hovered by the\n * mouse cursor.\n */\n unfreezeMenu = () => (this.view!.menuFrozen = false);\n}\n","import { EditorState, Plugin, PluginKey } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\n\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport type {\n BlockFromConfig,\n InlineContentSchema,\n StyleSchema,\n} from \"../../schema\";\nimport { UiElementPosition } from \"../../extensions-shared/UiElementPosition\";\nimport { EventEmitter } from \"../../util/EventEmitter\";\nimport { DefaultBlockSchema } from \"../../blocks/defaultBlocks\";\n\nexport type ImagePanelState<\n I extends InlineContentSchema,\n S extends StyleSchema\n> = UiElementPosition & {\n // TODO: This typing is not quite right (children should be from BSchema)\n block: BlockFromConfig<DefaultBlockSchema[\"image\"], I, S>;\n};\n\nexport class ImagePanelView<\n I extends InlineContentSchema,\n S extends StyleSchema\n> {\n public state?: ImagePanelState<I, S>;\n public emitUpdate: () => void;\n\n public prevWasEditable: boolean | null = null;\n\n constructor(\n private readonly pluginKey: PluginKey,\n private readonly pmView: EditorView,\n emitUpdate: (state: ImagePanelState<I, S>) => void\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized image panel\");\n }\n\n emitUpdate(this.state);\n };\n\n pmView.dom.addEventListener(\"mousedown\", this.mouseDownHandler);\n\n pmView.dom.addEventListener(\"dragstart\", this.dragstartHandler);\n\n pmView.dom.addEventListener(\"blur\", this.blurHandler);\n\n document.addEventListener(\"scroll\", this.scrollHandler);\n }\n\n mouseDownHandler = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n // For dragging the whole editor.\n dragstartHandler = () => {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n blurHandler = (event: FocusEvent) => {\n const editorWrapper = this.pmView.dom.parentElement!;\n\n // Checks if the focus is moving to an element outside the editor. If it is,\n // the panel is hidden.\n if (\n // An element is clicked.\n event &&\n event.relatedTarget &&\n // Element is inside the editor.\n (editorWrapper === (event.relatedTarget as Node) ||\n editorWrapper.contains(event.relatedTarget as Node))\n ) {\n return;\n }\n\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n };\n\n scrollHandler = () => {\n if (this.state?.show) {\n const blockElement = document.querySelector(\n `[data-node-type=\"blockContainer\"][data-id=\"${this.state.block.id}\"]`\n )!;\n\n this.state.referencePos = blockElement.getBoundingClientRect();\n this.emitUpdate();\n }\n };\n\n update(view: EditorView, prevState: EditorState) {\n const pluginState: {\n block: BlockFromConfig<DefaultBlockSchema[\"image\"], I, S>;\n } = this.pluginKey.getState(view.state);\n\n if (!this.state?.show && pluginState.block) {\n const blockElement = document.querySelector(\n `[data-node-type=\"blockContainer\"][data-id=\"${pluginState.block.id}\"]`\n )!;\n\n this.state = {\n show: true,\n referencePos: blockElement.getBoundingClientRect(),\n block: pluginState.block,\n };\n\n this.emitUpdate();\n\n return;\n }\n\n if (\n !view.state.selection.eq(prevState.selection) ||\n !view.state.doc.eq(prevState.doc)\n ) {\n if (this.state?.show) {\n this.state.show = false;\n\n this.emitUpdate();\n }\n }\n }\n\n destroy() {\n this.pmView.dom.removeEventListener(\"mousedown\", this.mouseDownHandler);\n\n this.pmView.dom.removeEventListener(\"dragstart\", this.dragstartHandler);\n\n this.pmView.dom.removeEventListener(\"blur\", this.blurHandler);\n\n document.removeEventListener(\"scroll\", this.scrollHandler);\n }\n}\n\nconst imagePanelPluginKey = new PluginKey(\"ImagePanelPlugin\");\n\nexport class ImagePanelProsemirrorPlugin<\n I extends InlineContentSchema,\n S extends StyleSchema\n> extends EventEmitter<any> {\n private view: ImagePanelView<I, S> | undefined;\n public readonly plugin: Plugin;\n\n constructor(\n _editor: BlockNoteEditor<{ image: DefaultBlockSchema[\"image\"] }, I, S>\n ) {\n super();\n this.plugin = new Plugin<{\n block: BlockFromConfig<DefaultBlockSchema[\"image\"], I, S> | undefined;\n }>({\n key: imagePanelPluginKey,\n view: (editorView) => {\n this.view = new ImagePanelView(\n // editor,\n imagePanelPluginKey,\n editorView,\n (state) => {\n this.emit(\"update\", state);\n }\n );\n return this.view;\n },\n state: {\n init: () => {\n return {\n block: undefined,\n };\n },\n apply: (transaction) => {\n const block:\n | BlockFromConfig<DefaultBlockSchema[\"image\"], I, S>\n | undefined = transaction.getMeta(imagePanelPluginKey)?.block;\n\n return {\n block,\n };\n },\n },\n });\n }\n\n public onUpdate(callback: (state: ImagePanelState<I, S>) => void) {\n return this.on(\"update\", callback);\n }\n}\n","import { Plugin, PluginKey, PluginView } from \"prosemirror-state\";\nimport { Decoration, DecorationSet, EditorView } from \"prosemirror-view\";\nimport { nodeToBlock } from \"../../api/nodeConversions/nodeConversions\";\nimport { Block, DefaultBlockSchema } from \"../../blocks/defaultBlocks\";\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport {\n BlockFromConfigNoChildren,\n BlockSchemaWithBlock,\n InlineContentSchema,\n SpecificBlock,\n StyleSchema,\n} from \"../../schema\";\nimport { EventEmitter } from \"../../util/EventEmitter\";\nimport { getDraggableBlockFromCoords } from \"../SideMenu/SideMenuPlugin\";\n\nlet dragImageElement: HTMLElement | undefined;\n\nexport type TableHandlesState<\n I extends InlineContentSchema,\n S extends StyleSchema\n> = {\n show: boolean;\n referencePosCell: DOMRect;\n referencePosTable: DOMRect;\n\n block: BlockFromConfigNoChildren<DefaultBlockSchema[\"table\"], I, S>;\n colIndex: number;\n rowIndex: number;\n\n draggingState:\n | {\n draggedCellOrientation: \"row\" | \"col\";\n originalIndex: number;\n mousePos: number;\n }\n | undefined;\n};\n\nfunction setHiddenDragImage() {\n if (dragImageElement) {\n return;\n }\n\n dragImageElement = document.createElement(\"div\");\n dragImageElement.innerHTML = \"_\";\n dragImageElement.style.opacity = \"0\";\n dragImageElement.style.height = \"1px\";\n dragImageElement.style.width = \"1px\";\n document.body.appendChild(dragImageElement);\n}\n\nfunction unsetHiddenDragImage() {\n if (dragImageElement) {\n document.body.removeChild(dragImageElement);\n dragImageElement = undefined;\n }\n}\n\nfunction getChildIndex(node: Element) {\n return Array.prototype.indexOf.call(node.parentElement!.childNodes, node);\n}\n\n// Finds the DOM element corresponding to the table cell that the target element\n// is currently in. If the target element is not in a table cell, returns null.\nfunction domCellAround(target: Element | null): Element | null {\n while (target && target.nodeName !== \"TD\" && target.nodeName !== \"TH\") {\n target =\n target.classList && target.classList.contains(\"ProseMirror\")\n ? null\n : (target.parentNode as Element);\n }\n return target;\n}\n\n// Hides elements in the DOMwith the provided class names.\nfunction hideElementsWithClassNames(classNames: string[]) {\n classNames.forEach((className) => {\n const elementsToHide = document.getElementsByClassName(className);\n for (let i = 0; i < elementsToHide.length; i++) {\n (elementsToHide[i] as HTMLElement).style.visibility = \"hidden\";\n }\n });\n}\n\nexport class TableHandlesView<\n BSchema extends BlockSchemaWithBlock<\"table\", DefaultBlockSchema[\"table\"]>,\n I extends InlineContentSchema,\n S extends StyleSchema\n> implements PluginView\n{\n public state?: TableHandlesState<I, S>;\n public emitUpdate: () => void;\n\n public tableId: string | undefined;\n public tablePos: number | undefined;\n\n public menuFrozen = false;\n\n public prevWasEditable: boolean | null = null;\n\n constructor(\n private readonly editor: BlockNoteEditor<\n BlockSchemaWithBlock<\"table\", DefaultBlockSchema[\"table\"]>,\n I,\n S\n >,\n private readonly pmView: EditorView,\n emitUpdate: (state: TableHandlesState<I, S>) => void\n ) {\n this.emitUpdate = () => {\n if (!this.state) {\n throw new Error(\"Attempting to update uninitialized image toolbar\");\n }\n\n emitUpdate(this.state);\n };\n\n pmView.dom.addEventListener(\"mousemove\", this.mouseMoveHandler);\n\n document.addEventListener(\"dragover\", this.dragOverHandler);\n document.addEventListener(\"drop\", this.dropHandler);\n\n document.addEventListener(\"scroll\", this.scrollHandler);\n }\n\n mouseMoveHandler = (event: MouseEvent) => {\n if (this.menuFrozen) {\n return;\n }\n\n const target = domCellAround(event.target as HTMLElement);\n\n if (!target || !this.editor.isEditable) {\n if (this.state?.show) {\n this.state.show = false;\n this.emitUpdate();\n }\n return;\n }\n\n const colIndex = getChildIndex(target);\n const rowIndex = getChildIndex(target.parentElement!);\n const cellRect = target.getBoundingClientRect();\n const tableRect =\n target.parentElement!.parentElement!.getBoundingClientRect();\n\n const blockEl = getDraggableBlockFromCoords(cellRect, this.pmView);\n if (!blockEl) {\n throw new Error(\n \"Found table cell element, but could not find surrounding blockContent element.\"\n );\n }\n this.tableId = blockEl.id;\n\n if (\n this.state !== undefined &&\n this.state.show &&\n this.tableId === blockEl.id &&\n this.state.rowIndex === rowIndex &&\n this.state.colIndex === colIndex\n ) {\n return;\n }\n\n let block: Block<any, any, any> | undefined = undefined;\n\n // Copied from `getBlock`. We don't use `getBlock` since we also need the PM\n // node for the table, so we would effectively be doing the same work twice.\n this.editor._tiptapEditor.state.doc.descendants((node, pos) => {\n if (typeof block !== \"undefined\") {\n return false;\n }\n\n if (node.type.name !== \"blockContainer\" || node.attrs.id !== blockEl.id) {\n return true;\n }\n\n block = nodeToBlock(\n node,\n this.editor.schema.blockSchema,\n this.editor.schema.inlineContentSchema,\n this.editor.schema.styleSchema,\n this.editor.blockCache\n );\n this.tablePos = pos + 1;\n\n return false;\n });\n\n this.state = {\n show: true,\n referencePosCell: cellRect,\n referencePosTable: tableRect,\n\n block: block! as SpecificBlock<BSchema, \"table\", I, S>,\n colIndex: colIndex,\n rowIndex: rowIndex,\n\n draggingState: undefined,\n };\n this.emitUpdate();\n\n return false;\n };\n\n dragOverHandler = (event: DragEvent) => {\n if (this.state?.draggingState === undefined) {\n return;\n }\n\n event.preventDefault();\n event.dataTransfer!.dropEffect = \"move\";\n\n hideElementsWithClassNames([\n \"column-resize-handle\",\n \"prosemirror-dropcursor-block\",\n \"prosemirror-dropcursor-inline\",\n ]);\n\n // The mouse cursor coordinates, bounded to the table's bounding box. The\n // bounding box is shrunk by 1px on each side to ensure that the bounded\n // coordinates are always inside a table cell.\n const boundedMouseCoords = {\n left: Math.min(\n Math.max(event.clientX, this.state.referencePosTable.left + 1),\n this.state.referencePosTable.right - 1\n ),\n top: Math.min(\n Math.max(event.clientY, this.state.referencePosTable.top + 1),\n this.state.referencePosTable.bottom - 1\n ),\n };\n\n // Gets the table cell element that the bounded mouse cursor coordinates lie\n // in.\n const tableCellElements = document\n .elementsFromPoint(boundedMouseCoords.left, boundedMouseCoords.top)\n .filter(\n (element) => element.tagName === \"TD\" || element.tagName === \"TH\"\n );\n if (tableCellElements.length === 0) {\n throw new Error(\n \"Could not find table cell element that the mouse cursor is hovering over.\"\n );\n }\n const tableCellElement = tableCellElements[0];\n\n let emitStateUpdate = false;\n\n // Gets current row and column index.\n const rowIndex = getChildIndex(tableCellElement.parentElement!);\n const colIndex = getChildIndex(tableCellElement);\n\n // Checks if the drop cursor needs to be updated. This affects decorations\n // only so it doesn't trigger a state update.\n const oldIndex =\n this.state.draggingState.draggedCellOrientation === \"row\"\n ? this.state.rowIndex\n : this.state.colIndex;\n const newIndex =\n this.state.draggingState.draggedCellOrientation === \"row\"\n ? rowIndex\n : colIndex;\n const dispatchDecorationsTransaction = newIndex !== oldIndex;\n\n // Checks if either the hovered cell has changed and updates the row and\n // column index. Also updates the reference DOMRect.\n if (this.state.rowIndex !== rowIndex || this.state.colIndex !== colIndex) {\n this.state.rowIndex = rowIndex;\n this.state.colIndex = colIndex;\n\n this.state.referencePosCell = tableCellElement.getBoundingClientRect();\n\n emitStateUpdate = true;\n }\n\n // Checks if the mouse cursor position along the axis that the user is\n // dragging on has changed and updates it.\n const mousePos =\n this.state.draggingState.draggedCellOrientation === \"row\"\n ? boundedMouseCoords.top\n : boundedMouseCoords.left;\n if (this.state.draggingState.mousePos !== mousePos) {\n this.state.draggingState.mousePos = mousePos;\n\n emitStateUpdate = true;\n }\n\n // Emits a state update if any of the fields have changed.\n if (emitStateUpdate) {\n this.emitUpdate();\n }\n\n // Dispatches a dummy transaction to force a decorations update if\n // necessary.\n if (dispatchDecorationsTransaction) {\n this.pmView.dispatch(\n this.pmView.state.tr.setMeta(tableHandlesPluginKey, true)\n );\n }\n };\n\n dropHandler = (event: DragEvent) => {\n if (this.state === undefined || this.state.draggingState === undefined) {\n return;\n }\n\n event.preventDefault();\n\n const rows = this.state.block.content.rows;\n\n if (this.state.draggingState.draggedCellOrientation === \"row\") {\n const rowToMove = rows[this.state.draggingState.originalIndex];\n rows.splice(this.state.draggingState.originalIndex, 1);\n rows.splice(this.state.rowIndex, 0, rowToMove);\n } else {\n const cellsToMove = rows.map(\n (row) => row.cells[this.state!.draggingState!.originalIndex]\n );\n rows.forEach((row, rowIndex) => {\n row.cells.splice(this.state!.draggingState!.originalIndex, 1);\n row.cells.splice(this.state!.colIndex, 0, cellsToMove[rowIndex]);\n });\n }\n\n this.editor.updateBlock(this.state.block, {\n type: \"table\",\n content: {\n type: \"tableContent\",\n rows: rows,\n },\n });\n };\n\n scrollHandler = () => {\n if (this.state?.show) {\n const tableElement = document.querySelector(\n `[data-node-type=\"blockContainer\"][data-id=\"${this.tableId}\"] table`\n )!;\n const cellElement = tableElement.querySelector(\n `tr:nth-child(${this.state.rowIndex + 1}) > td:nth-child(${\n this.state.colIndex + 1\n })`\n )!;\n\n this.state.referencePosTable = tableElement.getBoundingClientRect();\n this.state.referencePosCell = cellElement.getBoundingClientRect();\n this.emitUpdate();\n }\n };\n\n destroy() {\n this.pmView.dom.removeEventListener(\"mousedown\", this.mouseMoveHandler);\n\n document.removeEventListener(\"dragover\", this.dragOverHandler);\n document.removeEventListener(\"drop\", this.dropHandler);\n\n document.removeEventListener(\"scroll\", this.scrollHandler);\n }\n}\n\nexport const tableHandlesPluginKey = new PluginKey(\"TableHandlesPlugin\");\n\nexport class TableHandlesProsemirrorPlugin<\n I extends InlineContentSchema,\n S extends StyleSchema\n> extends EventEmitter<any> {\n private view:\n | TableHandlesView<\n BlockSchemaWithBlock<\"table\", DefaultBlockSchema[\"table\"]>,\n I,\n S\n >\n | undefined;\n public readonly plugin: Plugin;\n\n constructor(\n private readonly editor: BlockNoteEditor<\n BlockSchemaWithBlock<\"table\", DefaultBlockSchema[\"table\"]>,\n I,\n S\n >\n ) {\n super();\n this.plugin = new Plugin({\n key: tableHandlesPluginKey,\n view: (editorView) => {\n this.view = new TableHandlesView(editor, editorView, (state) => {\n this.emit(\"update\", state);\n });\n return this.view;\n },\n // We use decorations to render the drop cursor when dragging a table row\n // or column. The decorations are updated in the `dragOverHandler` method.\n props: {\n decorations: (state) => {\n if (\n this.view === undefined ||\n this.view.state === undefined ||\n this.view.state.draggingState === undefined ||\n this.view.tablePos === undefined\n ) {\n return;\n }\n\n const newIndex =\n this.view.state.draggingState.draggedCellOrientation === \"row\"\n ? this.view.state.rowIndex\n : this.view.state.colIndex;\n\n const decorations: Decoration[] = [];\n\n if (newIndex === this.view.state.draggingState.originalIndex) {\n return DecorationSet.create(state.doc, decorations);\n }\n\n // Gets the table to show the drop cursor in.\n const tableResolvedPos = state.doc.resolve(this.view.tablePos + 1);\n const tableNode = tableResolvedPos.node();\n\n if (this.view.state.draggingState.draggedCellOrientation === \"row\") {\n // Gets the row at the new index.\n const rowResolvedPos = state.doc.resolve(\n tableResolvedPos.posAtIndex(newIndex) + 1\n );\n const rowNode = rowResolvedPos.node();\n\n // Iterates over all cells in the row.\n for (let i = 0; i < rowNode.childCount; i++) {\n // Gets each cell in the row.\n const cellResolvedPos = state.doc.resolve(\n rowResolvedPos.posAtIndex(i) + 1\n );\n const cellNode = cellResolvedPos.node();\n\n // Creates a decoration at the start or end of each cell,\n // depending on whether the new index is before or after the\n // original index.\n const decorationPos =\n cellResolvedPos.pos +\n (newIndex > this.view.state.draggingState.originalIndex\n ? cellNode.nodeSize - 2\n : 0);\n decorations.push(\n // The widget is a small bar which spans the width of the cell.\n Decoration.widget(decorationPos, () => {\n const widget = document.createElement(\"div\");\n widget.className = \"bn-table-drop-cursor\";\n widget.style.left = \"0\";\n widget.style.right = \"0\";\n // This is only necessary because the drop indicator's height\n // is an even number of pixels, whereas the border between\n // table cells is an odd number of pixels. So this makes the\n // positioning slightly more consistent regardless of where\n // the row is being dropped.\n if (\n newIndex > this.view!.state!.draggingState!.originalIndex\n ) {\n widget.style.bottom = \"-2px\";\n } else {\n widget.style.top = \"-3px\";\n }\n widget.style.height = \"4px\";\n\n return widget;\n })\n );\n }\n } else {\n // Iterates over all rows in the table.\n for (let i = 0; i < tableNode.childCount; i++) {\n // Gets each row in the table.\n const rowResolvedPos = state.doc.resolve(\n tableResolvedPos.posAtIndex(i) + 1\n );\n\n // Gets the cell at the new index in the row.\n const cellResolvedPos = state.doc.resolve(\n rowResolvedPos.posAtIndex(newIndex) + 1\n );\n const cellNode = cellResolvedPos.node();\n\n // Creates a decoration at the start or end of each cell,\n // depending on whether the new index is before or after the\n // original index.\n const decorationPos =\n cellResolvedPos.pos +\n (newIndex > this.view.state.draggingState.originalIndex\n ? cellNode.nodeSize - 2\n : 0);\n decorations.push(\n // The widget is a small bar which spans the height of the cell.\n Decoration.widget(decorationPos, () => {\n const widget = document.createElement(\"div\");\n widget.className = \"bn-table-drop-cursor\";\n widget.style.top = \"0\";\n widget.style.bottom = \"0\";\n // This is only necessary because the drop indicator's width\n // is an even number of pixels, whereas the border between\n // table cells is an odd number of pixels. So this makes the\n // positioning slightly more consistent regardless of where\n // the column is being dropped.\n if (\n newIndex > this.view!.state!.draggingState!.originalIndex\n ) {\n widget.style.right = \"-2px\";\n } else {\n widget.style.left = \"-3px\";\n }\n widget.style.width = \"4px\";\n\n return widget;\n })\n );\n }\n }\n\n return DecorationSet.create(state.doc, decorations);\n },\n },\n });\n }\n\n public onUpdate(callback: (state: TableHandlesState<I, S>) => void) {\n return this.on(\"update\", callback);\n }\n\n /**\n * Callback that should be set on the `dragStart` event for whichever element\n * is used as the column drag handle.\n */\n colDragStart = (event: {\n dataTransfer: DataTransfer | null;\n clientX: number;\n }) => {\n if (this.view!.state === undefined) {\n throw new Error(\n \"Attempted to drag table column, but no table block was hovered prior.\"\n );\n }\n\n this.view!.state.draggingState = {\n draggedCellOrientation: \"col\",\n originalIndex: this.view!.state.colIndex,\n mousePos: event.clientX,\n };\n this.view!.emitUpdate();\n\n this.editor._tiptapEditor.view.dispatch(\n this.editor._tiptapEditor.state.tr.setMeta(tableHandlesPluginKey, {\n draggedCellOrientation:\n this.view!.state.draggingState.draggedCellOrientation,\n originalIndex: this.view!.state.colIndex,\n newIndex: this.view!.state.colIndex,\n tablePos: this.view!.tablePos,\n })\n );\n\n setHiddenDragImage();\n event.dataTransfer!.setDragImage(dragImageElement!, 0, 0);\n event.dataTransfer!.effectAllowed = \"move\";\n };\n\n /**\n * Callback that should be set on the `dragStart` event for whichever element\n * is used as the row drag handle.\n */\n rowDragStart = (event: {\n dataTransfer: DataTransfer | null;\n clientY: number;\n }) => {\n if (this.view!.state === undefined) {\n throw new Error(\n \"Attempted to drag table row, but no table block was hovered prior.\"\n );\n }\n\n this.view!.state.draggingState = {\n draggedCellOrientation: \"row\",\n originalIndex: this.view!.state.rowIndex,\n mousePos: event.clientY,\n };\n this.view!.emitUpdate();\n\n this.editor._tiptapEditor.view.dispatch(\n this.editor._tiptapEditor.state.tr.setMeta(tableHandlesPluginKey, {\n draggedCellOrientation:\n this.view!.state.draggingState.draggedCellOrientation,\n originalIndex: this.view!.state.rowIndex,\n newIndex: this.view!.state.rowIndex,\n tablePos: this.view!.tablePos,\n })\n );\n\n setHiddenDragImage();\n event.dataTransfer!.setDragImage(dragImageElement!, 0, 0);\n event.dataTransfer!.effectAllowed = \"copyMove\";\n };\n\n /**\n * Callback that should be set on the `dragEnd` event for both the element\n * used as the row drag handle, and the one used as the column drag handle.\n */\n dragEnd = () => {\n if (this.view!.state === undefined) {\n throw new Error(\n \"Attempted to drag table row, but no table block was hovered prior.\"\n );\n }\n\n this.view!.state.draggingState = undefined;\n this.view!.emitUpdate();\n\n this.editor._tiptapEditor.view.dispatch(\n this.editor._tiptapEditor.state.tr.setMeta(tableHandlesPluginKey, null)\n );\n\n unsetHiddenDragImage();\n };\n\n /**\n * Freezes the drag handles. When frozen, they will stay attached to the same\n * cell regardless of which cell is hovered by the mouse cursor.\n */\n freezeHandles = () => {\n this.view!.menuFrozen = true;\n };\n\n /**\n * Unfreezes the drag handles. When frozen, they will stay attached to the\n * same cell regardless of which cell is hovered by the mouse cursor.\n */\n unfreezeHandles = () => {\n this.view!.menuFrozen = false;\n };\n}\n","import { Extension } from \"@tiptap/core\";\nimport { NodeSelection, Plugin } from \"prosemirror-state\";\nimport { Node } from \"prosemirror-model\";\n\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../schema\";\nimport { createExternalHTMLExporter } from \"./html/externalHTMLExporter\";\nimport { createInternalHTMLSerializer } from \"./html/internalHTMLSerializer\";\nimport { cleanHTMLToMarkdown } from \"./markdown/markdownExporter\";\nimport { EditorView } from \"prosemirror-view\";\n\nfunction selectedFragmentToHTML<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n view: EditorView,\n editor: BlockNoteEditor<BSchema, I, S>\n): {\n internalHTML: string;\n externalHTML: string;\n plainText: string;\n} {\n const selectedFragment = view.state.selection.content().content;\n\n const internalHTMLSerializer = createInternalHTMLSerializer(\n view.state.schema,\n editor\n );\n const internalHTML =\n internalHTMLSerializer.serializeProseMirrorFragment(selectedFragment);\n\n const externalHTMLExporter = createExternalHTMLExporter(\n view.state.schema,\n editor\n );\n const externalHTML =\n externalHTMLExporter.exportProseMirrorFragment(selectedFragment);\n\n const plainText = cleanHTMLToMarkdown(externalHTML);\n\n return { internalHTML, externalHTML, plainText };\n}\n\nexport const createCopyToClipboardExtension = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n editor: BlockNoteEditor<BSchema, I, S>\n) =>\n Extension.create<{ editor: BlockNoteEditor<BSchema, I, S> }, undefined>({\n name: \"copyToClipboard\",\n addProseMirrorPlugins() {\n return [\n new Plugin({\n props: {\n handleDOMEvents: {\n copy(view, event) {\n // Stops the default browser copy behaviour.\n event.preventDefault();\n event.clipboardData!.clearData();\n\n // Checks if a `blockContent` node is being copied and expands\n // the selection to the parent `blockContainer` node. This is\n // for the use-case in which only a block without content is\n // selected, e.g. an image block.\n if (\n \"node\" in view.state.selection &&\n (view.state.selection.node as Node).type.spec.group ===\n \"blockContent\"\n ) {\n view.dispatch(\n view.state.tr.setSelection(\n new NodeSelection(\n view.state.doc.resolve(view.state.selection.from - 1)\n )\n )\n );\n }\n\n const { internalHTML, externalHTML, plainText } =\n selectedFragmentToHTML(view, editor);\n\n // TODO: Writing to other MIME types not working in Safari for\n // some reason.\n event.clipboardData!.setData(\"blocknote/html\", internalHTML);\n event.clipboardData!.setData(\"text/html\", externalHTML);\n event.clipboardData!.setData(\"text/plain\", plainText);\n\n // Prevent default PM handler to be called\n return true;\n },\n // This is for the use-case in which only a block without content\n // is selected, e.g. an image block, and dragged (not using the\n // drag handle).\n dragstart(view, event) {\n // Checks if a `NodeSelection` is active.\n if (!(\"node\" in view.state.selection)) {\n return;\n }\n\n // Checks if a `blockContent` node is being dragged.\n if (\n (view.state.selection.node as Node).type.spec.group !==\n \"blockContent\"\n ) {\n return;\n }\n\n // Expands the selection to the parent `blockContainer` node.\n view.dispatch(\n view.state.tr.setSelection(\n new NodeSelection(\n view.state.doc.resolve(view.state.selection.from - 1)\n )\n )\n );\n\n // Stops the default browser drag start behaviour.\n event.preventDefault();\n event.dataTransfer!.clearData();\n\n const { internalHTML, externalHTML, plainText } =\n selectedFragmentToHTML(view, editor);\n\n // TODO: Writing to other MIME types not working in Safari for\n // some reason.\n event.dataTransfer!.setData(\"blocknote/html\", internalHTML);\n event.dataTransfer!.setData(\"text/html\", externalHTML);\n event.dataTransfer!.setData(\"text/plain\", plainText);\n\n // Prevent default PM handler to be called\n return true;\n },\n },\n },\n }),\n ];\n },\n });\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin } from \"prosemirror-state\";\n\nimport type { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport { BlockSchema, InlineContentSchema, StyleSchema } from \"../../schema\";\nimport { nestedListsToBlockNoteStructure } from \"./html/util/nestedLists\";\n\nconst acceptedMIMETypes = [\n \"blocknote/html\",\n \"text/html\",\n \"text/plain\",\n] as const;\n\nexport const createPasteFromClipboardExtension = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n editor: BlockNoteEditor<BSchema, I, S>\n) =>\n Extension.create<{ editor: BlockNoteEditor<BSchema, I, S> }, undefined>({\n name: \"pasteFromClipboard\",\n addProseMirrorPlugins() {\n return [\n new Plugin({\n props: {\n handleDOMEvents: {\n paste(_view, event) {\n event.preventDefault();\n let format: (typeof acceptedMIMETypes)[number] | null = null;\n\n for (const mimeType of acceptedMIMETypes) {\n if (event.clipboardData!.types.includes(mimeType)) {\n format = mimeType;\n break;\n }\n }\n\n if (format !== null) {\n let data = event.clipboardData!.getData(format);\n if (format === \"text/html\") {\n const htmlNode = nestedListsToBlockNoteStructure(\n data.trim()\n );\n\n data = htmlNode.innerHTML;\n }\n editor._tiptapEditor.view.pasteHTML(data);\n }\n\n return true;\n },\n },\n },\n }),\n ];\n },\n });\n","import { Extension } from \"@tiptap/core\";\nimport { defaultProps } from \"../../blocks/defaultProps\";\n\nexport const BackgroundColorExtension = Extension.create({\n name: \"blockBackgroundColor\",\n\n addGlobalAttributes() {\n return [\n {\n types: [\"blockContainer\"],\n attributes: {\n backgroundColor: {\n default: defaultProps.backgroundColor.default,\n parseHTML: (element) =>\n element.hasAttribute(\"data-background-color\")\n ? element.getAttribute(\"data-background-color\")\n : defaultProps.backgroundColor.default,\n renderHTML: (attributes) =>\n attributes.backgroundColor !==\n defaultProps.backgroundColor.default && {\n \"data-background-color\": attributes.backgroundColor,\n },\n },\n },\n },\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet } from \"prosemirror-view\";\n\nconst PLUGIN_KEY = new PluginKey(`blocknote-placeholder`);\n\n/**\n * This is a modified version of the tiptap\n * placeholder plugin, that also sets hasAnchorClass\n *\n * It does not set a data-placeholder (text is currently done in css)\n *\n */\nexport interface PlaceholderOptions {\n placeholders: Record<string | \"default\", string>;\n}\n\nexport const Placeholder = Extension.create<PlaceholderOptions>({\n name: \"placeholder\",\n\n addOptions() {\n return {\n placeholders: {\n default: \"Enter text or type '/' for commands\",\n heading: \"Heading\",\n bulletListItem: \"List\",\n numberedListItem: \"List\",\n },\n };\n },\n\n addProseMirrorPlugins() {\n const placeholders = this.options.placeholders;\n return [\n new Plugin({\n key: PLUGIN_KEY,\n view: () => {\n const styleEl = document.createElement(\"style\");\n document.head.appendChild(styleEl);\n const styleSheet = styleEl.sheet!;\n\n const getBaseSelector = (additionalSelectors = \"\") =>\n `.bn-block-content${additionalSelectors} .bn-inline-content:has(> .ProseMirror-trailingBreak):before`;\n\n const getSelector = (\n blockType: string | \"default\",\n mustBeFocused = true\n ) => {\n const mustBeFocusedSelector = mustBeFocused\n ? `[data-is-empty-and-focused]`\n : ``;\n\n if (blockType === \"default\") {\n return getBaseSelector(mustBeFocusedSelector);\n }\n\n const blockTypeSelector = `[data-content-type=\"${blockType}\"]`;\n return getBaseSelector(mustBeFocusedSelector + blockTypeSelector);\n };\n\n for (const [blockType, placeholder] of Object.entries(placeholders)) {\n const mustBeFocused = blockType === \"default\";\n\n styleSheet.insertRule(\n `${getSelector(\n blockType,\n mustBeFocused\n )}{ content: ${JSON.stringify(placeholder)}; }`\n );\n\n // For some reason, the placeholders which show when the block is focused\n // take priority over ones which show depending on block type, so we need\n // to make sure the block specific ones are also used when the block is\n // focused.\n if (!mustBeFocused) {\n styleSheet.insertRule(\n `${getSelector(blockType, true)}{ content: ${JSON.stringify(\n placeholder\n )}; }`\n );\n }\n }\n\n return {\n destroy: () => {\n document.head.removeChild(styleEl);\n },\n };\n },\n props: {\n // TODO: maybe also add placeholder for empty document (\"e.g.: start writing..\")\n decorations: (state) => {\n const { doc, selection } = state;\n\n const active = this.editor.isEditable;\n\n if (!active) {\n return;\n }\n\n if (!selection.empty) {\n return;\n }\n\n const $pos = selection.$anchor;\n const node = $pos.parent;\n\n if (node.content.size > 0) {\n return null;\n }\n\n const before = $pos.before();\n\n const dec = Decoration.node(before, before + node.nodeSize, {\n \"data-is-empty-and-focused\": \"true\",\n });\n\n return DecorationSet.create(doc, [dec]);\n },\n },\n }),\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\n\nexport const TextAlignmentExtension = Extension.create({\n name: \"textAlignment\",\n\n addGlobalAttributes() {\n return [\n {\n // Attribute is applied to block content instead of container so that child blocks don't inherit the text\n // alignment styling.\n types: [\"paragraph\", \"heading\", \"bulletListItem\", \"numberedListItem\"],\n attributes: {\n textAlignment: {\n default: \"left\",\n parseHTML: (element) => {\n return element.getAttribute(\"data-text-alignment\");\n },\n renderHTML: (attributes) =>\n attributes.textAlignment !== \"left\" && {\n \"data-text-alignment\": attributes.textAlignment,\n },\n },\n },\n },\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { defaultProps } from \"../../blocks/defaultProps\";\n\nexport const TextColorExtension = Extension.create({\n name: \"blockTextColor\",\n\n addGlobalAttributes() {\n return [\n {\n types: [\"blockContainer\"],\n attributes: {\n textColor: {\n default: defaultProps.textColor.default,\n parseHTML: (element) =>\n element.hasAttribute(\"data-text-color\")\n ? element.getAttribute(\"data-text-color\")\n : defaultProps.textColor.default,\n renderHTML: (attributes) =>\n attributes.textColor !== defaultProps.textColor.default && {\n \"data-text-color\": attributes.textColor,\n },\n },\n },\n },\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\n\n// based on https://github.com/ueberdosis/tiptap/blob/40a9404c94c7fef7900610c195536384781ae101/demos/src/Experiments/TrailingNode/Vue/trailing-node.ts\n\n/**\n * Extension based on:\n * - https://github.com/ueberdosis/tiptap/blob/v1/packages/tiptap-extensions/src/extensions/TrailingNode.js\n * - https://github.com/remirror/remirror/blob/e0f1bec4a1e8073ce8f5500d62193e52321155b9/packages/prosemirror-trailing-node/src/trailing-node-plugin.ts\n */\n\nexport interface TrailingNodeOptions {\n node: string;\n}\n\n/**\n * Add a trailing node to the document so the user can always click at the bottom of the document and start typing\n */\nexport const TrailingNode = Extension.create<TrailingNodeOptions>({\n name: \"trailingNode\",\n\n addProseMirrorPlugins() {\n const plugin = new PluginKey(this.name);\n // const disabledNodes = Object.entries(this.editor.schema.nodes)\n // .map(([, value]) => value)\n // .filter((node) => this.options.notAfter.includes(node.name));\n\n return [\n new Plugin({\n key: plugin,\n appendTransaction: (_, __, state) => {\n const { doc, tr, schema } = state;\n const shouldInsertNodeAtEnd = plugin.getState(state);\n const endPosition = doc.content.size - 2;\n const type = schema.nodes[\"blockContainer\"];\n const contentType = schema.nodes[\"paragraph\"];\n if (!shouldInsertNodeAtEnd) {\n return;\n }\n\n return tr.insert(\n endPosition,\n type.create(undefined, contentType.create())\n );\n },\n state: {\n init: (_, _state) => {\n // (maybe fix): use same logic as apply() here\n // so it works when initializing\n },\n apply: (tr, value) => {\n if (!tr.docChanged) {\n return value;\n }\n\n let lastNode = tr.doc.lastChild;\n\n if (!lastNode || lastNode.type.name !== \"blockGroup\") {\n throw new Error(\"Expected blockGroup\");\n }\n\n lastNode = lastNode.lastChild;\n\n if (!lastNode || lastNode.type.name !== \"blockContainer\") {\n throw new Error(\"Expected blockContainer\");\n }\n\n const lastContentNode = lastNode.firstChild;\n\n if (!lastContentNode) {\n throw new Error(\"Expected blockContent\");\n }\n\n // If last node is not empty (size > 4) or it doesn't contain\n // inline content, we need to add a trailing node.\n return (\n lastNode.nodeSize > 4 ||\n lastContentNode.type.spec.content !== \"inline*\"\n );\n },\n },\n }),\n ];\n },\n});\n","import { Plugin, PluginKey } from \"prosemirror-state\";\n\nconst PLUGIN_KEY = new PluginKey(\"non-editable-block\");\n// Prevent typing for blocks without inline content, as this would otherwise\n// convert them into paragraph blocks.\nexport const NonEditableBlockPlugin = () => {\n return new Plugin({\n key: PLUGIN_KEY,\n props: {\n handleKeyDown: (view, event) => {\n // Checks for node selection\n if (\"node\" in view.state.selection) {\n // Checks if key input will insert a character - we want to block this\n // as it will convert the block into a paragraph.\n if (\n event.key.length === 1 &&\n !event.ctrlKey &&\n !event.altKey &&\n !event.metaKey &&\n !event.shiftKey\n ) {\n event.preventDefault();\n }\n }\n },\n },\n });\n};\n","import { findChildren } from \"@tiptap/core\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet } from \"prosemirror-view\";\n\nconst PLUGIN_KEY = new PluginKey(`previous-blocks`);\n\nconst nodeAttributes: Record<string, string> = {\n // Numbered List Items\n index: \"index\",\n // Headings\n level: \"level\",\n // All Blocks\n type: \"type\",\n depth: \"depth\",\n \"depth-change\": \"depth-change\",\n};\n\n/**\n * This plugin tracks transformation of Block node attributes, so we can support CSS transitions.\n *\n * Problem it solves: ProseMirror recreates the DOM when transactions happen. So when a transaction changes a Node attribute,\n * it results in a completely new DOM element. This means CSS transitions don't work.\n *\n * Solution: When attributes change on a node, this plugin sets a data-* attribute with the \"previous\" value. This way we can still use CSS transitions. (See block.module.css)\n */\nexport const PreviousBlockTypePlugin = () => {\n let timeout: any;\n return new Plugin({\n key: PLUGIN_KEY,\n view(_editorView) {\n return {\n update: async (view, _prevState) => {\n if (this.key?.getState(view.state).updatedBlocks.size > 0) {\n // use setTimeout 0 to clear the decorations so that at least\n // for one DOM-render the decorations have been applied\n timeout = setTimeout(() => {\n view.dispatch(\n view.state.tr.setMeta(PLUGIN_KEY, { clearUpdate: true })\n );\n }, 0);\n }\n },\n destroy: () => {\n if (timeout) {\n clearTimeout(timeout);\n }\n },\n };\n },\n state: {\n init() {\n return {\n // Block attributes, by block ID, from just before the previous transaction.\n prevTransactionOldBlockAttrs: {} as any,\n // Block attributes, by block ID, from just before the current transaction.\n currentTransactionOldBlockAttrs: {} as any,\n // Set of IDs of blocks whose attributes changed from the current transaction.\n updatedBlocks: new Set<string>(),\n };\n },\n\n apply(transaction, prev, oldState, newState) {\n prev.currentTransactionOldBlockAttrs = {};\n prev.updatedBlocks.clear();\n\n if (!transaction.docChanged || oldState.doc.eq(newState.doc)) {\n return prev;\n }\n\n // TODO: Instead of iterating through the entire document, only check nodes affected by the transactions. Will\n // also probably require checking nodes affected by the previous transaction too.\n // We didn't get this to work yet:\n // const transform = combineTransactionSteps(oldState.doc, [transaction]);\n // // const { mapping } = transform;\n // const changes = getChangedRanges(transform);\n //\n // changes.forEach(({ oldRange, newRange }) => {\n // const oldNodes = findChildrenInRange(\n // oldState.doc,\n // oldRange,\n // (node) => node.attrs.id\n // );\n //\n // const newNodes = findChildrenInRange(\n // newState.doc,\n // newRange,\n // (node) => node.attrs.id\n // );\n\n const currentTransactionOriginalOldBlockAttrs = {} as any;\n\n const oldNodes = findChildren(oldState.doc, (node) => node.attrs.id);\n const oldNodesById = new Map(\n oldNodes.map((node) => [node.node.attrs.id, node])\n );\n const newNodes = findChildren(newState.doc, (node) => node.attrs.id);\n\n // Traverses all block containers in the new editor state.\n for (const node of newNodes) {\n const oldNode = oldNodesById.get(node.node.attrs.id);\n\n const oldContentNode = oldNode?.node.firstChild;\n const newContentNode = node.node.firstChild;\n\n if (oldNode && oldContentNode && newContentNode) {\n const newAttrs = {\n index: newContentNode.attrs.index,\n level: newContentNode.attrs.level,\n type: newContentNode.type.name,\n depth: newState.doc.resolve(node.pos).depth,\n };\n\n let oldAttrs = {\n index: oldContentNode.attrs.index,\n level: oldContentNode.attrs.level,\n type: oldContentNode.type.name,\n depth: oldState.doc.resolve(oldNode.pos).depth,\n };\n\n currentTransactionOriginalOldBlockAttrs[node.node.attrs.id] =\n oldAttrs;\n\n // Whenever a transaction is appended by the OrderedListItemIndexPlugin, it's given the metadata:\n // { \"orderedListIndexing\": true }\n // These appended transactions happen immediately after any transaction which causes ordered list item\n // indices to require updating, including those which trigger animations. Therefore, these animations are\n // immediately overridden when the PreviousBlockTypePlugin processes the appended transaction, despite only\n // the listItemIndex attribute changing. To solve this, oldAttrs must be edited for transactions with the\n // \"orderedListIndexing\" metadata, so the correct animation can be re-triggered.\n if (transaction.getMeta(\"numberedListIndexing\")) {\n // If the block existed before the transaction, gets the attributes from before the previous transaction\n // (i.e. the transaction that caused list item indices to need updating).\n if (node.node.attrs.id in prev.prevTransactionOldBlockAttrs) {\n oldAttrs =\n prev.prevTransactionOldBlockAttrs[node.node.attrs.id];\n }\n\n // Stops list item indices themselves being animated (looks smoother), unless the block's content type is\n // changing from a numbered list item to something else.\n if (newAttrs.type === \"numberedListItem\") {\n oldAttrs.index = newAttrs.index;\n }\n }\n\n prev.currentTransactionOldBlockAttrs[node.node.attrs.id] = oldAttrs;\n\n // TODO: faster deep equal?\n if (JSON.stringify(oldAttrs) !== JSON.stringify(newAttrs)) {\n (oldAttrs as any)[\"depth-change\"] =\n oldAttrs.depth - newAttrs.depth;\n\n // for debugging:\n // console.log(\n // \"id:\",\n // node.node.attrs.id,\n // \"previousBlockTypePlugin changes detected, oldAttrs\",\n // oldAttrs,\n // \"new\",\n // newAttrs\n // );\n\n prev.updatedBlocks.add(node.node.attrs.id);\n }\n }\n }\n\n prev.prevTransactionOldBlockAttrs =\n currentTransactionOriginalOldBlockAttrs;\n\n return prev;\n },\n },\n props: {\n decorations(state) {\n const pluginState = (this as Plugin).getState(state);\n if (pluginState.updatedBlocks.size === 0) {\n return undefined;\n }\n\n const decorations: Decoration[] = [];\n\n state.doc.descendants((node, pos) => {\n if (!node.attrs.id) {\n return;\n }\n\n if (!pluginState.updatedBlocks.has(node.attrs.id)) {\n return;\n }\n\n const prevAttrs =\n pluginState.currentTransactionOldBlockAttrs[node.attrs.id];\n const decorationAttrs: any = {};\n\n for (const [nodeAttr, val] of Object.entries(prevAttrs)) {\n decorationAttrs[\"data-prev-\" + nodeAttributes[nodeAttr]] =\n val || \"none\";\n }\n\n // for debugging:\n // console.log(\n // \"previousBlockTypePlugin committing decorations\",\n // decorationAttrs\n // );\n\n const decoration = Decoration.node(pos, pos + node.nodeSize, {\n ...decorationAttrs,\n });\n\n decorations.push(decoration);\n });\n\n return DecorationSet.create(state.doc, decorations);\n },\n },\n });\n};\n","import { Node } from \"@tiptap/core\";\nimport { Fragment, Node as PMNode, Slice } from \"prosemirror-model\";\nimport { NodeSelection, TextSelection } from \"prosemirror-state\";\n\nimport { getBlockInfoFromPos } from \"../api/getBlockInfoFromPos\";\nimport {\n blockToNode,\n inlineContentToNodes,\n tableContentToNodes,\n} from \"../api/nodeConversions/nodeConversions\";\nimport { PartialBlock } from \"../blocks/defaultBlocks\";\nimport type { BlockNoteEditor } from \"../editor/BlockNoteEditor\";\nimport { NonEditableBlockPlugin } from \"../extensions/NonEditableBlocks/NonEditableBlockPlugin\";\nimport { PreviousBlockTypePlugin } from \"../extensions/PreviousBlockType/PreviousBlockTypePlugin\";\nimport {\n BlockNoteDOMAttributes,\n BlockSchema,\n InlineContentSchema,\n StyleSchema,\n} from \"../schema\";\nimport { mergeCSSClasses } from \"../util/browser\";\nimport { UnreachableCaseError } from \"../util/typescript\";\n\n// Object containing all possible block attributes.\nconst BlockAttributes: Record<string, string> = {\n blockColor: \"data-block-color\",\n blockStyle: \"data-block-style\",\n id: \"data-id\",\n depth: \"data-depth\",\n depthChange: \"data-depth-change\",\n};\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n block: {\n BNCreateBlock: (pos: number) => ReturnType;\n BNDeleteBlock: (posInBlock: number) => ReturnType;\n BNMergeBlocks: (posBetweenBlocks: number) => ReturnType;\n BNSplitBlock: (posInBlock: number, keepType: boolean) => ReturnType;\n BNUpdateBlock: <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n >(\n posInBlock: number,\n block: PartialBlock<BSchema, I, S>\n ) => ReturnType;\n BNCreateOrUpdateBlock: <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n >(\n posInBlock: number,\n block: PartialBlock<BSchema, I, S>\n ) => ReturnType;\n };\n }\n}\n\n/**\n * The main \"Block node\" documents consist of\n */\nexport const BlockContainer = Node.create<{\n domAttributes?: BlockNoteDOMAttributes;\n editor: BlockNoteEditor<BlockSchema, InlineContentSchema, StyleSchema>;\n}>({\n name: \"blockContainer\",\n group: \"blockContainer\",\n // A block always contains content, and optionally a blockGroup which contains nested blocks\n content: \"blockContent blockGroup?\",\n // Ensures content-specific keyboard handlers trigger first.\n priority: 50,\n defining: true,\n\n parseHTML() {\n return [\n {\n tag: \"div\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n const attrs: Record<string, string> = {};\n for (const [nodeAttr, HTMLAttr] of Object.entries(BlockAttributes)) {\n if (element.getAttribute(HTMLAttr)) {\n attrs[nodeAttr] = element.getAttribute(HTMLAttr)!;\n }\n }\n\n if (element.getAttribute(\"data-node-type\") === \"blockContainer\") {\n return attrs;\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n const blockOuter = document.createElement(\"div\");\n blockOuter.className = \"bn-block-outer\";\n blockOuter.setAttribute(\"data-node-type\", \"blockOuter\");\n for (const [attribute, value] of Object.entries(HTMLAttributes)) {\n if (attribute !== \"class\") {\n blockOuter.setAttribute(attribute, value);\n }\n }\n\n const blockHTMLAttributes = {\n ...(this.options.domAttributes?.block || {}),\n ...HTMLAttributes,\n };\n const block = document.createElement(\"div\");\n block.className = mergeCSSClasses(\"bn-block\", blockHTMLAttributes.class);\n block.setAttribute(\"data-node-type\", this.name);\n for (const [attribute, value] of Object.entries(blockHTMLAttributes)) {\n if (attribute !== \"class\") {\n block.setAttribute(attribute, value);\n }\n }\n\n blockOuter.appendChild(block);\n\n return {\n dom: blockOuter,\n contentDOM: block,\n };\n },\n\n addCommands() {\n return {\n // Creates a new text block at a given position.\n BNCreateBlock:\n (pos) =>\n ({ state, dispatch }) => {\n const newBlock =\n state.schema.nodes[\"blockContainer\"].createAndFill()!;\n\n if (dispatch) {\n state.tr.insert(pos, newBlock);\n }\n\n return true;\n },\n // Deletes a block at a given position.\n BNDeleteBlock:\n (posInBlock) =>\n ({ state, dispatch }) => {\n const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);\n if (blockInfo === undefined) {\n return false;\n }\n\n const { startPos, endPos } = blockInfo;\n\n if (dispatch) {\n state.tr.deleteRange(startPos, endPos);\n }\n\n return true;\n },\n // Updates a block at a given position.\n BNUpdateBlock:\n (posInBlock, block) =>\n ({ state, dispatch }) => {\n const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);\n if (blockInfo === undefined) {\n return false;\n }\n\n const { startPos, endPos, node, contentNode } = blockInfo;\n\n if (dispatch) {\n // Adds blockGroup node with child blocks if necessary.\n if (block.children !== undefined) {\n const childNodes = [];\n\n // Creates ProseMirror nodes for each child block, including their descendants.\n for (const child of block.children) {\n childNodes.push(\n blockToNode(\n child,\n state.schema,\n this.options.editor.schema.styleSchema\n )\n );\n }\n\n // Checks if a blockGroup node already exists.\n if (node.childCount === 2) {\n // Replaces all child nodes in the existing blockGroup with the ones created earlier.\n state.tr.replace(\n startPos + contentNode.nodeSize + 1,\n endPos - 1,\n new Slice(Fragment.from(childNodes), 0, 0)\n );\n } else {\n // Inserts a new blockGroup containing the child nodes created earlier.\n state.tr.insert(\n startPos + contentNode.nodeSize,\n state.schema.nodes[\"blockGroup\"].create({}, childNodes)\n );\n }\n }\n\n const oldType = contentNode.type.name;\n const newType = block.type || oldType;\n\n // The code below determines the new content of the block.\n // or \"keep\" to keep as-is\n let content: PMNode[] | \"keep\" = \"keep\";\n\n // Has there been any custom content provided?\n if (block.content) {\n if (typeof block.content === \"string\") {\n // Adds a single text node with no marks to the content.\n content = [state.schema.text(block.content)];\n } else if (Array.isArray(block.content)) {\n // Adds a text node with the provided styles converted into marks to the content,\n // for each InlineContent object.\n content = inlineContentToNodes(\n block.content,\n state.schema,\n this.options.editor.schema.styleSchema\n );\n } else if (block.content.type === \"tableContent\") {\n content = tableContentToNodes(\n block.content,\n state.schema,\n this.options.editor.schema.styleSchema\n );\n } else {\n throw new UnreachableCaseError(block.content.type);\n }\n } else {\n // no custom content has been provided, use existing content IF possible\n\n // Since some block types contain inline content and others don't,\n // we either need to call setNodeMarkup to just update type &\n // attributes, or replaceWith to replace the whole blockContent.\n const oldContentType = state.schema.nodes[oldType].spec.content;\n const newContentType = state.schema.nodes[newType].spec.content;\n\n if (oldContentType === \"\") {\n // keep old content, because it's empty anyway and should be compatible with\n // any newContentType\n } else if (newContentType !== oldContentType) {\n // the content type changed, replace the previous content\n content = [];\n } else {\n // keep old content, because the content type is the same and should be compatible\n }\n }\n\n // Now, changes the blockContent node type and adds the provided props\n // as attributes. Also preserves all existing attributes that are\n // compatible with the new type.\n //\n // Use either setNodeMarkup or replaceWith depending on whether the\n // content is being replaced or not.\n if (content === \"keep\") {\n // use setNodeMarkup to only update the type and attributes\n state.tr.setNodeMarkup(\n startPos,\n block.type === undefined\n ? undefined\n : state.schema.nodes[block.type],\n {\n ...contentNode.attrs,\n ...block.props,\n }\n );\n } else {\n // use replaceWith to replace the content and the block itself\n // also reset the selection since replacing the block content\n // sets it to the next block.\n state.tr\n .replaceWith(\n startPos,\n endPos,\n state.schema.nodes[newType].create(\n {\n ...contentNode.attrs,\n ...block.props,\n },\n content\n )\n )\n // If the node doesn't contain editable content, we want to\n // select the whole node. But if it does have editable content,\n // we want to set the selection to the start of it.\n .setSelection(\n state.schema.nodes[newType].spec.content === \"\"\n ? new NodeSelection(state.tr.doc.resolve(startPos))\n : state.schema.nodes[newType].spec.content === \"inline*\"\n ? new TextSelection(state.tr.doc.resolve(startPos))\n : // Need to offset the position as we have to get through the\n // `tableRow` and `tableCell` nodes to get to the\n // `tableParagraph` node we want to set the selection in.\n new TextSelection(state.tr.doc.resolve(startPos + 4))\n );\n }\n\n // Adds all provided props as attributes to the parent blockContainer node too, and also preserves existing\n // attributes.\n state.tr.setNodeMarkup(startPos - 1, undefined, {\n ...node.attrs,\n ...block.props,\n });\n }\n\n return true;\n },\n // Appends the text contents of a block to the nearest previous block, given a position between them. Children of\n // the merged block are moved out of it first, rather than also being merged.\n //\n // In the example below, the position passed into the function is between Block1 and Block2.\n //\n // Block1\n // Block2\n // Block3\n // Block4\n // Block5\n //\n // Becomes:\n //\n // Block1\n // Block2Block3\n // Block4\n // Block5\n BNMergeBlocks:\n (posBetweenBlocks) =>\n ({ state, dispatch }) => {\n const nextNodeIsBlock =\n state.doc.resolve(posBetweenBlocks + 1).node().type.name ===\n \"blockContainer\";\n const prevNodeIsBlock =\n state.doc.resolve(posBetweenBlocks - 1).node().type.name ===\n \"blockContainer\";\n\n if (!nextNodeIsBlock || !prevNodeIsBlock) {\n return false;\n }\n\n const nextBlockInfo = getBlockInfoFromPos(\n state.doc,\n posBetweenBlocks + 1\n );\n\n const { node, contentNode, startPos, endPos, depth } = nextBlockInfo!;\n\n // Removes a level of nesting all children of the next block by 1 level, if it contains both content and block\n // group nodes.\n if (node.childCount === 2) {\n const childBlocksStart = state.doc.resolve(\n startPos + contentNode.nodeSize + 1\n );\n const childBlocksEnd = state.doc.resolve(endPos - 1);\n const childBlocksRange =\n childBlocksStart.blockRange(childBlocksEnd);\n\n // Moves the block group node inside the block into the block group node that the current block is in.\n if (dispatch) {\n state.tr.lift(childBlocksRange!, depth - 1);\n }\n }\n\n let prevBlockEndPos = posBetweenBlocks - 1;\n let prevBlockInfo = getBlockInfoFromPos(state.doc, prevBlockEndPos);\n\n // Finds the nearest previous block, regardless of nesting level.\n while (prevBlockInfo!.numChildBlocks > 0) {\n prevBlockEndPos--;\n prevBlockInfo = getBlockInfoFromPos(state.doc, prevBlockEndPos);\n if (prevBlockInfo === undefined) {\n return false;\n }\n }\n\n // Deletes next block and adds its text content to the nearest previous block.\n\n if (dispatch) {\n dispatch(\n state.tr\n .deleteRange(startPos, startPos + contentNode.nodeSize)\n .replace(\n prevBlockEndPos - 1,\n startPos,\n new Slice(contentNode.content, 0, 0)\n )\n .scrollIntoView()\n );\n\n state.tr.setSelection(\n new TextSelection(state.doc.resolve(prevBlockEndPos - 1))\n );\n }\n\n return true;\n },\n // Splits a block at a given position. Content after the position is moved to a new block below, at the same\n // nesting level.\n BNSplitBlock:\n (posInBlock, keepType) =>\n ({ state, dispatch }) => {\n const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);\n if (blockInfo === undefined) {\n return false;\n }\n\n const { contentNode, contentType, startPos, endPos, depth } =\n blockInfo;\n\n const originalBlockContent = state.doc.cut(startPos + 1, posInBlock);\n const newBlockContent = state.doc.cut(posInBlock, endPos - 1);\n\n const newBlock =\n state.schema.nodes[\"blockContainer\"].createAndFill()!;\n\n const newBlockInsertionPos = endPos + 1;\n const newBlockContentPos = newBlockInsertionPos + 2;\n\n if (dispatch) {\n // Creates a new block. Since the schema requires it to have a content node, a paragraph node is created\n // automatically, spanning newBlockContentPos to newBlockContentPos + 1.\n state.tr.insert(newBlockInsertionPos, newBlock);\n\n // Replaces the content of the newly created block's content node. Doesn't replace the whole content node so\n // its type doesn't change.\n state.tr.replace(\n newBlockContentPos,\n newBlockContentPos + 1,\n newBlockContent.content.size > 0\n ? new Slice(\n Fragment.from(newBlockContent),\n depth + 2,\n depth + 2\n )\n : undefined\n );\n\n // Changes the type of the content node. The range doesn't matter as long as both from and to positions are\n // within the content node.\n if (keepType) {\n state.tr.setBlockType(\n newBlockContentPos,\n newBlockContentPos,\n state.schema.node(contentType).type,\n contentNode.attrs\n );\n }\n\n // Sets the selection to the start of the new block's content node.\n state.tr.setSelection(\n new TextSelection(state.doc.resolve(newBlockContentPos))\n );\n\n // Replaces the content of the original block's content node. Doesn't replace the whole content node so its\n // type doesn't change.\n state.tr.replace(\n startPos + 1,\n endPos - 1,\n originalBlockContent.content.size > 0\n ? new Slice(\n Fragment.from(originalBlockContent),\n depth + 2,\n depth + 2\n )\n : undefined\n );\n }\n\n return true;\n },\n };\n },\n\n addProseMirrorPlugins() {\n return [PreviousBlockTypePlugin(), NonEditableBlockPlugin()];\n },\n\n addKeyboardShortcuts() {\n // handleBackspace is partially adapted from https://github.com/ueberdosis/tiptap/blob/ed56337470efb4fd277128ab7ef792b37cfae992/packages/core/src/extensions/keymap.ts\n const handleBackspace = () =>\n this.editor.commands.first(({ commands }) => [\n // Deletes the selection if it's not empty.\n () => commands.deleteSelection(),\n // Undoes an input rule if one was triggered in the last editor state change.\n () => commands.undoInputRule(),\n // Reverts block content type to a paragraph if the selection is at the start of the block.\n () =>\n commands.command(({ state }) => {\n const { contentType, startPos } = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n )!;\n\n const selectionAtBlockStart = state.selection.from === startPos + 1;\n const isParagraph = contentType.name === \"paragraph\";\n\n if (selectionAtBlockStart && !isParagraph) {\n return commands.BNUpdateBlock(state.selection.from, {\n type: \"paragraph\",\n props: {},\n });\n }\n\n return false;\n }),\n // Removes a level of nesting if the block is indented if the selection is at the start of the block.\n () =>\n commands.command(({ state }) => {\n const { startPos } = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n )!;\n\n const selectionAtBlockStart = state.selection.from === startPos + 1;\n\n if (selectionAtBlockStart) {\n return commands.liftListItem(\"blockContainer\");\n }\n\n return false;\n }),\n // Merges block with the previous one if it isn't indented, isn't the first block in the doc, and the selection\n // is at the start of the block.\n () =>\n commands.command(({ state }) => {\n const { depth, startPos } = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n )!;\n\n const selectionAtBlockStart = state.selection.from === startPos + 1;\n const selectionEmpty = state.selection.empty;\n const blockAtDocStart = startPos === 2;\n\n const posBetweenBlocks = startPos - 1;\n\n if (\n !blockAtDocStart &&\n selectionAtBlockStart &&\n selectionEmpty &&\n depth === 2\n ) {\n return commands.BNMergeBlocks(posBetweenBlocks);\n }\n\n return false;\n }),\n ]);\n\n const handleDelete = () =>\n this.editor.commands.first(({ commands }) => [\n // Deletes the selection if it's not empty.\n () => commands.deleteSelection(),\n // Merges block with the next one (at the same nesting level or lower),\n // if one exists, the block has no children, and the selection is at the\n // end of the block.\n () =>\n commands.command(({ state }) => {\n const { node, depth, endPos } = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n )!;\n\n const blockAtDocEnd = endPos === state.doc.nodeSize - 4;\n const selectionAtBlockEnd = state.selection.from === endPos - 1;\n const selectionEmpty = state.selection.empty;\n const hasChildBlocks = node.childCount === 2;\n\n if (\n !blockAtDocEnd &&\n selectionAtBlockEnd &&\n selectionEmpty &&\n !hasChildBlocks\n ) {\n let oldDepth = depth;\n let newPos = endPos + 2;\n let newDepth = state.doc.resolve(newPos).depth;\n\n while (newDepth < oldDepth) {\n oldDepth = newDepth;\n newPos += 2;\n newDepth = state.doc.resolve(newPos).depth;\n }\n\n return commands.BNMergeBlocks(newPos - 1);\n }\n\n return false;\n }),\n ]);\n\n const handleEnter = () =>\n this.editor.commands.first(({ commands }) => [\n // Removes a level of nesting if the block is empty & indented, while the selection is also empty & at the start\n // of the block.\n () =>\n commands.command(({ state }) => {\n const { node, depth } = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n )!;\n\n const selectionAtBlockStart =\n state.selection.$anchor.parentOffset === 0;\n const selectionEmpty =\n state.selection.anchor === state.selection.head;\n const blockEmpty = node.textContent.length === 0;\n const blockIndented = depth > 2;\n\n if (\n selectionAtBlockStart &&\n selectionEmpty &&\n blockEmpty &&\n blockIndented\n ) {\n return commands.liftListItem(\"blockContainer\");\n }\n\n return false;\n }),\n // Creates a new block and moves the selection to it if the current one is empty, while the selection is also\n // empty & at the start of the block.\n () =>\n commands.command(({ state, chain }) => {\n const { node, endPos } = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n )!;\n\n const selectionAtBlockStart =\n state.selection.$anchor.parentOffset === 0;\n const selectionEmpty =\n state.selection.anchor === state.selection.head;\n const blockEmpty = node.textContent.length === 0;\n\n if (selectionAtBlockStart && selectionEmpty && blockEmpty) {\n const newBlockInsertionPos = endPos + 1;\n const newBlockContentPos = newBlockInsertionPos + 2;\n\n chain()\n .BNCreateBlock(newBlockInsertionPos)\n .setTextSelection(newBlockContentPos)\n .run();\n\n return true;\n }\n\n return false;\n }),\n // Splits the current block, moving content inside that's after the cursor to a new text block below. Also\n // deletes the selection beforehand, if it's not empty.\n () =>\n commands.command(({ state, chain }) => {\n const { node } = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n )!;\n\n const selectionAtBlockStart =\n state.selection.$anchor.parentOffset === 0;\n const blockEmpty = node.textContent.length === 0;\n\n if (!blockEmpty) {\n chain()\n .deleteSelection()\n .BNSplitBlock(state.selection.from, selectionAtBlockStart)\n .run();\n\n return true;\n }\n\n return false;\n }),\n ]);\n\n return {\n Backspace: handleBackspace,\n Delete: handleDelete,\n Enter: handleEnter,\n // Always returning true for tab key presses ensures they're not captured by the browser. Otherwise, they blur the\n // editor since the browser will try to use tab for keyboard navigation.\n Tab: () => {\n this.editor.commands.sinkListItem(\"blockContainer\");\n return true;\n },\n \"Shift-Tab\": () => {\n this.editor.commands.liftListItem(\"blockContainer\");\n return true;\n },\n };\n },\n});\n","import { Node } from \"@tiptap/core\";\nimport { BlockNoteDOMAttributes } from \"../schema\";\nimport { mergeCSSClasses } from \"../util/browser\";\n\nexport const BlockGroup = Node.create<{\n domAttributes?: BlockNoteDOMAttributes;\n}>({\n name: \"blockGroup\",\n group: \"blockGroup\",\n content: \"blockContainer+\",\n\n parseHTML() {\n return [\n {\n tag: \"div\",\n getAttrs: (element) => {\n if (typeof element === \"string\") {\n return false;\n }\n\n if (element.getAttribute(\"data-node-type\") === \"blockGroup\") {\n // Null means the element matches, but we don't want to add any attributes to the node.\n return null;\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n const blockGroupHTMLAttributes = {\n ...(this.options.domAttributes?.blockGroup || {}),\n ...HTMLAttributes,\n };\n const blockGroup = document.createElement(\"div\");\n blockGroup.className = mergeCSSClasses(\n \"bn-block-group\",\n blockGroupHTMLAttributes.class\n );\n blockGroup.setAttribute(\"data-node-type\", \"blockGroup\");\n for (const [attribute, value] of Object.entries(blockGroupHTMLAttributes)) {\n if (attribute !== \"class\") {\n blockGroup.setAttribute(attribute, value);\n }\n }\n\n return {\n dom: blockGroup,\n contentDOM: blockGroup,\n };\n },\n});\n","import {Node} from \"@tiptap/core\";\n\nexport const Doc = Node.create({\n name: \"doc\",\n topNode: true,\n content: \"blockGroup\",\n});\n","import { Extensions, extensions } from \"@tiptap/core\";\n\nimport type { BlockNoteEditor } from \"./BlockNoteEditor\";\n\nimport Collaboration from \"@tiptap/extension-collaboration\";\nimport CollaborationCursor from \"@tiptap/extension-collaboration-cursor\";\nimport { Dropcursor } from \"@tiptap/extension-dropcursor\";\nimport { Gapcursor } from \"@tiptap/extension-gapcursor\";\nimport { HardBreak } from \"@tiptap/extension-hard-break\";\nimport { History } from \"@tiptap/extension-history\";\nimport { Link } from \"@tiptap/extension-link\";\nimport { Text } from \"@tiptap/extension-text\";\nimport * as Y from \"yjs\";\nimport { createCopyToClipboardExtension } from \"../api/exporters/copyExtension\";\nimport { createPasteFromClipboardExtension } from \"../api/parsers/pasteExtension\";\nimport { BackgroundColorExtension } from \"../extensions/BackgroundColor/BackgroundColorExtension\";\nimport { Placeholder } from \"../extensions/Placeholder/PlaceholderExtension\";\nimport { TextAlignmentExtension } from \"../extensions/TextAlignment/TextAlignmentExtension\";\nimport { TextColorExtension } from \"../extensions/TextColor/TextColorExtension\";\nimport { TrailingNode } from \"../extensions/TrailingNode/TrailingNodeExtension\";\nimport UniqueID from \"../extensions/UniqueID/UniqueID\";\nimport { BlockContainer, BlockGroup, Doc } from \"../pm-nodes\";\nimport {\n BlockNoteDOMAttributes,\n BlockSchema,\n BlockSpecs,\n InlineContentSchema,\n InlineContentSpecs,\n StyleSchema,\n StyleSpecs,\n} from \"../schema\";\n\n/**\n * Get all the Tiptap extensions BlockNote is configured with by default\n */\nexport const getBlockNoteExtensions = <\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(opts: {\n editor: BlockNoteEditor<BSchema, I, S>;\n placeholders?: Record<string | \"default\", string>;\n domAttributes: Partial<BlockNoteDOMAttributes>;\n blockSchema: BSchema;\n blockSpecs: BlockSpecs;\n inlineContentSpecs: InlineContentSpecs;\n styleSpecs: StyleSpecs;\n collaboration?: {\n fragment: Y.XmlFragment;\n user: {\n name: string;\n color: string;\n };\n provider: any;\n renderCursor?: (user: any) => HTMLElement;\n };\n}) => {\n const ret: Extensions = [\n extensions.ClipboardTextSerializer,\n extensions.Commands,\n extensions.Editable,\n extensions.FocusEvents,\n extensions.Tabindex,\n\n // DevTools,\n Gapcursor,\n\n // DropCursor,\n Placeholder.configure({\n // TODO: This shorthand is kind of ugly\n ...(opts.placeholders !== undefined\n ? { placeholders: opts.placeholders }\n : {}),\n }),\n UniqueID.configure({\n types: [\"blockContainer\"],\n }),\n HardBreak,\n // Comments,\n\n // basics:\n Text,\n\n // marks:\n Link,\n ...Object.values(opts.styleSpecs).map((styleSpec) => {\n return styleSpec.implementation.mark;\n }),\n\n TextColorExtension,\n\n BackgroundColorExtension,\n TextAlignmentExtension,\n\n // nodes\n Doc,\n BlockContainer.configure({\n editor: opts.editor as any,\n domAttributes: opts.domAttributes,\n }),\n BlockGroup.configure({\n domAttributes: opts.domAttributes,\n }),\n ...Object.values(opts.inlineContentSpecs)\n .filter((a) => a.config !== \"link\" && a.config !== \"text\")\n .map((inlineContentSpec) => {\n return inlineContentSpec.implementation!.node.configure({\n editor: opts.editor as any,\n });\n }),\n\n ...Object.values(opts.blockSpecs).flatMap((blockSpec) => {\n return [\n // dependent nodes (e.g.: tablecell / row)\n ...(blockSpec.implementation.requiredExtensions || []).map((ext) =>\n ext.configure({\n editor: opts.editor,\n domAttributes: opts.domAttributes,\n })\n ),\n // the actual node itself\n blockSpec.implementation.node.configure({\n editor: opts.editor,\n domAttributes: opts.domAttributes,\n }),\n ];\n }),\n createCopyToClipboardExtension(opts.editor),\n createPasteFromClipboardExtension(opts.editor),\n\n Dropcursor.configure({ width: 5, color: \"#ddeeff\" }),\n // This needs to be at the bottom of this list, because Key events (such as enter, when selecting a /command),\n // should be handled before Enter handlers in other components like splitListItem\n TrailingNode,\n ];\n\n if (opts.collaboration) {\n ret.push(\n Collaboration.configure({\n fragment: opts.collaboration.fragment,\n })\n );\n if (opts.collaboration.provider?.awareness) {\n const defaultRender = (user: { color: string; name: string }) => {\n const cursor = document.createElement(\"span\");\n\n cursor.classList.add(\"collaboration-cursor__caret\");\n cursor.setAttribute(\"style\", `border-color: ${user.color}`);\n\n const label = document.createElement(\"span\");\n\n label.classList.add(\"collaboration-cursor__label\");\n label.setAttribute(\"style\", `background-color: ${user.color}`);\n label.insertBefore(document.createTextNode(user.name), null);\n\n const nonbreakingSpace1 = document.createTextNode(\"\\u2060\");\n const nonbreakingSpace2 = document.createTextNode(\"\\u2060\");\n cursor.insertBefore(nonbreakingSpace1, null);\n cursor.insertBefore(label, null);\n cursor.insertBefore(nonbreakingSpace2, null);\n return cursor;\n };\n ret.push(\n CollaborationCursor.configure({\n user: opts.collaboration.user,\n render: opts.collaboration.renderCursor || defaultRender,\n provider: opts.collaboration.provider,\n })\n );\n }\n } else {\n // disable history extension when collaboration is enabled as Yjs takes care of undo / redo\n ret.push(History);\n }\n\n return ret;\n};\n","import { Fragment, Slice } from \"@tiptap/pm/model\";\nimport { EditorView } from \"@tiptap/pm/view\";\n\n// helper function to remove a child from a fragment\nfunction removeChild(node: Fragment, n: number) {\n const children: any[] = [];\n node.forEach((child, _, i) => {\n if (i !== n) {\n children.push(child);\n }\n });\n return Fragment.from(children);\n}\n\n/**\n * fix for https://github.com/ProseMirror/prosemirror/issues/1430#issuecomment-1822570821\n *\n * Without this fix, pasting two paragraphs would cause the second one to be indented in the other\n * this fix wraps every element in the slice in it's own blockContainer, to prevent Prosemirror from nesting the\n * elements on paste.\n *\n * The exception is when we encounter blockGroups with listitems, because those actually should be nested\n */\nexport function transformPasted(slice: Slice, view: EditorView) {\n let f = Fragment.from(slice.content);\n for (let i = 0; i < f.childCount; i++) {\n if (f.child(i).type.spec.group === \"blockContent\") {\n const content = [f.child(i)];\n\n // when there is a blockGroup with lists, it should be nested in the new blockcontainer\n // (if we remove this if-block, the nesting bug will be fixed, but lists won't be nested correctly)\n if (\n i + 1 < f.childCount &&\n f.child(i + 1).type.spec.group === \"blockGroup\"\n ) {\n const nestedChild = f\n .child(i + 1)\n .child(0)\n .child(0);\n\n if (\n nestedChild.type.name === \"bulletListItem\" ||\n nestedChild.type.name === \"numberedListItem\"\n ) {\n content.push(f.child(i + 1));\n f = removeChild(f, i + 1);\n }\n }\n const container = view.state.schema.nodes.blockContainer.create(\n undefined,\n content\n );\n f = f.replaceChild(i, container);\n }\n }\n\n return new Slice(f, slice.openStart, slice.openEnd);\n}\n","import {\n defaultBlockSpecs,\n defaultInlineContentSpecs,\n defaultStyleSpecs,\n} from \"../blocks/defaultBlocks\";\nimport {\n BlockSchema,\n BlockSchemaFromSpecs,\n BlockSpecs,\n InlineContentSchema,\n InlineContentSchemaFromSpecs,\n InlineContentSpecs,\n StyleSchema,\n StyleSchemaFromSpecs,\n StyleSpecs,\n getBlockSchemaFromSpecs,\n getInlineContentSchemaFromSpecs,\n getStyleSchemaFromSpecs,\n} from \"../schema\";\nimport type {\n BlockNoDefaults,\n PartialBlockNoDefaults,\n} from \"../schema/blocks/types\";\nimport type { BlockNoteEditor } from \"./BlockNoteEditor\";\n\nexport class BlockNoteSchema<\n BSchema extends BlockSchema,\n ISchema extends InlineContentSchema,\n SSchema extends StyleSchema\n> {\n public readonly blockSpecs: BlockSpecs;\n public readonly inlineContentSpecs: InlineContentSpecs;\n public readonly styleSpecs: StyleSpecs;\n\n public readonly blockSchema: BSchema;\n public readonly inlineContentSchema: ISchema;\n public readonly styleSchema: SSchema;\n\n // Helper so that you can use typeof schema.BlockNoteEditor\n public readonly BlockNoteEditor: BlockNoteEditor<BSchema, ISchema, SSchema> =\n \"only for types\" as any;\n\n public readonly Block: BlockNoDefaults<BSchema, ISchema, SSchema> =\n \"only for types\" as any;\n\n public readonly PartialBlock: PartialBlockNoDefaults<\n BSchema,\n ISchema,\n SSchema\n > = \"only for types\" as any;\n\n public static create<\n BSpecs extends BlockSpecs = typeof defaultBlockSpecs,\n ISpecs extends InlineContentSpecs = typeof defaultInlineContentSpecs,\n SSpecs extends StyleSpecs = typeof defaultStyleSpecs\n >(options?: {\n /**\n * A list of custom block types that should be available in the editor.\n */\n blockSpecs?: BSpecs;\n /**\n * A list of custom InlineContent types that should be available in the editor.\n */\n inlineContentSpecs?: ISpecs;\n /**\n * A list of custom Styles that should be available in the editor.\n */\n styleSpecs?: SSpecs;\n }) {\n return new BlockNoteSchema<\n BlockSchemaFromSpecs<BSpecs>,\n InlineContentSchemaFromSpecs<ISpecs>,\n StyleSchemaFromSpecs<SSpecs>\n >(options);\n // as BlockNoteSchema<\n // BlockSchemaFromSpecs<BSpecs>,\n // InlineContentSchemaFromSpecs<ISpecs>,\n // StyleSchemaFromSpecs<SSpecs>\n // >;\n }\n\n constructor(opts?: {\n blockSpecs?: BlockSpecs;\n inlineContentSpecs?: InlineContentSpecs;\n styleSpecs?: StyleSpecs;\n }) {\n this.blockSpecs = opts?.blockSpecs || defaultBlockSpecs;\n this.inlineContentSpecs =\n opts?.inlineContentSpecs || defaultInlineContentSpecs;\n this.styleSpecs = opts?.styleSpecs || defaultStyleSpecs;\n\n this.blockSchema = getBlockSchemaFromSpecs(this.blockSpecs) as any;\n this.inlineContentSchema = getInlineContentSchemaFromSpecs(\n this.inlineContentSpecs\n ) as any;\n this.styleSchema = getStyleSchemaFromSpecs(this.styleSpecs) as any;\n }\n}\n","import { EditorOptions, createDocument } from \"@tiptap/core\";\n// import \"./blocknote.css\";\nimport { Editor as TiptapEditor } from \"@tiptap/core\";\nimport { Node } from \"@tiptap/pm/model\";\nimport { EditorView } from \"@tiptap/pm/view\";\nimport { EditorState } from \"prosemirror-state\";\n\nimport { blockToNode } from \"../api/nodeConversions/nodeConversions\";\nimport { PartialBlock } from \"../blocks/defaultBlocks\";\nimport { StyleSchema } from \"../schema\";\n\nexport type BlockNoteTipTapEditorOptions = Partial<\n Omit<EditorOptions, \"content\">\n> & {\n content: PartialBlock<any, any, any>[];\n};\n\n/**\n * Custom Editor class that extends TiptapEditor and separates\n * the creation of the view from the constructor.\n */\n// @ts-ignore\nexport class BlockNoteTipTapEditor extends TiptapEditor {\n private _state: EditorState;\n\n constructor(options: BlockNoteTipTapEditorOptions, styleSchema: StyleSchema) {\n // possible fix for next.js server side rendering\n // const d = globalThis.document;\n // const w = globalThis.window;\n // if (!globalThis.document) {\n // globalThis.document = {\n // createElement: () => {},\n // };\n // }\n // if (!globalThis.window) {\n // globalThis.window = {\n // setTimeout: () => {},\n // };\n // }\n // options.injectCSS = false\n super({ ...options, content: undefined });\n\n // try {\n // globalThis.window = w;\n // } catch(e) {}\n // try {\n // globalThis.document = d;\n // } catch(e) {}\n\n // This is a hack to make \"initial content detection\" by y-prosemirror (and also tiptap isEmpty)\n // properly detect whether or not the document has changed.\n // We change the doc.createAndFill function to make sure the initial block id is set, instead of null\n const schema = this.schema;\n let cache: any;\n const oldCreateAndFill = schema.nodes.doc.createAndFill;\n (schema.nodes.doc as any).createAndFill = (...args: any) => {\n if (cache) {\n return cache;\n }\n const ret = oldCreateAndFill.apply(schema.nodes.doc, args);\n\n // create a copy that we can mutate (otherwise, assigning attrs is not safe and corrupts the pm state)\n const jsonNode = JSON.parse(JSON.stringify(ret!.toJSON()));\n jsonNode.content[0].content[0].attrs.id = \"initialBlockId\";\n\n cache = Node.fromJSON(schema, jsonNode);\n return cache;\n };\n\n let doc: Node;\n\n try {\n const pmNodes = options?.content.map((b) =>\n blockToNode(b, this.schema, styleSchema).toJSON()\n );\n doc = createDocument(\n {\n type: \"doc\",\n content: [\n {\n type: \"blockGroup\",\n content: pmNodes,\n },\n ],\n },\n this.schema,\n this.options.parseOptions\n );\n } catch (e) {\n console.error(\n \"Error creating document from blocks passed as `initialContent`. Caused by exception: \",\n e\n );\n throw new Error(\n \"Error creating document from blocks passed as `initialContent`:\\n\" +\n +JSON.stringify(options.content)\n );\n }\n\n // Create state immediately, so that it's available independently from the View,\n // the way Prosemirror \"intends it to be\". This also makes sure that we can access\n // the state before the view is created / mounted.\n this._state = EditorState.create({\n doc,\n schema: this.schema,\n // selection: selection || undefined,\n });\n }\n\n get state() {\n if (this.view) {\n this._state = this.view.state;\n }\n return this._state;\n }\n\n createView() {\n // no-op\n // Disable default call to `createView` in the Editor constructor.\n // We should call `createView` manually only when a DOM element is available\n }\n\n /**\n * Replace the default `createView` method with a custom one - which we call on mount\n */\n private createViewAlternative() {\n // Without queueMicrotask, custom IC / styles will give a React FlushSync error\n queueMicrotask(() => {\n this.view = new EditorView(this.options.element, {\n ...this.options.editorProps,\n // @ts-ignore\n dispatchTransaction: this.dispatchTransaction.bind(this),\n state: this.state,\n });\n\n // `editor.view` is not yet available at this time.\n // Therefore we will add all plugins and node views directly afterwards.\n const newState = this.state.reconfigure({\n plugins: this.extensionManager.plugins,\n });\n\n this.view.updateState(newState);\n\n this.createNodeViews();\n });\n }\n\n /**\n * Mounts / unmounts the editor to a dom element\n *\n * @param element DOM element to mount to, ur null / undefined to destroy\n */\n public mount = (element?: HTMLElement | null) => {\n if (!element) {\n this.destroy();\n } else {\n this.options.element = element;\n // @ts-ignore\n this.createViewAlternative();\n }\n };\n}\n","import { EditorOptions, Extension } from \"@tiptap/core\";\nimport { Node } from \"prosemirror-model\";\n// import \"./blocknote.css\";\nimport * as Y from \"yjs\";\nimport {\n insertBlocks,\n insertContentAt,\n removeBlocks,\n replaceBlocks,\n updateBlock,\n} from \"../api/blockManipulation/blockManipulation\";\nimport { createExternalHTMLExporter } from \"../api/exporters/html/externalHTMLExporter\";\nimport { blocksToMarkdown } from \"../api/exporters/markdown/markdownExporter\";\nimport { getBlockInfoFromPos } from \"../api/getBlockInfoFromPos\";\nimport {\n inlineContentToNodes,\n nodeToBlock,\n} from \"../api/nodeConversions/nodeConversions\";\nimport { getNodeById } from \"../api/nodeUtil\";\nimport { HTMLToBlocks } from \"../api/parsers/html/parseHTML\";\nimport { markdownToBlocks } from \"../api/parsers/markdown/parseMarkdown\";\nimport {\n Block,\n DefaultBlockSchema,\n DefaultInlineContentSchema,\n DefaultStyleSchema,\n PartialBlock,\n} from \"../blocks/defaultBlocks\";\nimport { FormattingToolbarProsemirrorPlugin } from \"../extensions/FormattingToolbar/FormattingToolbarPlugin\";\nimport { LinkToolbarProsemirrorPlugin } from \"../extensions/LinkToolbar/LinkToolbarPlugin\";\nimport { SideMenuProsemirrorPlugin } from \"../extensions/SideMenu/SideMenuPlugin\";\nimport { SuggestionMenuProseMirrorPlugin } from \"../extensions/SuggestionMenu/SuggestionPlugin\";\nimport { ImagePanelProsemirrorPlugin } from \"../extensions/ImagePanel/ImageToolbarPlugin\";\nimport { TableHandlesProsemirrorPlugin } from \"../extensions/TableHandles/TableHandlesPlugin\";\nimport { UniqueID } from \"../extensions/UniqueID/UniqueID\";\nimport {\n BlockIdentifier,\n BlockNoteDOMAttributes,\n BlockSchema,\n BlockSpecs,\n InlineContentSchema,\n InlineContentSpecs,\n PartialInlineContent,\n StyleSchema,\n StyleSpecs,\n Styles,\n} from \"../schema\";\nimport { mergeCSSClasses } from \"../util/browser\";\nimport { NoInfer, UnreachableCaseError } from \"../util/typescript\";\n\nimport { getBlockNoteExtensions } from \"./BlockNoteExtensions\";\nimport { TextCursorPosition } from \"./cursorPositionTypes\";\n\nimport { Selection } from \"./selectionTypes\";\nimport { transformPasted } from \"./transformPasted\";\n\nimport { checkDefaultBlockTypeInSchema } from \"../blocks/defaultBlockTypeGuards\";\nimport { BlockNoteSchema } from \"./BlockNoteSchema\";\nimport {\n BlockNoteTipTapEditor,\n BlockNoteTipTapEditorOptions,\n} from \"./BlockNoteTipTapEditor\";\n\n// CSS\nimport \"./Block.css\";\nimport \"./editor.css\";\n\nexport type BlockNoteEditorOptions<\n BSchema extends BlockSchema,\n ISchema extends InlineContentSchema,\n SSchema extends StyleSchema\n> = {\n // TODO: Figure out if enableBlockNoteExtensions/disableHistoryExtension are needed and document them.\n enableBlockNoteExtensions: boolean;\n\n placeholders: Record<string | \"default\", string>;\n\n /**\n * An object containing attributes that should be added to HTML elements of the editor.\n *\n * @example { editor: { class: \"my-editor-class\" } }\n */\n domAttributes: Partial<BlockNoteDOMAttributes>;\n\n /**\n * The content that should be in the editor when it's created, represented as an array of partial block objects.\n */\n initialContent: PartialBlock<\n NoInfer<BSchema>,\n NoInfer<ISchema>,\n NoInfer<SSchema>\n >[];\n /**\n * Use default BlockNote font and reset the styles of <p> <li> <h1> elements etc., that are used in BlockNote.\n *\n * @default true\n */\n defaultStyles: boolean;\n\n schema: BlockNoteSchema<BSchema, ISchema, SSchema>;\n\n /**\n * A custom function to handle file uploads.\n * @param file The file that should be uploaded.\n * @returns The URL of the uploaded file.\n */\n uploadFile: (file: File) => Promise<string>;\n\n /**\n * When enabled, allows for collaboration between multiple users.\n */\n collaboration: {\n /**\n * The Yjs XML fragment that's used for collaboration.\n */\n fragment: Y.XmlFragment;\n /**\n * The user info for the current user that's shown to other collaborators.\n */\n user: {\n name: string;\n color: string;\n };\n /**\n * A Yjs provider (used for awareness / cursor information)\n */\n provider: any;\n /**\n * Optional function to customize how cursors of users are rendered\n */\n renderCursor?: (user: any) => HTMLElement;\n };\n\n // tiptap options, undocumented\n _tiptapOptions: Partial<EditorOptions>;\n};\n\nconst blockNoteTipTapOptions = {\n enableInputRules: true,\n enablePasteRules: true,\n enableCoreExtensions: false,\n};\n\nexport class BlockNoteEditor<\n BSchema extends BlockSchema = DefaultBlockSchema,\n ISchema extends InlineContentSchema = DefaultInlineContentSchema,\n SSchema extends StyleSchema = DefaultStyleSchema\n> {\n public readonly _tiptapEditor: BlockNoteTipTapEditor & {\n contentComponent: any;\n };\n public blockCache = new WeakMap<Node, Block<any, any, any>>();\n public readonly schema: BlockNoteSchema<BSchema, ISchema, SSchema>;\n\n public readonly blockImplementations: BlockSpecs;\n public readonly inlineContentImplementations: InlineContentSpecs;\n public readonly styleImplementations: StyleSpecs;\n\n public readonly formattingToolbar: FormattingToolbarProsemirrorPlugin;\n public readonly linkToolbar: LinkToolbarProsemirrorPlugin<\n BSchema,\n ISchema,\n SSchema\n >;\n public readonly sideMenu: SideMenuProsemirrorPlugin<\n BSchema,\n ISchema,\n SSchema\n >;\n public readonly suggestionMenus: SuggestionMenuProseMirrorPlugin<\n BSchema,\n ISchema,\n SSchema\n >;\n public readonly imagePanel?: ImagePanelProsemirrorPlugin<ISchema, SSchema>;\n public readonly tableHandles?: TableHandlesProsemirrorPlugin<\n ISchema,\n SSchema\n >;\n\n public readonly uploadFile: ((file: File) => Promise<string>) | undefined;\n\n public static create<\n BSchema extends BlockSchema = DefaultBlockSchema,\n ISchema extends InlineContentSchema = DefaultInlineContentSchema,\n SSchema extends StyleSchema = DefaultStyleSchema\n >(options: Partial<BlockNoteEditorOptions<BSchema, ISchema, SSchema>> = {}) {\n return new BlockNoteEditor<BSchema, ISchema, SSchema>(options);\n }\n\n private constructor(\n private readonly options: Partial<BlockNoteEditorOptions<any, any, any>>\n ) {\n const anyOpts = options as any;\n if (anyOpts.onEditorContentChange) {\n throw new Error(\n \"onEditorContentChange initialization option is deprecated, use <BlockNoteView onChange={...} />, the useEditorChange(...) hook, or editor.onChange(...)\"\n );\n }\n\n if (anyOpts.onTextCursorPositionChange) {\n throw new Error(\n \"onTextCursorPositionChange initialization option is deprecated, use <BlockNoteView onSelectionChange={...} />, the useEditorSelectionChange(...) hook, or editor.onSelectionChange(...)\"\n );\n }\n\n if (anyOpts.onEditorReady) {\n throw new Error(\n \"onEditorReady is deprecated. Editor is immediately ready for use after creation.\"\n );\n }\n\n if (anyOpts.editable) {\n throw new Error(\n \"editable initialization option is deprecated, use <BlockNoteView editable={true/false} />, or alternatively editor.isEditable = true/false\"\n );\n }\n\n // apply defaults\n const newOptions = {\n defaultStyles: true,\n schema: options.schema || BlockNoteSchema.create(),\n ...options,\n };\n\n // @ts-ignore\n this.schema = newOptions.schema;\n this.blockImplementations = newOptions.schema.blockSpecs;\n this.inlineContentImplementations = newOptions.schema.inlineContentSpecs;\n this.styleImplementations = newOptions.schema.styleSpecs;\n\n this.formattingToolbar = new FormattingToolbarProsemirrorPlugin(this);\n this.linkToolbar = new LinkToolbarProsemirrorPlugin(this);\n this.sideMenu = new SideMenuProsemirrorPlugin(this);\n this.suggestionMenus = new SuggestionMenuProseMirrorPlugin(this);\n if (checkDefaultBlockTypeInSchema(\"image\", this)) {\n // Type guards only work on `const`s? Not working for `this`\n this.imagePanel = new ImagePanelProsemirrorPlugin(this as any);\n }\n if (checkDefaultBlockTypeInSchema(\"table\", this)) {\n this.tableHandles = new TableHandlesProsemirrorPlugin(this as any);\n }\n\n const extensions = getBlockNoteExtensions({\n editor: this,\n placeholders: newOptions.placeholders,\n domAttributes: newOptions.domAttributes || {},\n blockSchema: this.schema.blockSchema,\n blockSpecs: this.schema.blockSpecs,\n styleSpecs: this.schema.styleSpecs,\n inlineContentSpecs: this.schema.inlineContentSpecs,\n collaboration: newOptions.collaboration,\n });\n\n const blockNoteUIExtension = Extension.create({\n name: \"BlockNoteUIExtension\",\n\n addProseMirrorPlugins: () => {\n return [\n this.formattingToolbar.plugin,\n this.linkToolbar.plugin,\n this.sideMenu.plugin,\n this.suggestionMenus.plugin,\n ...(this.imagePanel ? [this.imagePanel.plugin] : []),\n ...(this.tableHandles ? [this.tableHandles.plugin] : []),\n ];\n },\n });\n extensions.push(blockNoteUIExtension);\n\n this.uploadFile = newOptions.uploadFile;\n\n if (newOptions.collaboration && newOptions.initialContent) {\n console.warn(\n \"When using Collaboration, initialContent might cause conflicts, because changes should come from the collaboration provider\"\n );\n }\n\n const initialContent =\n newOptions.initialContent ||\n (options.collaboration\n ? [\n {\n type: \"paragraph\",\n id: \"initialBlockId\",\n },\n ]\n : [\n {\n type: \"paragraph\",\n id: UniqueID.options.generateID(),\n },\n ]);\n\n if (!Array.isArray(initialContent) || initialContent.length === 0) {\n throw new Error(\n \"initialContent must be a non-empty array of blocks, received: \" +\n initialContent\n );\n }\n\n const tiptapOptions: BlockNoteTipTapEditorOptions = {\n ...blockNoteTipTapOptions,\n ...newOptions._tiptapOptions,\n content: initialContent,\n extensions:\n newOptions.enableBlockNoteExtensions === false\n ? newOptions._tiptapOptions?.extensions || []\n : [...(newOptions._tiptapOptions?.extensions || []), ...extensions],\n editorProps: {\n ...newOptions._tiptapOptions?.editorProps,\n attributes: {\n ...newOptions._tiptapOptions?.editorProps?.attributes,\n ...newOptions.domAttributes?.editor,\n class: mergeCSSClasses(\n \"bn-editor\",\n newOptions.defaultStyles ? \"bn-default-styles\" : \"\",\n newOptions.domAttributes?.editor?.class || \"\"\n ),\n },\n transformPasted,\n },\n };\n\n this._tiptapEditor = new BlockNoteTipTapEditor(\n tiptapOptions,\n this.schema.styleSchema\n ) as BlockNoteTipTapEditor & {\n contentComponent: any;\n };\n }\n\n /**\n * Mount the editor to a parent DOM element. Call mount(undefined) to clean up\n *\n * @warning Not needed for React, use BlockNoteView to take care of this\n */\n public mount(parentElement?: HTMLElement | null) {\n this._tiptapEditor.mount(parentElement);\n }\n\n public get prosemirrorView() {\n return this._tiptapEditor.view;\n }\n\n public get domElement() {\n return this._tiptapEditor.view.dom as HTMLDivElement;\n }\n\n public isFocused() {\n return this._tiptapEditor.view.hasFocus();\n }\n\n public focus() {\n this._tiptapEditor.view.focus();\n }\n\n /**\n * @deprecated, use `editor.document` instead\n */\n public get topLevelBlocks(): Block<BSchema, ISchema, SSchema>[] {\n return this.topLevelBlocks;\n }\n\n /**\n * Gets a snapshot of all top-level (non-nested) blocks in the editor.\n * @returns A snapshot of all top-level (non-nested) blocks in the editor.\n */\n public get document(): Block<BSchema, ISchema, SSchema>[] {\n const blocks: Block<BSchema, ISchema, SSchema>[] = [];\n\n this._tiptapEditor.state.doc.firstChild!.descendants((node) => {\n blocks.push(\n nodeToBlock(\n node,\n this.schema.blockSchema,\n this.schema.inlineContentSchema,\n this.schema.styleSchema,\n this.blockCache\n )\n );\n\n return false;\n });\n\n return blocks;\n }\n\n /**\n * Gets a snapshot of an existing block from the editor.\n * @param blockIdentifier The identifier of an existing block that should be retrieved.\n * @returns The block that matches the identifier, or `undefined` if no matching block was found.\n */\n public getBlock(\n blockIdentifier: BlockIdentifier\n ): Block<BSchema, ISchema, SSchema> | undefined {\n const id =\n typeof blockIdentifier === \"string\"\n ? blockIdentifier\n : blockIdentifier.id;\n let newBlock: Block<BSchema, ISchema, SSchema> | undefined = undefined;\n\n this._tiptapEditor.state.doc.firstChild!.descendants((node) => {\n if (typeof newBlock !== \"undefined\") {\n return false;\n }\n\n if (node.type.name !== \"blockContainer\" || node.attrs.id !== id) {\n return true;\n }\n\n newBlock = nodeToBlock(\n node,\n this.schema.blockSchema,\n this.schema.inlineContentSchema,\n this.schema.styleSchema,\n this.blockCache\n );\n\n return false;\n });\n\n return newBlock;\n }\n\n /**\n * Traverses all blocks in the editor depth-first, and executes a callback for each.\n * @param callback The callback to execute for each block. Returning `false` stops the traversal.\n * @param reverse Whether the blocks should be traversed in reverse order.\n */\n public forEachBlock(\n callback: (block: Block<BSchema, ISchema, SSchema>) => boolean,\n reverse = false\n ): void {\n const blocks = this.document.slice();\n\n if (reverse) {\n blocks.reverse();\n }\n\n function traverseBlockArray(\n blockArray: Block<BSchema, ISchema, SSchema>[]\n ): boolean {\n for (const block of blockArray) {\n if (!callback(block)) {\n return false;\n }\n\n const children = reverse\n ? block.children.slice().reverse()\n : block.children;\n\n if (!traverseBlockArray(children)) {\n return false;\n }\n }\n\n return true;\n }\n\n traverseBlockArray(blocks);\n }\n\n /**\n * Executes a callback whenever the editor's contents change.\n * @param callback The callback to execute.\n */\n public onEditorContentChange(callback: () => void) {\n this._tiptapEditor.on(\"update\", callback);\n }\n\n /**\n * Executes a callback whenever the editor's selection changes.\n * @param callback The callback to execute.\n */\n public onEditorSelectionChange(callback: () => void) {\n this._tiptapEditor.on(\"selectionUpdate\", callback);\n }\n\n /**\n * Gets a snapshot of the current text cursor position.\n * @returns A snapshot of the current text cursor position.\n */\n public getTextCursorPosition(): TextCursorPosition<\n BSchema,\n ISchema,\n SSchema\n > {\n const { node, depth, startPos, endPos } = getBlockInfoFromPos(\n this._tiptapEditor.state.doc,\n this._tiptapEditor.state.selection.from\n )!;\n\n // Index of the current blockContainer node relative to its parent blockGroup.\n const nodeIndex = this._tiptapEditor.state.doc\n .resolve(endPos)\n .index(depth - 1);\n // Number of the parent blockGroup's child blockContainer nodes.\n const numNodes = this._tiptapEditor.state.doc\n .resolve(endPos + 1)\n .node().childCount;\n\n // Gets previous blockContainer node at the same nesting level, if the current node isn't the first child.\n let prevNode: Node | undefined = undefined;\n if (nodeIndex > 0) {\n prevNode = this._tiptapEditor.state.doc.resolve(startPos - 2).node();\n }\n\n // Gets next blockContainer node at the same nesting level, if the current node isn't the last child.\n let nextNode: Node | undefined = undefined;\n if (nodeIndex < numNodes - 1) {\n nextNode = this._tiptapEditor.state.doc.resolve(endPos + 2).node();\n }\n\n return {\n block: nodeToBlock(\n node,\n this.schema.blockSchema,\n this.schema.inlineContentSchema,\n this.schema.styleSchema,\n this.blockCache\n ),\n prevBlock:\n prevNode === undefined\n ? undefined\n : nodeToBlock(\n prevNode,\n this.schema.blockSchema,\n this.schema.inlineContentSchema,\n this.schema.styleSchema,\n this.blockCache\n ),\n nextBlock:\n nextNode === undefined\n ? undefined\n : nodeToBlock(\n nextNode,\n this.schema.blockSchema,\n this.schema.inlineContentSchema,\n this.schema.styleSchema,\n this.blockCache\n ),\n };\n }\n\n /**\n * Sets the text cursor position to the start or end of an existing block. Throws an error if the target block could\n * not be found.\n * @param targetBlock The identifier of an existing block that the text cursor should be moved to.\n * @param placement Whether the text cursor should be placed at the start or end of the block.\n */\n public setTextCursorPosition(\n targetBlock: BlockIdentifier,\n placement: \"start\" | \"end\" = \"start\"\n ) {\n const id = typeof targetBlock === \"string\" ? targetBlock : targetBlock.id;\n\n const { posBeforeNode } = getNodeById(id, this._tiptapEditor.state.doc);\n const { startPos, contentNode } = getBlockInfoFromPos(\n this._tiptapEditor.state.doc,\n posBeforeNode + 2\n )!;\n\n const contentType: \"none\" | \"inline\" | \"table\" =\n this.schema.blockSchema[contentNode.type.name]!.content;\n\n if (contentType === \"none\") {\n this._tiptapEditor.commands.setNodeSelection(startPos);\n return;\n }\n\n if (contentType === \"inline\") {\n if (placement === \"start\") {\n this._tiptapEditor.commands.setTextSelection(startPos + 1);\n } else {\n this._tiptapEditor.commands.setTextSelection(\n startPos + contentNode.nodeSize - 1\n );\n }\n } else if (contentType === \"table\") {\n if (placement === \"start\") {\n // Need to offset the position as we have to get through the `tableRow`\n // and `tableCell` nodes to get to the `tableParagraph` node we want to\n // set the selection in.\n this._tiptapEditor.commands.setTextSelection(startPos + 4);\n } else {\n this._tiptapEditor.commands.setTextSelection(\n startPos + contentNode.nodeSize - 4\n );\n }\n } else {\n throw new UnreachableCaseError(contentType);\n }\n }\n\n /**\n * Gets a snapshot of the current selection.\n */\n public getSelection(): Selection<BSchema, ISchema, SSchema> | undefined {\n // Either the TipTap selection is empty, or it's a node selection. In either\n // case, it only spans one block, so we return undefined.\n if (\n this._tiptapEditor.state.selection.from ===\n this._tiptapEditor.state.selection.to ||\n \"node\" in this._tiptapEditor.state.selection\n ) {\n return undefined;\n }\n\n const blocks: Block<BSchema, ISchema, SSchema>[] = [];\n\n // TODO: This adds all child blocks to the same array. Needs to find min\n // depth and only add blocks at that depth.\n this._tiptapEditor.state.doc.descendants((node, pos) => {\n if (node.type.spec.group !== \"blockContent\") {\n return true;\n }\n\n if (\n pos + node.nodeSize < this._tiptapEditor.state.selection.from ||\n pos > this._tiptapEditor.state.selection.to\n ) {\n return true;\n }\n\n blocks.push(\n nodeToBlock(\n this._tiptapEditor.state.doc.resolve(pos).node(),\n this.schema.blockSchema,\n this.schema.inlineContentSchema,\n this.schema.styleSchema,\n this.blockCache\n )\n );\n\n return false;\n });\n\n return { blocks: blocks };\n }\n\n /**\n * Checks if the editor is currently editable, or if it's locked.\n * @returns True if the editor is editable, false otherwise.\n */\n public get isEditable(): boolean {\n return this._tiptapEditor.isEditable;\n }\n\n /**\n * Makes the editor editable or locks it, depending on the argument passed.\n * @param editable True to make the editor editable, or false to lock it.\n */\n public set isEditable(editable: boolean) {\n if (this._tiptapEditor.options.editable !== editable) {\n this._tiptapEditor.setEditable(editable);\n }\n }\n\n /**\n * Inserts new blocks into the editor. If a block's `id` is undefined, BlockNote generates one automatically. Throws an\n * error if the reference block could not be found.\n * @param blocksToInsert An array of partial blocks that should be inserted.\n * @param referenceBlock An identifier for an existing block, at which the new blocks should be inserted.\n * @param placement Whether the blocks should be inserted just before, just after, or nested inside the\n * `referenceBlock`. Inserts the blocks at the start of the existing block's children if \"nested\" is used.\n */\n public insertBlocks(\n blocksToInsert: PartialBlock<BSchema, ISchema, SSchema>[],\n referenceBlock: BlockIdentifier,\n placement: \"before\" | \"after\" | \"nested\" = \"before\"\n ) {\n return insertBlocks(blocksToInsert, referenceBlock, placement, this);\n }\n\n /**\n * Updates an existing block in the editor. Since updatedBlock is a PartialBlock object, some fields might not be\n * defined. These undefined fields are kept as-is from the existing block. Throws an error if the block to update could\n * not be found.\n * @param blockToUpdate The block that should be updated.\n * @param update A partial block which defines how the existing block should be changed.\n */\n public updateBlock(\n blockToUpdate: BlockIdentifier,\n update: PartialBlock<BSchema, ISchema, SSchema>\n ) {\n return updateBlock(blockToUpdate, update, this);\n }\n\n /**\n * Removes existing blocks from the editor. Throws an error if any of the blocks could not be found.\n * @param blocksToRemove An array of identifiers for existing blocks that should be removed.\n */\n public removeBlocks(blocksToRemove: BlockIdentifier[]) {\n return removeBlocks(blocksToRemove, this);\n }\n\n /**\n * Replaces existing blocks in the editor with new blocks. If the blocks that should be removed are not adjacent or\n * are at different nesting levels, `blocksToInsert` will be inserted at the position of the first block in\n * `blocksToRemove`. Throws an error if any of the blocks to remove could not be found.\n * @param blocksToRemove An array of blocks that should be replaced.\n * @param blocksToInsert An array of partial blocks to replace the old ones with.\n */\n public replaceBlocks(\n blocksToRemove: BlockIdentifier[],\n blocksToInsert: PartialBlock<BSchema, ISchema, SSchema>[]\n ) {\n return replaceBlocks(blocksToRemove, blocksToInsert, this);\n }\n\n /**\n * Insert a piece of content at the current cursor position.\n *\n * @param content can be a string, or array of partial inline content elements\n */\n public insertInlineContent(content: PartialInlineContent<ISchema, SSchema>) {\n const nodes = inlineContentToNodes(\n content,\n this._tiptapEditor.schema,\n this.schema.styleSchema\n );\n\n insertContentAt(\n {\n from: this._tiptapEditor.state.selection.from,\n to: this._tiptapEditor.state.selection.to,\n },\n nodes,\n this\n );\n }\n\n /**\n * Gets the active text styles at the text cursor position or at the end of the current selection if it's active.\n */\n public getActiveStyles() {\n const styles: Styles<SSchema> = {};\n const marks = this._tiptapEditor.state.selection.$to.marks();\n\n for (const mark of marks) {\n const config = this.schema.styleSchema[mark.type.name];\n if (!config) {\n console.warn(\"mark not found in styleschema\", mark.type.name);\n continue;\n }\n if (config.propSchema === \"boolean\") {\n (styles as any)[config.type] = true;\n } else {\n (styles as any)[config.type] = mark.attrs.stringValue;\n }\n }\n\n return styles;\n }\n\n /**\n * Adds styles to the currently selected content.\n * @param styles The styles to add.\n */\n public addStyles(styles: Styles<SSchema>) {\n this._tiptapEditor.view.focus();\n\n for (const [style, value] of Object.entries(styles)) {\n const config = this.schema.styleSchema[style];\n if (!config) {\n throw new Error(`style ${style} not found in styleSchema`);\n }\n if (config.propSchema === \"boolean\") {\n this._tiptapEditor.commands.setMark(style);\n } else if (config.propSchema === \"string\") {\n this._tiptapEditor.commands.setMark(style, { stringValue: value });\n } else {\n throw new UnreachableCaseError(config.propSchema);\n }\n }\n }\n\n /**\n * Removes styles from the currently selected content.\n * @param styles The styles to remove.\n */\n public removeStyles(styles: Styles<SSchema>) {\n this._tiptapEditor.view.focus();\n\n for (const style of Object.keys(styles)) {\n this._tiptapEditor.commands.unsetMark(style);\n }\n }\n\n /**\n * Toggles styles on the currently selected content.\n * @param styles The styles to toggle.\n */\n public toggleStyles(styles: Styles<SSchema>) {\n this._tiptapEditor.view.focus();\n\n for (const [style, value] of Object.entries(styles)) {\n const config = this.schema.styleSchema[style];\n if (!config) {\n throw new Error(`style ${style} not found in styleSchema`);\n }\n if (config.propSchema === \"boolean\") {\n this._tiptapEditor.commands.toggleMark(style);\n } else if (config.propSchema === \"string\") {\n this._tiptapEditor.commands.toggleMark(style, { stringValue: value });\n } else {\n throw new UnreachableCaseError(config.propSchema);\n }\n }\n }\n\n /**\n * Gets the currently selected text.\n */\n public getSelectedText() {\n return this._tiptapEditor.state.doc.textBetween(\n this._tiptapEditor.state.selection.from,\n this._tiptapEditor.state.selection.to\n );\n }\n\n /**\n * Gets the URL of the last link in the current selection, or `undefined` if there are no links in the selection.\n */\n public getSelectedLinkUrl() {\n return this._tiptapEditor.getAttributes(\"link\").href as string | undefined;\n }\n\n /**\n * Creates a new link to replace the selected content.\n * @param url The link URL.\n * @param text The text to display the link with.\n */\n public createLink(url: string, text?: string) {\n if (url === \"\") {\n return;\n }\n\n const { from, to } = this._tiptapEditor.state.selection;\n\n if (!text) {\n text = this._tiptapEditor.state.doc.textBetween(from, to);\n }\n\n const mark = this._tiptapEditor.schema.mark(\"link\", { href: url });\n\n this._tiptapEditor.view.dispatch(\n this._tiptapEditor.view.state.tr\n .insertText(text, from, to)\n .addMark(from, from + text.length, mark)\n );\n }\n\n /**\n * Checks if the block containing the text cursor can be nested.\n */\n public canNestBlock() {\n const { startPos, depth } = getBlockInfoFromPos(\n this._tiptapEditor.state.doc,\n this._tiptapEditor.state.selection.from\n )!;\n\n return this._tiptapEditor.state.doc.resolve(startPos).index(depth - 1) > 0;\n }\n\n /**\n * Nests the block containing the text cursor into the block above it.\n */\n public nestBlock() {\n this._tiptapEditor.commands.sinkListItem(\"blockContainer\");\n }\n\n /**\n * Checks if the block containing the text cursor is nested.\n */\n public canUnnestBlock() {\n const { depth } = getBlockInfoFromPos(\n this._tiptapEditor.state.doc,\n this._tiptapEditor.state.selection.from\n )!;\n\n return depth > 2;\n }\n\n /**\n * Lifts the block containing the text cursor out of its parent.\n */\n public unnestBlock() {\n this._tiptapEditor.commands.liftListItem(\"blockContainer\");\n }\n\n // TODO: Fix when implementing HTML/Markdown import & export\n /**\n * Serializes blocks into an HTML string. To better conform to HTML standards, children of blocks which aren't list\n * items are un-nested in the output HTML.\n * @param blocks An array of blocks that should be serialized into HTML.\n * @returns The blocks, serialized as an HTML string.\n */\n public async blocksToHTMLLossy(\n blocks: Block<BSchema, ISchema, SSchema>[] = this.document\n ): Promise<string> {\n const exporter = createExternalHTMLExporter(\n this._tiptapEditor.schema,\n this\n );\n return exporter.exportBlocks(blocks);\n }\n\n /**\n * Parses blocks from an HTML string. Tries to create `Block` objects out of any HTML block-level elements, and\n * `InlineNode` objects from any HTML inline elements, though not all element types are recognized. If BlockNote\n * doesn't recognize an HTML element's tag, it will parse it as a paragraph or plain text.\n * @param html The HTML string to parse blocks from.\n * @returns The blocks parsed from the HTML string.\n */\n public async tryParseHTMLToBlocks(\n html: string\n ): Promise<Block<BSchema, ISchema, SSchema>[]> {\n return HTMLToBlocks(\n html,\n this.schema.blockSchema,\n this.schema.inlineContentSchema,\n this.schema.styleSchema,\n this._tiptapEditor.schema\n );\n }\n\n /**\n * Serializes blocks into a Markdown string. The output is simplified as Markdown does not support all features of\n * BlockNote - children of blocks which aren't list items are un-nested and certain styles are removed.\n * @param blocks An array of blocks that should be serialized into Markdown.\n * @returns The blocks, serialized as a Markdown string.\n */\n public async blocksToMarkdownLossy(\n blocks: Block<BSchema, ISchema, SSchema>[] = this.document\n ): Promise<string> {\n return blocksToMarkdown(blocks, this._tiptapEditor.schema, this);\n }\n\n /**\n * Creates a list of blocks from a Markdown string. Tries to create `Block` and `InlineNode` objects based on\n * Markdown syntax, though not all symbols are recognized. If BlockNote doesn't recognize a symbol, it will parse it\n * as text.\n * @param markdown The Markdown string to parse blocks from.\n * @returns The blocks parsed from the Markdown string.\n */\n public async tryParseMarkdownToBlocks(\n markdown: string\n ): Promise<Block<BSchema, ISchema, SSchema>[]> {\n return markdownToBlocks(\n markdown,\n this.schema.blockSchema,\n this.schema.inlineContentSchema,\n this.schema.styleSchema,\n this._tiptapEditor.schema\n );\n }\n\n /**\n * Updates the user info for the current user that's shown to other collaborators.\n */\n public updateCollaborationUserInfo(user: { name: string; color: string }) {\n if (!this.options.collaboration) {\n throw new Error(\n \"Cannot update collaboration user info when collaboration is disabled.\"\n );\n }\n this._tiptapEditor.commands.updateUser(user);\n }\n\n /**\n * A callback function that runs whenever the editor's contents change.\n *\n * @param callback The callback to execute.\n * @returns A function to remove the callback.\n */\n public onChange(\n callback: (editor: BlockNoteEditor<BSchema, ISchema, SSchema>) => void\n ) {\n const cb = () => {\n callback(this);\n };\n\n this._tiptapEditor.on(\"update\", cb);\n\n return () => {\n this._tiptapEditor.off(\"update\", cb);\n };\n }\n\n /**\n * A callback function that runs whenever the text cursor position or selection changes.\n *\n * @param callback The callback to execute.\n * @returns A function to remove the callback.\n */\n public onSelectionChange(\n callback: (editor: BlockNoteEditor<BSchema, ISchema, SSchema>) => void\n ) {\n const cb = () => {\n callback(this);\n };\n\n this._tiptapEditor.on(\"selectionUpdate\", cb);\n\n return () => {\n this._tiptapEditor.off(\"selectionUpdate\", cb);\n };\n }\n}\n","import { Block, PartialBlock } from \"../../blocks/defaultBlocks\";\nimport { checkDefaultBlockTypeInSchema } from \"../../blocks/defaultBlockTypeGuards\";\nimport { BlockNoteEditor } from \"../../editor/BlockNoteEditor\";\nimport {\n BlockSchema,\n InlineContentSchema,\n isStyledTextInlineContent,\n StyleSchema,\n} from \"../../schema\";\nimport { formatKeyboardShortcut } from \"../../util/browser\";\nimport { DefaultSuggestionItem } from \"./DefaultSuggestionItem\";\n\n// Sets the editor's text cursor position to the next content editable block,\n// so either a block with inline content or a table. The last block is always a\n// paragraph, so this function won't try to set the cursor position past the\n// last block.\nfunction setSelectionToNextContentEditableBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(editor: BlockNoteEditor<BSchema, I, S>) {\n let block = editor.getTextCursorPosition().block;\n let contentType = editor.schema.blockSchema[block.type].content;\n\n while (contentType === \"none\") {\n block = editor.getTextCursorPosition().nextBlock!;\n contentType = editor.schema.blockSchema[block.type].content as\n | \"inline\"\n | \"table\"\n | \"none\";\n editor.setTextCursorPosition(block, \"end\");\n }\n}\n\n// Checks if the current block is empty or only contains a slash, and if so,\n// updates the current block instead of inserting a new one below. If the new\n// block doesn't contain editable content, the cursor is moved to the next block\n// that does.\nexport function insertOrUpdateBlock<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n editor: BlockNoteEditor<BSchema, I, S>,\n block: PartialBlock<BSchema, I, S>\n): Block<BSchema, I, S> {\n const currentBlock = editor.getTextCursorPosition().block;\n\n if (currentBlock.content === undefined) {\n throw new Error(\"Slash Menu open in a block that doesn't contain content.\");\n }\n\n if (\n Array.isArray(currentBlock.content) &&\n ((currentBlock.content.length === 1 &&\n isStyledTextInlineContent(currentBlock.content[0]) &&\n currentBlock.content[0].type === \"text\" &&\n currentBlock.content[0].text === \"/\") ||\n currentBlock.content.length === 0)\n ) {\n editor.updateBlock(currentBlock, block);\n } else {\n editor.insertBlocks([block], currentBlock, \"after\");\n editor.setTextCursorPosition(\n editor.getTextCursorPosition().nextBlock!,\n \"end\"\n );\n }\n\n const insertedBlock = editor.getTextCursorPosition().block;\n setSelectionToNextContentEditableBlock(editor);\n\n return insertedBlock;\n}\n\nexport function getDefaultSlashMenuItems<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(editor: BlockNoteEditor<BSchema, I, S>) {\n const items: DefaultSuggestionItem[] = [];\n\n if (checkDefaultBlockTypeInSchema(\"heading\", editor)) {\n items.push(\n {\n title: \"Heading 1\",\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: 1 },\n });\n },\n subtext: \"Used for a top-level heading\",\n badge: formatKeyboardShortcut(\"Mod-Alt-1\"),\n aliases: [\"h\", \"heading1\", \"h1\"],\n group: \"Headings\",\n },\n {\n title: \"Heading 2\",\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: 2 },\n });\n },\n subtext: \"Used for key sections\",\n badge: formatKeyboardShortcut(\"Mod-Alt-2\"),\n aliases: [\"h2\", \"heading2\", \"subheading\"],\n group: \"Headings\",\n },\n {\n title: \"Heading 3\",\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: 3 },\n });\n },\n subtext: \"Used for subsections and group headings\",\n badge: formatKeyboardShortcut(\"Mod-Alt-3\"),\n aliases: [\"h3\", \"heading3\", \"subheading\"],\n group: \"Headings\",\n }\n );\n }\n\n if (checkDefaultBlockTypeInSchema(\"numberedListItem\", editor)) {\n items.push({\n title: \"Numbered List\",\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"numberedListItem\",\n });\n },\n subtext: \"Used to display a numbered list\",\n badge: formatKeyboardShortcut(\"Mod-Shift-7\"),\n aliases: [\"ol\", \"li\", \"list\", \"numberedlist\", \"numbered list\"],\n group: \"Basic blocks\",\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"bulletListItem\", editor)) {\n items.push({\n title: \"Bullet List\",\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"bulletListItem\",\n });\n },\n subtext: \"Used to display an unordered list\",\n badge: formatKeyboardShortcut(\"Mod-Shift-8\"),\n aliases: [\"ul\", \"li\", \"list\", \"bulletlist\", \"bullet list\"],\n group: \"Basic blocks\",\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"paragraph\", editor)) {\n items.push({\n title: \"Paragraph\",\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"paragraph\",\n });\n },\n subtext: \"Used for the body of your document\",\n badge: formatKeyboardShortcut(\"Mod-Alt-0\"),\n aliases: [\"p\", \"paragraph\"],\n group: \"Basic blocks\",\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"table\", editor)) {\n items.push({\n title: \"Table\",\n onItemClick: () => {\n insertOrUpdateBlock(editor, {\n type: \"table\",\n content: {\n type: \"tableContent\",\n rows: [\n {\n cells: [\"\", \"\", \"\"],\n },\n {\n cells: [\"\", \"\", \"\"],\n },\n ],\n },\n });\n },\n subtext: \"Used for for tables\",\n aliases: [\"table\"],\n group: \"Advanced\",\n badge: undefined,\n });\n }\n\n if (checkDefaultBlockTypeInSchema(\"image\", editor)) {\n items.push({\n title: \"Image\",\n onItemClick: () => {\n const insertedBlock = insertOrUpdateBlock(editor, {\n type: \"image\",\n });\n\n // Immediately open the image toolbar\n editor.prosemirrorView.dispatch(\n editor._tiptapEditor.state.tr.setMeta(editor.imagePanel!.plugin, {\n block: insertedBlock,\n })\n );\n },\n subtext: \"Insert an image\",\n aliases: [\n \"image\",\n \"imageUpload\",\n \"upload\",\n \"img\",\n \"picture\",\n \"media\",\n \"url\",\n \"drive\",\n \"dropbox\",\n ],\n group: \"Media\",\n });\n }\n\n return items;\n}\n\nexport function filterSuggestionItems<\n T extends { title: string; aliases?: readonly string[] }\n>(items: T[], query: string) {\n return items.filter(\n ({ title, aliases }) =>\n title.toLowerCase().startsWith(query.toLowerCase()) ||\n (aliases &&\n aliases.filter((alias) =>\n alias.toLowerCase().startsWith(query.toLowerCase())\n ).length !== 0)\n );\n}\n","import { Block, PartialBlock } from \"../../blocks/defaultBlocks\";\nimport UniqueID from \"../../extensions/UniqueID/UniqueID\";\nimport { BlockSchema, TableContent } from \"../../schema/blocks/types\";\nimport {\n InlineContent,\n InlineContentSchema,\n PartialInlineContent,\n StyledText,\n isPartialLinkInlineContent,\n isStyledTextInlineContent,\n} from \"../../schema/inlineContent/types\";\nimport { StyleSchema } from \"../../schema/styles/types\";\n\nfunction textShorthandToStyledText(\n content: string | StyledText<any>[] = \"\"\n): StyledText<any>[] {\n if (typeof content === \"string\") {\n return [\n {\n type: \"text\",\n text: content,\n styles: {},\n },\n ];\n }\n return content;\n}\n\nfunction partialContentToInlineContent(\n content: PartialInlineContent<any, any> | TableContent<any> | undefined\n): InlineContent<any, any>[] | TableContent<any> | undefined {\n if (typeof content === \"string\") {\n return textShorthandToStyledText(content);\n }\n\n if (Array.isArray(content)) {\n return content.flatMap((partialContent) => {\n if (typeof partialContent === \"string\") {\n return textShorthandToStyledText(partialContent);\n } else if (isPartialLinkInlineContent(partialContent)) {\n return {\n ...partialContent,\n content: textShorthandToStyledText(partialContent.content),\n };\n } else if (isStyledTextInlineContent(partialContent)) {\n return partialContent;\n } else {\n // custom inline content\n\n return {\n props: {},\n ...partialContent,\n content: partialContentToInlineContent(partialContent.content),\n } as any;\n }\n });\n }\n\n return content;\n}\n\nexport function partialBlocksToBlocksForTesting<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n schema: BSchema,\n partialBlocks: Array<PartialBlock<BSchema, I, S>>\n): Array<Block<BSchema, I, S>> {\n return partialBlocks.map((partialBlock) =>\n partialBlockToBlockForTesting(schema, partialBlock)\n );\n}\n\nexport function partialBlockToBlockForTesting<\n BSchema extends BlockSchema,\n I extends InlineContentSchema,\n S extends StyleSchema\n>(\n schema: BSchema,\n partialBlock: PartialBlock<BSchema, I, S>\n): Block<BSchema, I, S> {\n const withDefaults: Block<BSchema, I, S> = {\n id: \"\",\n type: partialBlock.type!,\n props: {} as any,\n content:\n schema[partialBlock.type!].content === \"inline\" ? [] : (undefined as any),\n children: [] as any,\n ...partialBlock,\n };\n\n Object.entries(schema[partialBlock.type!].propSchema).forEach(\n ([propKey, propValue]) => {\n if (withDefaults.props[propKey] === undefined) {\n (withDefaults.props as any)[propKey] = propValue.default;\n }\n }\n );\n\n return {\n ...withDefaults,\n content: partialContentToInlineContent(withDefaults.content),\n children: withDefaults.children.map((c) => {\n return partialBlockToBlockForTesting(schema, c);\n }),\n } as any;\n}\n\nexport function addIdsToBlock(block: PartialBlock<any, any, any>) {\n if (!block.id) {\n block.id = UniqueID.options.generateID();\n }\n if (block.children) {\n addIdsToBlocks(block.children);\n }\n}\n\nexport function addIdsToBlocks(blocks: PartialBlock<any, any, any>[]) {\n for (const block of blocks) {\n addIdsToBlock(block);\n }\n}\n"],"names":["removeDuplicates","array","by","seen","item","key","findDuplicates","items","filtered","el","index","UniqueID","Extension","testOptions","v4","element","attributes","dragSourceElement","transformPasted","Plugin","PluginKey","transactions","oldState","newState","docChanges","transaction","filterTransactions","tr","_a","_b","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","getBlockInfo","blockContainer","contentNode","contentType","numChildBlocks","getBlockInfoFromPos","doc","outerBlockGroupEndPos","$pos","maxDepth","depth","startPos","endPos","isLinkInlineContent","content","isPartialLinkInlineContent","isStyledTextInlineContent","UnreachableCaseError","val","styledTextToNodes","styledText","schema","styleSchema","marks","style","value","config","text","linkToNodes","link","linkMark","styledTextArrayToNodes","nodes","inlineContentToNodes","blockContent","blockOrInlineContentToContentNode","tableContentToNodes","tableContent","rowNodes","row","columnNodes","cell","pNode","textNodes","cellNode","rowNode","block","type","blockToNode","children","child","groupNode","contentNodeToTableContent","inlineContentSchema","ret","contentNodeToInlineContent","currentContent","nodeToCustomInlineContent","styles","mark","props","icConfig","attr","propSchema","nodeToBlock","blockSchema","blockCache","cachedBlock","blockInfo","blockSpec","blockConfig","i","options","serializeNodeInner","serializer","editor","toExternalHTML","dom","contentDOM","DOMSerializer","blockContentNode","blockGroupNode","impl","serializeProseMirrorFragment","internalHTML","parent","simplifyBlocks","listItemBlockTypes","simplifyBlocksHelper","tree","blockGroup","numChildElements","activeList","isListItemBlock","listItemBlockType","numElementsRemoved","fromDom","listItemElement","numElementsAdded","createExternalHTMLExporter","unified","rehypeParse","rehypeStringify","blocks","createInternalHTMLSerializer","uploadToTmpFilesDotOrg_DEV_ONLY","file","body","isAppleOS","formatKeyboardShortcut","shortcut","mergeCSSClasses","classes","c","isSafari","createDefaultBlockDOMOutputSpec","blockName","htmlTag","blockContentHTMLAttributes","inlineContentHTMLAttributes","attribute","inlineContent","defaultBlockToHTML","toDOM","renderSpec","defaultProps","inheritedProps","camelToDataKebab","str","propsToAttributes","tiptapAttributes","name","_spec","spec","asNumber","getBlockFromPos","getPos","tipTapEditor","blockIdentifier","wrapInBlockStructure","blockType","blockProps","domAttributes","prop","createStronglyTypedTiptapNode","Node","createInternalBlockSpec","implementation","createBlockSpecFromStronglyTypedTiptapNode","requiredExtensions","getBlockSchemaFromSpecs","specs","getParseRules","customParseFunction","rules","createBlockSpec","blockImplementation","div","blockContentDOMAttributes","output","addInlineContentAttributes","inlineContentType","inlineContentProps","addInlineContentKeyboardShortcuts","resolvedPos","createInternalInlineContentSpec","createInlineContentSpecFromTipTapNode","getInlineContentSchemaFromSpecs","getInlineContentParseRules","htmlElement","createInlineContentSpec","inlineContentConfig","inlineContentImplementation","stylePropsToAttributes","addStyleAttributes","styleType","styleValue","createInternalStyleSpec","createStyleSpecFromTipTapMark","getStyleSchemaFromSpecs","getStyleParseRules","createStyleSpec","styleConfig","styleImplementation","Mark","renderResult","BackgroundColorMark","HTMLAttributes","BackgroundColor","TextColorMark","TextColor","getCurrentBlockContentType","headingPropSchema","HeadingBlockContent","parsed","level","InputRule","state","chain","range","Heading","imagePropSchema","textAlignmentToAlignItems","textAlignment","minWidth","Image","wrapper","addImageButton","addImageButtonIcon","addImageButtonText","imageAndCaptionWrapper","imageWrapper","image","leftResizeHandle","rightResizeHandle","caption","handleEditorUpdate","selection","selectedBlock","resizeParams","windowMouseMoveHandler","newWidth","windowMouseUpHandler","addImageButtonMouseDownHandler","addImageButtonClickHandler","imageMouseEnterHandler","imageMouseLeaveHandler","leftResizeHandleMouseDownHandler","rightResizeHandleMouseDownHandler","figure","img","figcaption","handleEnter","selectionEmpty","commands","bulletListItemPropSchema","BulletListItemBlockContent","BulletListItem","PLUGIN_KEY","NumberedListIndexingPlugin","_transactions","_oldState","modified","newIndex","isFirstBlockInDoc","prevBlockInfo","prevBlockContentNode","prevBlockIndex","numberedListItemPropSchema","NumberedListItemBlockContent","NumberedListItem","paragraphPropSchema","ParagraphBlockContent","Paragraph","TableExtension","columnResizing","tableEditing","selectionIsEmpty","selectionIsAtStartOfNode","selectionIsInTableParagraphNode","extension","context","callOrReturn","getExtensionField","tablePropSchema","TableBlockContent","TableParagraph","mergeAttributes","Table","TableHeader","TableCell","TableRow","defaultBlockSpecs","defaultBlockSchema","defaultStyleSpecs","Bold","Italic","Underline","Strike","Code","defaultStyleSchema","defaultInlineContentSpecs","defaultInlineContentSchema","checkDefaultBlockTypeInSchema","checkBlockIsDefaultType","checkBlockTypeHasDefaultProp","checkBlockHasDefaultProp","getNodeById","targetNode","posBeforeNode","insertBlocks","blocksToInsert","referenceBlock","placement","ttEditor","nodesToInsert","insertedBlocks","updateBlock","blockToUpdate","update","blockContainerNode","removeBlocksWithCallback","blocksToRemove","callback","idsOfBlocksToRemove","removedBlocks","removedSize","oldDocSize","newDocSize","notFoundIds","removeBlocks","replaceBlocks","idOfFirstBlock","insertContentAt","position","from","to","isOnlyTextContent","isOnlyBlockContent","selectionToInsertionEnd","removeUnderlines","removeUnderlinesHelper","cleanHTMLToMarkdown","cleanHTMLString","rehypeRemark","remarkGfm","remarkStringify","blocksToMarkdown","externalHTML","getChildIndex","isWhitespaceNode","liftNestedListsToParent","parentListItem","siblingsAfter","sibling","siblingContainer","createGroups","listItem","_detachedDoc","detachedDoc","nestedListsToBlockNoteStructure","elementOrHTML","HTMLToBlocks","html","icSchema","pmSchema","htmlNode","parentNode","DOMParser","code","properties","result","markdownToBlocks","markdown","htmlString","remarkParse","remarkRehype","defaultHandlers","EventEmitter","__publicField","fn","args","callbacks","FormattingToolbarView","pmView","emitUpdate","editorWrapper","composing","isSame","ranges","shouldShow","isNodeSelection","posToDOMRect","formattingToolbarPluginKey","FormattingToolbarProsemirrorPlugin","editorView","LinkToolbarView","hoveredLinkElement","posInHoveredLinkMark","resolvedPosInHoveredLinkMark","marksAtPos","getMarkRange","url","prevLinkMark","linkToolbarPluginKey","LinkToolbarProsemirrorPlugin","findBlock","findParentNode","SuggestionMenuView","decorationNode","suggestionMenuPluginKey","menuName","prevState","prev","next","started","stopped","SuggestionMenuProseMirrorPlugin","triggerCharacter","triggerCharacters","suggestionPluginTransactionMeta","_from","_to","suggestionPluginState","blockNode","DecorationSet","Decoration","createSuggestionMenu","MultipleNodeSelection","Selection","$anchor","$head","_pos","fromResult","toResult","dragImageElement","getDraggableBlockFromCoords","coords","blockPositionFromCoords","docView","desc","blockPositionsFromSelection","beforeFirstBlockPos","afterLastBlockPos","selectionStartInBlockContent","selectionEndInBlockContent","minDepth","startFirstBlockPos","endLastBlockPos","setDragImage","parentClone","getElementIndex","parentElement","targetElement","firstSelectedBlockIndex","lastSelectedBlockIndex","unsetDragImage","inheritedClasses","className","dragStart","e","editorBoundingBox","draggedBlockInSelection","multipleBlocksSelected","NodeSelection","selectedSlice","plainText","SideMenuView","evt","_event","editorOuterBoundingBox","cursorWithinEditor","_c","_d","_e","blockContentBoundingBox","newBlockInsertionPos","newBlockContentPos","sideMenuPluginKey","SideMenuProsemirrorPlugin","ImagePanelView","pluginKey","blockElement","pluginState","imagePanelPluginKey","ImagePanelProsemirrorPlugin","_editor","setHiddenDragImage","unsetHiddenDragImage","domCellAround","target","hideElementsWithClassNames","classNames","elementsToHide","TableHandlesView","colIndex","rowIndex","cellRect","tableRect","blockEl","boundedMouseCoords","tableCellElements","tableCellElement","emitStateUpdate","oldIndex","dispatchDecorationsTransaction","mousePos","tableHandlesPluginKey","rows","rowToMove","cellsToMove","tableElement","cellElement","TableHandlesProsemirrorPlugin","decorations","tableResolvedPos","tableNode","rowResolvedPos","cellResolvedPos","decorationPos","widget","selectedFragmentToHTML","selectedFragment","createCopyToClipboardExtension","acceptedMIMETypes","createPasteFromClipboardExtension","_view","format","mimeType","data","BackgroundColorExtension","Placeholder","placeholders","styleEl","styleSheet","getBaseSelector","additionalSelectors","getSelector","mustBeFocused","mustBeFocusedSelector","blockTypeSelector","placeholder","before","dec","TextAlignmentExtension","TextColorExtension","TrailingNode","plugin","_","__","shouldInsertNodeAtEnd","endPosition","_state","lastNode","lastContentNode","NonEditableBlockPlugin","nodeAttributes","PreviousBlockTypePlugin","timeout","_editorView","_prevState","currentTransactionOriginalOldBlockAttrs","oldNodes","findChildren","oldNodesById","oldNode","oldContentNode","newContentNode","newAttrs","oldAttrs","prevAttrs","decorationAttrs","nodeAttr","decoration","BlockAttributes","BlockContainer","attrs","HTMLAttr","blockOuter","blockHTMLAttributes","dispatch","newBlock","posInBlock","childNodes","oldType","newType","oldContentType","newContentType","TextSelection","posBetweenBlocks","nextNodeIsBlock","prevNodeIsBlock","nextBlockInfo","childBlocksStart","childBlocksEnd","childBlocksRange","prevBlockEndPos","keepType","originalBlockContent","newBlockContent","selectionAtBlockStart","isParagraph","blockAtDocStart","blockAtDocEnd","selectionAtBlockEnd","hasChildBlocks","oldDepth","newPos","newDepth","blockEmpty","blockIndented","BlockGroup","blockGroupHTMLAttributes","Doc","getBlockNoteExtensions","opts","extensions","Gapcursor","HardBreak","Text","Link","styleSpec","a","inlineContentSpec","ext","Dropcursor","Collaboration","defaultRender","user","cursor","label","nonbreakingSpace1","nonbreakingSpace2","CollaborationCursor","History","removeChild","n","f","nestedChild","container","BlockNoteSchema","BlockNoteTipTapEditor","TiptapEditor","cache","oldCreateAndFill","pmNodes","b","createDocument","EditorState","EditorView","blockNoteTipTapOptions","BlockNoteEditor","anyOpts","newOptions","blockNoteUIExtension","initialContent","tiptapOptions","_f","_h","_g","reverse","traverseBlockArray","blockArray","nodeIndex","numNodes","prevNode","nextNode","targetBlock","editable","cb","setSelectionToNextContentEditableBlock","insertOrUpdateBlock","currentBlock","insertedBlock","getDefaultSlashMenuItems","filterSuggestionItems","query","title","aliases","alias","textShorthandToStyledText","partialContentToInlineContent","partialContent","partialBlocksToBlocksForTesting","partialBlocks","partialBlock","partialBlockToBlockForTesting","withDefaults","propKey","propValue","addIdsToBlock","addIdsToBlocks"],"mappings":"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"}