@blocknote/core 0.8.3 → 0.8.4-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/blocknote.js.map +1 -1
- package/dist/blocknote.umd.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +4 -4
- package/src/node_modules/.vitest/results.json +0 -1
- package/types/src/EventEmitter.d.ts +0 -11
- package/types/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.d.ts +0 -0
- package/types/src/extensions/DraggableBlocks/DraggableBlocksExtension.d.ts +0 -16
- package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +0 -55
- package/types/src/extensions/DraggableBlocks/MultipleNodeSelection.d.ts +0 -24
- package/types/src/extensions/FormattingToolbar/FormattingToolbarExtension.d.ts +0 -11
- package/types/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.d.ts +0 -10
- package/types/src/extensions/HyperlinkToolbar/HyperlinkMark.d.ts +0 -8
- package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.d.ts +0 -0
- package/types/src/extensions/SlashMenu/SlashMenuExtension.d.ts +0 -13
- package/types/src/extensions/SlashMenu/index.d.ts +0 -3
- package/types/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.d.ts +0 -12
package/dist/blocknote.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blocknote.js","sources":["../src/extensions/Blocks/helpers/getBlockInfoFromPos.ts","../src/extensions/BackgroundColor/BackgroundColorExtension.ts","../src/extensions/BackgroundColor/BackgroundColorMark.ts","../src/extensions/Blocks/api/block.ts","../src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContent.ts","../src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/ListItemKeyboardShortcuts.ts","../src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts","../src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts","../src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts","../src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.ts","../src/extensions/Blocks/api/defaultBlocks.ts","../src/extensions/UniqueID/UniqueID.ts","../src/shared/utils.ts","../src/api/nodeConversions/nodeConversions.ts","../src/extensions/Blocks/PreviousBlockTypePlugin.ts","../src/extensions/Blocks/nodes/BlockAttributes.ts","../src/extensions/Blocks/nodes/BlockContainer.ts","../src/extensions/Blocks/nodes/BlockGroup.ts","../src/extensions/Blocks/index.ts","../src/extensions/Blocks/api/serialization.ts","../src/shared/EventEmitter.ts","../src/extensions/Blocks/helpers/findBlock.ts","../src/shared/plugins/suggestion/SuggestionPlugin.ts","../src/extensions/SlashMenu/SlashMenuPlugin.ts","../src/extensions/Placeholder/PlaceholderExtension.ts","../src/extensions/TextAlignment/TextAlignmentExtension.ts","../src/extensions/TextColor/TextColorExtension.ts","../src/extensions/TextColor/TextColorMark.ts","../src/extensions/TrailingNode/TrailingNodeExtension.ts","../src/BlockNoteExtensions.ts","../src/api/util/nodeUtil.ts","../src/api/blockManipulation/blockManipulation.ts","../src/api/formatConversions/removeUnderlinesRehypePlugin.ts","../src/api/formatConversions/simplifyBlocksRehypePlugin.ts","../src/api/formatConversions/formatConversions.ts","../src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts","../src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts","../src/extensions/SideMenu/MultipleNodeSelection.ts","../src/extensions/SideMenu/SideMenuPlugin.ts","../src/extensions/SlashMenu/defaultSlashMenuItems.ts","../src/BlockNoteEditor.ts"],"sourcesContent":["import { Node, NodeType } from \"prosemirror-model\";\n\nexport type BlockInfo = {\n id: string;\n node: Node;\n contentNode: Node;\n contentType: NodeType;\n numChildBlocks: number;\n startPos: number;\n endPos: number;\n depth: number;\n};\n\n/**\n * Retrieves information regarding the most nested block node in a ProseMirror doc, that a given position lies in.\n * @param doc The ProseMirror doc.\n * @param posInBlock A position somewhere within a block node.\n * @returns A BlockInfo object for the block the given position is in, or undefined if the position is not in a block\n * for the given doc.\n */\nexport function getBlockInfoFromPos(\n doc: Node,\n posInBlock: number\n): BlockInfo | undefined {\n if (posInBlock < 0 || posInBlock > doc.nodeSize) {\n return undefined;\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(posInBlock).parent.type.name === \"blockGroup\") {\n posInBlock++;\n }\n\n const $pos = doc.resolve(posInBlock);\n\n const maxDepth = $pos.depth;\n let node = $pos.node(maxDepth);\n let depth = maxDepth;\n\n while (true) {\n if (depth < 0) {\n return undefined;\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 = node.attrs[\"id\"];\n const contentNode = node.firstChild!;\n const contentType = contentNode.type;\n const numChildBlocks = node.childCount === 2 ? node.lastChild!.childCount : 0;\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 { Extension } from \"@tiptap/core\";\nimport { getBlockInfoFromPos } from \"../Blocks/helpers/getBlockInfoFromPos\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n blockBackgroundColor: {\n setBlockBackgroundColor: (\n posInBlock: number,\n color: string\n ) => ReturnType;\n };\n }\n}\n\nexport const BackgroundColorExtension = Extension.create({\n name: \"blockBackgroundColor\",\n\n addGlobalAttributes() {\n return [\n {\n types: [\"blockContainer\"],\n attributes: {\n backgroundColor: {\n default: \"default\",\n parseHTML: (element) =>\n element.hasAttribute(\"data-background-color\")\n ? element.getAttribute(\"data-background-color\")\n : \"default\",\n renderHTML: (attributes) =>\n attributes.backgroundColor !== \"default\" && {\n \"data-background-color\": attributes.backgroundColor,\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setBlockBackgroundColor:\n (posInBlock, color) =>\n ({ state, view }) => {\n const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);\n if (blockInfo === undefined) {\n return false;\n }\n\n state.tr.setNodeAttribute(\n blockInfo.startPos - 1,\n \"backgroundColor\",\n color\n );\n\n view.focus();\n\n return true;\n },\n };\n },\n});\n","import { Mark } from \"@tiptap/core\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n backgroundColor: {\n setBackgroundColor: (color: string) => ReturnType;\n };\n }\n}\n\nexport const BackgroundColorMark = Mark.create({\n name: \"backgroundColor\",\n\n addAttributes() {\n return {\n color: {\n default: undefined,\n parseHTML: (element) => element.getAttribute(\"data-background-color\"),\n renderHTML: (attributes) => ({\n \"data-background-color\": attributes.color,\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 { color: element.getAttribute(\"data-background-color\") };\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"span\", HTMLAttributes, 0];\n },\n\n addCommands() {\n return {\n setBackgroundColor:\n (color) =>\n ({ commands }) => {\n if (color !== \"default\") {\n return commands.setMark(this.name, { color: color });\n }\n\n return commands.unsetMark(this.name);\n },\n };\n },\n});\n","import { Attribute, Node } from \"@tiptap/core\";\nimport { BlockNoteEditor } from \"../../..\";\nimport styles from \"../nodes/Block.module.css\";\nimport {\n BlockConfig,\n BlockSchema,\n BlockSpec,\n PropSchema,\n TipTapNode,\n TipTapNodeConfig,\n} from \"./blockTypes\";\n\nexport function camelToDataKebab(str: string): string {\n return \"data-\" + str.replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase();\n}\n\n// Function that uses the 'propSchema' of a blockConfig to create a TipTap\n// node's `addAttributes` property.\nexport function propsToAttributes<\n BType extends string,\n PSchema extends PropSchema,\n ContainsInlineContent extends boolean,\n BSchema extends BlockSchema\n>(\n blockConfig: Omit<\n BlockConfig<BType, PSchema, ContainsInlineContent, BSchema>,\n \"render\"\n >\n) {\n const tiptapAttributes: Record<string, Attribute> = {};\n\n Object.entries(blockConfig.propSchema).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) => element.getAttribute(camelToDataKebab(name)),\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// 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 parse<\n BType extends string,\n PSchema extends PropSchema,\n ContainsInlineContent extends boolean,\n BSchema extends BlockSchema\n>(\n blockConfig: Omit<\n BlockConfig<BType, PSchema, ContainsInlineContent, BSchema>,\n \"render\"\n >\n) {\n return [\n {\n tag: \"div[data-content-type=\" + blockConfig.type + \"]\",\n },\n ];\n}\n\n// Function that uses the 'render' function of a blockConfig to create a\n// TipTap node's `renderHTML` property. Since custom blocks use node views,\n// this is only used for serializing content to the clipboard.\nexport function render<\n BType extends string,\n PSchema extends PropSchema,\n ContainsInlineContent extends boolean,\n BSchema extends BlockSchema\n>(\n blockConfig: Omit<\n BlockConfig<BType, PSchema, ContainsInlineContent, BSchema>,\n \"render\"\n >,\n HTMLAttributes: Record<string, any>\n) {\n // Create blockContent element\n const blockContent = document.createElement(\"div\");\n // Add blockContent HTML attribute\n blockContent.setAttribute(\"data-content-type\", blockConfig.type);\n // Add props as HTML attributes in kebab-case with \"data-\" prefix\n for (const [attribute, value] of Object.entries(HTMLAttributes)) {\n blockContent.setAttribute(attribute, value);\n }\n\n // TODO: This only works for content copied within BlockNote.\n // Creates contentDOM element to serialize inline content into.\n let contentDOM: HTMLDivElement | undefined;\n if (blockConfig.containsInlineContent) {\n contentDOM = document.createElement(\"div\");\n blockContent.appendChild(contentDOM);\n } else {\n contentDOM = undefined;\n }\n\n return contentDOM !== undefined\n ? {\n dom: blockContent,\n contentDOM: contentDOM,\n }\n : {\n dom: blockContent,\n };\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 BType extends string,\n PSchema extends PropSchema,\n ContainsInlineContent extends boolean,\n BSchema extends BlockSchema\n>(\n blockConfig: BlockConfig<BType, PSchema, ContainsInlineContent, BSchema>\n): BlockSpec<BType, PSchema> {\n const node = createTipTapBlock<BType>({\n name: blockConfig.type,\n content: blockConfig.containsInlineContent ? \"inline*\" : \"\",\n selectable: blockConfig.containsInlineContent,\n\n addOptions() {\n return {\n editor: undefined,\n };\n },\n\n addAttributes() {\n return propsToAttributes(blockConfig);\n },\n\n parseHTML() {\n return parse(blockConfig);\n },\n\n renderHTML({ HTMLAttributes }) {\n return render(blockConfig, HTMLAttributes);\n },\n\n addNodeView() {\n return ({ HTMLAttributes, getPos }) => {\n // Create blockContent element\n const blockContent = document.createElement(\"div\");\n // Sets blockContent class\n blockContent.className = styles.blockContent;\n // Add blockContent HTML attribute\n blockContent.setAttribute(\"data-content-type\", blockConfig.type);\n // Add props as HTML attributes in kebab-case with \"data-\" prefix\n for (const [attribute, value] of Object.entries(HTMLAttributes)) {\n blockContent.setAttribute(attribute, value);\n }\n\n // Gets BlockNote editor instance\n const editor = this.options.editor! as BlockNoteEditor<\n BSchema & { [k in BType]: BlockSpec<BType, PSchema> }\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 TipTap editor instance\n const tipTapEditor = editor._tiptapEditor;\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\n // Get the block\n const block = editor.getBlock(blockIdentifier)!;\n if (block.type !== blockConfig.type) {\n throw new Error(\"Block type does not match\");\n }\n\n // Render elements\n const rendered = blockConfig.render(block as any, editor);\n // Add inlineContent class to inline content\n if (\"contentDOM\" in rendered) {\n rendered.contentDOM.className = `${\n rendered.contentDOM.className\n ? rendered.contentDOM.className + \" \"\n : \"\"\n }${styles.inlineContent}`;\n }\n // Add elements to blockContent\n blockContent.appendChild(rendered.dom);\n\n return \"contentDOM\" in rendered\n ? {\n dom: blockContent,\n contentDOM: rendered.contentDOM,\n }\n : {\n dom: blockContent,\n };\n };\n },\n });\n\n return {\n node: node,\n propSchema: blockConfig.propSchema,\n };\n}\n\nexport function createTipTapBlock<Type extends string>(\n config: TipTapNodeConfig<Type>\n): TipTapNode<Type> {\n // Type cast is needed as Node.name is mutable, though there is basically no\n // reason to change it after creation. Alternative is to wrap Node in a new\n // class, which I don't think is worth it since we'd only be changing 1\n // attribute to be read only.\n return Node.create({\n ...config,\n group: \"blockContent\",\n }) as TipTapNode<Type>;\n}\n","import { InputRule, mergeAttributes } from \"@tiptap/core\";\nimport { createTipTapBlock } from \"../../../api/block\";\nimport styles from \"../../Block.module.css\";\n\nexport const HeadingBlockContent = createTipTapBlock<\"heading\">({\n name: \"heading\",\n content: \"inline*\",\n\n addAttributes() {\n return {\n level: {\n default: \"1\",\n // instead of \"level\" attributes, use \"data-level\"\n parseHTML: (element) => element.getAttribute(\"data-level\"),\n renderHTML: (attributes) => {\n return {\n \"data-level\": attributes.level,\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(`^(#{${parseInt(level)}})\\\\s$`),\n handler: ({ state, chain, range }) => {\n chain()\n .BNUpdateBlock(state.selection.from, {\n type: \"heading\",\n props: {\n level: level as \"1\" | \"2\" | \"3\",\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 parseHTML() {\n return [\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 [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n class: styles.blockContent,\n \"data-content-type\": this.name,\n }),\n [\"h\" + node.attrs.level, { class: styles.inlineContent }, 0],\n ];\n },\n});\n","import { Editor } from \"@tiptap/core\";\nimport { getBlockInfoFromPos } from \"../../../helpers/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 (!contentType.name.endsWith(\"ListItem\") || !selectionEmpty) {\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, mergeAttributes } from \"@tiptap/core\";\nimport { createTipTapBlock } from \"../../../../api/block\";\nimport { handleEnter } from \"../ListItemKeyboardShortcuts\";\nimport styles from \"../../../Block.module.css\";\n\nexport const BulletListItemBlockContent = createTipTapBlock<\"bulletListItem\">({\n name: \"bulletListItem\",\n content: \"inline*\",\n\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 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 };\n },\n\n parseHTML() {\n return [\n // Case for regular HTML list structure.\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 (parent.tagName === \"UL\") {\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 [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n class: styles.blockContent,\n \"data-content-type\": this.name,\n }),\n [\"p\", { class: styles.inlineContent }, 0],\n ];\n },\n});\n","import { Plugin, PluginKey } from \"prosemirror-state\";\nimport { getBlockInfoFromPos } from \"../../../../helpers/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, mergeAttributes } from \"@tiptap/core\";\nimport { createTipTapBlock } from \"../../../../api/block\";\nimport { handleEnter } from \"../ListItemKeyboardShortcuts\";\nimport { NumberedListIndexingPlugin } from \"./NumberedListIndexingPlugin\";\nimport styles from \"../../../Block.module.css\";\n\nexport const NumberedListItemBlockContent =\n createTipTapBlock<\"numberedListItem\">({\n name: \"numberedListItem\",\n content: \"inline*\",\n\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 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 };\n },\n\n addProseMirrorPlugins() {\n return [NumberedListIndexingPlugin()];\n },\n\n parseHTML() {\n return [\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 (parent.tagName === \"OL\") {\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 (\n parent.getAttribute(\"data-content-type\") === \"numberedListItem\"\n ) {\n return {};\n }\n\n return false;\n },\n priority: 300,\n node: \"numberedListItem\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n class: styles.blockContent,\n \"data-content-type\": this.name,\n }),\n // we use a <p> tag, because for <li> tags we'd need to add a <ul> parent for around siblings to be semantically correct,\n // which would be quite cumbersome\n [\"p\", { class: styles.inlineContent }, 0],\n ];\n },\n });\n","import { mergeAttributes } from \"@tiptap/core\";\nimport { createTipTapBlock } from \"../../../api/block\";\nimport styles from \"../../Block.module.css\";\n\nexport const ParagraphBlockContent = createTipTapBlock<\"paragraph\">({\n name: \"paragraph\",\n content: \"inline*\",\n\n parseHTML() {\n return [\n {\n tag: \"p\",\n priority: 200,\n node: \"paragraph\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n class: styles.blockContent,\n \"data-content-type\": this.name,\n }),\n [\"p\", { class: styles.inlineContent }, 0],\n ];\n },\n});\n","import { HeadingBlockContent } from \"../nodes/BlockContent/HeadingBlockContent/HeadingBlockContent\";\nimport { BulletListItemBlockContent } from \"../nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent\";\nimport { NumberedListItemBlockContent } from \"../nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent\";\nimport { ParagraphBlockContent } from \"../nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent\";\nimport { PropSchema, TypesMatch } from \"./blockTypes\";\n\nexport const defaultProps = {\n backgroundColor: {\n default: \"transparent\" as const,\n },\n textColor: {\n default: \"black\" as const, // TODO\n },\n textAlignment: {\n default: \"left\" as const,\n values: [\"left\", \"center\", \"right\", \"justify\"] as const,\n },\n} satisfies PropSchema;\n\nexport type DefaultProps = typeof defaultProps;\n\nexport const defaultBlockSchema = {\n paragraph: {\n propSchema: defaultProps,\n node: ParagraphBlockContent,\n },\n heading: {\n propSchema: {\n ...defaultProps,\n level: { default: \"1\", values: [\"1\", \"2\", \"3\"] as const },\n },\n node: HeadingBlockContent,\n },\n bulletListItem: {\n propSchema: defaultProps,\n node: BulletListItemBlockContent,\n },\n numberedListItem: {\n propSchema: defaultProps,\n node: NumberedListItemBlockContent,\n },\n} as const;\n\nexport type DefaultBlockSchema = TypesMatch<typeof defaultBlockSchema>;\n","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 ((window as any).__TEST_OPTIONS) {\n if ((window as any).__TEST_OPTIONS.mockID === undefined) {\n (window as any).__TEST_OPTIONS.mockID = 0;\n } else {\n (window as any).__TEST_OPTIONS.mockID++;\n }\n\n return (window as any).__TEST_OPTIONS.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 var _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 var _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 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 var _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 var _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, UniqueID as default };\n//# sourceMappingURL=tiptap-extension-unique-id.esm.js.map\n","export const isAppleOS = () =>\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 class UnreachableCaseError extends Error {\n constructor(val: never) {\n super(`Unreachable case: ${val}`);\n }\n}\n","import { Mark } from \"@tiptap/pm/model\";\nimport { Node, Schema } from \"prosemirror-model\";\nimport {\n Block,\n BlockSchema,\n PartialBlock,\n} from \"../../extensions/Blocks/api/blockTypes\";\n\nimport { defaultProps } from \"../../extensions/Blocks/api/defaultBlocks\";\nimport {\n ColorStyle,\n InlineContent,\n PartialInlineContent,\n PartialLink,\n StyledText,\n Styles,\n ToggledStyle,\n} from \"../../extensions/Blocks/api/inlineContentTypes\";\nimport { getBlockInfoFromPos } from \"../../extensions/Blocks/helpers/getBlockInfoFromPos\";\nimport UniqueID from \"../../extensions/UniqueID/UniqueID\";\nimport { UnreachableCaseError } from \"../../shared/utils\";\n\nconst toggleStyles = new Set<ToggledStyle>([\n \"bold\",\n \"italic\",\n \"underline\",\n \"strike\",\n \"code\",\n]);\nconst colorStyles = new Set<ColorStyle>([\"textColor\", \"backgroundColor\"]);\n\n/**\n * Convert a StyledText inline element to a\n * prosemirror text node with the appropriate marks\n */\nfunction styledTextToNodes(styledText: StyledText, schema: Schema): Node[] {\n const marks: Mark[] = [];\n\n for (const [style, value] of Object.entries(styledText.styles)) {\n if (toggleStyles.has(style as ToggledStyle)) {\n marks.push(schema.mark(style));\n } else if (colorStyles.has(style as ColorStyle)) {\n marks.push(schema.mark(style, { color: value }));\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(link: PartialLink, schema: Schema): Node[] {\n const linkMark = schema.marks.link.create({\n href: link.href,\n });\n\n return styledTextArrayToNodes(link.content, schema).map((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 * Converts an array of StyledText inline content elements to\n * prosemirror text nodes with the appropriate marks\n */\nfunction styledTextArrayToNodes(\n content: string | StyledText[],\n schema: Schema\n): Node[] {\n let nodes: Node[] = [];\n\n if (typeof content === \"string\") {\n nodes.push(\n ...styledTextToNodes({ type: \"text\", text: content, styles: {} }, schema)\n );\n return nodes;\n }\n\n for (const styledText of content) {\n nodes.push(...styledTextToNodes(styledText, schema));\n }\n return nodes;\n}\n\n/**\n * converts an array of inline content elements to prosemirror nodes\n */\nexport function inlineContentToNodes(\n blockContent: PartialInlineContent[],\n schema: Schema\n): Node[] {\n let nodes: Node[] = [];\n\n for (const content of blockContent) {\n if (content.type === \"link\") {\n nodes.push(...linkToNodes(content, schema));\n } else if (content.type === \"text\") {\n nodes.push(...styledTextArrayToNodes([content], schema));\n } else {\n throw new UnreachableCaseError(content);\n }\n }\n return nodes;\n}\n\n/**\n * Converts a BlockNote block to a TipTap node.\n */\nexport function blockToNode<BSchema extends BlockSchema>(\n block: PartialBlock<BSchema>,\n schema: Schema\n) {\n let id = block.id;\n\n if (id === undefined) {\n id = UniqueID.options.generateID();\n }\n\n let type = block.type;\n\n if (type === undefined) {\n type = \"paragraph\";\n }\n\n let contentNode: Node;\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 {\n const nodes = inlineContentToNodes(block.content, schema);\n contentNode = schema.nodes[type].create(block.props, nodes);\n }\n\n const children: Node[] = [];\n\n if (block.children) {\n for (const child of block.children) {\n children.push(blockToNode(child, schema));\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) content node to a BlockNote InlineContent array.\n */\nfunction contentNodeToInlineContent(contentNode: Node) {\n const content: InlineContent[] = [];\n let currentContent: InlineContent | 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 (currentContent.type === \"text\") {\n // Current content is text.\n currentContent.text += \"\\n\";\n } else if (currentContent.type === \"link\") {\n // Current content is a link.\n currentContent.content[currentContent.content.length - 1].text +=\n \"\\n\";\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 const styles: Styles = {};\n let linkMark: Mark | undefined;\n\n for (const mark of node.marks) {\n if (mark.type.name === \"link\") {\n linkMark = mark;\n } else if (toggleStyles.has(mark.type.name as ToggledStyle)) {\n styles[mark.type.name as ToggledStyle] = true;\n } else if (colorStyles.has(mark.type.name as ColorStyle)) {\n styles[mark.type.name as ColorStyle] = mark.attrs.color;\n } else {\n throw Error(\"Mark is of an unrecognized type: \" + mark.type.name);\n }\n }\n\n // Parsing links and text.\n // Current content exists.\n if (currentContent) {\n // Current content is text.\n if (currentContent.type === \"text\") {\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 (currentContent.type === \"link\") {\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 }\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;\n}\n\n/**\n * Convert a TipTap node to a BlockNote block.\n */\nexport function nodeToBlock<BSchema extends BlockSchema>(\n node: Node,\n blockSchema: BSchema,\n blockCache?: WeakMap<Node, Block<BSchema>>\n): Block<BSchema> {\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 = getBlockInfoFromPos(node, 0)!;\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 ...blockInfo.node.attrs,\n ...blockInfo.contentNode.attrs,\n })) {\n const blockSpec = blockSchema[blockInfo.contentType.name];\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 // Block ids are stored as node attributes the same way props are, so we\n // need to ensure we don't attempt to read block ids as props.\n\n // the second check is for the backgroundColor & textColor props.\n // Since we want them to be inherited by child blocks, we can't put them on the blockContent node,\n // and instead have to put them on the blockContainer node.\n // The blockContainer node is the same for all block types, but some custom blocks might not use backgroundColor & textColor,\n // so these 2 props are technically unexpected but we shouldn't log a warning.\n // (this is a bit hacky)\n else if (attr !== \"id\" && !(attr in defaultProps)) {\n console.warn(\"Block has an unrecognized attribute: \" + attr);\n }\n }\n\n const content = contentNodeToInlineContent(blockInfo.contentNode);\n\n const children: Block<BSchema>[] = [];\n for (let i = 0; i < blockInfo.numChildBlocks; i++) {\n children.push(\n nodeToBlock(blockInfo.node.lastChild!.child(i), blockSchema, blockCache)\n );\n }\n\n const block: Block<BSchema> = {\n id,\n type: blockInfo.contentType.name,\n props,\n content,\n children,\n };\n\n blockCache?.set(node, block);\n\n return block;\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 (let 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 (let [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","// 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\nexport default BlockAttributes;\n","import { mergeAttributes, Node } from \"@tiptap/core\";\nimport { Fragment, Node as PMNode, Slice } from \"prosemirror-model\";\nimport { TextSelection } from \"prosemirror-state\";\nimport {\n blockToNode,\n inlineContentToNodes,\n} from \"../../../api/nodeConversions/nodeConversions\";\n\nimport { getBlockInfoFromPos } from \"../helpers/getBlockInfoFromPos\";\nimport { PreviousBlockTypePlugin } from \"../PreviousBlockTypePlugin\";\nimport styles from \"./Block.module.css\";\nimport BlockAttributes from \"./BlockAttributes\";\nimport { BlockSchema, PartialBlock } from \"../api/blockTypes\";\n\n// TODO\nexport interface IBlock {\n HTMLAttributes: Record<string, any>;\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: <BSchema extends BlockSchema>(\n posInBlock: number,\n block: PartialBlock<BSchema>\n ) => ReturnType;\n BNCreateOrUpdateBlock: <BSchema extends BlockSchema>(\n posInBlock: number,\n block: PartialBlock<BSchema>\n ) => ReturnType;\n };\n }\n}\n\n/**\n * The main \"Block node\" documents consist of\n */\nexport const BlockContainer = Node.create<IBlock>({\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 addOptions() {\n return {\n HTMLAttributes: {},\n };\n },\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 (let [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 return [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n class: styles.blockOuter,\n \"data-node-type\": \"block-outer\",\n }),\n [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n // TODO: maybe remove html attributes from inner block\n class: styles.block,\n \"data-node-type\": this.name,\n }),\n 0,\n ],\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(blockToNode(child, state.schema));\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 // Replaces the blockContent node's content if necessary.\n if (block.content !== undefined) {\n let content: PMNode[] = [];\n\n // Checks if the provided content is a string or InlineContent[] type.\n if (typeof block.content === \"string\") {\n // Adds a single text node with no marks to the content.\n content.push(state.schema.text(block.content));\n } else {\n // Adds a text node with the provided styles converted into marks to the content, for each InlineContent\n // object.\n content = inlineContentToNodes(block.content, state.schema);\n }\n\n // Replaces the contents of the blockContent node with the previously created text node(s).\n state.tr.replace(\n startPos + 1,\n startPos + contentNode.nodeSize - 1,\n new Slice(Fragment.from(content), 0, 0)\n );\n }\n\n // Changes the blockContent node type and adds the provided props as attributes. Also preserves all existing\n // attributes that are compatible with the new type.\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\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()];\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 } = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n )!;\n\n const selectionAtBlockStart =\n state.selection.$anchor.parentOffset === 0;\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 selectionAtBlockStart =\n state.selection.$anchor.parentOffset === 0;\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 =\n state.selection.$anchor.parentOffset === 0;\n const selectionEmpty =\n state.selection.anchor === state.selection.head;\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 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 blockEmpty = node.textContent.length === 0;\n\n if (!blockEmpty) {\n chain()\n .deleteSelection()\n .BNSplitBlock(state.selection.from, false)\n .run();\n\n return true;\n }\n\n return false;\n }),\n ]);\n\n return {\n Backspace: handleBackspace,\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 \"Mod-Alt-0\": () =>\n this.editor.commands.BNCreateBlock(\n this.editor.state.selection.anchor + 2\n ),\n \"Mod-Alt-1\": () =>\n this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {\n type: \"heading\",\n props: {\n level: \"1\",\n },\n }),\n \"Mod-Alt-2\": () =>\n this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {\n type: \"heading\",\n props: {\n level: \"2\",\n },\n }),\n \"Mod-Alt-3\": () =>\n this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {\n type: \"heading\",\n props: {\n level: \"3\",\n },\n }),\n \"Mod-Shift-7\": () =>\n this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {\n type: \"bulletListItem\",\n props: {},\n }),\n \"Mod-Shift-8\": () =>\n this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {\n type: \"numberedListItem\",\n props: {},\n }),\n };\n },\n});\n","import { mergeAttributes, Node } from \"@tiptap/core\";\nimport styles from \"./Block.module.css\";\n\nexport const BlockGroup = Node.create({\n name: \"blockGroup\",\n group: \"blockGroup\",\n content: \"blockContainer+\",\n\n addOptions() {\n return {\n HTMLAttributes: {},\n };\n },\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 return [\n \"div\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n class: styles.blockGroup,\n \"data-node-type\": \"blockGroup\",\n }),\n 0,\n ];\n },\n});\n","import { Node } from \"@tiptap/core\";\nimport { BlockContainer } from \"./nodes/BlockContainer\";\nimport { BlockGroup } from \"./nodes/BlockGroup\";\n\nexport const blocks: any[] = [\n BlockContainer,\n BlockGroup,\n Node.create({\n name: \"doc\",\n topNode: true,\n content: \"blockGroup\",\n }),\n];\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin } from \"prosemirror-state\";\nimport { DOMSerializer, Schema } from \"prosemirror-model\";\n\nconst customBlockSerializer = (schema: Schema) => {\n const defaultSerializer = DOMSerializer.fromSchema(schema);\n\n return new DOMSerializer(\n {\n ...defaultSerializer.nodes,\n // TODO: If a serializer is defined in the config for a custom block, it\n // should be added here. We still need to figure out how the serializer\n // should be defined in the custom blocks API though, and implement that,\n // before we can do this.\n },\n defaultSerializer.marks\n );\n};\nexport const CustomBlockSerializerExtension = Extension.create({\n addProseMirrorPlugins() {\n return [\n new Plugin({\n props: {\n clipboardSerializer: customBlockSerializer(this.editor.schema),\n },\n }),\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 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 { findParentNode } from \"@tiptap/core\";\n\nexport const findBlock = findParentNode(\n (node) => node.type.name === \"blockContainer\"\n);\n","import { EditorState, Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet, EditorView } from \"prosemirror-view\";\nimport { BlockNoteEditor } from \"../../../BlockNoteEditor\";\nimport { BlockSchema } from \"../../../extensions/Blocks/api/blockTypes\";\nimport { findBlock } from \"../../../extensions/Blocks/helpers/findBlock\";\nimport { BaseUiElementState } from \"../../BaseUiElementTypes\";\nimport { SuggestionItem } from \"./SuggestionItem\";\n\nexport type SuggestionsMenuState<T extends SuggestionItem> =\n BaseUiElementState & {\n // The suggested items to display.\n filteredItems: T[];\n // The index of the suggested item that's currently hovered by the keyboard.\n keyboardHoveredItemIndex: number;\n };\n\nclass SuggestionsMenuView<\n T extends SuggestionItem,\n BSchema extends BlockSchema\n> {\n private suggestionsMenuState?: SuggestionsMenuState<T>;\n public updateSuggestionsMenu: () => void;\n\n pluginState: SuggestionPluginState<T>;\n\n constructor(\n private readonly editor: BlockNoteEditor<BSchema>,\n private readonly pluginKey: PluginKey,\n updateSuggestionsMenu: (\n suggestionsMenuState: SuggestionsMenuState<T>\n ) => void = () => {}\n ) {\n this.pluginState = getDefaultPluginState<T>();\n\n this.updateSuggestionsMenu = () => {\n if (!this.suggestionsMenuState) {\n throw new Error(\"Attempting to update uninitialized suggestions menu\");\n }\n\n updateSuggestionsMenu(this.suggestionsMenuState);\n };\n\n document.addEventListener(\"scroll\", this.handleScroll);\n }\n\n handleScroll = () => {\n if (this.suggestionsMenuState?.show) {\n const decorationNode = document.querySelector(\n `[data-decoration-id=\"${this.pluginState.decorationId}\"]`\n );\n this.suggestionsMenuState.referencePos =\n decorationNode!.getBoundingClientRect();\n this.updateSuggestionsMenu();\n }\n };\n\n update(view: EditorView, prevState: EditorState) {\n const prev = this.pluginKey.getState(prevState);\n const next = this.pluginKey.getState(view.state);\n\n // See how the state changed\n const started = !prev.active && next.active;\n const stopped = prev.active && !next.active;\n // TODO: Currently also true for cases in which an update isn't needed so selected list item index updates still\n // cause the view to update. May need to be more strict.\n const changed = prev.active && next.active;\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.suggestionsMenuState!.show = false;\n this.updateSuggestionsMenu();\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.suggestionsMenuState = {\n show: true,\n referencePos: decorationNode!.getBoundingClientRect(),\n filteredItems: this.pluginState.items,\n keyboardHoveredItemIndex: this.pluginState.keyboardHoveredItemIndex!,\n };\n\n this.updateSuggestionsMenu();\n }\n }\n\n destroy() {\n document.removeEventListener(\"scroll\", this.handleScroll);\n }\n}\n\ntype SuggestionPluginState<T extends SuggestionItem> = {\n // True when the menu is shown, false when hidden.\n active: boolean;\n // The character that triggered the menu being shown. Allowing the trigger to be different to the default\n // trigger allows other extensions to open it programmatically.\n triggerCharacter: string | undefined;\n // The editor position just after the trigger character, i.e. where the user query begins. Used to figure out\n // which menu items to show and can also be used to delete the trigger character.\n queryStartPos: number | undefined;\n // The items that should be shown in the menu.\n items: T[];\n // The index of the item in the menu that's currently hovered using the keyboard.\n keyboardHoveredItemIndex: number | undefined;\n // The number of characters typed after the last query that matched with at least 1 item. Used to close the\n // menu if the user keeps entering queries that don't return any results.\n notFoundCount: number | undefined;\n decorationId: string | undefined;\n};\n\nfunction getDefaultPluginState<\n T extends SuggestionItem\n>(): SuggestionPluginState<T> {\n return {\n active: false,\n triggerCharacter: undefined,\n queryStartPos: undefined,\n items: [] as T[],\n keyboardHoveredItemIndex: undefined,\n notFoundCount: 0,\n decorationId: undefined,\n };\n}\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 const setupSuggestionsMenu = <\n T extends SuggestionItem,\n BSchema extends BlockSchema\n>(\n editor: BlockNoteEditor<BSchema>,\n updateSuggestionsMenu: (\n suggestionsMenuState: SuggestionsMenuState<T>\n ) => void,\n\n pluginKey: PluginKey,\n defaultTriggerCharacter: string,\n items: (query: string) => T[] = () => [],\n onSelectItem: (props: {\n item: T;\n editor: BlockNoteEditor<BSchema>;\n }) => void = () => {}\n) => {\n // Assertions\n if (defaultTriggerCharacter.length !== 1) {\n throw new Error(\"'char' should be a single character\");\n }\n\n let suggestionsPluginView: SuggestionsMenuView<T, BSchema>;\n\n const deactivate = (view: EditorView) => {\n view.dispatch(view.state.tr.setMeta(pluginKey, { deactivate: true }));\n };\n\n return {\n plugin: new Plugin({\n key: pluginKey,\n\n view: () => {\n suggestionsPluginView = new SuggestionsMenuView<T, BSchema>(\n editor,\n pluginKey,\n\n updateSuggestionsMenu\n );\n return suggestionsPluginView;\n },\n\n state: {\n // Initialize the plugin's internal state.\n init(): SuggestionPluginState<T> {\n return getDefaultPluginState<T>();\n },\n\n // Apply changes to the plugin state from an editor transaction.\n apply(transaction, prev, oldState, newState): SuggestionPluginState<T> {\n // TODO: More clearly define which transactions should be ignored.\n if (transaction.getMeta(\"orderedListIndexing\") !== undefined) {\n return prev;\n }\n\n // Checks if the menu should be shown.\n if (transaction.getMeta(pluginKey)?.activate) {\n return {\n active: true,\n triggerCharacter:\n transaction.getMeta(pluginKey)?.triggerCharacter || \"\",\n queryStartPos: newState.selection.from,\n items: items(\"\"),\n keyboardHoveredItemIndex: 0,\n // TODO: Maybe should be 1 if the menu has no possible items? Probably redundant since a menu with no items\n // is useless in practice.\n notFoundCount: 0,\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.active) {\n return prev;\n }\n\n const next = { ...prev };\n\n // Updates which menu items to show by checking which items the current query (the text between the trigger\n // character and caret) matches with.\n next.items = items(\n newState.doc.textBetween(\n prev.queryStartPos!,\n newState.selection.from\n )\n );\n\n // Updates notFoundCount if the query doesn't match any items.\n next.notFoundCount = 0;\n if (next.items.length === 0) {\n // Checks how many characters were typed or deleted since the last transaction, and updates the notFoundCount\n // accordingly. Also ensures the notFoundCount does not become negative.\n next.notFoundCount = Math.max(\n 0,\n prev.notFoundCount! +\n (newState.selection.from - oldState.selection.from)\n );\n }\n\n // Hides the menu. This is done after items and notFoundCount are already updated as notFoundCount is needed to\n // check 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 {deactivate: true} should hide the menu.\n transaction.getMeta(pluginKey)?.deactivate ||\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.active && newState.selection.from < prev.queryStartPos!) ||\n // Entering more than 3 characters, after the last query that matched with at least 1 menu item, should hide\n // the menu.\n next.notFoundCount > 3\n ) {\n return getDefaultPluginState<T>();\n }\n\n // Updates keyboardHoveredItemIndex if the up or down arrow key was\n // pressed, or resets it if the keyboard cursor moved.\n if (\n transaction.getMeta(pluginKey)?.selectedItemIndexChanged !==\n undefined\n ) {\n let newIndex =\n transaction.getMeta(pluginKey).selectedItemIndexChanged;\n\n // Allows selection to jump between first and last items.\n if (newIndex < 0) {\n newIndex = prev.items.length - 1;\n } else if (newIndex >= prev.items.length) {\n newIndex = 0;\n }\n\n next.keyboardHoveredItemIndex = newIndex;\n } else if (oldState.selection.from !== newState.selection.from) {\n next.keyboardHoveredItemIndex = 0;\n }\n\n return next;\n },\n },\n\n props: {\n handleKeyDown(view, event) {\n const menuIsActive = (this as Plugin).getState(view.state).active;\n\n // Shows the menu if the default trigger character was pressed and the menu isn't active.\n if (event.key === defaultTriggerCharacter && !menuIsActive) {\n view.dispatch(\n view.state.tr\n .insertText(defaultTriggerCharacter)\n .scrollIntoView()\n .setMeta(pluginKey, {\n activate: true,\n triggerCharacter: defaultTriggerCharacter,\n })\n );\n\n return true;\n }\n\n // Doesn't handle other keystrokes if the menu isn't active.\n if (!menuIsActive) {\n return false;\n }\n\n // Handles keystrokes for navigating the menu.\n const {\n triggerCharacter,\n queryStartPos,\n items,\n keyboardHoveredItemIndex,\n } = pluginKey.getState(view.state);\n\n // Moves the keyboard selection to the previous item.\n if (event.key === \"ArrowUp\") {\n view.dispatch(\n view.state.tr.setMeta(pluginKey, {\n selectedItemIndexChanged: keyboardHoveredItemIndex - 1,\n })\n );\n return true;\n }\n\n // Moves the keyboard selection to the next item.\n if (event.key === \"ArrowDown\") {\n view.dispatch(\n view.state.tr.setMeta(pluginKey, {\n selectedItemIndexChanged: keyboardHoveredItemIndex + 1,\n })\n );\n return true;\n }\n\n // Selects an item and closes the menu.\n if (event.key === \"Enter\") {\n deactivate(view);\n editor._tiptapEditor\n .chain()\n .focus()\n .deleteRange({\n from: queryStartPos! - triggerCharacter!.length,\n to: editor._tiptapEditor.state.selection.from,\n })\n .run();\n\n onSelectItem({\n item: items[keyboardHoveredItemIndex],\n editor: editor,\n });\n\n return true;\n }\n\n // Closes the menu.\n if (event.key === \"Escape\") {\n deactivate(view);\n return true;\n }\n\n return false;\n },\n\n // Setup decorator on the currently active suggestion.\n decorations(state) {\n const { active, decorationId, queryStartPos, triggerCharacter } = (\n this as Plugin\n ).getState(state);\n\n if (!active) {\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 (triggerCharacter === \"\") {\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: \"suggestion-decorator\",\n \"data-decoration-id\": 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 queryStartPos - triggerCharacter.length,\n queryStartPos,\n {\n nodeName: \"span\",\n class: \"suggestion-decorator\",\n \"data-decoration-id\": decorationId,\n }\n ),\n ]);\n },\n },\n }),\n itemCallback: (item: T) => {\n deactivate(editor._tiptapEditor.view);\n editor._tiptapEditor\n .chain()\n .focus()\n .deleteRange({\n from:\n suggestionsPluginView.pluginState.queryStartPos! -\n suggestionsPluginView.pluginState.triggerCharacter!.length,\n to: editor._tiptapEditor.state.selection.from,\n })\n .run();\n\n onSelectItem({\n item: item,\n editor: editor,\n });\n },\n };\n};\n","import { Plugin, PluginKey } from \"prosemirror-state\";\n\nimport { BlockNoteEditor } from \"../../BlockNoteEditor\";\nimport { EventEmitter } from \"../../shared/EventEmitter\";\nimport {\n SuggestionsMenuState,\n setupSuggestionsMenu,\n} from \"../../shared/plugins/suggestion/SuggestionPlugin\";\nimport { BlockSchema } from \"../Blocks/api/blockTypes\";\nimport { BaseSlashMenuItem } from \"./BaseSlashMenuItem\";\n\nexport const slashMenuPluginKey = new PluginKey(\"SlashMenuPlugin\");\n\nexport class SlashMenuProsemirrorPlugin<\n BSchema extends BlockSchema,\n SlashMenuItem extends BaseSlashMenuItem<BSchema>\n> extends EventEmitter<any> {\n public readonly plugin: Plugin;\n public readonly itemCallback: (item: SlashMenuItem) => void;\n\n constructor(editor: BlockNoteEditor<BSchema>, items: SlashMenuItem[]) {\n super();\n const suggestions = setupSuggestionsMenu<SlashMenuItem, BSchema>(\n editor,\n (state) => {\n this.emit(\"update\", state);\n },\n slashMenuPluginKey,\n \"/\",\n (query) =>\n items.filter(\n ({ name, aliases }: SlashMenuItem) =>\n name.toLowerCase().startsWith(query.toLowerCase()) ||\n (aliases &&\n aliases.filter((alias) =>\n alias.toLowerCase().startsWith(query.toLowerCase())\n ).length !== 0)\n ),\n ({ item, editor }) => item.execute(editor)\n );\n\n this.plugin = suggestions.plugin;\n this.itemCallback = suggestions.itemCallback;\n }\n\n public onUpdate(\n callback: (state: SuggestionsMenuState<SlashMenuItem>) => void\n ) {\n return this.on(\"update\", callback);\n }\n}\n","import { Editor, Extension } from \"@tiptap/core\";\nimport { Node as ProsemirrorNode } from \"prosemirror-model\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet } from \"prosemirror-view\";\nimport { slashMenuPluginKey } from \"../SlashMenu/SlashMenuPlugin\";\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 emptyEditorClass: string;\n emptyNodeClass: string;\n isFilterClass: string;\n hasAnchorClass: string;\n placeholder:\n | ((PlaceholderProps: {\n editor: Editor;\n node: ProsemirrorNode;\n pos: number;\n hasAnchor: boolean;\n }) => string)\n | string;\n showOnlyWhenEditable: boolean;\n showOnlyCurrent: boolean;\n includeChildren: boolean;\n}\n\nexport const Placeholder = Extension.create<PlaceholderOptions>({\n name: \"placeholder\",\n\n addOptions() {\n return {\n emptyEditorClass: \"is-editor-empty\",\n emptyNodeClass: \"is-empty\",\n isFilterClass: \"is-filter\",\n hasAnchorClass: \"has-anchor\",\n placeholder: \"Write something …\",\n showOnlyWhenEditable: true,\n showOnlyCurrent: true,\n includeChildren: false,\n };\n },\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: PLUGIN_KEY,\n props: {\n decorations: (state) => {\n const { doc, selection } = state;\n // Get state of slash menu\n const menuState = slashMenuPluginKey.getState(state);\n const active =\n this.editor.isEditable || !this.options.showOnlyWhenEditable;\n const { anchor } = selection;\n const decorations: Decoration[] = [];\n\n if (!active) {\n return;\n }\n\n doc.descendants((node, pos) => {\n const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize;\n const isEmpty = !node.isLeaf && !node.childCount;\n\n if ((hasAnchor || !this.options.showOnlyCurrent) && isEmpty) {\n const classes = [this.options.emptyNodeClass];\n\n // TODO: Doesn't work?\n if (this.editor.isEmpty) {\n classes.push(this.options.emptyEditorClass);\n }\n\n if (hasAnchor) {\n classes.push(this.options.hasAnchorClass);\n }\n\n // If slash menu is of drag type and active, show the filter placeholder\n if (menuState?.triggerCharacter === \"\" && menuState?.active) {\n classes.push(this.options.isFilterClass);\n }\n // using widget, didn't work (caret position bug)\n // const decoration = Decoration.widget(\n // pos + 1,\n // () => {\n // const el = document.createElement(\"span\");\n // el.innerText = \"hello\";\n // return el;\n // },\n // { side: 0 }\n\n // Code that sets variables / classes\n // const ph =\n // typeof this.options.placeholder === \"function\"\n // ? this.options.placeholder({\n // editor: this.editor,\n // node,\n // pos,\n // hasAnchor,\n // })\n // : this.options.placeholder;\n // const decoration = Decoration.node(pos, pos + node.nodeSize, {\n // class: classes.join(\" \"),\n // style: `--placeholder:'${ph.replaceAll(\"'\", \"\\\\'\")}';`,\n // \"data-placeholder\": ph,\n // });\n\n // Latest version, only set isEmpty and hasAnchor, rest is done via CSS\n\n const decoration = Decoration.node(pos, pos + node.nodeSize, {\n class: classes.join(\" \"),\n });\n decorations.push(decoration);\n }\n\n return this.options.includeChildren;\n });\n\n return DecorationSet.create(doc, decorations);\n },\n },\n }),\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { getBlockInfoFromPos } from \"../Blocks/helpers/getBlockInfoFromPos\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n textAlignment: {\n setTextAlignment: (\n textAlignment: \"left\" | \"center\" | \"right\" | \"justify\"\n ) => ReturnType;\n };\n }\n}\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) => element.getAttribute(\"data-text-alignment\"),\n renderHTML: (attributes) =>\n attributes.textAlignment !== \"left\" && {\n \"data-text-alignment\": attributes.textAlignment,\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setTextAlignment:\n (textAlignment) =>\n ({ state }) => {\n const positionsBeforeSelectedContent = [];\n\n const blockInfo = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n );\n if (blockInfo === undefined) {\n return false;\n }\n\n // Finds all blockContent nodes that the current selection is in.\n let pos = blockInfo.startPos;\n while (pos < state.selection.to) {\n if (\n state.doc.resolve(pos).node().type.spec.group === \"blockContent\"\n ) {\n positionsBeforeSelectedContent.push(pos - 1);\n\n pos += state.doc.resolve(pos).node().nodeSize - 1;\n } else {\n pos += 1;\n }\n }\n\n // Sets text alignment for all blockContent nodes that the current selection is in.\n for (const pos of positionsBeforeSelectedContent) {\n state.tr.setNodeAttribute(pos, \"textAlignment\", textAlignment);\n }\n\n return true;\n },\n };\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { getBlockInfoFromPos } from \"../Blocks/helpers/getBlockInfoFromPos\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n blockTextColor: {\n setBlockTextColor: (posInBlock: number, color: string) => ReturnType;\n };\n }\n}\n\nexport const TextColorExtension = Extension.create({\n name: \"blockTextColor\",\n\n addGlobalAttributes() {\n return [\n {\n types: [\"blockContainer\"],\n attributes: {\n textColor: {\n default: \"default\",\n parseHTML: (element) =>\n element.hasAttribute(\"data-text-color\")\n ? element.getAttribute(\"data-text-color\")\n : \"default\",\n renderHTML: (attributes) =>\n attributes.textColor !== \"default\" && {\n \"data-text-color\": attributes.textColor,\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setBlockTextColor:\n (posInBlock, color) =>\n ({ state, view }) => {\n const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);\n if (blockInfo === undefined) {\n return false;\n }\n\n state.tr.setNodeAttribute(blockInfo.startPos - 1, \"textColor\", color);\n\n view.focus();\n\n return true;\n },\n };\n },\n});\n","import { Mark } from \"@tiptap/core\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n textColor: {\n setTextColor: (color: string) => ReturnType;\n };\n }\n}\n\nexport const TextColorMark = Mark.create({\n name: \"textColor\",\n\n addAttributes() {\n return {\n color: {\n default: undefined,\n parseHTML: (element) => element.getAttribute(\"data-text-color\"),\n renderHTML: (attributes) => ({\n \"data-text-color\": attributes.color,\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 { color: 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 addCommands() {\n return {\n setTextColor:\n (color) =>\n ({ commands }) => {\n if (color !== \"default\") {\n return commands.setMark(this.name, { color: color });\n }\n\n return commands.unsetMark(this.name);\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 return lastNode.nodeSize > 4; // empty <block><content/></block> is length 4\n },\n },\n }),\n ];\n },\n});\n","import { Extensions, extensions } from \"@tiptap/core\";\n\nimport { BlockNoteEditor } from \"./BlockNoteEditor\";\n\nimport { Bold } from \"@tiptap/extension-bold\";\nimport { Code } from \"@tiptap/extension-code\";\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 { Italic } from \"@tiptap/extension-italic\";\nimport { Link } from \"@tiptap/extension-link\";\nimport { Strike } from \"@tiptap/extension-strike\";\nimport { Text } from \"@tiptap/extension-text\";\nimport { Underline } from \"@tiptap/extension-underline\";\nimport * as Y from \"yjs\";\nimport styles from \"./editor.module.css\";\nimport { BackgroundColorExtension } from \"./extensions/BackgroundColor/BackgroundColorExtension\";\nimport { BackgroundColorMark } from \"./extensions/BackgroundColor/BackgroundColorMark\";\nimport { blocks } from \"./extensions/Blocks\";\nimport { BlockSchema } from \"./extensions/Blocks/api/blockTypes\";\nimport { CustomBlockSerializerExtension } from \"./extensions/Blocks/api/serialization\";\nimport blockStyles from \"./extensions/Blocks/nodes/Block.module.css\";\nimport { Placeholder } from \"./extensions/Placeholder/PlaceholderExtension\";\nimport { TextAlignmentExtension } from \"./extensions/TextAlignment/TextAlignmentExtension\";\nimport { TextColorExtension } from \"./extensions/TextColor/TextColorExtension\";\nimport { TextColorMark } from \"./extensions/TextColor/TextColorMark\";\nimport { TrailingNode } from \"./extensions/TrailingNode/TrailingNodeExtension\";\nimport UniqueID from \"./extensions/UniqueID/UniqueID\";\n\n/**\n * Get all the Tiptap extensions BlockNote is configured with by default\n */\nexport const getBlockNoteExtensions = <BSchema extends BlockSchema>(opts: {\n editor: BlockNoteEditor<BSchema>;\n blockSchema: BSchema;\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 emptyNodeClass: blockStyles.isEmpty,\n hasAnchorClass: blockStyles.hasAnchor,\n isFilterClass: blockStyles.isFilter,\n includeChildren: true,\n showOnlyCurrent: false,\n }),\n UniqueID.configure({\n types: [\"blockContainer\"],\n }),\n HardBreak,\n // Comments,\n\n // basics:\n Text,\n\n // marks:\n Bold,\n Code,\n Italic,\n Strike,\n Underline,\n Link,\n TextColorMark,\n TextColorExtension,\n BackgroundColorMark,\n BackgroundColorExtension,\n TextAlignmentExtension,\n\n // custom blocks:\n ...blocks,\n ...Object.values(opts.blockSchema).map((blockSpec) =>\n blockSpec.node.configure({ editor: opts.editor })\n ),\n CustomBlockSerializerExtension,\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 const defaultRender = (user: { color: string; name: string }) => {\n const cursor = document.createElement(\"span\");\n\n cursor.classList.add(styles[\"collaboration-cursor__caret\"]);\n cursor.setAttribute(\"style\", `border-color: ${user.color}`);\n\n const label = document.createElement(\"span\");\n\n label.classList.add(styles[\"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 } 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 { 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 { Editor } from \"@tiptap/core\";\nimport { Node } from \"prosemirror-model\";\nimport {\n BlockIdentifier,\n BlockSchema,\n PartialBlock,\n} from \"../../extensions/Blocks/api/blockTypes\";\nimport { blockToNode } from \"../nodeConversions/nodeConversions\";\nimport { getNodeById } from \"../util/nodeUtil\";\n\nexport function insertBlocks<BSchema extends BlockSchema>(\n blocksToInsert: PartialBlock<BSchema>[],\n referenceBlock: BlockIdentifier,\n placement: \"before\" | \"after\" | \"nested\" = \"before\",\n editor: Editor\n): void {\n const id =\n typeof referenceBlock === \"string\" ? referenceBlock : referenceBlock.id;\n\n const nodesToInsert: Node[] = [];\n for (const blockSpec of blocksToInsert) {\n nodesToInsert.push(blockToNode(blockSpec, editor.schema));\n }\n\n let insertionPos = -1;\n\n const { node, posBeforeNode } = getNodeById(id, editor.state.doc);\n\n if (placement === \"before\") {\n insertionPos = posBeforeNode;\n }\n\n if (placement === \"after\") {\n insertionPos = posBeforeNode + node.nodeSize;\n }\n\n if (placement === \"nested\") {\n // Case if block doesn't already have children.\n if (node.childCount < 2) {\n insertionPos = posBeforeNode + node.firstChild!.nodeSize + 1;\n\n const blockGroupNode = editor.state.schema.nodes[\"blockGroup\"].create(\n {},\n nodesToInsert\n );\n\n editor.view.dispatch(\n editor.state.tr.insert(insertionPos, blockGroupNode)\n );\n\n return;\n }\n\n insertionPos = posBeforeNode + node.firstChild!.nodeSize + 2;\n }\n\n editor.view.dispatch(editor.state.tr.insert(insertionPos, nodesToInsert));\n}\n\nexport function updateBlock<BSchema extends BlockSchema>(\n blockToUpdate: BlockIdentifier,\n update: PartialBlock<BSchema>,\n editor: Editor\n) {\n const id =\n typeof blockToUpdate === \"string\" ? blockToUpdate : blockToUpdate.id;\n const { posBeforeNode } = getNodeById(id, editor.state.doc);\n\n editor.commands.BNUpdateBlock(posBeforeNode + 1, update);\n}\n\nexport function removeBlocks(\n blocksToRemove: BlockIdentifier[],\n editor: Editor\n) {\n const idsOfBlocksToRemove = new Set<string>(\n blocksToRemove.map((block) =>\n typeof block === \"string\" ? block : block.id\n )\n );\n\n let removedSize = 0;\n\n editor.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 idsOfBlocksToRemove.delete(node.attrs.id);\n const oldDocSize = editor.state.doc.nodeSize;\n\n editor.commands.BNDeleteBlock(pos - removedSize + 1);\n\n const newDocSize = editor.state.doc.nodeSize;\n removedSize += oldDocSize - newDocSize;\n\n return false;\n });\n\n if (idsOfBlocksToRemove.size > 0) {\n let 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\nexport function replaceBlocks<BSchema extends BlockSchema>(\n blocksToRemove: BlockIdentifier[],\n blocksToInsert: PartialBlock<BSchema>[],\n editor: Editor\n) {\n insertBlocks(blocksToInsert, blocksToRemove[0], \"before\", editor);\n removeBlocks(blocksToRemove, editor);\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 { 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 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 { DOMParser, DOMSerializer, Schema } from \"prosemirror-model\";\nimport rehypeParse from \"rehype-parse\";\nimport rehypeRemark from \"rehype-remark\";\nimport rehypeStringify from \"rehype-stringify\";\nimport remarkGfm from \"remark-gfm\";\nimport remarkParse from \"remark-parse\";\nimport remarkRehype from \"remark-rehype\";\nimport remarkStringify from \"remark-stringify\";\nimport { unified } from \"unified\";\nimport { Block, BlockSchema } from \"../../extensions/Blocks/api/blockTypes\";\n\nimport { blockToNode, nodeToBlock } from \"../nodeConversions/nodeConversions\";\nimport { removeUnderlines } from \"./removeUnderlinesRehypePlugin\";\nimport { simplifyBlocks } from \"./simplifyBlocksRehypePlugin\";\n\nexport async function blocksToHTML<BSchema extends BlockSchema>(\n blocks: Block<BSchema>[],\n schema: Schema\n): Promise<string> {\n const htmlParentElement = document.createElement(\"div\");\n const serializer = DOMSerializer.fromSchema(schema);\n\n for (const block of blocks) {\n const node = blockToNode(block, schema);\n const htmlNode = serializer.serializeNode(node);\n htmlParentElement.appendChild(htmlNode);\n }\n\n const htmlString = await 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 .process(htmlParentElement.innerHTML);\n\n return htmlString.value as string;\n}\n\nexport async function HTMLToBlocks<BSchema extends BlockSchema>(\n html: string,\n blockSchema: BSchema,\n schema: Schema\n): Promise<Block<BSchema>[]> {\n const htmlNode = document.createElement(\"div\");\n htmlNode.innerHTML = html.trim();\n\n const parser = DOMParser.fromSchema(schema);\n const parentNode = parser.parse(htmlNode);\n\n const blocks: Block<BSchema>[] = [];\n\n for (let i = 0; i < parentNode.firstChild!.childCount; i++) {\n blocks.push(nodeToBlock(parentNode.firstChild!.child(i), blockSchema));\n }\n\n return blocks;\n}\n\nexport async function blocksToMarkdown<BSchema extends BlockSchema>(\n blocks: Block<BSchema>[],\n schema: Schema\n): Promise<string> {\n const markdownString = await unified()\n .use(rehypeParse, { fragment: true })\n .use(removeUnderlines)\n .use(rehypeRemark)\n .use(remarkGfm)\n .use(remarkStringify)\n .process(await blocksToHTML(blocks, schema));\n\n return markdownString.value as string;\n}\n\nexport async function markdownToBlocks<BSchema extends BlockSchema>(\n markdown: string,\n blockSchema: BSchema,\n schema: Schema\n): Promise<Block<BSchema>[]> {\n const htmlString = await unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkRehype)\n .use(rehypeStringify)\n .process(markdown);\n\n return HTMLToBlocks(htmlString.value as string, blockSchema, schema);\n}\n","import { isNodeSelection, isTextSelection, posToDOMRect } from \"@tiptap/core\";\nimport { EditorState, Plugin, PluginKey } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\nimport {\n BaseUiElementCallbacks,\n BaseUiElementState,\n BlockNoteEditor,\n BlockSchema,\n} from \"../..\";\nimport { EventEmitter } from \"../../shared/EventEmitter\";\n\nexport type FormattingToolbarCallbacks = BaseUiElementCallbacks;\n\nexport type FormattingToolbarState = BaseUiElementState;\n\nexport class FormattingToolbarView<BSchema extends BlockSchema> {\n private formattingToolbarState?: FormattingToolbarState;\n public updateFormattingToolbar: () => 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 = ({ view, state, from, to }) => {\n const { doc, selection } = state;\n const { empty } = selection;\n\n // Sometime check for `empty` is not enough.\n // Doubleclick an empty paragraph returns a node size of 2.\n // So we check also for an empty text size.\n const isEmptyTextBlock =\n !doc.textBetween(from, to).length && isTextSelection(state.selection);\n\n return !(!view.hasFocus() || empty || isEmptyTextBlock);\n };\n\n constructor(\n private readonly editor: BlockNoteEditor<BSchema>,\n private readonly pmView: EditorView,\n updateFormattingToolbar: (\n formattingToolbarState: FormattingToolbarState\n ) => void\n ) {\n this.updateFormattingToolbar = () => {\n if (!this.formattingToolbarState) {\n throw new Error(\n \"Attempting to update uninitialized formatting toolbar\"\n );\n }\n\n updateFormattingToolbar(this.formattingToolbarState);\n };\n\n pmView.dom.addEventListener(\"mousedown\", this.viewMousedownHandler);\n pmView.dom.addEventListener(\"mouseup\", this.viewMouseupHandler);\n pmView.dom.addEventListener(\"dragstart\", this.dragstartHandler);\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 dragstartHandler = () => {\n if (this.formattingToolbarState?.show) {\n this.formattingToolbarState.show = false;\n this.updateFormattingToolbar();\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.formattingToolbarState?.show) {\n this.formattingToolbarState.show = false;\n this.updateFormattingToolbar();\n }\n };\n\n scrollHandler = () => {\n if (this.formattingToolbarState?.show) {\n this.formattingToolbarState.referencePos = this.getSelectionBoundingBox();\n this.updateFormattingToolbar();\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.formattingToolbarState = {\n show: true,\n referencePos: this.getSelectionBoundingBox(),\n };\n\n this.updateFormattingToolbar();\n\n return;\n }\n\n // Checks if menu should be hidden.\n if (\n this.formattingToolbarState?.show &&\n !this.preventHide &&\n (!shouldShow || this.preventShow || !this.editor.isEditable)\n ) {\n this.formattingToolbarState.show = false;\n this.updateFormattingToolbar();\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.dragstartHandler);\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<\n BSchema extends BlockSchema\n> extends EventEmitter<any> {\n private view: FormattingToolbarView<BSchema> | undefined;\n public readonly plugin: Plugin;\n\n constructor(editor: BlockNoteEditor<BSchema>) {\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\";\nimport { BlockNoteEditor } from \"../../BlockNoteEditor\";\nimport { BaseUiElementState } from \"../../shared/BaseUiElementTypes\";\nimport { EventEmitter } from \"../../shared/EventEmitter\";\nimport { BlockSchema } from \"../Blocks/api/blockTypes\";\n\nexport type HyperlinkToolbarState = BaseUiElementState & {\n // The hovered hyperlink's URL, and the text it's displayed with in the\n // editor.\n url: string;\n text: string;\n};\n\nclass HyperlinkToolbarView<BSchema extends BlockSchema> {\n private hyperlinkToolbarState?: HyperlinkToolbarState;\n public updateHyperlinkToolbar: () => void;\n\n menuUpdateTimer: NodeJS.Timeout | undefined;\n startMenuUpdateTimer: () => void;\n stopMenuUpdateTimer: () => void;\n\n mouseHoveredHyperlinkMark: Mark | undefined;\n mouseHoveredHyperlinkMarkRange: Range | undefined;\n\n keyboardHoveredHyperlinkMark: Mark | undefined;\n keyboardHoveredHyperlinkMarkRange: Range | undefined;\n\n hyperlinkMark: Mark | undefined;\n hyperlinkMarkRange: Range | undefined;\n\n constructor(\n private readonly editor: BlockNoteEditor<BSchema>,\n private readonly pmView: EditorView,\n updateHyperlinkToolbar: (\n hyperlinkToolbarState: HyperlinkToolbarState\n ) => void\n ) {\n this.updateHyperlinkToolbar = () => {\n if (!this.hyperlinkToolbarState) {\n throw new Error(\"Attempting to update uninitialized hyperlink toolbar\");\n }\n\n updateHyperlinkToolbar(this.hyperlinkToolbarState);\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 hyperlink mark currently hovered by the mouse cursor.\n this.mouseHoveredHyperlinkMark = undefined;\n this.mouseHoveredHyperlinkMarkRange = 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 mouseHoveredHyperlinkMark and\n // mouseHoveredHyperlinkMarkRange.\n const hoveredHyperlinkElement = event.target;\n const posInHoveredHyperlinkMark =\n this.pmView.posAtDOM(hoveredHyperlinkElement, 0) + 1;\n const resolvedPosInHoveredHyperlinkMark = this.pmView.state.doc.resolve(\n posInHoveredHyperlinkMark\n );\n const marksAtPos = resolvedPosInHoveredHyperlinkMark.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.mouseHoveredHyperlinkMark = mark;\n this.mouseHoveredHyperlinkMarkRange =\n getMarkRange(\n resolvedPosInHoveredHyperlinkMark,\n mark.type,\n 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.hyperlinkMark &&\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.hyperlinkToolbarState?.show) {\n this.hyperlinkToolbarState.show = false;\n this.updateHyperlinkToolbar();\n }\n }\n };\n\n scrollHandler = () => {\n if (this.hyperlinkMark !== undefined) {\n if (this.hyperlinkToolbarState?.show) {\n this.hyperlinkToolbarState.referencePos = posToDOMRect(\n this.pmView,\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.to\n );\n this.updateHyperlinkToolbar();\n }\n }\n };\n\n editHyperlink(url: string, text: string) {\n const tr = this.pmView.state.tr.insertText(\n text,\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.to\n );\n tr.addMark(\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.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.hyperlinkToolbarState?.show) {\n this.hyperlinkToolbarState.show = false;\n this.updateHyperlinkToolbar();\n }\n }\n\n deleteHyperlink() {\n this.pmView.dispatch(\n this.pmView.state.tr\n .removeMark(\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.to,\n this.hyperlinkMark!.type\n )\n .setMeta(\"preventAutolink\", true)\n );\n this.pmView.focus();\n\n if (this.hyperlinkToolbarState?.show) {\n this.hyperlinkToolbarState.show = false;\n this.updateHyperlinkToolbar();\n }\n }\n\n update() {\n if (!this.pmView.hasFocus()) {\n return;\n }\n\n // Saves the currently hovered hyperlink mark before it's updated.\n const prevHyperlinkMark = this.hyperlinkMark;\n\n // Resets the currently hovered hyperlink mark.\n this.hyperlinkMark = undefined;\n this.hyperlinkMarkRange = undefined;\n\n // Resets the hyperlink mark currently hovered by the keyboard cursor.\n this.keyboardHoveredHyperlinkMark = undefined;\n this.keyboardHoveredHyperlinkMarkRange = undefined;\n\n // Finds link mark at the editor selection's position to update keyboardHoveredHyperlinkMark and\n // keyboardHoveredHyperlinkMarkRange.\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.keyboardHoveredHyperlinkMark = mark;\n this.keyboardHoveredHyperlinkMarkRange =\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.mouseHoveredHyperlinkMark) {\n this.hyperlinkMark = this.mouseHoveredHyperlinkMark;\n this.hyperlinkMarkRange = this.mouseHoveredHyperlinkMarkRange;\n }\n\n // Keyboard cursor position takes precedence over mouse hovered hyperlink.\n if (this.keyboardHoveredHyperlinkMark) {\n this.hyperlinkMark = this.keyboardHoveredHyperlinkMark;\n this.hyperlinkMarkRange = this.keyboardHoveredHyperlinkMarkRange;\n }\n\n if (this.hyperlinkMark && this.editor.isEditable) {\n this.hyperlinkToolbarState = {\n show: true,\n referencePos: posToDOMRect(\n this.pmView,\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.to\n ),\n url: this.hyperlinkMark!.attrs.href,\n text: this.pmView.state.doc.textBetween(\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.to\n ),\n };\n this.updateHyperlinkToolbar();\n\n return;\n }\n\n // Hides menu.\n if (\n this.hyperlinkToolbarState?.show &&\n prevHyperlinkMark &&\n (!this.hyperlinkMark || !this.editor.isEditable)\n ) {\n this.hyperlinkToolbarState.show = false;\n this.updateHyperlinkToolbar();\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 hyperlinkToolbarPluginKey = new PluginKey(\n \"HyperlinkToolbarPlugin\"\n);\n\nexport class HyperlinkToolbarProsemirrorPlugin<\n BSchema extends BlockSchema\n> extends EventEmitter<any> {\n private view: HyperlinkToolbarView<BSchema> | undefined;\n public readonly plugin: Plugin;\n\n constructor(editor: BlockNoteEditor<BSchema>) {\n super();\n this.plugin = new Plugin({\n key: hyperlinkToolbarPluginKey,\n view: (editorView) => {\n this.view = new HyperlinkToolbarView(editor, editorView, (state) => {\n this.emit(\"update\", state);\n });\n return this.view;\n },\n });\n }\n\n public onUpdate(callback: (state: HyperlinkToolbarState) => void) {\n return this.on(\"update\", callback);\n }\n\n /**\n * Edit the currently hovered hyperlink.\n */\n public editHyperlink = (url: string, text: string) => {\n this.view!.editHyperlink(url, text);\n };\n\n /**\n * Delete the currently hovered hyperlink.\n */\n public deleteHyperlink = () => {\n this.view!.deleteHyperlink();\n };\n\n /**\n * When hovering on/off hyperlinks using the mouse cursor, the hyperlink\n * toolbar will open & close with a delay.\n *\n * This function starts the delay timer, and should be used for when the mouse cursor enters the hyperlink toolbar.\n */\n public startHideTimer = () => {\n this.view!.startMenuUpdateTimer();\n };\n\n /**\n * When hovering on/off hyperlinks using the mouse cursor, the hyperlink\n * toolbar will open & close with a delay.\n *\n * This function stops the delay timer, and should be used for when the mouse cursor exits the hyperlink toolbar.\n */\n public stopHideTimer = () => {\n this.view!.stopMenuUpdateTimer();\n };\n}\n","import { Selection } from \"prosemirror-state\";\nimport { Fragment, Node, ResolvedPos, Slice } from \"prosemirror-model\";\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 let fromResult = mapping.mapResult(this.from);\n let 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 * as pv from \"prosemirror-view\";\nimport { EditorView } from \"prosemirror-view\";\nimport { BlockNoteEditor } from \"../../BlockNoteEditor\";\nimport styles from \"../../editor.module.css\";\nimport { BaseUiElementState } from \"../../shared/BaseUiElementTypes\";\nimport { EventEmitter } from \"../../shared/EventEmitter\";\nimport { Block, BlockSchema } from \"../Blocks/api/blockTypes\";\nimport { getBlockInfoFromPos } from \"../Blocks/helpers/getBlockInfoFromPos\";\nimport { slashMenuPluginKey } from \"../SlashMenu/SlashMenuPlugin\";\nimport { MultipleNodeSelection } from \"./MultipleNodeSelection\";\n\nconst serializeForClipboard = (pv as any).__serializeForClipboard;\n// code based on https://github.com/ueberdosis/tiptap/issues/323#issuecomment-506637799\n\nlet dragImageElement: Element | undefined;\n\nexport type SideMenuState<BSchema extends BlockSchema> = BaseUiElementState & {\n // The block that the side menu is attached to.\n block: Block<BSchema>;\n};\n\nfunction 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 let 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 let 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 let 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.includes(\"bn\") &&\n !className.includes(\"ProseMirror\") &&\n !className.includes(\"editor\")\n )\n .join(\" \");\n\n dragImageElement.className =\n dragImageElement.className +\n \" \" +\n styles.dragPreview +\n \" \" +\n 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 e: { dataTransfer: DataTransfer | null; clientY: number },\n view: EditorView\n) {\n if (!e.dataTransfer) {\n return;\n }\n\n const editorBoundingBox = view.dom.getBoundingClientRect();\n\n let coords = {\n left: editorBoundingBox.left + editorBoundingBox.width / 2, // take middle of editor\n top: e.clientY,\n };\n\n let 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 let slice = view.state.selection.content();\n let { dom, text } = serializeForClipboard(view, slice);\n\n e.dataTransfer.clearData();\n e.dataTransfer.setData(\"text/html\", dom.innerHTML);\n e.dataTransfer.setData(\"text/plain\", text);\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setDragImage(dragImageElement!, 0, 0);\n view.dragging = { slice, move: true };\n }\n}\n\nexport class SideMenuView<BSchema extends BlockSchema> implements PluginView {\n private sideMenuState?: SideMenuState<BSchema>;\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>,\n private readonly pmView: EditorView,\n private readonly updateSideMenu: (\n sideMenuState: SideMenuState<BSchema>\n ) => void\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 // 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 let 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 let 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.sideMenuState?.show) {\n this.sideMenuState.show = false;\n this.updateSideMenu(this.sideMenuState);\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.sideMenuState?.show) {\n this.sideMenuState.show = false;\n this.updateSideMenu(this.sideMenuState);\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.sideMenuState?.show) {\n this.sideMenuState.show = false;\n this.updateSideMenu(this.sideMenuState);\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.sideMenuState?.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.sideMenuState = {\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.updateSideMenu(this.sideMenuState);\n }\n };\n\n onScroll = () => {\n if (this.sideMenuState?.show) {\n const blockContent = this.hoveredBlock!.firstChild as HTMLElement;\n const blockContentBoundingBox = blockContent.getBoundingClientRect();\n\n this.sideMenuState.referencePos = new DOMRect(\n this.horizontalPosAnchoredAtRoot\n ? this.horizontalPosAnchor\n : blockContentBoundingBox.x,\n blockContentBoundingBox.y,\n blockContentBoundingBox.width,\n blockContentBoundingBox.height\n );\n this.updateSideMenu(this.sideMenuState);\n }\n };\n\n destroy() {\n if (this.sideMenuState?.show) {\n this.sideMenuState.show = false;\n this.updateSideMenu(this.sideMenuState);\n }\n document.body.removeEventListener(\"mousemove\", this.onMouseMove);\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(\"keydown\", this.onKeyDown, true);\n }\n\n addBlock() {\n if (this.sideMenuState?.show) {\n this.sideMenuState.show = false;\n this.updateSideMenu(this.sideMenuState);\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, endPos } = blockInfo;\n\n // Creates a new block if current one is not empty for the suggestion menu to open in.\n if (contentNode.textContent.length !== 0) {\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(endPos);\n }\n\n // Focuses and activates the suggestion menu.\n this.pmView.focus();\n this.pmView.dispatch(\n this.pmView.state.tr.scrollIntoView().setMeta(slashMenuPluginKey, {\n // TODO import suggestion plugin key\n activate: true,\n type: \"drag\",\n })\n );\n }\n}\n\nexport const sideMenuPluginKey = new PluginKey(\"SideMenuPlugin\");\n\nexport class SideMenuProsemirrorPlugin<\n BSchema extends BlockSchema\n> extends EventEmitter<any> {\n private sideMenuView: SideMenuView<BSchema> | undefined;\n public readonly plugin: Plugin;\n\n constructor(private readonly editor: BlockNoteEditor<BSchema>) {\n super();\n this.plugin = new Plugin({\n key: sideMenuPluginKey,\n view: (editorView) => {\n this.sideMenuView = new SideMenuView(\n editor,\n editorView,\n (sideMenuState) => {\n this.emit(\"update\", sideMenuState);\n }\n );\n return this.sideMenuView;\n },\n });\n }\n\n public onUpdate(callback: (state: SideMenuState<BSchema>) => 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.sideMenuView!.addBlock();\n\n /**\n * Handles drag & drop events for blocks.\n */\n blockDragStart = (event: {\n dataTransfer: DataTransfer | null;\n clientY: number;\n }) => {\n this.sideMenuView!.isDragging = true;\n dragStart(event, this.editor.prosemirrorView);\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.sideMenuView!.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.sideMenuView!.menuFrozen = false);\n}\n","import { BlockNoteEditor } from \"../../BlockNoteEditor\";\nimport { BlockSchema, PartialBlock } from \"../Blocks/api/blockTypes\";\nimport { BaseSlashMenuItem } from \"./BaseSlashMenuItem\";\nimport { defaultBlockSchema } from \"../Blocks/api/defaultBlocks\";\n\nfunction insertOrUpdateBlock<BSchema extends BlockSchema>(\n editor: BlockNoteEditor<BSchema>,\n block: PartialBlock<BSchema>\n) {\n const currentBlock = editor.getTextCursorPosition().block;\n\n if (\n (currentBlock.content.length === 1 &&\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(editor.getTextCursorPosition().nextBlock!);\n }\n}\n\nexport const getDefaultSlashMenuItems = <BSchema extends BlockSchema>(\n // This type casting is weird, but it's the best way of doing it, as it allows\n // the schema type to be automatically inferred if it is defined, or be\n // inferred as any if it is not defined. I don't think it's possible to make it\n // infer to DefaultBlockSchema if it is not defined.\n schema: BSchema = defaultBlockSchema as unknown as BSchema\n) => {\n const slashMenuItems: BaseSlashMenuItem<BSchema>[] = [];\n\n if (\"heading\" in schema && \"level\" in schema.heading.propSchema) {\n // Command for creating a level 1 heading\n if (schema.heading.propSchema.level.values?.includes(\"1\")) {\n slashMenuItems.push({\n name: \"Heading\",\n aliases: [\"h\", \"heading1\", \"h1\"],\n execute: (editor) =>\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: \"1\" },\n } as PartialBlock<BSchema>),\n });\n }\n\n // Command for creating a level 2 heading\n if (schema.heading.propSchema.level.values?.includes(\"2\")) {\n slashMenuItems.push({\n name: \"Heading 2\",\n aliases: [\"h2\", \"heading2\", \"subheading\"],\n execute: (editor) =>\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: \"2\" },\n } as PartialBlock<BSchema>),\n });\n }\n\n // Command for creating a level 3 heading\n if (schema.heading.propSchema.level.values?.includes(\"3\")) {\n slashMenuItems.push({\n name: \"Heading 3\",\n aliases: [\"h3\", \"heading3\", \"subheading\"],\n execute: (editor) =>\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: \"3\" },\n } as PartialBlock<BSchema>),\n });\n }\n }\n\n if (\"bulletListItem\" in schema) {\n slashMenuItems.push({\n name: \"Bullet List\",\n aliases: [\"ul\", \"list\", \"bulletlist\", \"bullet list\"],\n execute: (editor) =>\n insertOrUpdateBlock(editor, {\n type: \"bulletListItem\",\n } as PartialBlock<BSchema>),\n });\n }\n\n if (\"numberedListItem\" in schema) {\n slashMenuItems.push({\n name: \"Numbered List\",\n aliases: [\"li\", \"list\", \"numberedlist\", \"numbered list\"],\n execute: (editor) =>\n insertOrUpdateBlock(editor, {\n type: \"numberedListItem\",\n } as PartialBlock<BSchema>),\n });\n }\n\n if (\"paragraph\" in schema) {\n slashMenuItems.push({\n name: \"Paragraph\",\n aliases: [\"p\"],\n execute: (editor) =>\n insertOrUpdateBlock(editor, {\n type: \"paragraph\",\n } as PartialBlock<BSchema>),\n });\n }\n\n return slashMenuItems;\n};\n","import { Editor, EditorOptions, Extension } from \"@tiptap/core\";\nimport { Node } from \"prosemirror-model\";\n// import \"./blocknote.css\";\nimport { Editor as TiptapEditor } from \"@tiptap/core/dist/packages/core/src/Editor\";\nimport * as Y from \"yjs\";\nimport { getBlockNoteExtensions } from \"./BlockNoteExtensions\";\nimport {\n insertBlocks,\n removeBlocks,\n replaceBlocks,\n updateBlock,\n} from \"./api/blockManipulation/blockManipulation\";\nimport {\n HTMLToBlocks,\n blocksToHTML,\n blocksToMarkdown,\n markdownToBlocks,\n} from \"./api/formatConversions/formatConversions\";\nimport {\n blockToNode,\n nodeToBlock,\n} from \"./api/nodeConversions/nodeConversions\";\nimport { getNodeById } from \"./api/util/nodeUtil\";\nimport styles from \"./editor.module.css\";\nimport {\n Block,\n BlockIdentifier,\n BlockSchema,\n PartialBlock,\n} from \"./extensions/Blocks/api/blockTypes\";\nimport { TextCursorPosition } from \"./extensions/Blocks/api/cursorPositionTypes\";\nimport {\n DefaultBlockSchema,\n defaultBlockSchema,\n} from \"./extensions/Blocks/api/defaultBlocks\";\nimport {\n ColorStyle,\n Styles,\n ToggledStyle,\n} from \"./extensions/Blocks/api/inlineContentTypes\";\nimport { Selection } from \"./extensions/Blocks/api/selectionTypes\";\nimport { getBlockInfoFromPos } from \"./extensions/Blocks/helpers/getBlockInfoFromPos\";\n\nimport { FormattingToolbarProsemirrorPlugin } from \"./extensions/FormattingToolbar/FormattingToolbarPlugin\";\nimport { HyperlinkToolbarProsemirrorPlugin } from \"./extensions/HyperlinkToolbar/HyperlinkToolbarPlugin\";\nimport { SideMenuProsemirrorPlugin } from \"./extensions/SideMenu/SideMenuPlugin\";\nimport { BaseSlashMenuItem } from \"./extensions/SlashMenu/BaseSlashMenuItem\";\nimport { SlashMenuProsemirrorPlugin } from \"./extensions/SlashMenu/SlashMenuPlugin\";\nimport { getDefaultSlashMenuItems } from \"./extensions/SlashMenu/defaultSlashMenuItems\";\nimport { UniqueID } from \"./extensions/UniqueID/UniqueID\";\n\nexport type BlockNoteEditorOptions<BSchema extends BlockSchema> = {\n // TODO: Figure out if enableBlockNoteExtensions/disableHistoryExtension are needed and document them.\n enableBlockNoteExtensions: boolean;\n /**\n *\n * (couldn't fix any type, see https://github.com/TypeCellOS/BlockNote/pull/191#discussion_r1210708771)\n *\n * @default defaultSlashMenuItems from `./extensions/SlashMenu`\n */\n slashMenuItems: BaseSlashMenuItem<any>[];\n\n /**\n * The HTML element that should be used as the parent element for the editor.\n *\n * @default: undefined, the editor is not attached to the DOM\n */\n parentElement: HTMLElement;\n /**\n * An object containing attributes that should be added to the editor's HTML element.\n *\n * @example { class: \"my-editor-class\" }\n */\n editorDOMAttributes: Record<string, string>;\n /**\n * A callback function that runs when the editor is ready to be used.\n */\n onEditorReady: (editor: BlockNoteEditor<BSchema>) => void;\n /**\n * A callback function that runs whenever the editor's contents change.\n */\n onEditorContentChange: (editor: BlockNoteEditor<BSchema>) => void;\n /**\n * A callback function that runs whenever the text cursor position changes.\n */\n onTextCursorPositionChange: (editor: BlockNoteEditor<BSchema>) => void;\n /**\n * Locks the editor from being editable by the user if set to `false`.\n */\n editable: boolean;\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<BSchema>[];\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 * Whether to use the light or dark theme.\n *\n * @default \"light\"\n */\n theme: \"light\" | \"dark\";\n\n /**\n * A list of block types that should be available in the editor.\n */\n blockSchema: BSchema;\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: any;\n};\n\nconst blockNoteTipTapOptions = {\n enableInputRules: true,\n enablePasteRules: true,\n enableCoreExtensions: false,\n};\n\nexport class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {\n public readonly _tiptapEditor: TiptapEditor & { contentComponent: any };\n public blockCache = new WeakMap<Node, Block<BSchema>>();\n public readonly schema: BSchema;\n public ready = false;\n\n public readonly sideMenu: SideMenuProsemirrorPlugin<BSchema>;\n public readonly formattingToolbar: FormattingToolbarProsemirrorPlugin<BSchema>;\n public readonly slashMenu: SlashMenuProsemirrorPlugin<BSchema, any>;\n public readonly hyperlinkToolbar: HyperlinkToolbarProsemirrorPlugin<BSchema>;\n\n constructor(\n private readonly options: Partial<BlockNoteEditorOptions<BSchema>> = {}\n ) {\n // apply defaults\n const newOptions: Omit<typeof options, \"defaultStyles\" | \"blockSchema\"> & {\n defaultStyles: boolean;\n blockSchema: BSchema;\n } = {\n defaultStyles: true,\n // TODO: There's a lot of annoying typing stuff to deal with here. If\n // BSchema is specified, then options.blockSchema should also be required.\n // If BSchema is not specified, then options.blockSchema should also not\n // be defined. Unfortunately, trying to implement these constraints seems\n // to be a huge pain, hence the `as any` casts.\n blockSchema: options.blockSchema || (defaultBlockSchema as any),\n ...options,\n };\n\n this.sideMenu = new SideMenuProsemirrorPlugin(this);\n this.formattingToolbar = new FormattingToolbarProsemirrorPlugin(this);\n this.slashMenu = new SlashMenuProsemirrorPlugin(\n this,\n newOptions.slashMenuItems ||\n getDefaultSlashMenuItems(newOptions.blockSchema)\n );\n this.hyperlinkToolbar = new HyperlinkToolbarProsemirrorPlugin(this);\n\n const extensions = getBlockNoteExtensions<BSchema>({\n editor: this,\n blockSchema: newOptions.blockSchema,\n collaboration: newOptions.collaboration,\n });\n\n const blockNoteUIExtension = Extension.create({\n name: \"BlockNoteUIExtension\",\n\n addProseMirrorPlugins: () => {\n return [\n this.sideMenu.plugin,\n this.formattingToolbar.plugin,\n this.slashMenu.plugin,\n this.hyperlinkToolbar.plugin,\n ];\n },\n });\n extensions.push(blockNoteUIExtension);\n\n this.schema = newOptions.blockSchema;\n\n const initialContent = newOptions.initialContent || [\n {\n type: \"paragraph\",\n id: UniqueID.options.generateID(),\n },\n ];\n\n const tiptapOptions: EditorOptions = {\n ...blockNoteTipTapOptions,\n ...newOptions._tiptapOptions,\n onCreate: () => {\n newOptions.onEditorReady?.(this);\n this.ready = true;\n },\n onBeforeCreate(editor) {\n // we have to set the initial content here, because now we can use the editor schema\n // which has been created at this point\n const schema = editor.editor.schema;\n const ic = initialContent.map((block) => blockToNode(block, schema));\n\n const root = schema.node(\n \"doc\",\n undefined,\n schema.node(\"blockGroup\", undefined, ic)\n );\n // override the initialcontent\n editor.editor.options.content = root.toJSON();\n },\n onUpdate: () => {\n // This seems to be necessary due to a bug in TipTap:\n // https://github.com/ueberdosis/tiptap/issues/2583\n if (!this.ready) {\n return;\n }\n\n newOptions.onEditorContentChange?.(this);\n },\n onSelectionUpdate: () => {\n // This seems to be necessary due to a bug in TipTap:\n // https://github.com/ueberdosis/tiptap/issues/2583\n if (!this.ready) {\n return;\n }\n\n newOptions.onTextCursorPositionChange?.(this);\n },\n editable: options.editable === undefined ? true : options.editable,\n extensions:\n newOptions.enableBlockNoteExtensions === false\n ? newOptions._tiptapOptions?.extensions\n : [...(newOptions._tiptapOptions?.extensions || []), ...extensions],\n editorProps: {\n attributes: {\n \"data-theme\": options.theme || \"light\",\n ...(newOptions.editorDOMAttributes || {}),\n class: [\n styles.bnEditor,\n styles.bnRoot,\n newOptions.defaultStyles ? styles.defaultStyles : \"\",\n newOptions.editorDOMAttributes?.class || \"\",\n ].join(\" \"),\n },\n },\n };\n\n if (newOptions.parentElement) {\n tiptapOptions.element = newOptions.parentElement;\n }\n\n this._tiptapEditor = new Editor(tiptapOptions) as Editor & {\n contentComponent: any;\n };\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 * 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 topLevelBlocks(): Block<BSchema>[] {\n const blocks: Block<BSchema>[] = [];\n\n this._tiptapEditor.state.doc.firstChild!.descendants((node) => {\n blocks.push(nodeToBlock(node, this.schema, this.blockCache));\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> | undefined {\n const id =\n typeof blockIdentifier === \"string\"\n ? blockIdentifier\n : blockIdentifier.id;\n let newBlock: Block<BSchema> | 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(node, this.schema, this.blockCache);\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>) => boolean,\n reverse: boolean = false\n ): void {\n const blocks = this.topLevelBlocks.slice();\n\n if (reverse) {\n blocks.reverse();\n }\n\n function traverseBlockArray(blockArray: Block<BSchema>[]): 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<BSchema> {\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(node, this.schema, this.blockCache),\n prevBlock:\n prevNode === undefined\n ? undefined\n : nodeToBlock(prevNode, this.schema, this.blockCache),\n nextBlock:\n nextNode === undefined\n ? undefined\n : nodeToBlock(nextNode, this.schema, this.blockCache),\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 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 }\n\n /**\n * Gets a snapshot of the current selection.\n */\n public getSelection(): Selection<BSchema> | undefined {\n if (\n this._tiptapEditor.state.selection.from ===\n this._tiptapEditor.state.selection.to\n ) {\n return undefined;\n }\n\n const blocks: Block<BSchema>[] = [];\n\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,\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 this._tiptapEditor.setEditable(editable);\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>[],\n referenceBlock: BlockIdentifier,\n placement: \"before\" | \"after\" | \"nested\" = \"before\"\n ): void {\n insertBlocks(blocksToInsert, referenceBlock, placement, this._tiptapEditor);\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>\n ) {\n updateBlock(blockToUpdate, update, this._tiptapEditor);\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 removeBlocks(blocksToRemove, this._tiptapEditor);\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>[]\n ) {\n replaceBlocks(blocksToRemove, blocksToInsert, this._tiptapEditor);\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 = {};\n const marks = this._tiptapEditor.state.selection.$to.marks();\n\n const toggleStyles = new Set<ToggledStyle>([\n \"bold\",\n \"italic\",\n \"underline\",\n \"strike\",\n \"code\",\n ]);\n const colorStyles = new Set<ColorStyle>([\"textColor\", \"backgroundColor\"]);\n\n for (const mark of marks) {\n if (toggleStyles.has(mark.type.name as ToggledStyle)) {\n styles[mark.type.name as ToggledStyle] = true;\n } else if (colorStyles.has(mark.type.name as ColorStyle)) {\n styles[mark.type.name as ColorStyle] = mark.attrs.color;\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) {\n const toggleStyles = new Set<ToggledStyle>([\n \"bold\",\n \"italic\",\n \"underline\",\n \"strike\",\n \"code\",\n ]);\n const colorStyles = new Set<ColorStyle>([\"textColor\", \"backgroundColor\"]);\n\n this._tiptapEditor.view.focus();\n\n for (const [style, value] of Object.entries(styles)) {\n if (toggleStyles.has(style as ToggledStyle)) {\n this._tiptapEditor.commands.setMark(style);\n } else if (colorStyles.has(style as ColorStyle)) {\n this._tiptapEditor.commands.setMark(style, { color: value });\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) {\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) {\n const toggleStyles = new Set<ToggledStyle>([\n \"bold\",\n \"italic\",\n \"underline\",\n \"strike\",\n \"code\",\n ]);\n const colorStyles = new Set<ColorStyle>([\"textColor\", \"backgroundColor\"]);\n\n this._tiptapEditor.view.focus();\n\n for (const [style, value] of Object.entries(styles)) {\n if (toggleStyles.has(style as ToggledStyle)) {\n this._tiptapEditor.commands.toggleMark(style);\n } else if (colorStyles.has(style as ColorStyle)) {\n this._tiptapEditor.commands.toggleMark(style, { color: value });\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 let { 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 /**\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 blocksToHTML(blocks: Block<BSchema>[]): Promise<string> {\n return blocksToHTML(blocks, this._tiptapEditor.schema);\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 HTMLToBlocks(html: string): Promise<Block<BSchema>[]> {\n return HTMLToBlocks(html, this.schema, this._tiptapEditor.schema);\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 blocksToMarkdown(blocks: Block<BSchema>[]): Promise<string> {\n return blocksToMarkdown(blocks, this._tiptapEditor.schema);\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 markdownToBlocks(markdown: string): Promise<Block<BSchema>[]> {\n return markdownToBlocks(markdown, this.schema, this._tiptapEditor.schema);\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"],"names":["getBlockInfoFromPos","doc","posInBlock","$pos","maxDepth","node","depth","id","contentNode","contentType","numChildBlocks","startPos","endPos","BackgroundColorExtension","Extension","element","attributes","color","state","view","blockInfo","BackgroundColorMark","Mark","HTMLAttributes","commands","camelToDataKebab","str","propsToAttributes","blockConfig","tiptapAttributes","name","spec","parse","render","blockContent","attribute","value","contentDOM","createBlockSpec","createTipTapBlock","getPos","styles","editor","pos","blockIdentifier","block","rendered","config","Node","HeadingBlockContent","level","InputRule","chain","range","mergeAttributes","handleEnter","selectionEmpty","BulletListItemBlockContent","parent","PLUGIN_KEY","PluginKey","NumberedListIndexingPlugin","Plugin","_transactions","_oldState","newState","tr","modified","newIndex","isFirstBlockInDoc","prevBlockInfo","prevBlockContentNode","prevBlockIndex","NumberedListItemBlockContent","ParagraphBlockContent","defaultProps","defaultBlockSchema","removeDuplicates","array","by","seen","item","key","findDuplicates","items","filtered","el","index","UniqueID","v4","dragSourceElement","transformPasted","transactions","oldState","docChanges","transaction","filterTransactions","_a","_b","types","attributeName","generateID","transform","combineTransactionSteps","mapping","getChangedRanges","newRange","newNodes","findChildrenInRange","newIds","duplicatedNewIds","deleted","handleDragstart","event","slice","removeId","fragment","list","nodeWithoutId","Fragment","Slice","UnreachableCaseError","val","toggleStyles","colorStyles","styledTextToNodes","styledText","schema","marks","style","text","linkToNodes","link","linkMark","styledTextArrayToNodes","content","nodes","inlineContentToNodes","blockToNode","type","children","child","groupNode","contentNodeToInlineContent","currentContent","mark","nodeToBlock","blockSchema","blockCache","cachedBlock","props","attr","blockSpec","propSchema","i","nodeAttributes","PreviousBlockTypePlugin","timeout","_editorView","_prevState","prev","currentTransactionOriginalOldBlockAttrs","oldNodes","findChildren","oldNodesById","oldNode","oldContentNode","newContentNode","newAttrs","oldAttrs","pluginState","decorations","prevAttrs","decorationAttrs","nodeAttr","decoration","Decoration","DecorationSet","BlockAttributes","BlockContainer","attrs","HTMLAttr","dispatch","newBlock","childNodes","posBetweenBlocks","nextNodeIsBlock","prevNodeIsBlock","nextBlockInfo","childBlocksStart","childBlocksEnd","childBlocksRange","prevBlockEndPos","TextSelection","keepType","originalBlockContent","newBlockContent","newBlockInsertionPos","newBlockContentPos","selectionAtBlockStart","isParagraph","blockAtDocStart","blockEmpty","blockIndented","BlockGroup","blocks","customBlockSerializer","defaultSerializer","DOMSerializer","CustomBlockSerializerExtension","EventEmitter","__publicField","fn","args","callbacks","callback","findBlock","findParentNode","SuggestionsMenuView","pluginKey","updateSuggestionsMenu","decorationNode","getDefaultPluginState","prevState","next","started","stopped","changed","setupSuggestionsMenu","defaultTriggerCharacter","onSelectItem","suggestionsPluginView","deactivate","_c","_d","menuIsActive","triggerCharacter","queryStartPos","keyboardHoveredItemIndex","active","decorationId","blockNode","slashMenuPluginKey","SlashMenuProsemirrorPlugin","suggestions","query","aliases","alias","Placeholder","selection","menuState","anchor","hasAnchor","isEmpty","classes","TextAlignmentExtension","textAlignment","positionsBeforeSelectedContent","TextColorExtension","TextColorMark","TrailingNode","plugin","_","__","shouldInsertNodeAtEnd","endPosition","_state","lastNode","getBlockNoteExtensions","opts","ret","extensions","Gapcursor","blockStyles","HardBreak","Text","Bold","Code","Italic","Strike","Underline","Link","Dropcursor","Collaboration","defaultRender","user","cursor","label","nonbreakingSpace1","nonbreakingSpace2","CollaborationCursor","History","getNodeById","targetNode","posBeforeNode","insertBlocks","blocksToInsert","referenceBlock","placement","nodesToInsert","insertionPos","blockGroupNode","updateBlock","blockToUpdate","update","removeBlocks","blocksToRemove","idsOfBlocksToRemove","removedSize","oldDocSize","newDocSize","notFoundIds","replaceBlocks","removeUnderlines","removeUnderlinesHelper","tree","numChildElements","numElementsAdded","simplifyBlocks","options","listItemBlockTypes","simplifyBlocksHelper","activeList","blockContainer","blockGroup","isListItemBlock","listItemBlockType","numElementsRemoved","fromDom","listItemElement","blocksToHTML","htmlParentElement","serializer","htmlNode","unified","rehypeParse","rehypeStringify","HTMLToBlocks","html","parentNode","DOMParser","blocksToMarkdown","rehypeRemark","remarkGfm","remarkStringify","markdownToBlocks","markdown","htmlString","remarkParse","remarkRehype","FormattingToolbarView","pmView","updateFormattingToolbar","from","to","empty","isEmptyTextBlock","isTextSelection","editorWrapper","composing","isSame","ranges","shouldShow","isNodeSelection","posToDOMRect","formattingToolbarPluginKey","FormattingToolbarProsemirrorPlugin","editorView","HyperlinkToolbarView","updateHyperlinkToolbar","hoveredHyperlinkElement","posInHoveredHyperlinkMark","resolvedPosInHoveredHyperlinkMark","marksAtPos","getMarkRange","url","prevHyperlinkMark","hyperlinkToolbarPluginKey","HyperlinkToolbarProsemirrorPlugin","MultipleNodeSelection","Selection","$anchor","$head","_pos","fromResult","toResult","serializeForClipboard","pv","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","dom","SideMenuView","updateSideMenu","evt","_event","editorOuterBoundingBox","cursorWithinEditor","_e","blockContentBoundingBox","sideMenuPluginKey","SideMenuProsemirrorPlugin","sideMenuState","insertOrUpdateBlock","currentBlock","getDefaultSlashMenuItems","slashMenuItems","blockNoteTipTapOptions","BlockNoteEditor","newOptions","blockNoteUIExtension","initialContent","tiptapOptions","ic","root","Editor","reverse","traverseBlockArray","blockArray","nodeIndex","numNodes","prevNode","nextNode","targetBlock","editable"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"blocknote.js","sources":["../src/extensions/Blocks/helpers/getBlockInfoFromPos.ts","../src/extensions/BackgroundColor/BackgroundColorExtension.ts","../src/extensions/BackgroundColor/BackgroundColorMark.ts","../src/extensions/Blocks/api/block.ts","../src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContent.ts","../src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/ListItemKeyboardShortcuts.ts","../src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts","../src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts","../src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts","../src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.ts","../src/extensions/Blocks/api/defaultBlocks.ts","../src/extensions/UniqueID/UniqueID.ts","../src/shared/utils.ts","../src/api/nodeConversions/nodeConversions.ts","../src/extensions/Blocks/PreviousBlockTypePlugin.ts","../src/extensions/Blocks/nodes/BlockAttributes.ts","../src/extensions/Blocks/nodes/BlockContainer.ts","../src/extensions/Blocks/nodes/BlockGroup.ts","../src/extensions/Blocks/index.ts","../src/extensions/Blocks/api/serialization.ts","../src/shared/EventEmitter.ts","../src/extensions/Blocks/helpers/findBlock.ts","../src/shared/plugins/suggestion/SuggestionPlugin.ts","../src/extensions/SlashMenu/SlashMenuPlugin.ts","../src/extensions/Placeholder/PlaceholderExtension.ts","../src/extensions/TextAlignment/TextAlignmentExtension.ts","../src/extensions/TextColor/TextColorExtension.ts","../src/extensions/TextColor/TextColorMark.ts","../src/extensions/TrailingNode/TrailingNodeExtension.ts","../src/BlockNoteExtensions.ts","../src/api/util/nodeUtil.ts","../src/api/blockManipulation/blockManipulation.ts","../src/api/formatConversions/removeUnderlinesRehypePlugin.ts","../src/api/formatConversions/simplifyBlocksRehypePlugin.ts","../src/api/formatConversions/formatConversions.ts","../src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts","../src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts","../src/extensions/SideMenu/MultipleNodeSelection.ts","../src/extensions/SideMenu/SideMenuPlugin.ts","../src/extensions/SlashMenu/defaultSlashMenuItems.ts","../src/BlockNoteEditor.ts"],"sourcesContent":["import { Node, NodeType } from \"prosemirror-model\";\n\nexport type BlockInfo = {\n id: string;\n node: Node;\n contentNode: Node;\n contentType: NodeType;\n numChildBlocks: number;\n startPos: number;\n endPos: number;\n depth: number;\n};\n\n/**\n * Retrieves information regarding the most nested block node in a ProseMirror doc, that a given position lies in.\n * @param doc The ProseMirror doc.\n * @param posInBlock A position somewhere within a block node.\n * @returns A BlockInfo object for the block the given position is in, or undefined if the position is not in a block\n * for the given doc.\n */\nexport function getBlockInfoFromPos(\n doc: Node,\n posInBlock: number\n): BlockInfo | undefined {\n if (posInBlock < 0 || posInBlock > doc.nodeSize) {\n return undefined;\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(posInBlock).parent.type.name === \"blockGroup\") {\n posInBlock++;\n }\n\n const $pos = doc.resolve(posInBlock);\n\n const maxDepth = $pos.depth;\n let node = $pos.node(maxDepth);\n let depth = maxDepth;\n\n while (true) {\n if (depth < 0) {\n return undefined;\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 = node.attrs[\"id\"];\n const contentNode = node.firstChild!;\n const contentType = contentNode.type;\n const numChildBlocks = node.childCount === 2 ? node.lastChild!.childCount : 0;\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 { Extension } from \"@tiptap/core\";\nimport { getBlockInfoFromPos } from \"../Blocks/helpers/getBlockInfoFromPos\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n blockBackgroundColor: {\n setBlockBackgroundColor: (\n posInBlock: number,\n color: string\n ) => ReturnType;\n };\n }\n}\n\nexport const BackgroundColorExtension = Extension.create({\n name: \"blockBackgroundColor\",\n\n addGlobalAttributes() {\n return [\n {\n types: [\"blockContainer\"],\n attributes: {\n backgroundColor: {\n default: \"default\",\n parseHTML: (element) =>\n element.hasAttribute(\"data-background-color\")\n ? element.getAttribute(\"data-background-color\")\n : \"default\",\n renderHTML: (attributes) =>\n attributes.backgroundColor !== \"default\" && {\n \"data-background-color\": attributes.backgroundColor,\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setBlockBackgroundColor:\n (posInBlock, color) =>\n ({ state, view }) => {\n const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);\n if (blockInfo === undefined) {\n return false;\n }\n\n state.tr.setNodeAttribute(\n blockInfo.startPos - 1,\n \"backgroundColor\",\n color\n );\n\n view.focus();\n\n return true;\n },\n };\n },\n});\n","import { Mark } from \"@tiptap/core\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n backgroundColor: {\n setBackgroundColor: (color: string) => ReturnType;\n };\n }\n}\n\nexport const BackgroundColorMark = Mark.create({\n name: \"backgroundColor\",\n\n addAttributes() {\n return {\n color: {\n default: undefined,\n parseHTML: (element) => element.getAttribute(\"data-background-color\"),\n renderHTML: (attributes) => ({\n \"data-background-color\": attributes.color,\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 { color: element.getAttribute(\"data-background-color\") };\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\"span\", HTMLAttributes, 0];\n },\n\n addCommands() {\n return {\n setBackgroundColor:\n (color) =>\n ({ commands }) => {\n if (color !== \"default\") {\n return commands.setMark(this.name, { color: color });\n }\n\n return commands.unsetMark(this.name);\n },\n };\n },\n});\n","import { Attribute, Node } from \"@tiptap/core\";\nimport { BlockNoteEditor } from \"../../..\";\nimport styles from \"../nodes/Block.module.css\";\nimport {\n BlockConfig,\n BlockSchema,\n BlockSpec,\n PropSchema,\n TipTapNode,\n TipTapNodeConfig,\n} from \"./blockTypes\";\n\nexport function camelToDataKebab(str: string): string {\n return \"data-\" + str.replace(/([a-z])([A-Z])/g, \"$1-$2\").toLowerCase();\n}\n\n// Function that uses the 'propSchema' of a blockConfig to create a TipTap\n// node's `addAttributes` property.\nexport function propsToAttributes<\n BType extends string,\n PSchema extends PropSchema,\n ContainsInlineContent extends boolean,\n BSchema extends BlockSchema\n>(\n blockConfig: Omit<\n BlockConfig<BType, PSchema, ContainsInlineContent, BSchema>,\n \"render\"\n >\n) {\n const tiptapAttributes: Record<string, Attribute> = {};\n\n Object.entries(blockConfig.propSchema).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) => element.getAttribute(camelToDataKebab(name)),\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// 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 parse<\n BType extends string,\n PSchema extends PropSchema,\n ContainsInlineContent extends boolean,\n BSchema extends BlockSchema\n>(\n blockConfig: Omit<\n BlockConfig<BType, PSchema, ContainsInlineContent, BSchema>,\n \"render\"\n >\n) {\n return [\n {\n tag: \"div[data-content-type=\" + blockConfig.type + \"]\",\n },\n ];\n}\n\n// Function that uses the 'render' function of a blockConfig to create a\n// TipTap node's `renderHTML` property. Since custom blocks use node views,\n// this is only used for serializing content to the clipboard.\nexport function render<\n BType extends string,\n PSchema extends PropSchema,\n ContainsInlineContent extends boolean,\n BSchema extends BlockSchema\n>(\n blockConfig: Omit<\n BlockConfig<BType, PSchema, ContainsInlineContent, BSchema>,\n \"render\"\n >,\n HTMLAttributes: Record<string, any>\n) {\n // Create blockContent element\n const blockContent = document.createElement(\"div\");\n // Add blockContent HTML attribute\n blockContent.setAttribute(\"data-content-type\", blockConfig.type);\n // Add props as HTML attributes in kebab-case with \"data-\" prefix\n for (const [attribute, value] of Object.entries(HTMLAttributes)) {\n blockContent.setAttribute(attribute, value);\n }\n\n // TODO: This only works for content copied within BlockNote.\n // Creates contentDOM element to serialize inline content into.\n let contentDOM: HTMLDivElement | undefined;\n if (blockConfig.containsInlineContent) {\n contentDOM = document.createElement(\"div\");\n blockContent.appendChild(contentDOM);\n } else {\n contentDOM = undefined;\n }\n\n return contentDOM !== undefined\n ? {\n dom: blockContent,\n contentDOM: contentDOM,\n }\n : {\n dom: blockContent,\n };\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 BType extends string,\n PSchema extends PropSchema,\n ContainsInlineContent extends boolean,\n BSchema extends BlockSchema\n>(\n blockConfig: BlockConfig<BType, PSchema, ContainsInlineContent, BSchema>\n): BlockSpec<BType, PSchema> {\n const node = createTipTapBlock<BType>({\n name: blockConfig.type,\n content: blockConfig.containsInlineContent ? \"inline*\" : \"\",\n selectable: blockConfig.containsInlineContent,\n\n addOptions() {\n return {\n editor: undefined,\n };\n },\n\n addAttributes() {\n return propsToAttributes(blockConfig);\n },\n\n parseHTML() {\n return parse(blockConfig);\n },\n\n renderHTML({ HTMLAttributes }) {\n return render(blockConfig, HTMLAttributes);\n },\n\n addNodeView() {\n return ({ HTMLAttributes, getPos }) => {\n // Create blockContent element\n const blockContent = document.createElement(\"div\");\n // Sets blockContent class\n blockContent.className = styles.blockContent;\n // Add blockContent HTML attribute\n blockContent.setAttribute(\"data-content-type\", blockConfig.type);\n // Add props as HTML attributes in kebab-case with \"data-\" prefix\n for (const [attribute, value] of Object.entries(HTMLAttributes)) {\n blockContent.setAttribute(attribute, value);\n }\n\n // Gets BlockNote editor instance\n const editor = this.options.editor! as BlockNoteEditor<\n BSchema & { [k in BType]: BlockSpec<BType, PSchema> }\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 TipTap editor instance\n const tipTapEditor = editor._tiptapEditor;\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\n // Get the block\n const block = editor.getBlock(blockIdentifier)!;\n if (block.type !== blockConfig.type) {\n throw new Error(\"Block type does not match\");\n }\n\n // Render elements\n const rendered = blockConfig.render(block as any, editor);\n // Add inlineContent class to inline content\n if (\"contentDOM\" in rendered) {\n rendered.contentDOM.className = `${\n rendered.contentDOM.className\n ? rendered.contentDOM.className + \" \"\n : \"\"\n }${styles.inlineContent}`;\n }\n // Add elements to blockContent\n blockContent.appendChild(rendered.dom);\n\n return \"contentDOM\" in rendered\n ? {\n dom: blockContent,\n contentDOM: rendered.contentDOM,\n }\n : {\n dom: blockContent,\n };\n };\n },\n });\n\n return {\n node: node,\n propSchema: blockConfig.propSchema,\n };\n}\n\nexport function createTipTapBlock<Type extends string>(\n config: TipTapNodeConfig<Type>\n): TipTapNode<Type> {\n // Type cast is needed as Node.name is mutable, though there is basically no\n // reason to change it after creation. Alternative is to wrap Node in a new\n // class, which I don't think is worth it since we'd only be changing 1\n // attribute to be read only.\n return Node.create({\n ...config,\n group: \"blockContent\",\n }) as TipTapNode<Type>;\n}\n","import { InputRule, mergeAttributes } from \"@tiptap/core\";\nimport { createTipTapBlock } from \"../../../api/block\";\nimport styles from \"../../Block.module.css\";\n\nexport const HeadingBlockContent = createTipTapBlock<\"heading\">({\n name: \"heading\",\n content: \"inline*\",\n\n addAttributes() {\n return {\n level: {\n default: \"1\",\n // instead of \"level\" attributes, use \"data-level\"\n parseHTML: (element) => element.getAttribute(\"data-level\"),\n renderHTML: (attributes) => {\n return {\n \"data-level\": attributes.level,\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(`^(#{${parseInt(level)}})\\\\s$`),\n handler: ({ state, chain, range }) => {\n chain()\n .BNUpdateBlock(state.selection.from, {\n type: \"heading\",\n props: {\n level: level as \"1\" | \"2\" | \"3\",\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 parseHTML() {\n return [\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 [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n class: styles.blockContent,\n \"data-content-type\": this.name,\n }),\n [\"h\" + node.attrs.level, { class: styles.inlineContent }, 0],\n ];\n },\n});\n","import { Editor } from \"@tiptap/core\";\nimport { getBlockInfoFromPos } from \"../../../helpers/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 (!contentType.name.endsWith(\"ListItem\") || !selectionEmpty) {\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, mergeAttributes } from \"@tiptap/core\";\nimport { createTipTapBlock } from \"../../../../api/block\";\nimport { handleEnter } from \"../ListItemKeyboardShortcuts\";\nimport styles from \"../../../Block.module.css\";\n\nexport const BulletListItemBlockContent = createTipTapBlock<\"bulletListItem\">({\n name: \"bulletListItem\",\n content: \"inline*\",\n\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 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 };\n },\n\n parseHTML() {\n return [\n // Case for regular HTML list structure.\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 (parent.tagName === \"UL\") {\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 [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n class: styles.blockContent,\n \"data-content-type\": this.name,\n }),\n [\"p\", { class: styles.inlineContent }, 0],\n ];\n },\n});\n","import { Plugin, PluginKey } from \"prosemirror-state\";\nimport { getBlockInfoFromPos } from \"../../../../helpers/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, mergeAttributes } from \"@tiptap/core\";\nimport { createTipTapBlock } from \"../../../../api/block\";\nimport { handleEnter } from \"../ListItemKeyboardShortcuts\";\nimport { NumberedListIndexingPlugin } from \"./NumberedListIndexingPlugin\";\nimport styles from \"../../../Block.module.css\";\n\nexport const NumberedListItemBlockContent =\n createTipTapBlock<\"numberedListItem\">({\n name: \"numberedListItem\",\n content: \"inline*\",\n\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 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 };\n },\n\n addProseMirrorPlugins() {\n return [NumberedListIndexingPlugin()];\n },\n\n parseHTML() {\n return [\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 (parent.tagName === \"OL\") {\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 (\n parent.getAttribute(\"data-content-type\") === \"numberedListItem\"\n ) {\n return {};\n }\n\n return false;\n },\n priority: 300,\n node: \"numberedListItem\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n class: styles.blockContent,\n \"data-content-type\": this.name,\n }),\n // we use a <p> tag, because for <li> tags we'd need to add a <ul> parent for around siblings to be semantically correct,\n // which would be quite cumbersome\n [\"p\", { class: styles.inlineContent }, 0],\n ];\n },\n });\n","import { mergeAttributes } from \"@tiptap/core\";\nimport { createTipTapBlock } from \"../../../api/block\";\nimport styles from \"../../Block.module.css\";\n\nexport const ParagraphBlockContent = createTipTapBlock<\"paragraph\">({\n name: \"paragraph\",\n content: \"inline*\",\n\n parseHTML() {\n return [\n {\n tag: \"p\",\n priority: 200,\n node: \"paragraph\",\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n class: styles.blockContent,\n \"data-content-type\": this.name,\n }),\n [\"p\", { class: styles.inlineContent }, 0],\n ];\n },\n});\n","import { HeadingBlockContent } from \"../nodes/BlockContent/HeadingBlockContent/HeadingBlockContent\";\nimport { BulletListItemBlockContent } from \"../nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent\";\nimport { NumberedListItemBlockContent } from \"../nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent\";\nimport { ParagraphBlockContent } from \"../nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent\";\nimport { PropSchema, TypesMatch } from \"./blockTypes\";\n\nexport const defaultProps = {\n backgroundColor: {\n default: \"transparent\" as const,\n },\n textColor: {\n default: \"black\" as const, // TODO\n },\n textAlignment: {\n default: \"left\" as const,\n values: [\"left\", \"center\", \"right\", \"justify\"] as const,\n },\n} satisfies PropSchema;\n\nexport type DefaultProps = typeof defaultProps;\n\nexport const defaultBlockSchema = {\n paragraph: {\n propSchema: defaultProps,\n node: ParagraphBlockContent,\n },\n heading: {\n propSchema: {\n ...defaultProps,\n level: { default: \"1\", values: [\"1\", \"2\", \"3\"] as const },\n },\n node: HeadingBlockContent,\n },\n bulletListItem: {\n propSchema: defaultProps,\n node: BulletListItemBlockContent,\n },\n numberedListItem: {\n propSchema: defaultProps,\n node: NumberedListItemBlockContent,\n },\n} as const;\n\nexport type DefaultBlockSchema = TypesMatch<typeof defaultBlockSchema>;\n","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 ((window as any).__TEST_OPTIONS) {\n if ((window as any).__TEST_OPTIONS.mockID === undefined) {\n (window as any).__TEST_OPTIONS.mockID = 0;\n } else {\n (window as any).__TEST_OPTIONS.mockID++;\n }\n\n return (window as any).__TEST_OPTIONS.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 var _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 var _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 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 var _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 var _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, UniqueID as default };\n//# sourceMappingURL=tiptap-extension-unique-id.esm.js.map\n","export const isAppleOS = () =>\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 class UnreachableCaseError extends Error {\n constructor(val: never) {\n super(`Unreachable case: ${val}`);\n }\n}\n","import { Mark } from \"@tiptap/pm/model\";\nimport { Node, Schema } from \"prosemirror-model\";\nimport {\n Block,\n BlockSchema,\n PartialBlock,\n} from \"../../extensions/Blocks/api/blockTypes\";\n\nimport { defaultProps } from \"../../extensions/Blocks/api/defaultBlocks\";\nimport {\n ColorStyle,\n InlineContent,\n PartialInlineContent,\n PartialLink,\n StyledText,\n Styles,\n ToggledStyle,\n} from \"../../extensions/Blocks/api/inlineContentTypes\";\nimport { getBlockInfoFromPos } from \"../../extensions/Blocks/helpers/getBlockInfoFromPos\";\nimport UniqueID from \"../../extensions/UniqueID/UniqueID\";\nimport { UnreachableCaseError } from \"../../shared/utils\";\n\nconst toggleStyles = new Set<ToggledStyle>([\n \"bold\",\n \"italic\",\n \"underline\",\n \"strike\",\n \"code\",\n]);\nconst colorStyles = new Set<ColorStyle>([\"textColor\", \"backgroundColor\"]);\n\n/**\n * Convert a StyledText inline element to a\n * prosemirror text node with the appropriate marks\n */\nfunction styledTextToNodes(styledText: StyledText, schema: Schema): Node[] {\n const marks: Mark[] = [];\n\n for (const [style, value] of Object.entries(styledText.styles)) {\n if (toggleStyles.has(style as ToggledStyle)) {\n marks.push(schema.mark(style));\n } else if (colorStyles.has(style as ColorStyle)) {\n marks.push(schema.mark(style, { color: value }));\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(link: PartialLink, schema: Schema): Node[] {\n const linkMark = schema.marks.link.create({\n href: link.href,\n });\n\n return styledTextArrayToNodes(link.content, schema).map((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 * Converts an array of StyledText inline content elements to\n * prosemirror text nodes with the appropriate marks\n */\nfunction styledTextArrayToNodes(\n content: string | StyledText[],\n schema: Schema\n): Node[] {\n let nodes: Node[] = [];\n\n if (typeof content === \"string\") {\n nodes.push(\n ...styledTextToNodes({ type: \"text\", text: content, styles: {} }, schema)\n );\n return nodes;\n }\n\n for (const styledText of content) {\n nodes.push(...styledTextToNodes(styledText, schema));\n }\n return nodes;\n}\n\n/**\n * converts an array of inline content elements to prosemirror nodes\n */\nexport function inlineContentToNodes(\n blockContent: PartialInlineContent[],\n schema: Schema\n): Node[] {\n let nodes: Node[] = [];\n\n for (const content of blockContent) {\n if (content.type === \"link\") {\n nodes.push(...linkToNodes(content, schema));\n } else if (content.type === \"text\") {\n nodes.push(...styledTextArrayToNodes([content], schema));\n } else {\n throw new UnreachableCaseError(content);\n }\n }\n return nodes;\n}\n\n/**\n * Converts a BlockNote block to a TipTap node.\n */\nexport function blockToNode<BSchema extends BlockSchema>(\n block: PartialBlock<BSchema>,\n schema: Schema\n) {\n let id = block.id;\n\n if (id === undefined) {\n id = UniqueID.options.generateID();\n }\n\n let type = block.type;\n\n if (type === undefined) {\n type = \"paragraph\";\n }\n\n let contentNode: Node;\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 {\n const nodes = inlineContentToNodes(block.content, schema);\n contentNode = schema.nodes[type].create(block.props, nodes);\n }\n\n const children: Node[] = [];\n\n if (block.children) {\n for (const child of block.children) {\n children.push(blockToNode(child, schema));\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) content node to a BlockNote InlineContent array.\n */\nfunction contentNodeToInlineContent(contentNode: Node) {\n const content: InlineContent[] = [];\n let currentContent: InlineContent | 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 (currentContent.type === \"text\") {\n // Current content is text.\n currentContent.text += \"\\n\";\n } else if (currentContent.type === \"link\") {\n // Current content is a link.\n currentContent.content[currentContent.content.length - 1].text +=\n \"\\n\";\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 const styles: Styles = {};\n let linkMark: Mark | undefined;\n\n for (const mark of node.marks) {\n if (mark.type.name === \"link\") {\n linkMark = mark;\n } else if (toggleStyles.has(mark.type.name as ToggledStyle)) {\n styles[mark.type.name as ToggledStyle] = true;\n } else if (colorStyles.has(mark.type.name as ColorStyle)) {\n styles[mark.type.name as ColorStyle] = mark.attrs.color;\n } else {\n throw Error(\"Mark is of an unrecognized type: \" + mark.type.name);\n }\n }\n\n // Parsing links and text.\n // Current content exists.\n if (currentContent) {\n // Current content is text.\n if (currentContent.type === \"text\") {\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 (currentContent.type === \"link\") {\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 }\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;\n}\n\n/**\n * Convert a TipTap node to a BlockNote block.\n */\nexport function nodeToBlock<BSchema extends BlockSchema>(\n node: Node,\n blockSchema: BSchema,\n blockCache?: WeakMap<Node, Block<BSchema>>\n): Block<BSchema> {\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 = getBlockInfoFromPos(node, 0)!;\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 ...blockInfo.node.attrs,\n ...blockInfo.contentNode.attrs,\n })) {\n const blockSpec = blockSchema[blockInfo.contentType.name];\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 // Block ids are stored as node attributes the same way props are, so we\n // need to ensure we don't attempt to read block ids as props.\n\n // the second check is for the backgroundColor & textColor props.\n // Since we want them to be inherited by child blocks, we can't put them on the blockContent node,\n // and instead have to put them on the blockContainer node.\n // The blockContainer node is the same for all block types, but some custom blocks might not use backgroundColor & textColor,\n // so these 2 props are technically unexpected but we shouldn't log a warning.\n // (this is a bit hacky)\n else if (attr !== \"id\" && !(attr in defaultProps)) {\n console.warn(\"Block has an unrecognized attribute: \" + attr);\n }\n }\n\n const content = contentNodeToInlineContent(blockInfo.contentNode);\n\n const children: Block<BSchema>[] = [];\n for (let i = 0; i < blockInfo.numChildBlocks; i++) {\n children.push(\n nodeToBlock(blockInfo.node.lastChild!.child(i), blockSchema, blockCache)\n );\n }\n\n const block: Block<BSchema> = {\n id,\n type: blockInfo.contentType.name,\n props,\n content,\n children,\n };\n\n blockCache?.set(node, block);\n\n return block;\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 (let 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 (let [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","// 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\nexport default BlockAttributes;\n","import { mergeAttributes, Node } from \"@tiptap/core\";\nimport { Fragment, Node as PMNode, Slice } from \"prosemirror-model\";\nimport { TextSelection } from \"prosemirror-state\";\nimport {\n blockToNode,\n inlineContentToNodes,\n} from \"../../../api/nodeConversions/nodeConversions\";\n\nimport { getBlockInfoFromPos } from \"../helpers/getBlockInfoFromPos\";\nimport { PreviousBlockTypePlugin } from \"../PreviousBlockTypePlugin\";\nimport styles from \"./Block.module.css\";\nimport BlockAttributes from \"./BlockAttributes\";\nimport { BlockSchema, PartialBlock } from \"../api/blockTypes\";\n\n// TODO\nexport interface IBlock {\n HTMLAttributes: Record<string, any>;\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: <BSchema extends BlockSchema>(\n posInBlock: number,\n block: PartialBlock<BSchema>\n ) => ReturnType;\n BNCreateOrUpdateBlock: <BSchema extends BlockSchema>(\n posInBlock: number,\n block: PartialBlock<BSchema>\n ) => ReturnType;\n };\n }\n}\n\n/**\n * The main \"Block node\" documents consist of\n */\nexport const BlockContainer = Node.create<IBlock>({\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 addOptions() {\n return {\n HTMLAttributes: {},\n };\n },\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 (let [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 return [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n class: styles.blockOuter,\n \"data-node-type\": \"block-outer\",\n }),\n [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n // TODO: maybe remove html attributes from inner block\n class: styles.block,\n \"data-node-type\": this.name,\n }),\n 0,\n ],\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(blockToNode(child, state.schema));\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 // Replaces the blockContent node's content if necessary.\n if (block.content !== undefined) {\n let content: PMNode[] = [];\n\n // Checks if the provided content is a string or InlineContent[] type.\n if (typeof block.content === \"string\") {\n // Adds a single text node with no marks to the content.\n content.push(state.schema.text(block.content));\n } else {\n // Adds a text node with the provided styles converted into marks to the content, for each InlineContent\n // object.\n content = inlineContentToNodes(block.content, state.schema);\n }\n\n // Replaces the contents of the blockContent node with the previously created text node(s).\n state.tr.replace(\n startPos + 1,\n startPos + contentNode.nodeSize - 1,\n new Slice(Fragment.from(content), 0, 0)\n );\n }\n\n // Changes the blockContent node type and adds the provided props as attributes. Also preserves all existing\n // attributes that are compatible with the new type.\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\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()];\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 } = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n )!;\n\n const selectionAtBlockStart =\n state.selection.$anchor.parentOffset === 0;\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 selectionAtBlockStart =\n state.selection.$anchor.parentOffset === 0;\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 =\n state.selection.$anchor.parentOffset === 0;\n const selectionEmpty =\n state.selection.anchor === state.selection.head;\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 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 blockEmpty = node.textContent.length === 0;\n\n if (!blockEmpty) {\n chain()\n .deleteSelection()\n .BNSplitBlock(state.selection.from, false)\n .run();\n\n return true;\n }\n\n return false;\n }),\n ]);\n\n return {\n Backspace: handleBackspace,\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 \"Mod-Alt-0\": () =>\n this.editor.commands.BNCreateBlock(\n this.editor.state.selection.anchor + 2\n ),\n \"Mod-Alt-1\": () =>\n this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {\n type: \"heading\",\n props: {\n level: \"1\",\n },\n }),\n \"Mod-Alt-2\": () =>\n this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {\n type: \"heading\",\n props: {\n level: \"2\",\n },\n }),\n \"Mod-Alt-3\": () =>\n this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {\n type: \"heading\",\n props: {\n level: \"3\",\n },\n }),\n \"Mod-Shift-7\": () =>\n this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {\n type: \"bulletListItem\",\n props: {},\n }),\n \"Mod-Shift-8\": () =>\n this.editor.commands.BNUpdateBlock(this.editor.state.selection.anchor, {\n type: \"numberedListItem\",\n props: {},\n }),\n };\n },\n});\n","import { mergeAttributes, Node } from \"@tiptap/core\";\nimport styles from \"./Block.module.css\";\n\nexport const BlockGroup = Node.create({\n name: \"blockGroup\",\n group: \"blockGroup\",\n content: \"blockContainer+\",\n\n addOptions() {\n return {\n HTMLAttributes: {},\n };\n },\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 return [\n \"div\",\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n class: styles.blockGroup,\n \"data-node-type\": \"blockGroup\",\n }),\n 0,\n ];\n },\n});\n","import { Node } from \"@tiptap/core\";\nimport { BlockContainer } from \"./nodes/BlockContainer\";\nimport { BlockGroup } from \"./nodes/BlockGroup\";\n\nexport const blocks: any[] = [\n BlockContainer,\n BlockGroup,\n Node.create({\n name: \"doc\",\n topNode: true,\n content: \"blockGroup\",\n }),\n];\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin } from \"prosemirror-state\";\nimport { DOMSerializer, Schema } from \"prosemirror-model\";\n\nconst customBlockSerializer = (schema: Schema) => {\n const defaultSerializer = DOMSerializer.fromSchema(schema);\n\n return new DOMSerializer(\n {\n ...defaultSerializer.nodes,\n // TODO: If a serializer is defined in the config for a custom block, it\n // should be added here. We still need to figure out how the serializer\n // should be defined in the custom blocks API though, and implement that,\n // before we can do this.\n },\n defaultSerializer.marks\n );\n};\nexport const CustomBlockSerializerExtension = Extension.create({\n addProseMirrorPlugins() {\n return [\n new Plugin({\n props: {\n clipboardSerializer: customBlockSerializer(this.editor.schema),\n },\n }),\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 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 { findParentNode } from \"@tiptap/core\";\n\nexport const findBlock = findParentNode(\n (node) => node.type.name === \"blockContainer\"\n);\n","import { EditorState, Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet, EditorView } from \"prosemirror-view\";\nimport { BlockNoteEditor } from \"../../../BlockNoteEditor\";\nimport { BlockSchema } from \"../../../extensions/Blocks/api/blockTypes\";\nimport { findBlock } from \"../../../extensions/Blocks/helpers/findBlock\";\nimport { BaseUiElementState } from \"../../BaseUiElementTypes\";\nimport { SuggestionItem } from \"./SuggestionItem\";\n\nexport type SuggestionsMenuState<T extends SuggestionItem> =\n BaseUiElementState & {\n // The suggested items to display.\n filteredItems: T[];\n // The index of the suggested item that's currently hovered by the keyboard.\n keyboardHoveredItemIndex: number;\n };\n\nclass SuggestionsMenuView<\n T extends SuggestionItem,\n BSchema extends BlockSchema\n> {\n private suggestionsMenuState?: SuggestionsMenuState<T>;\n public updateSuggestionsMenu: () => void;\n\n pluginState: SuggestionPluginState<T>;\n\n constructor(\n private readonly editor: BlockNoteEditor<BSchema>,\n private readonly pluginKey: PluginKey,\n updateSuggestionsMenu: (\n suggestionsMenuState: SuggestionsMenuState<T>\n ) => void = () => {}\n ) {\n this.pluginState = getDefaultPluginState<T>();\n\n this.updateSuggestionsMenu = () => {\n if (!this.suggestionsMenuState) {\n throw new Error(\"Attempting to update uninitialized suggestions menu\");\n }\n\n updateSuggestionsMenu(this.suggestionsMenuState);\n };\n\n document.addEventListener(\"scroll\", this.handleScroll);\n }\n\n handleScroll = () => {\n if (this.suggestionsMenuState?.show) {\n const decorationNode = document.querySelector(\n `[data-decoration-id=\"${this.pluginState.decorationId}\"]`\n );\n this.suggestionsMenuState.referencePos =\n decorationNode!.getBoundingClientRect();\n this.updateSuggestionsMenu();\n }\n };\n\n update(view: EditorView, prevState: EditorState) {\n const prev = this.pluginKey.getState(prevState);\n const next = this.pluginKey.getState(view.state);\n\n // See how the state changed\n const started = !prev.active && next.active;\n const stopped = prev.active && !next.active;\n // TODO: Currently also true for cases in which an update isn't needed so selected list item index updates still\n // cause the view to update. May need to be more strict.\n const changed = prev.active && next.active;\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.suggestionsMenuState!.show = false;\n this.updateSuggestionsMenu();\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.suggestionsMenuState = {\n show: true,\n referencePos: decorationNode!.getBoundingClientRect(),\n filteredItems: this.pluginState.items,\n keyboardHoveredItemIndex: this.pluginState.keyboardHoveredItemIndex!,\n };\n\n this.updateSuggestionsMenu();\n }\n }\n\n destroy() {\n document.removeEventListener(\"scroll\", this.handleScroll);\n }\n}\n\ntype SuggestionPluginState<T extends SuggestionItem> = {\n // True when the menu is shown, false when hidden.\n active: boolean;\n // The character that triggered the menu being shown. Allowing the trigger to be different to the default\n // trigger allows other extensions to open it programmatically.\n triggerCharacter: string | undefined;\n // The editor position just after the trigger character, i.e. where the user query begins. Used to figure out\n // which menu items to show and can also be used to delete the trigger character.\n queryStartPos: number | undefined;\n // The items that should be shown in the menu.\n items: T[];\n // The index of the item in the menu that's currently hovered using the keyboard.\n keyboardHoveredItemIndex: number | undefined;\n // The number of characters typed after the last query that matched with at least 1 item. Used to close the\n // menu if the user keeps entering queries that don't return any results.\n notFoundCount: number | undefined;\n decorationId: string | undefined;\n};\n\nfunction getDefaultPluginState<\n T extends SuggestionItem\n>(): SuggestionPluginState<T> {\n return {\n active: false,\n triggerCharacter: undefined,\n queryStartPos: undefined,\n items: [] as T[],\n keyboardHoveredItemIndex: undefined,\n notFoundCount: 0,\n decorationId: undefined,\n };\n}\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 const setupSuggestionsMenu = <\n T extends SuggestionItem,\n BSchema extends BlockSchema\n>(\n editor: BlockNoteEditor<BSchema>,\n updateSuggestionsMenu: (\n suggestionsMenuState: SuggestionsMenuState<T>\n ) => void,\n\n pluginKey: PluginKey,\n defaultTriggerCharacter: string,\n items: (query: string) => T[] = () => [],\n onSelectItem: (props: {\n item: T;\n editor: BlockNoteEditor<BSchema>;\n }) => void = () => {}\n) => {\n // Assertions\n if (defaultTriggerCharacter.length !== 1) {\n throw new Error(\"'char' should be a single character\");\n }\n\n let suggestionsPluginView: SuggestionsMenuView<T, BSchema>;\n\n const deactivate = (view: EditorView) => {\n view.dispatch(view.state.tr.setMeta(pluginKey, { deactivate: true }));\n };\n\n return {\n plugin: new Plugin({\n key: pluginKey,\n\n view: () => {\n suggestionsPluginView = new SuggestionsMenuView<T, BSchema>(\n editor,\n pluginKey,\n\n updateSuggestionsMenu\n );\n return suggestionsPluginView;\n },\n\n state: {\n // Initialize the plugin's internal state.\n init(): SuggestionPluginState<T> {\n return getDefaultPluginState<T>();\n },\n\n // Apply changes to the plugin state from an editor transaction.\n apply(transaction, prev, oldState, newState): SuggestionPluginState<T> {\n // TODO: More clearly define which transactions should be ignored.\n if (transaction.getMeta(\"orderedListIndexing\") !== undefined) {\n return prev;\n }\n\n // Checks if the menu should be shown.\n if (transaction.getMeta(pluginKey)?.activate) {\n return {\n active: true,\n triggerCharacter:\n transaction.getMeta(pluginKey)?.triggerCharacter || \"\",\n queryStartPos: newState.selection.from,\n items: items(\"\"),\n keyboardHoveredItemIndex: 0,\n // TODO: Maybe should be 1 if the menu has no possible items? Probably redundant since a menu with no items\n // is useless in practice.\n notFoundCount: 0,\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.active) {\n return prev;\n }\n\n const next = { ...prev };\n\n // Updates which menu items to show by checking which items the current query (the text between the trigger\n // character and caret) matches with.\n next.items = items(\n newState.doc.textBetween(\n prev.queryStartPos!,\n newState.selection.from\n )\n );\n\n // Updates notFoundCount if the query doesn't match any items.\n next.notFoundCount = 0;\n if (next.items.length === 0) {\n // Checks how many characters were typed or deleted since the last transaction, and updates the notFoundCount\n // accordingly. Also ensures the notFoundCount does not become negative.\n next.notFoundCount = Math.max(\n 0,\n prev.notFoundCount! +\n (newState.selection.from - oldState.selection.from)\n );\n }\n\n // Hides the menu. This is done after items and notFoundCount are already updated as notFoundCount is needed to\n // check 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 {deactivate: true} should hide the menu.\n transaction.getMeta(pluginKey)?.deactivate ||\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.active && newState.selection.from < prev.queryStartPos!) ||\n // Entering more than 3 characters, after the last query that matched with at least 1 menu item, should hide\n // the menu.\n next.notFoundCount > 3\n ) {\n return getDefaultPluginState<T>();\n }\n\n // Updates keyboardHoveredItemIndex if the up or down arrow key was\n // pressed, or resets it if the keyboard cursor moved.\n if (\n transaction.getMeta(pluginKey)?.selectedItemIndexChanged !==\n undefined\n ) {\n let newIndex =\n transaction.getMeta(pluginKey).selectedItemIndexChanged;\n\n // Allows selection to jump between first and last items.\n if (newIndex < 0) {\n newIndex = prev.items.length - 1;\n } else if (newIndex >= prev.items.length) {\n newIndex = 0;\n }\n\n next.keyboardHoveredItemIndex = newIndex;\n } else if (oldState.selection.from !== newState.selection.from) {\n next.keyboardHoveredItemIndex = 0;\n }\n\n return next;\n },\n },\n\n props: {\n handleKeyDown(view, event) {\n const menuIsActive = (this as Plugin).getState(view.state).active;\n\n // Shows the menu if the default trigger character was pressed and the menu isn't active.\n if (event.key === defaultTriggerCharacter && !menuIsActive) {\n view.dispatch(\n view.state.tr\n .insertText(defaultTriggerCharacter)\n .scrollIntoView()\n .setMeta(pluginKey, {\n activate: true,\n triggerCharacter: defaultTriggerCharacter,\n })\n );\n\n return true;\n }\n\n // Doesn't handle other keystrokes if the menu isn't active.\n if (!menuIsActive) {\n return false;\n }\n\n // Handles keystrokes for navigating the menu.\n const {\n triggerCharacter,\n queryStartPos,\n items,\n keyboardHoveredItemIndex,\n } = pluginKey.getState(view.state);\n\n // Moves the keyboard selection to the previous item.\n if (event.key === \"ArrowUp\") {\n view.dispatch(\n view.state.tr.setMeta(pluginKey, {\n selectedItemIndexChanged: keyboardHoveredItemIndex - 1,\n })\n );\n return true;\n }\n\n // Moves the keyboard selection to the next item.\n if (event.key === \"ArrowDown\") {\n view.dispatch(\n view.state.tr.setMeta(pluginKey, {\n selectedItemIndexChanged: keyboardHoveredItemIndex + 1,\n })\n );\n return true;\n }\n\n // Selects an item and closes the menu.\n if (event.key === \"Enter\") {\n deactivate(view);\n editor._tiptapEditor\n .chain()\n .focus()\n .deleteRange({\n from: queryStartPos! - triggerCharacter!.length,\n to: editor._tiptapEditor.state.selection.from,\n })\n .run();\n\n onSelectItem({\n item: items[keyboardHoveredItemIndex],\n editor: editor,\n });\n\n return true;\n }\n\n // Closes the menu.\n if (event.key === \"Escape\") {\n deactivate(view);\n return true;\n }\n\n return false;\n },\n\n // Setup decorator on the currently active suggestion.\n decorations(state) {\n const { active, decorationId, queryStartPos, triggerCharacter } = (\n this as Plugin\n ).getState(state);\n\n if (!active) {\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 (triggerCharacter === \"\") {\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: \"suggestion-decorator\",\n \"data-decoration-id\": 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 queryStartPos - triggerCharacter.length,\n queryStartPos,\n {\n nodeName: \"span\",\n class: \"suggestion-decorator\",\n \"data-decoration-id\": decorationId,\n }\n ),\n ]);\n },\n },\n }),\n itemCallback: (item: T) => {\n deactivate(editor._tiptapEditor.view);\n editor._tiptapEditor\n .chain()\n .focus()\n .deleteRange({\n from:\n suggestionsPluginView.pluginState.queryStartPos! -\n suggestionsPluginView.pluginState.triggerCharacter!.length,\n to: editor._tiptapEditor.state.selection.from,\n })\n .run();\n\n onSelectItem({\n item: item,\n editor: editor,\n });\n },\n };\n};\n","import { Plugin, PluginKey } from \"prosemirror-state\";\n\nimport { BlockNoteEditor } from \"../../BlockNoteEditor\";\nimport { EventEmitter } from \"../../shared/EventEmitter\";\nimport {\n SuggestionsMenuState,\n setupSuggestionsMenu,\n} from \"../../shared/plugins/suggestion/SuggestionPlugin\";\nimport { BlockSchema } from \"../Blocks/api/blockTypes\";\nimport { BaseSlashMenuItem } from \"./BaseSlashMenuItem\";\n\nexport const slashMenuPluginKey = new PluginKey(\"SlashMenuPlugin\");\n\nexport class SlashMenuProsemirrorPlugin<\n BSchema extends BlockSchema,\n SlashMenuItem extends BaseSlashMenuItem<BSchema>\n> extends EventEmitter<any> {\n public readonly plugin: Plugin;\n public readonly itemCallback: (item: SlashMenuItem) => void;\n\n constructor(editor: BlockNoteEditor<BSchema>, items: SlashMenuItem[]) {\n super();\n const suggestions = setupSuggestionsMenu<SlashMenuItem, BSchema>(\n editor,\n (state) => {\n this.emit(\"update\", state);\n },\n slashMenuPluginKey,\n \"/\",\n (query) =>\n items.filter(\n ({ name, aliases }: SlashMenuItem) =>\n name.toLowerCase().startsWith(query.toLowerCase()) ||\n (aliases &&\n aliases.filter((alias) =>\n alias.toLowerCase().startsWith(query.toLowerCase())\n ).length !== 0)\n ),\n ({ item, editor }) => item.execute(editor)\n );\n\n this.plugin = suggestions.plugin;\n this.itemCallback = suggestions.itemCallback;\n }\n\n public onUpdate(\n callback: (state: SuggestionsMenuState<SlashMenuItem>) => void\n ) {\n return this.on(\"update\", callback);\n }\n}\n","import { Editor, Extension } from \"@tiptap/core\";\nimport { Node as ProsemirrorNode } from \"prosemirror-model\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet } from \"prosemirror-view\";\nimport { slashMenuPluginKey } from \"../SlashMenu/SlashMenuPlugin\";\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 emptyEditorClass: string;\n emptyNodeClass: string;\n isFilterClass: string;\n hasAnchorClass: string;\n placeholder:\n | ((PlaceholderProps: {\n editor: Editor;\n node: ProsemirrorNode;\n pos: number;\n hasAnchor: boolean;\n }) => string)\n | string;\n showOnlyWhenEditable: boolean;\n showOnlyCurrent: boolean;\n includeChildren: boolean;\n}\n\nexport const Placeholder = Extension.create<PlaceholderOptions>({\n name: \"placeholder\",\n\n addOptions() {\n return {\n emptyEditorClass: \"is-editor-empty\",\n emptyNodeClass: \"is-empty\",\n isFilterClass: \"is-filter\",\n hasAnchorClass: \"has-anchor\",\n placeholder: \"Write something …\",\n showOnlyWhenEditable: true,\n showOnlyCurrent: true,\n includeChildren: false,\n };\n },\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n key: PLUGIN_KEY,\n props: {\n decorations: (state) => {\n const { doc, selection } = state;\n // Get state of slash menu\n const menuState = slashMenuPluginKey.getState(state);\n const active =\n this.editor.isEditable || !this.options.showOnlyWhenEditable;\n const { anchor } = selection;\n const decorations: Decoration[] = [];\n\n if (!active) {\n return;\n }\n\n doc.descendants((node, pos) => {\n const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize;\n const isEmpty = !node.isLeaf && !node.childCount;\n\n if ((hasAnchor || !this.options.showOnlyCurrent) && isEmpty) {\n const classes = [this.options.emptyNodeClass];\n\n // TODO: Doesn't work?\n if (this.editor.isEmpty) {\n classes.push(this.options.emptyEditorClass);\n }\n\n if (hasAnchor) {\n classes.push(this.options.hasAnchorClass);\n }\n\n // If slash menu is of drag type and active, show the filter placeholder\n if (menuState?.triggerCharacter === \"\" && menuState?.active) {\n classes.push(this.options.isFilterClass);\n }\n // using widget, didn't work (caret position bug)\n // const decoration = Decoration.widget(\n // pos + 1,\n // () => {\n // const el = document.createElement(\"span\");\n // el.innerText = \"hello\";\n // return el;\n // },\n // { side: 0 }\n\n // Code that sets variables / classes\n // const ph =\n // typeof this.options.placeholder === \"function\"\n // ? this.options.placeholder({\n // editor: this.editor,\n // node,\n // pos,\n // hasAnchor,\n // })\n // : this.options.placeholder;\n // const decoration = Decoration.node(pos, pos + node.nodeSize, {\n // class: classes.join(\" \"),\n // style: `--placeholder:'${ph.replaceAll(\"'\", \"\\\\'\")}';`,\n // \"data-placeholder\": ph,\n // });\n\n // Latest version, only set isEmpty and hasAnchor, rest is done via CSS\n\n const decoration = Decoration.node(pos, pos + node.nodeSize, {\n class: classes.join(\" \"),\n });\n decorations.push(decoration);\n }\n\n return this.options.includeChildren;\n });\n\n return DecorationSet.create(doc, decorations);\n },\n },\n }),\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { getBlockInfoFromPos } from \"../Blocks/helpers/getBlockInfoFromPos\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n textAlignment: {\n setTextAlignment: (\n textAlignment: \"left\" | \"center\" | \"right\" | \"justify\"\n ) => ReturnType;\n };\n }\n}\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) => element.getAttribute(\"data-text-alignment\"),\n renderHTML: (attributes) =>\n attributes.textAlignment !== \"left\" && {\n \"data-text-alignment\": attributes.textAlignment,\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setTextAlignment:\n (textAlignment) =>\n ({ state }) => {\n const positionsBeforeSelectedContent = [];\n\n const blockInfo = getBlockInfoFromPos(\n state.doc,\n state.selection.from\n );\n if (blockInfo === undefined) {\n return false;\n }\n\n // Finds all blockContent nodes that the current selection is in.\n let pos = blockInfo.startPos;\n while (pos < state.selection.to) {\n if (\n state.doc.resolve(pos).node().type.spec.group === \"blockContent\"\n ) {\n positionsBeforeSelectedContent.push(pos - 1);\n\n pos += state.doc.resolve(pos).node().nodeSize - 1;\n } else {\n pos += 1;\n }\n }\n\n // Sets text alignment for all blockContent nodes that the current selection is in.\n for (const pos of positionsBeforeSelectedContent) {\n state.tr.setNodeAttribute(pos, \"textAlignment\", textAlignment);\n }\n\n return true;\n },\n };\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { getBlockInfoFromPos } from \"../Blocks/helpers/getBlockInfoFromPos\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n blockTextColor: {\n setBlockTextColor: (posInBlock: number, color: string) => ReturnType;\n };\n }\n}\n\nexport const TextColorExtension = Extension.create({\n name: \"blockTextColor\",\n\n addGlobalAttributes() {\n return [\n {\n types: [\"blockContainer\"],\n attributes: {\n textColor: {\n default: \"default\",\n parseHTML: (element) =>\n element.hasAttribute(\"data-text-color\")\n ? element.getAttribute(\"data-text-color\")\n : \"default\",\n renderHTML: (attributes) =>\n attributes.textColor !== \"default\" && {\n \"data-text-color\": attributes.textColor,\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setBlockTextColor:\n (posInBlock, color) =>\n ({ state, view }) => {\n const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);\n if (blockInfo === undefined) {\n return false;\n }\n\n state.tr.setNodeAttribute(blockInfo.startPos - 1, \"textColor\", color);\n\n view.focus();\n\n return true;\n },\n };\n },\n});\n","import { Mark } from \"@tiptap/core\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n textColor: {\n setTextColor: (color: string) => ReturnType;\n };\n }\n}\n\nexport const TextColorMark = Mark.create({\n name: \"textColor\",\n\n addAttributes() {\n return {\n color: {\n default: undefined,\n parseHTML: (element) => element.getAttribute(\"data-text-color\"),\n renderHTML: (attributes) => ({\n \"data-text-color\": attributes.color,\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 { color: 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 addCommands() {\n return {\n setTextColor:\n (color) =>\n ({ commands }) => {\n if (color !== \"default\") {\n return commands.setMark(this.name, { color: color });\n }\n\n return commands.unsetMark(this.name);\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 return lastNode.nodeSize > 4; // empty <block><content/></block> is length 4\n },\n },\n }),\n ];\n },\n});\n","import { Extensions, extensions } from \"@tiptap/core\";\n\nimport { BlockNoteEditor } from \"./BlockNoteEditor\";\n\nimport { Bold } from \"@tiptap/extension-bold\";\nimport { Code } from \"@tiptap/extension-code\";\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 { Italic } from \"@tiptap/extension-italic\";\nimport { Link } from \"@tiptap/extension-link\";\nimport { Strike } from \"@tiptap/extension-strike\";\nimport { Text } from \"@tiptap/extension-text\";\nimport { Underline } from \"@tiptap/extension-underline\";\nimport * as Y from \"yjs\";\nimport styles from \"./editor.module.css\";\nimport { BackgroundColorExtension } from \"./extensions/BackgroundColor/BackgroundColorExtension\";\nimport { BackgroundColorMark } from \"./extensions/BackgroundColor/BackgroundColorMark\";\nimport { blocks } from \"./extensions/Blocks\";\nimport { BlockSchema } from \"./extensions/Blocks/api/blockTypes\";\nimport { CustomBlockSerializerExtension } from \"./extensions/Blocks/api/serialization\";\nimport blockStyles from \"./extensions/Blocks/nodes/Block.module.css\";\nimport { Placeholder } from \"./extensions/Placeholder/PlaceholderExtension\";\nimport { TextAlignmentExtension } from \"./extensions/TextAlignment/TextAlignmentExtension\";\nimport { TextColorExtension } from \"./extensions/TextColor/TextColorExtension\";\nimport { TextColorMark } from \"./extensions/TextColor/TextColorMark\";\nimport { TrailingNode } from \"./extensions/TrailingNode/TrailingNodeExtension\";\nimport UniqueID from \"./extensions/UniqueID/UniqueID\";\n\n/**\n * Get all the Tiptap extensions BlockNote is configured with by default\n */\nexport const getBlockNoteExtensions = <BSchema extends BlockSchema>(opts: {\n editor: BlockNoteEditor<BSchema>;\n blockSchema: BSchema;\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 emptyNodeClass: blockStyles.isEmpty,\n hasAnchorClass: blockStyles.hasAnchor,\n isFilterClass: blockStyles.isFilter,\n includeChildren: true,\n showOnlyCurrent: false,\n }),\n UniqueID.configure({\n types: [\"blockContainer\"],\n }),\n HardBreak,\n // Comments,\n\n // basics:\n Text,\n\n // marks:\n Bold,\n Code,\n Italic,\n Strike,\n Underline,\n Link,\n TextColorMark,\n TextColorExtension,\n BackgroundColorMark,\n BackgroundColorExtension,\n TextAlignmentExtension,\n\n // custom blocks:\n ...blocks,\n ...Object.values(opts.blockSchema).map((blockSpec) =>\n blockSpec.node.configure({ editor: opts.editor })\n ),\n CustomBlockSerializerExtension,\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 const defaultRender = (user: { color: string; name: string }) => {\n const cursor = document.createElement(\"span\");\n\n cursor.classList.add(styles[\"collaboration-cursor__caret\"]);\n cursor.setAttribute(\"style\", `border-color: ${user.color}`);\n\n const label = document.createElement(\"span\");\n\n label.classList.add(styles[\"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 } 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 { 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 { Editor } from \"@tiptap/core\";\nimport { Node } from \"prosemirror-model\";\nimport {\n BlockIdentifier,\n BlockSchema,\n PartialBlock,\n} from \"../../extensions/Blocks/api/blockTypes\";\nimport { blockToNode } from \"../nodeConversions/nodeConversions\";\nimport { getNodeById } from \"../util/nodeUtil\";\n\nexport function insertBlocks<BSchema extends BlockSchema>(\n blocksToInsert: PartialBlock<BSchema>[],\n referenceBlock: BlockIdentifier,\n placement: \"before\" | \"after\" | \"nested\" = \"before\",\n editor: Editor\n): void {\n const id =\n typeof referenceBlock === \"string\" ? referenceBlock : referenceBlock.id;\n\n const nodesToInsert: Node[] = [];\n for (const blockSpec of blocksToInsert) {\n nodesToInsert.push(blockToNode(blockSpec, editor.schema));\n }\n\n let insertionPos = -1;\n\n const { node, posBeforeNode } = getNodeById(id, editor.state.doc);\n\n if (placement === \"before\") {\n insertionPos = posBeforeNode;\n }\n\n if (placement === \"after\") {\n insertionPos = posBeforeNode + node.nodeSize;\n }\n\n if (placement === \"nested\") {\n // Case if block doesn't already have children.\n if (node.childCount < 2) {\n insertionPos = posBeforeNode + node.firstChild!.nodeSize + 1;\n\n const blockGroupNode = editor.state.schema.nodes[\"blockGroup\"].create(\n {},\n nodesToInsert\n );\n\n editor.view.dispatch(\n editor.state.tr.insert(insertionPos, blockGroupNode)\n );\n\n return;\n }\n\n insertionPos = posBeforeNode + node.firstChild!.nodeSize + 2;\n }\n\n editor.view.dispatch(editor.state.tr.insert(insertionPos, nodesToInsert));\n}\n\nexport function updateBlock<BSchema extends BlockSchema>(\n blockToUpdate: BlockIdentifier,\n update: PartialBlock<BSchema>,\n editor: Editor\n) {\n const id =\n typeof blockToUpdate === \"string\" ? blockToUpdate : blockToUpdate.id;\n const { posBeforeNode } = getNodeById(id, editor.state.doc);\n\n editor.commands.BNUpdateBlock(posBeforeNode + 1, update);\n}\n\nexport function removeBlocks(\n blocksToRemove: BlockIdentifier[],\n editor: Editor\n) {\n const idsOfBlocksToRemove = new Set<string>(\n blocksToRemove.map((block) =>\n typeof block === \"string\" ? block : block.id\n )\n );\n\n let removedSize = 0;\n\n editor.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 idsOfBlocksToRemove.delete(node.attrs.id);\n const oldDocSize = editor.state.doc.nodeSize;\n\n editor.commands.BNDeleteBlock(pos - removedSize + 1);\n\n const newDocSize = editor.state.doc.nodeSize;\n removedSize += oldDocSize - newDocSize;\n\n return false;\n });\n\n if (idsOfBlocksToRemove.size > 0) {\n let 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\nexport function replaceBlocks<BSchema extends BlockSchema>(\n blocksToRemove: BlockIdentifier[],\n blocksToInsert: PartialBlock<BSchema>[],\n editor: Editor\n) {\n insertBlocks(blocksToInsert, blocksToRemove[0], \"before\", editor);\n removeBlocks(blocksToRemove, editor);\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 { 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 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 { DOMParser, DOMSerializer, Schema } from \"prosemirror-model\";\nimport rehypeParse from \"rehype-parse\";\nimport rehypeRemark from \"rehype-remark\";\nimport rehypeStringify from \"rehype-stringify\";\nimport remarkGfm from \"remark-gfm\";\nimport remarkParse from \"remark-parse\";\nimport remarkRehype from \"remark-rehype\";\nimport remarkStringify from \"remark-stringify\";\nimport { unified } from \"unified\";\nimport { Block, BlockSchema } from \"../../extensions/Blocks/api/blockTypes\";\n\nimport { blockToNode, nodeToBlock } from \"../nodeConversions/nodeConversions\";\nimport { removeUnderlines } from \"./removeUnderlinesRehypePlugin\";\nimport { simplifyBlocks } from \"./simplifyBlocksRehypePlugin\";\n\nexport async function blocksToHTML<BSchema extends BlockSchema>(\n blocks: Block<BSchema>[],\n schema: Schema\n): Promise<string> {\n const htmlParentElement = document.createElement(\"div\");\n const serializer = DOMSerializer.fromSchema(schema);\n\n for (const block of blocks) {\n const node = blockToNode(block, schema);\n const htmlNode = serializer.serializeNode(node);\n htmlParentElement.appendChild(htmlNode);\n }\n\n const htmlString = await 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 .process(htmlParentElement.innerHTML);\n\n return htmlString.value as string;\n}\n\nexport async function HTMLToBlocks<BSchema extends BlockSchema>(\n html: string,\n blockSchema: BSchema,\n schema: Schema\n): Promise<Block<BSchema>[]> {\n const htmlNode = document.createElement(\"div\");\n htmlNode.innerHTML = html.trim();\n\n const parser = DOMParser.fromSchema(schema);\n const parentNode = parser.parse(htmlNode);\n\n const blocks: Block<BSchema>[] = [];\n\n for (let i = 0; i < parentNode.firstChild!.childCount; i++) {\n blocks.push(nodeToBlock(parentNode.firstChild!.child(i), blockSchema));\n }\n\n return blocks;\n}\n\nexport async function blocksToMarkdown<BSchema extends BlockSchema>(\n blocks: Block<BSchema>[],\n schema: Schema\n): Promise<string> {\n const markdownString = await unified()\n .use(rehypeParse, { fragment: true })\n .use(removeUnderlines)\n .use(rehypeRemark)\n .use(remarkGfm)\n .use(remarkStringify)\n .process(await blocksToHTML(blocks, schema));\n\n return markdownString.value as string;\n}\n\nexport async function markdownToBlocks<BSchema extends BlockSchema>(\n markdown: string,\n blockSchema: BSchema,\n schema: Schema\n): Promise<Block<BSchema>[]> {\n const htmlString = await unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkRehype)\n .use(rehypeStringify)\n .process(markdown);\n\n return HTMLToBlocks(htmlString.value as string, blockSchema, schema);\n}\n","import { isNodeSelection, isTextSelection, posToDOMRect } from \"@tiptap/core\";\nimport { EditorState, Plugin, PluginKey } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\nimport {\n BaseUiElementCallbacks,\n BaseUiElementState,\n BlockNoteEditor,\n BlockSchema,\n} from \"../..\";\nimport { EventEmitter } from \"../../shared/EventEmitter\";\n\nexport type FormattingToolbarCallbacks = BaseUiElementCallbacks;\n\nexport type FormattingToolbarState = BaseUiElementState;\n\nexport class FormattingToolbarView<BSchema extends BlockSchema> {\n private formattingToolbarState?: FormattingToolbarState;\n public updateFormattingToolbar: () => 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 = ({ view, state, from, to }) => {\n const { doc, selection } = state;\n const { empty } = selection;\n\n // Sometime check for `empty` is not enough.\n // Doubleclick an empty paragraph returns a node size of 2.\n // So we check also for an empty text size.\n const isEmptyTextBlock =\n !doc.textBetween(from, to).length && isTextSelection(state.selection);\n\n return !(!view.hasFocus() || empty || isEmptyTextBlock);\n };\n\n constructor(\n private readonly editor: BlockNoteEditor<BSchema>,\n private readonly pmView: EditorView,\n updateFormattingToolbar: (\n formattingToolbarState: FormattingToolbarState\n ) => void\n ) {\n this.updateFormattingToolbar = () => {\n if (!this.formattingToolbarState) {\n throw new Error(\n \"Attempting to update uninitialized formatting toolbar\"\n );\n }\n\n updateFormattingToolbar(this.formattingToolbarState);\n };\n\n pmView.dom.addEventListener(\"mousedown\", this.viewMousedownHandler);\n pmView.dom.addEventListener(\"mouseup\", this.viewMouseupHandler);\n pmView.dom.addEventListener(\"dragstart\", this.dragstartHandler);\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 dragstartHandler = () => {\n if (this.formattingToolbarState?.show) {\n this.formattingToolbarState.show = false;\n this.updateFormattingToolbar();\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.formattingToolbarState?.show) {\n this.formattingToolbarState.show = false;\n this.updateFormattingToolbar();\n }\n };\n\n scrollHandler = () => {\n if (this.formattingToolbarState?.show) {\n this.formattingToolbarState.referencePos = this.getSelectionBoundingBox();\n this.updateFormattingToolbar();\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.formattingToolbarState = {\n show: true,\n referencePos: this.getSelectionBoundingBox(),\n };\n\n this.updateFormattingToolbar();\n\n return;\n }\n\n // Checks if menu should be hidden.\n if (\n this.formattingToolbarState?.show &&\n !this.preventHide &&\n (!shouldShow || this.preventShow || !this.editor.isEditable)\n ) {\n this.formattingToolbarState.show = false;\n this.updateFormattingToolbar();\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.dragstartHandler);\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<\n BSchema extends BlockSchema\n> extends EventEmitter<any> {\n private view: FormattingToolbarView<BSchema> | undefined;\n public readonly plugin: Plugin;\n\n constructor(editor: BlockNoteEditor<BSchema>) {\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\";\nimport { BlockNoteEditor } from \"../../BlockNoteEditor\";\nimport { BaseUiElementState } from \"../../shared/BaseUiElementTypes\";\nimport { EventEmitter } from \"../../shared/EventEmitter\";\nimport { BlockSchema } from \"../Blocks/api/blockTypes\";\n\nexport type HyperlinkToolbarState = BaseUiElementState & {\n // The hovered hyperlink's URL, and the text it's displayed with in the\n // editor.\n url: string;\n text: string;\n};\n\nclass HyperlinkToolbarView<BSchema extends BlockSchema> {\n private hyperlinkToolbarState?: HyperlinkToolbarState;\n public updateHyperlinkToolbar: () => void;\n\n menuUpdateTimer: NodeJS.Timeout | undefined;\n startMenuUpdateTimer: () => void;\n stopMenuUpdateTimer: () => void;\n\n mouseHoveredHyperlinkMark: Mark | undefined;\n mouseHoveredHyperlinkMarkRange: Range | undefined;\n\n keyboardHoveredHyperlinkMark: Mark | undefined;\n keyboardHoveredHyperlinkMarkRange: Range | undefined;\n\n hyperlinkMark: Mark | undefined;\n hyperlinkMarkRange: Range | undefined;\n\n constructor(\n private readonly editor: BlockNoteEditor<BSchema>,\n private readonly pmView: EditorView,\n updateHyperlinkToolbar: (\n hyperlinkToolbarState: HyperlinkToolbarState\n ) => void\n ) {\n this.updateHyperlinkToolbar = () => {\n if (!this.hyperlinkToolbarState) {\n throw new Error(\"Attempting to update uninitialized hyperlink toolbar\");\n }\n\n updateHyperlinkToolbar(this.hyperlinkToolbarState);\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 hyperlink mark currently hovered by the mouse cursor.\n this.mouseHoveredHyperlinkMark = undefined;\n this.mouseHoveredHyperlinkMarkRange = 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 mouseHoveredHyperlinkMark and\n // mouseHoveredHyperlinkMarkRange.\n const hoveredHyperlinkElement = event.target;\n const posInHoveredHyperlinkMark =\n this.pmView.posAtDOM(hoveredHyperlinkElement, 0) + 1;\n const resolvedPosInHoveredHyperlinkMark = this.pmView.state.doc.resolve(\n posInHoveredHyperlinkMark\n );\n const marksAtPos = resolvedPosInHoveredHyperlinkMark.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.mouseHoveredHyperlinkMark = mark;\n this.mouseHoveredHyperlinkMarkRange =\n getMarkRange(\n resolvedPosInHoveredHyperlinkMark,\n mark.type,\n 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.hyperlinkMark &&\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.hyperlinkToolbarState?.show) {\n this.hyperlinkToolbarState.show = false;\n this.updateHyperlinkToolbar();\n }\n }\n };\n\n scrollHandler = () => {\n if (this.hyperlinkMark !== undefined) {\n if (this.hyperlinkToolbarState?.show) {\n this.hyperlinkToolbarState.referencePos = posToDOMRect(\n this.pmView,\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.to\n );\n this.updateHyperlinkToolbar();\n }\n }\n };\n\n editHyperlink(url: string, text: string) {\n const tr = this.pmView.state.tr.insertText(\n text,\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.to\n );\n tr.addMark(\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.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.hyperlinkToolbarState?.show) {\n this.hyperlinkToolbarState.show = false;\n this.updateHyperlinkToolbar();\n }\n }\n\n deleteHyperlink() {\n this.pmView.dispatch(\n this.pmView.state.tr\n .removeMark(\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.to,\n this.hyperlinkMark!.type\n )\n .setMeta(\"preventAutolink\", true)\n );\n this.pmView.focus();\n\n if (this.hyperlinkToolbarState?.show) {\n this.hyperlinkToolbarState.show = false;\n this.updateHyperlinkToolbar();\n }\n }\n\n update() {\n if (!this.pmView.hasFocus()) {\n return;\n }\n\n // Saves the currently hovered hyperlink mark before it's updated.\n const prevHyperlinkMark = this.hyperlinkMark;\n\n // Resets the currently hovered hyperlink mark.\n this.hyperlinkMark = undefined;\n this.hyperlinkMarkRange = undefined;\n\n // Resets the hyperlink mark currently hovered by the keyboard cursor.\n this.keyboardHoveredHyperlinkMark = undefined;\n this.keyboardHoveredHyperlinkMarkRange = undefined;\n\n // Finds link mark at the editor selection's position to update keyboardHoveredHyperlinkMark and\n // keyboardHoveredHyperlinkMarkRange.\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.keyboardHoveredHyperlinkMark = mark;\n this.keyboardHoveredHyperlinkMarkRange =\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.mouseHoveredHyperlinkMark) {\n this.hyperlinkMark = this.mouseHoveredHyperlinkMark;\n this.hyperlinkMarkRange = this.mouseHoveredHyperlinkMarkRange;\n }\n\n // Keyboard cursor position takes precedence over mouse hovered hyperlink.\n if (this.keyboardHoveredHyperlinkMark) {\n this.hyperlinkMark = this.keyboardHoveredHyperlinkMark;\n this.hyperlinkMarkRange = this.keyboardHoveredHyperlinkMarkRange;\n }\n\n if (this.hyperlinkMark && this.editor.isEditable) {\n this.hyperlinkToolbarState = {\n show: true,\n referencePos: posToDOMRect(\n this.pmView,\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.to\n ),\n url: this.hyperlinkMark!.attrs.href,\n text: this.pmView.state.doc.textBetween(\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.to\n ),\n };\n this.updateHyperlinkToolbar();\n\n return;\n }\n\n // Hides menu.\n if (\n this.hyperlinkToolbarState?.show &&\n prevHyperlinkMark &&\n (!this.hyperlinkMark || !this.editor.isEditable)\n ) {\n this.hyperlinkToolbarState.show = false;\n this.updateHyperlinkToolbar();\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 hyperlinkToolbarPluginKey = new PluginKey(\n \"HyperlinkToolbarPlugin\"\n);\n\nexport class HyperlinkToolbarProsemirrorPlugin<\n BSchema extends BlockSchema\n> extends EventEmitter<any> {\n private view: HyperlinkToolbarView<BSchema> | undefined;\n public readonly plugin: Plugin;\n\n constructor(editor: BlockNoteEditor<BSchema>) {\n super();\n this.plugin = new Plugin({\n key: hyperlinkToolbarPluginKey,\n view: (editorView) => {\n this.view = new HyperlinkToolbarView(editor, editorView, (state) => {\n this.emit(\"update\", state);\n });\n return this.view;\n },\n });\n }\n\n public onUpdate(callback: (state: HyperlinkToolbarState) => void) {\n return this.on(\"update\", callback);\n }\n\n /**\n * Edit the currently hovered hyperlink.\n */\n public editHyperlink = (url: string, text: string) => {\n this.view!.editHyperlink(url, text);\n };\n\n /**\n * Delete the currently hovered hyperlink.\n */\n public deleteHyperlink = () => {\n this.view!.deleteHyperlink();\n };\n\n /**\n * When hovering on/off hyperlinks using the mouse cursor, the hyperlink\n * toolbar will open & close with a delay.\n *\n * This function starts the delay timer, and should be used for when the mouse cursor enters the hyperlink toolbar.\n */\n public startHideTimer = () => {\n this.view!.startMenuUpdateTimer();\n };\n\n /**\n * When hovering on/off hyperlinks using the mouse cursor, the hyperlink\n * toolbar will open & close with a delay.\n *\n * This function stops the delay timer, and should be used for when the mouse cursor exits the hyperlink toolbar.\n */\n public stopHideTimer = () => {\n this.view!.stopMenuUpdateTimer();\n };\n}\n","import { Selection } from \"prosemirror-state\";\nimport { Fragment, Node, ResolvedPos, Slice } from \"prosemirror-model\";\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 let fromResult = mapping.mapResult(this.from);\n let 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 * as pv from \"prosemirror-view\";\nimport { EditorView } from \"prosemirror-view\";\nimport { BlockNoteEditor } from \"../../BlockNoteEditor\";\nimport styles from \"../../editor.module.css\";\nimport { BaseUiElementState } from \"../../shared/BaseUiElementTypes\";\nimport { EventEmitter } from \"../../shared/EventEmitter\";\nimport { Block, BlockSchema } from \"../Blocks/api/blockTypes\";\nimport { getBlockInfoFromPos } from \"../Blocks/helpers/getBlockInfoFromPos\";\nimport { slashMenuPluginKey } from \"../SlashMenu/SlashMenuPlugin\";\nimport { MultipleNodeSelection } from \"./MultipleNodeSelection\";\n\nconst serializeForClipboard = (pv as any).__serializeForClipboard;\n// code based on https://github.com/ueberdosis/tiptap/issues/323#issuecomment-506637799\n\nlet dragImageElement: Element | undefined;\n\nexport type SideMenuState<BSchema extends BlockSchema> = BaseUiElementState & {\n // The block that the side menu is attached to.\n block: Block<BSchema>;\n};\n\nfunction 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 let 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 let 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 let 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.includes(\"bn\") &&\n !className.includes(\"ProseMirror\") &&\n !className.includes(\"editor\")\n )\n .join(\" \");\n\n dragImageElement.className =\n dragImageElement.className +\n \" \" +\n styles.dragPreview +\n \" \" +\n 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 e: { dataTransfer: DataTransfer | null; clientY: number },\n view: EditorView\n) {\n if (!e.dataTransfer) {\n return;\n }\n\n const editorBoundingBox = view.dom.getBoundingClientRect();\n\n let coords = {\n left: editorBoundingBox.left + editorBoundingBox.width / 2, // take middle of editor\n top: e.clientY,\n };\n\n let 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 let slice = view.state.selection.content();\n let { dom, text } = serializeForClipboard(view, slice);\n\n e.dataTransfer.clearData();\n e.dataTransfer.setData(\"text/html\", dom.innerHTML);\n e.dataTransfer.setData(\"text/plain\", text);\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setDragImage(dragImageElement!, 0, 0);\n view.dragging = { slice, move: true };\n }\n}\n\nexport class SideMenuView<BSchema extends BlockSchema> implements PluginView {\n private sideMenuState?: SideMenuState<BSchema>;\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>,\n private readonly pmView: EditorView,\n private readonly updateSideMenu: (\n sideMenuState: SideMenuState<BSchema>\n ) => void\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 // 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 let 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 let 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.sideMenuState?.show) {\n this.sideMenuState.show = false;\n this.updateSideMenu(this.sideMenuState);\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.sideMenuState?.show) {\n this.sideMenuState.show = false;\n this.updateSideMenu(this.sideMenuState);\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.sideMenuState?.show) {\n this.sideMenuState.show = false;\n this.updateSideMenu(this.sideMenuState);\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.sideMenuState?.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.sideMenuState = {\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.updateSideMenu(this.sideMenuState);\n }\n };\n\n onScroll = () => {\n if (this.sideMenuState?.show) {\n const blockContent = this.hoveredBlock!.firstChild as HTMLElement;\n const blockContentBoundingBox = blockContent.getBoundingClientRect();\n\n this.sideMenuState.referencePos = new DOMRect(\n this.horizontalPosAnchoredAtRoot\n ? this.horizontalPosAnchor\n : blockContentBoundingBox.x,\n blockContentBoundingBox.y,\n blockContentBoundingBox.width,\n blockContentBoundingBox.height\n );\n this.updateSideMenu(this.sideMenuState);\n }\n };\n\n destroy() {\n if (this.sideMenuState?.show) {\n this.sideMenuState.show = false;\n this.updateSideMenu(this.sideMenuState);\n }\n document.body.removeEventListener(\"mousemove\", this.onMouseMove);\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(\"keydown\", this.onKeyDown, true);\n }\n\n addBlock() {\n if (this.sideMenuState?.show) {\n this.sideMenuState.show = false;\n this.updateSideMenu(this.sideMenuState);\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, endPos } = blockInfo;\n\n // Creates a new block if current one is not empty for the suggestion menu to open in.\n if (contentNode.textContent.length !== 0) {\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(endPos);\n }\n\n // Focuses and activates the suggestion menu.\n this.pmView.focus();\n this.pmView.dispatch(\n this.pmView.state.tr.scrollIntoView().setMeta(slashMenuPluginKey, {\n // TODO import suggestion plugin key\n activate: true,\n type: \"drag\",\n })\n );\n }\n}\n\nexport const sideMenuPluginKey = new PluginKey(\"SideMenuPlugin\");\n\nexport class SideMenuProsemirrorPlugin<\n BSchema extends BlockSchema\n> extends EventEmitter<any> {\n private sideMenuView: SideMenuView<BSchema> | undefined;\n public readonly plugin: Plugin;\n\n constructor(private readonly editor: BlockNoteEditor<BSchema>) {\n super();\n this.plugin = new Plugin({\n key: sideMenuPluginKey,\n view: (editorView) => {\n this.sideMenuView = new SideMenuView(\n editor,\n editorView,\n (sideMenuState) => {\n this.emit(\"update\", sideMenuState);\n }\n );\n return this.sideMenuView;\n },\n });\n }\n\n public onUpdate(callback: (state: SideMenuState<BSchema>) => 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.sideMenuView!.addBlock();\n\n /**\n * Handles drag & drop events for blocks.\n */\n blockDragStart = (event: {\n dataTransfer: DataTransfer | null;\n clientY: number;\n }) => {\n this.sideMenuView!.isDragging = true;\n dragStart(event, this.editor.prosemirrorView);\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.sideMenuView!.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.sideMenuView!.menuFrozen = false);\n}\n","import { BlockNoteEditor } from \"../../BlockNoteEditor\";\nimport { BlockSchema, PartialBlock } from \"../Blocks/api/blockTypes\";\nimport { BaseSlashMenuItem } from \"./BaseSlashMenuItem\";\nimport { defaultBlockSchema } from \"../Blocks/api/defaultBlocks\";\n\nfunction insertOrUpdateBlock<BSchema extends BlockSchema>(\n editor: BlockNoteEditor<BSchema>,\n block: PartialBlock<BSchema>\n) {\n const currentBlock = editor.getTextCursorPosition().block;\n\n if (\n (currentBlock.content.length === 1 &&\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(editor.getTextCursorPosition().nextBlock!);\n }\n}\n\nexport const getDefaultSlashMenuItems = <BSchema extends BlockSchema>(\n // This type casting is weird, but it's the best way of doing it, as it allows\n // the schema type to be automatically inferred if it is defined, or be\n // inferred as any if it is not defined. I don't think it's possible to make it\n // infer to DefaultBlockSchema if it is not defined.\n schema: BSchema = defaultBlockSchema as unknown as BSchema\n) => {\n const slashMenuItems: BaseSlashMenuItem<BSchema>[] = [];\n\n if (\"heading\" in schema && \"level\" in schema.heading.propSchema) {\n // Command for creating a level 1 heading\n if (schema.heading.propSchema.level.values?.includes(\"1\")) {\n slashMenuItems.push({\n name: \"Heading\",\n aliases: [\"h\", \"heading1\", \"h1\"],\n execute: (editor) =>\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: \"1\" },\n } as PartialBlock<BSchema>),\n });\n }\n\n // Command for creating a level 2 heading\n if (schema.heading.propSchema.level.values?.includes(\"2\")) {\n slashMenuItems.push({\n name: \"Heading 2\",\n aliases: [\"h2\", \"heading2\", \"subheading\"],\n execute: (editor) =>\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: \"2\" },\n } as PartialBlock<BSchema>),\n });\n }\n\n // Command for creating a level 3 heading\n if (schema.heading.propSchema.level.values?.includes(\"3\")) {\n slashMenuItems.push({\n name: \"Heading 3\",\n aliases: [\"h3\", \"heading3\", \"subheading\"],\n execute: (editor) =>\n insertOrUpdateBlock(editor, {\n type: \"heading\",\n props: { level: \"3\" },\n } as PartialBlock<BSchema>),\n });\n }\n }\n\n if (\"bulletListItem\" in schema) {\n slashMenuItems.push({\n name: \"Bullet List\",\n aliases: [\"ul\", \"list\", \"bulletlist\", \"bullet list\"],\n execute: (editor) =>\n insertOrUpdateBlock(editor, {\n type: \"bulletListItem\",\n } as PartialBlock<BSchema>),\n });\n }\n\n if (\"numberedListItem\" in schema) {\n slashMenuItems.push({\n name: \"Numbered List\",\n aliases: [\"li\", \"list\", \"numberedlist\", \"numbered list\"],\n execute: (editor) =>\n insertOrUpdateBlock(editor, {\n type: \"numberedListItem\",\n } as PartialBlock<BSchema>),\n });\n }\n\n if (\"paragraph\" in schema) {\n slashMenuItems.push({\n name: \"Paragraph\",\n aliases: [\"p\"],\n execute: (editor) =>\n insertOrUpdateBlock(editor, {\n type: \"paragraph\",\n } as PartialBlock<BSchema>),\n });\n }\n\n return slashMenuItems;\n};\n","import { Editor, EditorOptions, Extension } from \"@tiptap/core\";\nimport { Node } from \"prosemirror-model\";\n// import \"./blocknote.css\";\nimport { Editor as TiptapEditor } from \"@tiptap/core/dist/packages/core/src/Editor\";\nimport * as Y from \"yjs\";\nimport { getBlockNoteExtensions } from \"./BlockNoteExtensions\";\nimport {\n insertBlocks,\n removeBlocks,\n replaceBlocks,\n updateBlock,\n} from \"./api/blockManipulation/blockManipulation\";\nimport {\n HTMLToBlocks,\n blocksToHTML,\n blocksToMarkdown,\n markdownToBlocks,\n} from \"./api/formatConversions/formatConversions\";\nimport {\n blockToNode,\n nodeToBlock,\n} from \"./api/nodeConversions/nodeConversions\";\nimport { getNodeById } from \"./api/util/nodeUtil\";\nimport styles from \"./editor.module.css\";\nimport {\n Block,\n BlockIdentifier,\n BlockSchema,\n PartialBlock,\n} from \"./extensions/Blocks/api/blockTypes\";\nimport { TextCursorPosition } from \"./extensions/Blocks/api/cursorPositionTypes\";\nimport {\n DefaultBlockSchema,\n defaultBlockSchema,\n} from \"./extensions/Blocks/api/defaultBlocks\";\nimport {\n ColorStyle,\n Styles,\n ToggledStyle,\n} from \"./extensions/Blocks/api/inlineContentTypes\";\nimport { Selection } from \"./extensions/Blocks/api/selectionTypes\";\nimport { getBlockInfoFromPos } from \"./extensions/Blocks/helpers/getBlockInfoFromPos\";\n\nimport { FormattingToolbarProsemirrorPlugin } from \"./extensions/FormattingToolbar/FormattingToolbarPlugin\";\nimport { HyperlinkToolbarProsemirrorPlugin } from \"./extensions/HyperlinkToolbar/HyperlinkToolbarPlugin\";\nimport { SideMenuProsemirrorPlugin } from \"./extensions/SideMenu/SideMenuPlugin\";\nimport { BaseSlashMenuItem } from \"./extensions/SlashMenu/BaseSlashMenuItem\";\nimport { SlashMenuProsemirrorPlugin } from \"./extensions/SlashMenu/SlashMenuPlugin\";\nimport { getDefaultSlashMenuItems } from \"./extensions/SlashMenu/defaultSlashMenuItems\";\nimport { UniqueID } from \"./extensions/UniqueID/UniqueID\";\n\nexport type BlockNoteEditorOptions<BSchema extends BlockSchema> = {\n // TODO: Figure out if enableBlockNoteExtensions/disableHistoryExtension are needed and document them.\n enableBlockNoteExtensions: boolean;\n /**\n *\n * (couldn't fix any type, see https://github.com/TypeCellOS/BlockNote/pull/191#discussion_r1210708771)\n *\n * @default defaultSlashMenuItems from `./extensions/SlashMenu`\n */\n slashMenuItems: BaseSlashMenuItem<any>[];\n\n /**\n * The HTML element that should be used as the parent element for the editor.\n *\n * @default: undefined, the editor is not attached to the DOM\n */\n parentElement: HTMLElement;\n /**\n * An object containing attributes that should be added to the editor's HTML element.\n *\n * @example { class: \"my-editor-class\" }\n */\n editorDOMAttributes: Record<string, string>;\n /**\n * A callback function that runs when the editor is ready to be used.\n */\n onEditorReady: (editor: BlockNoteEditor<BSchema>) => void;\n /**\n * A callback function that runs whenever the editor's contents change.\n */\n onEditorContentChange: (editor: BlockNoteEditor<BSchema>) => void;\n /**\n * A callback function that runs whenever the text cursor position changes.\n */\n onTextCursorPositionChange: (editor: BlockNoteEditor<BSchema>) => void;\n /**\n * Locks the editor from being editable by the user if set to `false`.\n */\n editable: boolean;\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<BSchema>[];\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 * Whether to use the light or dark theme.\n *\n * @default \"light\"\n */\n theme: \"light\" | \"dark\";\n\n /**\n * A list of block types that should be available in the editor.\n */\n blockSchema: BSchema;\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: any;\n};\n\nconst blockNoteTipTapOptions = {\n enableInputRules: true,\n enablePasteRules: true,\n enableCoreExtensions: false,\n};\n\nexport class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {\n public readonly _tiptapEditor: TiptapEditor & { contentComponent: any };\n public blockCache = new WeakMap<Node, Block<BSchema>>();\n public readonly schema: BSchema;\n public ready = false;\n\n public readonly sideMenu: SideMenuProsemirrorPlugin<BSchema>;\n public readonly formattingToolbar: FormattingToolbarProsemirrorPlugin<BSchema>;\n public readonly slashMenu: SlashMenuProsemirrorPlugin<BSchema, any>;\n public readonly hyperlinkToolbar: HyperlinkToolbarProsemirrorPlugin<BSchema>;\n\n constructor(\n private readonly options: Partial<BlockNoteEditorOptions<BSchema>> = {}\n ) {\n // apply defaults\n const newOptions: Omit<typeof options, \"defaultStyles\" | \"blockSchema\"> & {\n defaultStyles: boolean;\n blockSchema: BSchema;\n } = {\n defaultStyles: true,\n // TODO: There's a lot of annoying typing stuff to deal with here. If\n // BSchema is specified, then options.blockSchema should also be required.\n // If BSchema is not specified, then options.blockSchema should also not\n // be defined. Unfortunately, trying to implement these constraints seems\n // to be a huge pain, hence the `as any` casts.\n blockSchema: options.blockSchema || (defaultBlockSchema as any),\n ...options,\n };\n\n this.sideMenu = new SideMenuProsemirrorPlugin(this);\n this.formattingToolbar = new FormattingToolbarProsemirrorPlugin(this);\n this.slashMenu = new SlashMenuProsemirrorPlugin(\n this,\n newOptions.slashMenuItems ||\n getDefaultSlashMenuItems(newOptions.blockSchema)\n );\n this.hyperlinkToolbar = new HyperlinkToolbarProsemirrorPlugin(this);\n\n const extensions = getBlockNoteExtensions<BSchema>({\n editor: this,\n blockSchema: newOptions.blockSchema,\n collaboration: newOptions.collaboration,\n });\n\n const blockNoteUIExtension = Extension.create({\n name: \"BlockNoteUIExtension\",\n\n addProseMirrorPlugins: () => {\n return [\n this.sideMenu.plugin,\n this.formattingToolbar.plugin,\n this.slashMenu.plugin,\n this.hyperlinkToolbar.plugin,\n ];\n },\n });\n extensions.push(blockNoteUIExtension);\n\n this.schema = newOptions.blockSchema;\n\n const initialContent = newOptions.initialContent || [\n {\n type: \"paragraph\",\n id: UniqueID.options.generateID(),\n },\n ];\n\n const tiptapOptions: EditorOptions = {\n ...blockNoteTipTapOptions,\n ...newOptions._tiptapOptions,\n onCreate: () => {\n newOptions.onEditorReady?.(this);\n this.ready = true;\n },\n onBeforeCreate(editor) {\n // we have to set the initial content here, because now we can use the editor schema\n // which has been created at this point\n const schema = editor.editor.schema;\n const ic = initialContent.map((block) => blockToNode(block, schema));\n\n const root = schema.node(\n \"doc\",\n undefined,\n schema.node(\"blockGroup\", undefined, ic)\n );\n // override the initialcontent\n editor.editor.options.content = root.toJSON();\n },\n onUpdate: () => {\n // This seems to be necessary due to a bug in TipTap:\n // https://github.com/ueberdosis/tiptap/issues/2583\n if (!this.ready) {\n return;\n }\n\n newOptions.onEditorContentChange?.(this);\n },\n onSelectionUpdate: () => {\n // This seems to be necessary due to a bug in TipTap:\n // https://github.com/ueberdosis/tiptap/issues/2583\n if (!this.ready) {\n return;\n }\n\n newOptions.onTextCursorPositionChange?.(this);\n },\n editable: options.editable === undefined ? true : options.editable,\n extensions:\n newOptions.enableBlockNoteExtensions === false\n ? newOptions._tiptapOptions?.extensions\n : [...(newOptions._tiptapOptions?.extensions || []), ...extensions],\n editorProps: {\n attributes: {\n \"data-theme\": options.theme || \"light\",\n ...(newOptions.editorDOMAttributes || {}),\n class: [\n styles.bnEditor,\n styles.bnRoot,\n newOptions.defaultStyles ? styles.defaultStyles : \"\",\n newOptions.editorDOMAttributes?.class || \"\",\n ].join(\" \"),\n },\n },\n };\n\n if (newOptions.parentElement) {\n tiptapOptions.element = newOptions.parentElement;\n }\n\n this._tiptapEditor = new Editor(tiptapOptions) as Editor & {\n contentComponent: any;\n };\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 * 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 topLevelBlocks(): Block<BSchema>[] {\n const blocks: Block<BSchema>[] = [];\n\n this._tiptapEditor.state.doc.firstChild!.descendants((node) => {\n blocks.push(nodeToBlock(node, this.schema, this.blockCache));\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> | undefined {\n const id =\n typeof blockIdentifier === \"string\"\n ? blockIdentifier\n : blockIdentifier.id;\n let newBlock: Block<BSchema> | 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(node, this.schema, this.blockCache);\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>) => boolean,\n reverse: boolean = false\n ): void {\n const blocks = this.topLevelBlocks.slice();\n\n if (reverse) {\n blocks.reverse();\n }\n\n function traverseBlockArray(blockArray: Block<BSchema>[]): 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<BSchema> {\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(node, this.schema, this.blockCache),\n prevBlock:\n prevNode === undefined\n ? undefined\n : nodeToBlock(prevNode, this.schema, this.blockCache),\n nextBlock:\n nextNode === undefined\n ? undefined\n : nodeToBlock(nextNode, this.schema, this.blockCache),\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 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 }\n\n /**\n * Gets a snapshot of the current selection.\n */\n public getSelection(): Selection<BSchema> | undefined {\n if (\n this._tiptapEditor.state.selection.from ===\n this._tiptapEditor.state.selection.to\n ) {\n return undefined;\n }\n\n const blocks: Block<BSchema>[] = [];\n\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,\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 this._tiptapEditor.setEditable(editable);\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>[],\n referenceBlock: BlockIdentifier,\n placement: \"before\" | \"after\" | \"nested\" = \"before\"\n ): void {\n insertBlocks(blocksToInsert, referenceBlock, placement, this._tiptapEditor);\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>\n ) {\n updateBlock(blockToUpdate, update, this._tiptapEditor);\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 removeBlocks(blocksToRemove, this._tiptapEditor);\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>[]\n ) {\n replaceBlocks(blocksToRemove, blocksToInsert, this._tiptapEditor);\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 = {};\n const marks = this._tiptapEditor.state.selection.$to.marks();\n\n const toggleStyles = new Set<ToggledStyle>([\n \"bold\",\n \"italic\",\n \"underline\",\n \"strike\",\n \"code\",\n ]);\n const colorStyles = new Set<ColorStyle>([\"textColor\", \"backgroundColor\"]);\n\n for (const mark of marks) {\n if (toggleStyles.has(mark.type.name as ToggledStyle)) {\n styles[mark.type.name as ToggledStyle] = true;\n } else if (colorStyles.has(mark.type.name as ColorStyle)) {\n styles[mark.type.name as ColorStyle] = mark.attrs.color;\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) {\n const toggleStyles = new Set<ToggledStyle>([\n \"bold\",\n \"italic\",\n \"underline\",\n \"strike\",\n \"code\",\n ]);\n const colorStyles = new Set<ColorStyle>([\"textColor\", \"backgroundColor\"]);\n\n this._tiptapEditor.view.focus();\n\n for (const [style, value] of Object.entries(styles)) {\n if (toggleStyles.has(style as ToggledStyle)) {\n this._tiptapEditor.commands.setMark(style);\n } else if (colorStyles.has(style as ColorStyle)) {\n this._tiptapEditor.commands.setMark(style, { color: value });\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) {\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) {\n const toggleStyles = new Set<ToggledStyle>([\n \"bold\",\n \"italic\",\n \"underline\",\n \"strike\",\n \"code\",\n ]);\n const colorStyles = new Set<ColorStyle>([\"textColor\", \"backgroundColor\"]);\n\n this._tiptapEditor.view.focus();\n\n for (const [style, value] of Object.entries(styles)) {\n if (toggleStyles.has(style as ToggledStyle)) {\n this._tiptapEditor.commands.toggleMark(style);\n } else if (colorStyles.has(style as ColorStyle)) {\n this._tiptapEditor.commands.toggleMark(style, { color: value });\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 let { 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 /**\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 blocksToHTML(blocks: Block<BSchema>[]): Promise<string> {\n return blocksToHTML(blocks, this._tiptapEditor.schema);\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 HTMLToBlocks(html: string): Promise<Block<BSchema>[]> {\n return HTMLToBlocks(html, this.schema, this._tiptapEditor.schema);\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 blocksToMarkdown(blocks: Block<BSchema>[]): Promise<string> {\n return blocksToMarkdown(blocks, this._tiptapEditor.schema);\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 markdownToBlocks(markdown: string): Promise<Block<BSchema>[]> {\n return markdownToBlocks(markdown, this.schema, this._tiptapEditor.schema);\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"],"names":["getBlockInfoFromPos","doc","posInBlock","$pos","maxDepth","node","depth","id","contentNode","contentType","numChildBlocks","startPos","endPos","BackgroundColorExtension","Extension","element","attributes","color","state","view","blockInfo","BackgroundColorMark","Mark","HTMLAttributes","commands","camelToDataKebab","str","propsToAttributes","blockConfig","tiptapAttributes","name","spec","parse","render","blockContent","attribute","value","contentDOM","createBlockSpec","createTipTapBlock","getPos","styles","editor","pos","blockIdentifier","block","rendered","config","Node","HeadingBlockContent","level","InputRule","chain","range","mergeAttributes","handleEnter","selectionEmpty","BulletListItemBlockContent","parent","PLUGIN_KEY","PluginKey","NumberedListIndexingPlugin","Plugin","_transactions","_oldState","newState","tr","modified","newIndex","isFirstBlockInDoc","prevBlockInfo","prevBlockContentNode","prevBlockIndex","NumberedListItemBlockContent","ParagraphBlockContent","defaultProps","defaultBlockSchema","removeDuplicates","array","by","seen","item","key","findDuplicates","items","filtered","el","index","UniqueID","v4","dragSourceElement","transformPasted","transactions","oldState","docChanges","transaction","filterTransactions","_a","_b","types","attributeName","generateID","transform","combineTransactionSteps","mapping","getChangedRanges","newRange","newNodes","findChildrenInRange","newIds","duplicatedNewIds","deleted","handleDragstart","event","slice","removeId","fragment","list","nodeWithoutId","Fragment","Slice","UnreachableCaseError","val","toggleStyles","colorStyles","styledTextToNodes","styledText","schema","marks","style","text","linkToNodes","link","linkMark","styledTextArrayToNodes","content","nodes","inlineContentToNodes","blockToNode","type","children","child","groupNode","contentNodeToInlineContent","currentContent","mark","nodeToBlock","blockSchema","blockCache","cachedBlock","props","attr","blockSpec","propSchema","i","nodeAttributes","PreviousBlockTypePlugin","timeout","_editorView","_prevState","prev","currentTransactionOriginalOldBlockAttrs","oldNodes","findChildren","oldNodesById","oldNode","oldContentNode","newContentNode","newAttrs","oldAttrs","pluginState","decorations","prevAttrs","decorationAttrs","nodeAttr","decoration","Decoration","DecorationSet","BlockAttributes","BlockContainer","attrs","HTMLAttr","dispatch","newBlock","childNodes","posBetweenBlocks","nextNodeIsBlock","prevNodeIsBlock","nextBlockInfo","childBlocksStart","childBlocksEnd","childBlocksRange","prevBlockEndPos","TextSelection","keepType","originalBlockContent","newBlockContent","newBlockInsertionPos","newBlockContentPos","selectionAtBlockStart","isParagraph","blockAtDocStart","blockEmpty","blockIndented","BlockGroup","blocks","customBlockSerializer","defaultSerializer","DOMSerializer","CustomBlockSerializerExtension","EventEmitter","__publicField","fn","args","callbacks","callback","findBlock","findParentNode","SuggestionsMenuView","pluginKey","updateSuggestionsMenu","decorationNode","getDefaultPluginState","prevState","next","started","stopped","changed","setupSuggestionsMenu","defaultTriggerCharacter","onSelectItem","suggestionsPluginView","deactivate","_c","_d","menuIsActive","triggerCharacter","queryStartPos","keyboardHoveredItemIndex","active","decorationId","blockNode","slashMenuPluginKey","SlashMenuProsemirrorPlugin","suggestions","query","aliases","alias","Placeholder","selection","menuState","anchor","hasAnchor","isEmpty","classes","TextAlignmentExtension","textAlignment","positionsBeforeSelectedContent","TextColorExtension","TextColorMark","TrailingNode","plugin","_","__","shouldInsertNodeAtEnd","endPosition","_state","lastNode","getBlockNoteExtensions","opts","ret","extensions","Gapcursor","blockStyles","HardBreak","Text","Bold","Code","Italic","Strike","Underline","Link","Dropcursor","Collaboration","defaultRender","user","cursor","label","nonbreakingSpace1","nonbreakingSpace2","CollaborationCursor","History","getNodeById","targetNode","posBeforeNode","insertBlocks","blocksToInsert","referenceBlock","placement","nodesToInsert","insertionPos","blockGroupNode","updateBlock","blockToUpdate","update","removeBlocks","blocksToRemove","idsOfBlocksToRemove","removedSize","oldDocSize","newDocSize","notFoundIds","replaceBlocks","removeUnderlines","removeUnderlinesHelper","tree","numChildElements","numElementsAdded","simplifyBlocks","options","listItemBlockTypes","simplifyBlocksHelper","activeList","blockContainer","blockGroup","isListItemBlock","listItemBlockType","numElementsRemoved","fromDom","listItemElement","blocksToHTML","htmlParentElement","serializer","htmlNode","unified","rehypeParse","rehypeStringify","HTMLToBlocks","html","parentNode","DOMParser","blocksToMarkdown","rehypeRemark","remarkGfm","remarkStringify","markdownToBlocks","markdown","htmlString","remarkParse","remarkRehype","FormattingToolbarView","pmView","updateFormattingToolbar","from","to","empty","isEmptyTextBlock","isTextSelection","editorWrapper","composing","isSame","ranges","shouldShow","isNodeSelection","posToDOMRect","formattingToolbarPluginKey","FormattingToolbarProsemirrorPlugin","editorView","HyperlinkToolbarView","updateHyperlinkToolbar","hoveredHyperlinkElement","posInHoveredHyperlinkMark","resolvedPosInHoveredHyperlinkMark","marksAtPos","getMarkRange","url","prevHyperlinkMark","hyperlinkToolbarPluginKey","HyperlinkToolbarProsemirrorPlugin","MultipleNodeSelection","Selection","$anchor","$head","_pos","fromResult","toResult","serializeForClipboard","pv","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","dom","SideMenuView","updateSideMenu","evt","_event","editorOuterBoundingBox","cursorWithinEditor","_e","blockContentBoundingBox","sideMenuPluginKey","SideMenuProsemirrorPlugin","sideMenuState","insertOrUpdateBlock","currentBlock","getDefaultSlashMenuItems","slashMenuItems","blockNoteTipTapOptions","BlockNoteEditor","newOptions","blockNoteUIExtension","initialContent","tiptapOptions","ic","root","Editor","reverse","traverseBlockArray","blockArray","nodeIndex","numNodes","prevNode","nextNode","targetBlock","editable"],"mappings":"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"}
|