@blocknote/core 0.2.2 → 0.2.4-alpha.7

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.
Files changed (89) hide show
  1. package/dist/blocknote.js +1061 -936
  2. package/dist/blocknote.js.map +1 -1
  3. package/dist/blocknote.umd.cjs +1 -1
  4. package/dist/blocknote.umd.cjs.map +1 -1
  5. package/dist/style.css +1 -1
  6. package/package.json +22 -29
  7. package/src/BlockNoteExtensions.ts +11 -10
  8. package/src/extensions/BackgroundColor/BackgroundColorExtension.ts +61 -0
  9. package/src/extensions/BackgroundColor/BackgroundColorMark.ts +62 -0
  10. package/src/extensions/Blocks/PreviousBlockTypePlugin.ts +112 -106
  11. package/src/extensions/Blocks/apiTypes.ts +48 -0
  12. package/src/extensions/Blocks/helpers/findBlock.ts +3 -1
  13. package/src/extensions/Blocks/helpers/getBlockInfoFromPos.ts +1 -1
  14. package/src/extensions/Blocks/index.ts +10 -8
  15. package/src/extensions/Blocks/nodes/Block.module.css +122 -35
  16. package/src/extensions/Blocks/{BlockAttributes.ts → nodes/BlockAttributes.ts} +0 -0
  17. package/src/extensions/Blocks/nodes/{Block.ts → BlockContainer.ts} +113 -119
  18. package/src/extensions/Blocks/nodes/{BlockTypes/HeadingBlock/HeadingContent.ts → BlockContent/HeadingBlockContent/HeadingBlockContent.ts} +16 -24
  19. package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +76 -0
  20. package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/ListItemKeyboardShortcuts.ts +47 -0
  21. package/src/extensions/Blocks/nodes/{BlockTypes/ListItemBlock/OrderedListItemIndexPlugin.ts → BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts} +10 -14
  22. package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +95 -0
  23. package/src/extensions/Blocks/nodes/{BlockTypes/TextBlock/TextContent.ts → BlockContent/ParagraphBlockContent/ParagraphBlockContent.ts} +7 -12
  24. package/src/extensions/Blocks/nodes/BlockGroup.ts +4 -4
  25. package/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.ts +9 -1
  26. package/src/extensions/DraggableBlocks/DraggableBlocksPlugin.ts +87 -42
  27. package/src/extensions/{Blocks → DraggableBlocks}/MultipleNodeSelection.ts +0 -0
  28. package/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.ts +20 -7
  29. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +51 -12
  30. package/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.ts +1 -1
  31. package/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts +3 -1
  32. package/src/extensions/Placeholder/PlaceholderExtension.ts +1 -1
  33. package/src/extensions/SlashMenu/SlashMenuExtension.ts +1 -1
  34. package/src/extensions/SlashMenu/SlashMenuItem.ts +3 -28
  35. package/src/extensions/SlashMenu/defaultCommands.tsx +36 -55
  36. package/src/extensions/SlashMenu/index.ts +1 -6
  37. package/src/extensions/TextAlignment/TextAlignmentExtension.ts +75 -0
  38. package/src/extensions/TextColor/TextColorExtension.ts +54 -0
  39. package/src/extensions/TextColor/TextColorMark.ts +62 -0
  40. package/src/extensions/TrailingNode/TrailingNodeExtension.ts +4 -4
  41. package/src/extensions/UniqueID/UniqueID.ts +6 -0
  42. package/src/index.ts +2 -1
  43. package/src/shared/EditorElement.ts +12 -6
  44. package/src/shared/plugins/suggestion/SuggestionItem.ts +0 -9
  45. package/src/shared/plugins/suggestion/SuggestionPlugin.ts +191 -228
  46. package/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.ts +2 -2
  47. package/types/src/BlockNoteEditor.d.ts +1 -1
  48. package/types/src/BlockNoteExtensions.d.ts +1 -3
  49. package/types/src/api/Document.d.ts +5 -0
  50. package/types/src/extensions/BackgroundColor/BackgroundColorExtension.d.ts +9 -0
  51. package/types/src/extensions/BackgroundColor/BackgroundColorMark.d.ts +9 -0
  52. package/types/src/extensions/Blocks/PreviousBlockTypePlugin.d.ts +3 -2
  53. package/types/src/extensions/Blocks/apiTypes.d.ts +16 -0
  54. package/types/src/extensions/Blocks/helpers/getBlockInfoFromPos.d.ts +1 -1
  55. package/types/src/extensions/Blocks/nodes/BlockAttributes.d.ts +2 -0
  56. package/types/src/extensions/Blocks/nodes/BlockContainer.d.ts +21 -0
  57. package/types/src/extensions/Blocks/nodes/BlockContent/BlockContentTypes.d.ts +4 -0
  58. package/types/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContent.d.ts +2 -0
  59. package/types/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContentTypes.d.ts +4 -0
  60. package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.d.ts +2 -0
  61. package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContentTypes.d.ts +2 -0
  62. package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/ListItemKeyboardShortcuts.d.ts +2 -0
  63. package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.d.ts +2 -0
  64. package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.d.ts +2 -0
  65. package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContentTypes.d.ts +2 -0
  66. package/types/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.d.ts +2 -0
  67. package/types/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContentTypes.d.ts +2 -0
  68. package/types/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.d.ts +9 -5
  69. package/types/src/extensions/DraggableBlocks/DraggableBlocksExtension.d.ts +1 -1
  70. package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +6 -11
  71. package/types/src/extensions/DraggableBlocks/MultipleNodeSelection.d.ts +24 -0
  72. package/types/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.d.ts +18 -8
  73. package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +1 -1
  74. package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes.d.ts +5 -5
  75. package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.d.ts +2 -2
  76. package/types/src/extensions/SlashMenu/SlashMenuExtension.d.ts +1 -1
  77. package/types/src/extensions/SlashMenu/SlashMenuItem.d.ts +2 -19
  78. package/types/src/extensions/SlashMenu/defaultSlashCommands.d.ts +5 -0
  79. package/types/src/extensions/SlashMenu/index.d.ts +1 -2
  80. package/types/src/extensions/TextAlignment/TextAlignmentExtension.d.ts +9 -0
  81. package/types/src/extensions/TextColor/TextColorExtension.d.ts +9 -0
  82. package/types/src/extensions/TextColor/TextColorMark.d.ts +9 -0
  83. package/types/src/index.d.ts +2 -1
  84. package/types/src/shared/EditorElement.d.ts +6 -2
  85. package/types/src/shared/plugins/suggestion/SuggestionItem.d.ts +0 -6
  86. package/types/src/shared/plugins/suggestion/SuggestionPlugin.d.ts +11 -25
  87. package/types/src/shared/plugins/suggestion/SuggestionsMenuFactoryTypes.d.ts +6 -6
  88. package/src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/ListItemContent.ts +0 -177
  89. package/src/extensions/Paragraph/FixedParagraph.ts +0 -12
@@ -1 +1 @@
1
- {"version":3,"file":"blocknote.js","sources":["../src/extensions/Blocks/BlockAttributes.ts","../src/extensions/Blocks/helpers/getBlockInfoFromPos.ts","../src/extensions/Blocks/PreviousBlockTypePlugin.ts","../src/extensions/Blocks/nodes/Block.ts","../src/extensions/Blocks/nodes/BlockGroup.ts","../src/extensions/Blocks/nodes/BlockTypes/TextBlock/TextContent.ts","../src/extensions/Blocks/nodes/BlockTypes/HeadingBlock/HeadingContent.ts","../src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/OrderedListItemIndexPlugin.ts","../src/extensions/Blocks/nodes/BlockTypes/ListItemBlock/ListItemContent.ts","../src/extensions/Blocks/index.ts","../src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts","../src/extensions/FormattingToolbar/FormattingToolbarExtension.ts","../src/extensions/Blocks/MultipleNodeSelection.ts","../src/extensions/Blocks/helpers/findBlock.ts","../src/shared/plugins/suggestion/SuggestionPlugin.ts","../src/shared/utils.ts","../src/extensions/SlashMenu/SlashMenuItem.ts","../src/extensions/SlashMenu/defaultCommands.tsx","../src/extensions/SlashMenu/SlashMenuExtension.ts","../src/extensions/DraggableBlocks/DraggableBlocksPlugin.ts","../src/extensions/DraggableBlocks/DraggableBlocksExtension.ts","../src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts","../src/extensions/HyperlinkToolbar/HyperlinkMark.ts","../src/extensions/Paragraph/FixedParagraph.ts","../src/extensions/Placeholder/PlaceholderExtension.ts","../src/extensions/TrailingNode/TrailingNodeExtension.ts","../src/extensions/UniqueID/UniqueID.ts","../src/BlockNoteExtensions.ts","../src/BlockNoteEditor.ts"],"sourcesContent":["// 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 { 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 const $pos = doc.resolve(posInBlock);\n\n const maxDepth = $pos.depth;\n let node = $pos.node(maxDepth);\n let depth = maxDepth;\n\n while (depth >= 0) {\n // If the outermost node is not a block, it means the position does not lie within a block.\n if (depth === 0) {\n return undefined;\n }\n if (node.type.name === \"block\") {\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 {\n combineTransactionSteps,\n findChildren,\n getChangedRanges,\n} 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 listItemType: \"list-item-type\",\n listItemIndex: \"list-item-index\",\n headingLevel: \"heading-level\",\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 return new Plugin({\n key: PLUGIN_KEY,\n view(_editorView) {\n return {\n update: async (view, _prevState) => {\n if (this.key?.getState(view.state).needsUpdate) {\n // use setTimeout 0 to clear the decorations so that at least\n // for one DOM-render the decorations have been applied\n setTimeout(() => {\n view.dispatch(\n view.state.tr.setMeta(PLUGIN_KEY, { clearUpdate: true })\n );\n }, 0);\n }\n },\n };\n },\n state: {\n init() {\n return {\n prevBlockAttrs: {} as any,\n needsUpdate: false,\n };\n },\n\n apply(transaction, prev, oldState, newState) {\n prev.needsUpdate = false;\n prev.prevBlockAttrs = {};\n if (!transaction.docChanged || oldState.doc.eq(newState.doc)) {\n return prev;\n }\n\n const transform = combineTransactionSteps(oldState.doc, [transaction]);\n // const { mapping } = transform;\n const changes = getChangedRanges(transform);\n\n // TODO: instead of iterating through the entire document, only check nodes affected by the transactions\n // We didn't get this to work yet:\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 changes.forEach(() => {\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\n const newNodes = findChildren(newState.doc, (node) => node.attrs.id);\n\n for (let node of newNodes) {\n const oldNode = oldNodesById.get(node.node.attrs.id);\n const oldContentNode = oldNode?.node.firstChild;\n const newContentNode = node.node.firstChild;\n if (oldNode && oldContentNode && newContentNode) {\n const newAttrs = {\n listItemType: newContentNode.attrs.listItemType,\n listItemIndex: newContentNode.attrs.listItemIndex,\n headingLevel: newContentNode.attrs.headingLevel,\n type: newContentNode.type.name,\n depth: newState.doc.resolve(node.pos).depth,\n };\n\n const oldAttrs = {\n listItemType: oldContentNode.attrs.listItemType,\n listItemIndex: oldContentNode.attrs.listItemIndex,\n headingLevel: oldContentNode.attrs.headingLevel,\n type: oldContentNode.type.name,\n depth: oldState.doc.resolve(oldNode.pos).depth,\n };\n\n // Hacky fix to avoid processing certain transactions created by ordered list indexing plugin.\n\n // True when an existing ordered list item is assigned an index for the first time, which happens\n // immediately after it's created. Using this condition to start an animation ensures it's not\n // immediately overridden by a different transaction created by the ordered list indexing plugin.\n const indexInitialized =\n oldAttrs.listItemIndex === null &&\n newAttrs.listItemIndex !== null;\n\n // True when an existing ordered list item changes nesting levels, before its index is updated by the\n // ordered list indexing plugin. This condition ensures that animations for indentation still work with\n // ordered list items, while preventing unnecessary animations being done when dragging/dropping them.\n const depthChanged =\n oldAttrs.listItemIndex !== null &&\n newAttrs.listItemIndex !== null &&\n oldAttrs.listItemIndex === newAttrs.listItemIndex;\n\n // Only false for transactions in which the block remains an ordered list item before & after, but neither\n // of the previous conditions apply.\n const shouldUpdate =\n oldAttrs.listItemType === \"ordered\" &&\n newAttrs.listItemType === \"ordered\"\n ? indexInitialized || depthChanged\n : true;\n\n if (\n JSON.stringify(oldAttrs) !== JSON.stringify(newAttrs) && // TODO: faster deep equal?\n shouldUpdate\n ) {\n (oldAttrs as any)[\"depth-change\"] =\n oldAttrs.depth - newAttrs.depth;\n prev.prevBlockAttrs[node.node.attrs.id] = oldAttrs;\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.needsUpdate = true;\n }\n }\n }\n });\n\n return prev;\n },\n },\n props: {\n decorations(state) {\n const pluginState = (this as Plugin).getState(state);\n if (!pluginState.needsUpdate) {\n // console.log(\"0\");\n return undefined;\n }\n\n const decorations: Decoration[] = [];\n\n state.doc.descendants((node, pos) => {\n if (!node.attrs.id) {\n // console.log(\"1\");\n return;\n }\n const prevAttrs = pluginState.prevBlockAttrs[node.attrs.id];\n if (!prevAttrs) {\n // console.log(\"2\");\n return;\n }\n\n const decorationAttributes: any = {};\n for (let [nodeAttr, val] of Object.entries(prevAttrs)) {\n decorationAttributes[\"data-prev-\" + nodeAttributes[nodeAttr]] =\n val || \"none\";\n }\n\n // for debugging:\n console.log(\n \"previousBlockTypePlugin committing decorations\",\n decorationAttributes\n );\n\n const decoration = Decoration.node(pos, pos + node.nodeSize, {\n ...decorationAttributes,\n });\n\n decorations.push(decoration);\n });\n\n return DecorationSet.create(state.doc, decorations);\n },\n },\n });\n};\n","import { mergeAttributes, Node } from \"@tiptap/core\";\nimport { Slice } from \"prosemirror-model\";\nimport { TextSelection } from \"prosemirror-state\";\nimport BlockAttributes from \"../BlockAttributes\";\nimport { getBlockInfoFromPos } from \"../helpers/getBlockInfoFromPos\";\nimport { PreviousBlockTypePlugin } from \"../PreviousBlockTypePlugin\";\nimport styles from \"./Block.module.css\";\nimport { TextContentType } from \"./BlockTypes/TextBlock/TextContent\";\nimport { HeadingContentType } from \"./BlockTypes/HeadingBlock/HeadingContent\";\nimport { ListItemContentType } from \"./BlockTypes/ListItemBlock/ListItemContent\";\n\nexport interface IBlock {\n HTMLAttributes: Record<string, any>;\n}\n\nexport type BlockContentType =\n | TextContentType\n | HeadingContentType\n | ListItemContentType;\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 BNSetContentType: (\n posInBlock: number,\n type: BlockContentType\n ) => ReturnType;\n BNCreateBlockOrSetContentType: (\n posInBlock: number,\n type: BlockContentType\n ) => ReturnType;\n };\n }\n}\n\n/**\n * The main \"Block node\" documents consist of\n */\nexport const Block = Node.create<IBlock>({\n name: \"block\",\n group: \"block\",\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 addAttributes() {\n return {\n blockColor: {\n default: undefined,\n },\n blockStyle: {\n default: undefined,\n },\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\") === \"block\") {\n return attrs;\n }\n\n return false;\n },\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n const attrs: Record<string, string> = {};\n for (let [nodeAttr, HTMLAttr] of Object.entries(BlockAttributes)) {\n // Ensure falsy values are not misinterpreted.\n if (HTMLAttributes[nodeAttr] !== undefined) {\n attrs[HTMLAttr] = HTMLAttributes[nodeAttr];\n }\n }\n\n return [\n \"div\",\n mergeAttributes(attrs, {\n class: styles.blockOuter,\n \"data-node-type\": \"block-outer\",\n }),\n [\n \"div\",\n mergeAttributes(attrs, {\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 = state.schema.nodes[\"block\"].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 and sets the selection to where the block was.\n BNDeleteBlock:\n (posInBlock) =>\n ({ state, view, 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 state.tr.setSelection(\n new TextSelection(state.doc.resolve(startPos + 1))\n );\n view.focus();\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 \"block\";\n const prevNodeIsBlock =\n state.doc.resolve(posBetweenBlocks - 1).node().type.name ===\n \"block\";\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 // TODO: Is there any situation where we need the whole block content, not just text? Implementation for this\n // is trickier.\n if (dispatch) {\n state.tr.deleteRange(startPos, startPos + contentNode.nodeSize);\n state.tr.insertText(contentNode.textContent, prevBlockEndPos - 1);\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 newBlockInsertionPos = endPos + 1;\n\n // Creates new block first, otherwise positions get changed due to the original block's content changing.\n // Only text content is transferred to the new block.\n const secondBlockContent = state.doc.textBetween(posInBlock, endPos);\n\n const newBlock = state.schema.nodes[\"block\"].createAndFill()!;\n const newBlockContentPos = newBlockInsertionPos + 2;\n\n if (dispatch) {\n state.tr.insert(newBlockInsertionPos, newBlock);\n state.tr.insertText(secondBlockContent, newBlockContentPos);\n\n if (keepType) {\n state.tr.setBlockType(\n newBlockContentPos,\n newBlockContentPos,\n state.schema.node(contentType).type,\n contentNode.attrs\n );\n }\n }\n\n // Updates content of original block.\n const firstBlockContent = state.doc.content.cut(startPos, posInBlock);\n\n if (dispatch) {\n state.tr.replace(\n startPos,\n endPos,\n new Slice(firstBlockContent, depth, depth)\n );\n }\n\n return true;\n },\n // Changes the content of a block at a given position to a given type.\n BNSetContentType:\n (posInBlock, type) =>\n ({ state, dispatch }) => {\n const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);\n if (blockInfo === undefined) {\n return false;\n }\n\n const { startPos, contentNode } = blockInfo;\n\n if (dispatch) {\n state.tr.setBlockType(\n startPos + 1,\n startPos + contentNode.nodeSize + 1,\n state.schema.node(type.name).type,\n type.attrs\n );\n }\n\n return true;\n },\n // Changes the block at a given position to a given content type if it's empty, otherwise creates a new block of\n // that type below it.\n BNCreateBlockOrSetContentType:\n (posInBlock, type) =>\n ({ state, chain }) => {\n const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);\n if (blockInfo === undefined) {\n return false;\n }\n\n const { node, startPos, endPos } = blockInfo;\n\n if (node.textContent.length === 0) {\n const oldBlockContentPos = startPos + 1;\n\n return chain()\n .BNSetContentType(posInBlock, type)\n .setTextSelection(oldBlockContentPos)\n .run();\n } else {\n const newBlockInsertionPos = endPos + 1;\n const newBlockContentPos = newBlockInsertionPos + 1;\n\n return chain()\n .BNCreateBlock(newBlockInsertionPos)\n .BNSetContentType(newBlockContentPos, type)\n .setTextSelection(newBlockContentPos)\n .run();\n }\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 // Changes block type to a text block if it's not already, while 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 isTextBlock = contentType.name === \"textContent\";\n\n if (selectionAtBlockStart && !isTextBlock) {\n return commands.BNSetContentType(state.selection.from, {\n name: \"textContent\",\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(\"block\");\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(\"block\");\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 Tab: () => this.editor.commands.sinkListItem(\"block\"),\n \"Shift-Tab\": () => this.editor.commands.liftListItem(\"block\"),\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.BNSetContentType(\n this.editor.state.selection.anchor,\n {\n name: \"headingContent\",\n attrs: {\n headingLevel: \"1\",\n },\n }\n ),\n \"Mod-Alt-2\": () =>\n this.editor.commands.BNSetContentType(\n this.editor.state.selection.anchor,\n {\n name: \"headingContent\",\n attrs: {\n headingLevel: \"2\",\n },\n }\n ),\n \"Mod-Alt-3\": () =>\n this.editor.commands.BNSetContentType(\n this.editor.state.selection.anchor,\n {\n name: \"headingContent\",\n attrs: {\n headingLevel: \"3\",\n },\n }\n ),\n \"Mod-Shift-7\": () =>\n this.editor.commands.BNSetContentType(\n this.editor.state.selection.anchor,\n {\n name: \"listItemContent\",\n attrs: {\n listItemType: \"unordered\",\n },\n }\n ),\n \"Mod-Shift-8\": () =>\n this.editor.commands.BNSetContentType(\n this.editor.state.selection.anchor,\n {\n name: \"listItemContent\",\n attrs: {\n listItemType: \"ordered\",\n },\n }\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\n addOptions() {\n return {\n HTMLAttributes: {},\n };\n },\n\n content: \"block+\",\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\") === \"block-group\") {\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\": \"block-group\",\n }),\n 0,\n ];\n },\n});\n","import { Node } from \"@tiptap/core\";\nimport styles from \"../../Block.module.css\";\n\nexport type TextContentType = {\n name: \"textContent\";\n attrs?: {};\n};\n\nexport const TextContent = Node.create({\n name: \"textContent\",\n group: \"blockContent\",\n content: \"inline*\",\n\n parseHTML() {\n return [\n {\n tag: \"p\",\n priority: 200,\n node: \"block\",\n },\n ];\n },\n\n renderHTML() {\n return [\n \"div\",\n {\n class: styles.blockContent,\n \"data-content-type\": this.name,\n },\n [\"p\", 0],\n ];\n },\n});\n","import { InputRule, mergeAttributes, Node } from \"@tiptap/core\";\nimport styles from \"../../Block.module.css\";\n\nexport type HeadingContentType = {\n name: \"headingContent\";\n attrs?: {\n headingLevel: string;\n };\n};\n\nexport const HeadingContent = Node.create({\n name: \"headingContent\",\n group: \"blockContent\",\n content: \"inline*\",\n\n addAttributes() {\n return {\n headingLevel: {\n default: \"1\",\n // instead of \"level\" attributes, use \"data-level\"\n parseHTML: (element) => element.getAttribute(\"data-heading-level\"),\n renderHTML: (attributes) => {\n return {\n \"data-heading-level\": attributes.headingLevel,\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 .BNSetContentType(state.selection.from, {\n name: \"headingContent\",\n attrs: {\n headingLevel: level,\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: { headingLevel: \"1\" },\n node: \"block\",\n },\n {\n tag: \"h2\",\n attrs: { headingLevel: \"2\" },\n node: \"block\",\n },\n {\n tag: \"h3\",\n attrs: { headingLevel: \"3\" },\n node: \"block\",\n },\n ];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n console.log(node.attrs);\n return [\n \"div\",\n mergeAttributes(HTMLAttributes, {\n class: styles.blockContent,\n \"data-content-type\": this.name,\n }),\n [\"h\" + node.attrs[\"headingLevel\"], 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(`ordered-list-item-index`);\nexport const OrderedListItemIndexPlugin = () => {\n return new Plugin({\n key: PLUGIN_KEY,\n appendTransaction: (_transactions, _oldState, newState) => {\n const tr = newState.tr;\n tr.setMeta(\"orderedListIndexing\", 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 === \"block\" &&\n node.firstChild!.type.name === \"listItemContent\" &&\n node.firstChild!.attrs[\"listItemType\"] === \"ordered\"\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 === \"listItemContent\" &&\n prevBlockContentNode.attrs[\"listItemType\"] === \"ordered\";\n\n if (isPrevBlockOrderedListItem) {\n const prevBlockIndex =\n prevBlockContentNode.attrs[\"listItemIndex\"];\n\n newIndex = (parseInt(prevBlockIndex) + 1).toString();\n }\n }\n }\n\n const contentNode = blockInfo.contentNode;\n const index = contentNode.attrs[\"listItemIndex\"];\n\n if (index !== newIndex) {\n modified = true;\n\n tr.setNodeMarkup(pos + 1, undefined, {\n listItemType: \"ordered\",\n listItemIndex: newIndex,\n });\n }\n }\n });\n\n return modified ? tr : null;\n },\n });\n};\n","import { InputRule, mergeAttributes, Node } from \"@tiptap/core\";\nimport { OrderedListItemIndexPlugin } from \"./OrderedListItemIndexPlugin\";\nimport { getBlockInfoFromPos } from \"../../../helpers/getBlockInfoFromPos\";\nimport styles from \"../../Block.module.css\";\n\nexport type ListItemContentType = {\n name: \"listItemContent\";\n attrs?: {\n listItemType: string;\n };\n};\n\nexport const ListItemContent = Node.create({\n name: \"listItemContent\",\n group: \"blockContent\",\n content: \"inline*\",\n\n addAttributes() {\n return {\n listItemType: {\n default: \"unordered\",\n parseHTML: (element) => element.getAttribute(\"data-list-item-type\"),\n renderHTML: (attributes) => {\n return {\n \"data-list-item-type\": attributes.listItemType,\n };\n },\n },\n listItemIndex: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-list-item-index\"),\n renderHTML: (attributes) => {\n return {\n \"data-list-item-index\": attributes.listItemIndex,\n };\n },\n },\n };\n },\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 .BNSetContentType(state.selection.from, {\n name: \"listItemContent\",\n attrs: {\n listItemType: \"unordered\",\n },\n })\n // Removes the \"-\", \"+\", or \"*\" character used to set the list.\n .deleteRange({ from: range.from, to: range.to });\n },\n }),\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 .BNSetContentType(state.selection.from, {\n name: \"listItemContent\",\n attrs: {\n listItemType: \"ordered\",\n },\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 const handleEnter = () => {\n const { node, contentType } = getBlockInfoFromPos(\n this.editor.state.doc,\n this.editor.state.selection.from\n )!;\n\n const selectionEmpty =\n this.editor.state.selection.anchor === this.editor.state.selection.head;\n\n if (contentType.name !== \"listItemContent\" || !selectionEmpty) {\n return false;\n }\n\n return this.editor.commands.first(({ state, chain, commands }) => [\n () =>\n // Changes list item block to a text block if both the content is empty.\n commands.command(() => {\n if (node.textContent.length === 0) {\n return commands.BNSetContentType(state.selection.from, {\n name: \"textContent\",\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\n return {\n Enter: handleEnter,\n };\n },\n\n addProseMirrorPlugins() {\n return [OrderedListItemIndexPlugin()];\n },\n\n parseHTML() {\n return [\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 // Case for BlockNote list structure.\n // Gets type of list item (ordered/unordered) based on the block content's listItemType attribute.\n if (parent.getAttribute(\"data-content-type\") === \"listItemContent\") {\n return { listItemType: parent.getAttribute(\"data-list-item-type\") };\n }\n\n // Case for regular HTML list structure.\n // Gets type of list item (ordered/unordered) based on parent element's tag (\"ol\"/\"ul\").\n if (parent.tagName === \"UL\") {\n return { listItemType: \"unordered\" };\n }\n if (parent.tagName === \"OL\") {\n return { listItemType: \"ordered\" };\n }\n\n return false;\n },\n node: \"block\",\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 [\"li\", 0],\n ];\n },\n});\n","import { Node } from \"@tiptap/core\";\nimport { Block } from \"./nodes/Block\";\nimport { BlockGroup } from \"./nodes/BlockGroup\";\nimport { TextContent } from \"./nodes/BlockTypes/TextBlock/TextContent\";\nimport { HeadingContent } from \"./nodes/BlockTypes/HeadingBlock/HeadingContent\";\nimport { ListItemContent } from \"./nodes/BlockTypes/ListItemBlock/ListItemContent\";\n\nexport const blocks: any[] = [\n TextContent,\n HeadingContent,\n ListItemContent,\n Block,\n BlockGroup,\n Node.create({\n name: \"doc\",\n topNode: true,\n content: \"blockGroup\",\n }),\n];\n","import {\n Editor,\n isNodeSelection,\n isTextSelection,\n posToDOMRect,\n} from \"@tiptap/core\";\nimport { EditorState, Plugin, PluginKey } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\nimport {\n FormattingToolbar,\n FormattingToolbarDynamicParams,\n FormattingToolbarFactory,\n FormattingToolbarStaticParams,\n} from \"./FormattingToolbarFactoryTypes\";\nimport { BlockContentType } from \"../Blocks/nodes/Block\";\n\n// Same as TipTap bubblemenu plugin, but with these changes:\n// https://github.com/ueberdosis/tiptap/pull/2596/files\nexport interface FormattingToolbarPluginProps {\n pluginKey: PluginKey;\n editor: Editor;\n formattingToolbarFactory: FormattingToolbarFactory;\n shouldShow?:\n | ((props: {\n editor: Editor;\n view: EditorView;\n state: EditorState;\n oldState?: EditorState;\n from: number;\n to: number;\n }) => boolean)\n | null;\n}\n\nexport type FormattingToolbarViewProps = FormattingToolbarPluginProps & {\n view: EditorView;\n};\n\nexport class FormattingToolbarView {\n public editor: Editor;\n\n public view: EditorView;\n\n public formattingToolbar: FormattingToolbar;\n\n public preventHide = false;\n\n public preventShow = false;\n\n public toolbarIsOpen = false;\n\n public shouldShow: Exclude<FormattingToolbarPluginProps[\"shouldShow\"], null> =\n ({ 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 editor,\n formattingToolbarFactory,\n view,\n shouldShow,\n }: FormattingToolbarViewProps) {\n this.editor = editor;\n this.view = view;\n\n this.formattingToolbar = formattingToolbarFactory(this.getStaticParams());\n\n if (shouldShow) {\n this.shouldShow = shouldShow;\n }\n\n this.view.dom.addEventListener(\"mousedown\", this.viewMousedownHandler);\n this.view.dom.addEventListener(\"mouseup\", this.viewMouseupHandler);\n this.view.dom.addEventListener(\"dragstart\", this.dragstartHandler);\n\n this.editor.on(\"focus\", this.focusHandler);\n this.editor.on(\"blur\", this.blurHandler);\n }\n\n viewMousedownHandler = () => {\n this.preventShow = true;\n };\n\n viewMouseupHandler = () => {\n this.preventShow = false;\n setTimeout(() => this.update(this.editor.view));\n };\n\n dragstartHandler = () => {\n this.formattingToolbar.hide();\n this.toolbarIsOpen = false;\n };\n\n focusHandler = () => {\n // we use `setTimeout` to make sure `selection` is already updated\n setTimeout(() => this.update(this.editor.view));\n };\n\n blurHandler = ({ event }: { event: FocusEvent }) => {\n if (this.preventHide) {\n this.preventHide = false;\n\n return;\n }\n\n if (\n event?.relatedTarget &&\n this.formattingToolbar.element?.parentNode?.contains(\n event.relatedTarget as Node\n )\n ) {\n return;\n }\n\n if (this.toolbarIsOpen) {\n this.formattingToolbar.hide();\n this.toolbarIsOpen = false;\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 (composing || isSame) {\n return;\n }\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 editor: this.editor,\n view,\n state,\n oldState,\n from,\n to,\n });\n\n // Checks if menu should be shown.\n if (\n !this.toolbarIsOpen &&\n !this.preventShow &&\n (shouldShow || this.preventHide)\n ) {\n this.formattingToolbar.render(this.getDynamicParams(), true);\n this.toolbarIsOpen = true;\n\n // TODO: Is this necessary? Also for other menu plugins.\n // Listener stops focus moving to the menu on click.\n this.formattingToolbar.element!.addEventListener(\"mousedown\", (event) =>\n event.preventDefault()\n );\n\n return;\n }\n\n // Checks if menu should be updated.\n if (\n this.toolbarIsOpen &&\n !this.preventShow &&\n (shouldShow || this.preventHide)\n ) {\n this.formattingToolbar.render(this.getDynamicParams(), false);\n return;\n }\n\n // Checks if menu should be hidden.\n if (\n this.toolbarIsOpen &&\n !this.preventHide &&\n (!shouldShow || this.preventShow)\n ) {\n this.formattingToolbar.hide();\n this.toolbarIsOpen = false;\n\n // Listener stops focus moving to the menu on click.\n this.formattingToolbar.element!.removeEventListener(\n \"mousedown\",\n (event) => event.preventDefault()\n );\n\n return;\n }\n }\n\n destroy() {\n this.view.dom.removeEventListener(\"mousedown\", this.viewMousedownHandler);\n this.view.dom.removeEventListener(\"mouseup\", this.viewMouseupHandler);\n this.view.dom.removeEventListener(\"dragstart\", this.dragstartHandler);\n\n this.editor.off(\"focus\", this.focusHandler);\n this.editor.off(\"blur\", this.blurHandler);\n }\n\n getSelectionBoundingBox() {\n const { state } = this.editor.view;\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.editor.view.nodeDOM(from) as HTMLElement;\n\n if (node) {\n return node.getBoundingClientRect();\n }\n }\n\n return posToDOMRect(this.editor.view, from, to);\n }\n\n getStaticParams(): FormattingToolbarStaticParams {\n return {\n toggleBold: () => {\n this.editor.view.focus();\n this.editor.commands.toggleBold();\n },\n toggleItalic: () => {\n this.editor.view.focus();\n this.editor.commands.toggleItalic();\n },\n toggleUnderline: () => {\n this.editor.view.focus();\n this.editor.commands.toggleUnderline();\n },\n toggleStrike: () => {\n this.editor.view.focus();\n this.editor.commands.toggleStrike();\n },\n setHyperlink: (url: string, text?: string) => {\n if (url === \"\") {\n return;\n }\n\n let { from, to } = this.editor.state.selection;\n\n if (!text) {\n text = this.editor.state.doc.textBetween(from, to);\n }\n\n const mark = this.editor.schema.mark(\"link\", { href: url });\n\n this.editor.view.dispatch(\n this.editor.view.state.tr\n .insertText(text, from, to)\n .addMark(from, from + text.length, mark)\n );\n this.editor.view.focus();\n },\n setBlockType: (type: BlockContentType) => {\n this.editor.view.focus();\n this.editor.commands.BNSetContentType(\n this.editor.state.selection.from,\n type\n );\n },\n };\n }\n\n getDynamicParams(): FormattingToolbarDynamicParams {\n return {\n boldIsActive: this.editor.isActive(\"bold\"),\n italicIsActive: this.editor.isActive(\"italic\"),\n underlineIsActive: this.editor.isActive(\"underline\"),\n strikeIsActive: this.editor.isActive(\"strike\"),\n hyperlinkIsActive: this.editor.isActive(\"link\"),\n activeHyperlinkUrl: this.editor.getAttributes(\"link\").href\n ? this.editor.getAttributes(\"link\").href\n : \"\",\n activeHyperlinkText: this.editor.state.doc.textBetween(\n this.editor.state.selection.from,\n this.editor.state.selection.to\n ),\n activeBlockType: {\n name: this.editor.state.selection.$from.node().type.name,\n attrs: this.editor.state.selection.$from.node().attrs,\n } as Required<BlockContentType>,\n selectionBoundingBox: this.getSelectionBoundingBox(),\n };\n }\n}\n\nexport const createFormattingToolbarPlugin = (\n options: FormattingToolbarPluginProps\n) => {\n return new Plugin({\n key: new PluginKey(\"FormattingToolbarPlugin\"),\n view: (view) => new FormattingToolbarView({ view, ...options }),\n });\n};\n","import { Extension } from \"@tiptap/core\";\nimport { PluginKey } from \"prosemirror-state\";\nimport { FormattingToolbarFactory } from \"./FormattingToolbarFactoryTypes\";\nimport { createFormattingToolbarPlugin } from \"./FormattingToolbarPlugin\";\n\n/**\n * The menu that is displayed when selecting a piece of text.\n */\nexport const FormattingToolbarExtension = Extension.create<{\n formattingToolbarFactory: FormattingToolbarFactory;\n}>({\n name: \"FormattingToolbarExtension\",\n\n addProseMirrorPlugins() {\n if (!this.options.formattingToolbarFactory) {\n throw new Error(\n \"UI Element factory not defined for FormattingToolbarExtension\"\n );\n }\n\n return [\n createFormattingToolbarPlugin({\n editor: this.editor,\n formattingToolbarFactory: this.options.formattingToolbarFactory,\n pluginKey: new PluginKey(\"FormattingToolbarPlugin\"),\n }),\n ];\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 { findParentNode } from \"@tiptap/core\";\n\nexport const findBlock = findParentNode((node) => node.type.name === \"block\");\n","import { Editor, Range } from \"@tiptap/core\";\nimport { escapeRegExp } from \"lodash\";\nimport { EditorState, Plugin, PluginKey, Selection } from \"prosemirror-state\";\nimport { Decoration, DecorationSet, EditorView } from \"prosemirror-view\";\nimport { findBlock } from \"../../../extensions/Blocks/helpers/findBlock\";\nimport {\n SuggestionsMenu,\n SuggestionsMenuDynamicParams,\n SuggestionsMenuFactory,\n SuggestionsMenuStaticParams,\n} from \"./SuggestionsMenuFactoryTypes\";\nimport { SuggestionItem } from \"./SuggestionItem\";\n\nexport type SuggestionPluginOptions<T extends SuggestionItem> = {\n /**\n * The name of the plugin.\n *\n * Used for ensuring that the plugin key is unique when more than one instance of the SuggestionPlugin is used.\n */\n pluginKey: PluginKey;\n\n /**\n * The TipTap editor.\n */\n editor: Editor;\n\n /**\n * The character that should trigger the suggestion menu to pop up (e.g. a '/' for commands)\n */\n char: string;\n\n suggestionsMenuFactory: SuggestionsMenuFactory<T>;\n\n /**\n * The callback that gets executed when an item is selected by the user.\n *\n * **NOTE:** The command text is not removed automatically from the editor by this plugin,\n * this should be done manually. The `editor` and `range` properties passed\n * to the callback function might come in handy when doing this.\n */\n onSelectItem?: (props: { item: T; editor: Editor; range: Range }) => void;\n\n /**\n * A function that should supply the plugin with items to suggest, based on a certain query string.\n */\n items?: (query: string) => T[];\n\n allow?: (props: { editor: Editor; range: Range }) => boolean;\n};\n\ntype SuggestionPluginState<T extends SuggestionItem> = {\n active: boolean;\n range: Range | null;\n query: string | null;\n notFoundCount: number;\n items: T[];\n selectedItemIndex: number;\n type: string;\n decorationId: string | null;\n};\n\ntype SuggestionPluginViewOptions<T extends SuggestionItem> = {\n editor: Editor;\n pluginKey: PluginKey;\n onSelectItem: (props: { item: T; editor: Editor; range: Range }) => void;\n suggestionsMenuFactory: SuggestionsMenuFactory<T>;\n};\n\nexport type MenuType = \"slash\" | \"drag\";\n\n/**\n * Finds a command: a specified character (e.g. '/') followed by a string of characters (all characters except the specified character are allowed).\n * Returns the string following the specified character or undefined if no command was found.\n *\n * @param char the character that indicates the start of a command\n * @param selection the selection (only works if the selection is empty; i.e. is a blinking cursor).\n * @returns an object containing the matching word (excluding the specified character) and the range of the match (including the specified character) or undefined if there is no match.\n */\nexport function findCommandBeforeCursor(\n char: string,\n selection: Selection\n): { range: Range; query: string } | undefined {\n if (!selection.empty) {\n return undefined;\n }\n\n // get the text before the cursor as a node\n const node = selection.$anchor.nodeBefore;\n if (!node || !node.text) {\n return undefined;\n }\n\n // regex to match anything between with the specified char (e.g. '/') and the end of text (which is the end of selection)\n const regex = new RegExp(`${escapeRegExp(char)}([^${escapeRegExp(char)}]*)$`);\n const match = node.text.match(regex);\n\n if (!match) {\n return undefined;\n }\n\n return {\n query: match[1],\n range: {\n from: selection.$anchor.pos - match[1].length - char.length,\n to: selection.$anchor.pos,\n },\n };\n}\n\nclass SuggestionPluginView<T extends SuggestionItem> {\n editor: Editor;\n pluginKey: PluginKey;\n\n suggestionsMenu: SuggestionsMenu<T>;\n\n pluginState: SuggestionPluginState<T>;\n itemCallback: (item: T) => void;\n\n constructor({\n editor,\n pluginKey,\n onSelectItem: selectItemCallback = () => {},\n suggestionsMenuFactory,\n }: SuggestionPluginViewOptions<T>) {\n this.editor = editor;\n this.pluginKey = pluginKey;\n\n this.pluginState = {\n active: false,\n range: null,\n query: null,\n notFoundCount: 0,\n items: [],\n selectedItemIndex: 0,\n type: \"slash\",\n decorationId: null,\n };\n\n this.itemCallback = (item: T) =>\n selectItemCallback({\n item: item,\n editor: editor,\n range: this.pluginState.range as Range,\n });\n\n this.suggestionsMenu = suggestionsMenuFactory(this.getStaticParams());\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) {\n this.suggestionsMenu.hide();\n\n // Listener stops focus moving to the menu on click.\n this.suggestionsMenu.element!.removeEventListener(\"mousedown\", (event) =>\n event.preventDefault()\n );\n }\n\n if (changed) {\n this.suggestionsMenu.render(this.getDynamicParams(), false);\n }\n\n if (started) {\n this.suggestionsMenu.render(this.getDynamicParams(), true);\n\n // Listener stops focus moving to the menu on click.\n this.suggestionsMenu.element!.addEventListener(\"mousedown\", (event) =>\n event.preventDefault()\n );\n }\n }\n\n getStaticParams(): SuggestionsMenuStaticParams<T> {\n return {\n itemCallback: (item: T) => this.itemCallback(item),\n };\n }\n\n getDynamicParams(): SuggestionsMenuDynamicParams<T> {\n const decorationNode = document.querySelector(\n `[data-decoration-id=\"${this.pluginState.decorationId}\"]`\n );\n\n return {\n items: this.pluginState.items,\n selectedItemIndex: this.pluginState.selectedItemIndex,\n queryStartBoundingBox: decorationNode!.getBoundingClientRect(),\n };\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 *\n * @param options options for configuring the plugin\n * @returns the prosemirror plugin\n */\nexport function createSuggestionPlugin<T extends SuggestionItem>({\n pluginKey,\n editor,\n char,\n suggestionsMenuFactory,\n onSelectItem: selectItemCallback = () => {},\n items = () => [],\n}: SuggestionPluginOptions<T>) {\n // Assertions\n if (char.length !== 1) {\n throw new Error(\"'char' should be a single character\");\n }\n\n const deactivate = (view: EditorView) => {\n view.dispatch(view.state.tr.setMeta(pluginKey, { deactivate: true }));\n };\n\n // Plugin key is passed in parameter so it can be exported and used in draghandle\n return new Plugin({\n key: pluginKey,\n\n view: (view: EditorView) =>\n new SuggestionPluginView({\n editor: editor,\n pluginKey: pluginKey,\n onSelectItem: (props: { item: T; editor: Editor; range: Range }) => {\n deactivate(view);\n selectItemCallback(props);\n },\n suggestionsMenuFactory: suggestionsMenuFactory,\n }),\n\n state: {\n // Initialize the plugin's internal state.\n init(): SuggestionPluginState<T> {\n return {\n active: false,\n range: null, // TODO\n query: null,\n notFoundCount: 0,\n items: [] as T[],\n selectedItemIndex: 0,\n type: \"slash\",\n decorationId: null,\n };\n },\n\n // Apply changes to the plugin state from a view transaction.\n apply(transaction, prev, _oldState, newState) {\n const { selection } = transaction;\n const next = { ...prev };\n\n // TODO: More clearly define which transactions should be ignored and which should deactivate the menu.\n if (transaction.getMeta(\"orderedListIndexing\") !== undefined) {\n return next;\n }\n\n // Handles transactions created by navigating the menu using the up/down arrow keys.\n if (\n transaction.getMeta(pluginKey)?.selectedItemIndexChanged !== undefined\n ) {\n let newIndex =\n transaction.getMeta(pluginKey).selectedItemIndexChanged;\n\n if (newIndex < 0) {\n newIndex = prev.items.length - 1;\n }\n\n if (newIndex >= prev.items.length) {\n newIndex = 0;\n }\n\n next.selectedItemIndex = newIndex;\n\n return next;\n }\n\n if (\n // only show popup if selection is a blinking cursor\n selection.from === selection.to &&\n // deactivate popup from view (e.g.: choice has been made or esc has been pressed)\n !transaction.getMeta(pluginKey)?.deactivate &&\n // deactivate because a mouse event occurs (user clicks somewhere else in the document)\n !transaction.getMeta(\"focus\") &&\n !transaction.getMeta(\"blur\") &&\n !transaction.getMeta(\"pointer\")\n ) {\n // Reset active state if we just left the previous suggestion range (e.g.: key arrows moving before /)\n if (prev.active && selection.from <= prev.range!.from) {\n next.active = false;\n } else if (transaction.getMeta(pluginKey)?.activate) {\n // Start showing suggestions. activate has been set after typing a \"/\" (or whatever the specified character is), so let's create the decoration and initialize\n const newDecorationId = `id_${Math.floor(\n Math.random() * 0xffffffff\n )}`;\n next.decorationId = newDecorationId;\n next.range = {\n from: selection.from - 1,\n to: selection.to,\n };\n next.query = \"\";\n next.active = true;\n next.type = transaction.getMeta(pluginKey)?.type;\n next.selectedItemIndex = 0;\n } else if (prev.active) {\n // Try to match against where our cursor currently is\n // if the type is slash we get the command after the character\n // otherwise we get the whole query\n const match = findCommandBeforeCursor(\n prev.type === \"slash\" ? char : \"\",\n newState.selection\n );\n if (!match) {\n throw new Error(\"active but no match (suggestions)\");\n }\n\n next.range = match.range;\n next.active = true;\n next.decorationId = prev.decorationId;\n next.query = match.query;\n next.selectedItemIndex = 0;\n }\n } else {\n next.active = false;\n }\n\n if (next.active) {\n next.items = items(next.query!);\n if (next.items.length) {\n next.notFoundCount = 0;\n } else {\n // Update the \"notFoundCount\",\n // which indicates how many characters have been typed after showing no results\n if (next.range!.to > prev.range!.to) {\n // Text has been entered (selection moved to right), but still no items found, update Count\n next.notFoundCount = prev.notFoundCount + 1;\n } else {\n // No text has been entered in this tr, keep not found count\n // (e.g.: user hits backspace after no results)\n next.notFoundCount = prev.notFoundCount;\n }\n }\n\n if (next.notFoundCount > 3) {\n next.active = false;\n }\n }\n\n // Make sure to empty the range if suggestion is inactive\n if (!next.active) {\n next.decorationId = null;\n next.range = null;\n next.query = null;\n next.notFoundCount = 0;\n next.items = [];\n }\n\n return next;\n },\n },\n\n props: {\n handleKeyDown(view, event) {\n const { active } = (this as Plugin).getState(view.state);\n\n if (!active) {\n // activate the popup on 'char' keypress (e.g. '/')\n if (event.key === char) {\n view.dispatch(\n view.state.tr\n .insertText(char)\n .scrollIntoView()\n .setMeta(pluginKey, { activate: true, type: \"slash\" })\n );\n // return true to cancel the original event, as we insert / ourselves\n return true;\n }\n } else {\n const { items, range, selectedItemIndex } = pluginKey.getState(\n view.state\n );\n\n if (event.key === \"ArrowUp\") {\n view.dispatch(\n view.state.tr.setMeta(pluginKey, {\n selectedItemIndexChanged: selectedItemIndex - 1,\n })\n );\n return true;\n }\n\n if (event.key === \"ArrowDown\") {\n view.dispatch(\n view.state.tr.setMeta(pluginKey, {\n selectedItemIndexChanged: selectedItemIndex + 1,\n })\n );\n return true;\n }\n\n if (event.key === \"Enter\") {\n deactivate(view);\n selectItemCallback({\n item: items[selectedItemIndex],\n editor: editor,\n range: range,\n });\n return true;\n }\n\n if (event.key === \"Escape\") {\n deactivate(view);\n return true;\n }\n }\n\n return false;\n },\n\n // Hides menu in cases where mouse click does not cause an editor state change.\n handleClick(view) {\n deactivate(view);\n },\n\n // Setup decorator on the currently active suggestion.\n decorations(state) {\n const { active, range, decorationId, type } = (this as Plugin).getState(\n state\n );\n\n if (!active) {\n return null;\n }\n\n // If type in meta is drag, create decoration node that wraps block\n // Because the block does not have content yet (slash menu has the '/' in its content),\n // so we can't use an inline decoration.\n if (type === \"drag\") {\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 // Create inline decoration that wraps / or whatever the specified character is\n return DecorationSet.create(state.doc, [\n Decoration.inline(range.from, range.to, {\n nodeName: \"span\",\n class: \"suggestion-decorator\",\n \"data-decoration-id\": decorationId,\n }),\n ]);\n },\n },\n });\n}\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","import { Editor, Range } from \"@tiptap/core\";\nimport { SuggestionItem } from \"../../shared/plugins/suggestion/SuggestionItem\";\n\nexport type SlashMenuCallback = (editor: Editor, range: Range) => boolean;\n\nexport enum SlashMenuGroups {\n HEADINGS = \"Headings\",\n BASIC_BLOCKS = \"Basic Blocks\",\n CODE = \"Code Blocks\",\n\n // Just some examples, that are not currently in use\n INLINE = \"Inline\",\n EMBED = \"Embed\",\n PLUGIN = \"Plugin\",\n}\n\n/**\n * A class that defines a slash command (/<command>).\n *\n * Not to be confused with ProseMirror commands nor TipTap commands.\n */\nexport class SlashMenuItem implements SuggestionItem {\n groupName: string;\n // other parameters initialized in the constructor\n\n /**\n * Constructs a new slash-command.\n *\n * @param name The name of the command\n * @param group Used to organize the menu\n * @param execute The callback for creating a new node\n * @param aliases Aliases for this command\n * @param icon To be shown next to the name in the menu\n * @param hint Short description of command\n * @param shortcut Info about keyboard shortcut that would activate this command\n */\n constructor(\n public readonly name: string,\n public readonly group: SlashMenuGroups,\n public readonly execute: SlashMenuCallback,\n public readonly aliases: string[] = [],\n public readonly hint?: string,\n public readonly shortcut?: string\n ) {\n this.groupName = group;\n }\n\n match(query: string): boolean {\n return (\n this.name.toLowerCase().startsWith(query.toLowerCase()) ||\n this.aliases.filter((alias) =>\n alias.toLowerCase().startsWith(query.toLowerCase())\n ).length !== 0\n );\n }\n}\n","import { formatKeyboardShortcut } from \"../../shared/utils\";\nimport { SlashMenuGroups, SlashMenuItem } from \"./SlashMenuItem\";\n\n/**\n * An array containing commands for creating all default blocks.\n */\nconst defaultCommands: { [key: string]: SlashMenuItem } = {\n // Command for creating a level 1 heading\n heading: new SlashMenuItem(\n \"Heading\",\n SlashMenuGroups.HEADINGS,\n (editor, range) => {\n return editor\n .chain()\n .focus()\n .deleteRange(range)\n .BNCreateBlockOrSetContentType(range.from, {\n name: \"headingContent\",\n attrs: {\n headingLevel: \"1\",\n },\n })\n .run();\n },\n [\"h\", \"heading1\", \"h1\"],\n \"Used for a top-level heading\",\n formatKeyboardShortcut(\"Mod-Alt-1\")\n ),\n\n // Command for creating a level 2 heading\n heading2: new SlashMenuItem(\n \"Heading 2\",\n SlashMenuGroups.HEADINGS,\n (editor, range) => {\n return editor\n .chain()\n .focus()\n .deleteRange(range)\n .BNCreateBlockOrSetContentType(range.from, {\n name: \"headingContent\",\n attrs: {\n headingLevel: \"2\",\n },\n })\n .run();\n },\n [\"h2\", \"heading2\", \"subheading\"],\n \"Used for key sections\",\n formatKeyboardShortcut(\"Mod-Alt-2\")\n ),\n\n // Command for creating a level 3 heading\n heading3: new SlashMenuItem(\n \"Heading 3\",\n SlashMenuGroups.HEADINGS,\n (editor, range) => {\n return editor\n .chain()\n .focus()\n .deleteRange(range)\n .BNCreateBlockOrSetContentType(range.from, {\n name: \"headingContent\",\n attrs: {\n headingLevel: \"3\",\n },\n })\n .run();\n },\n [\"h3\", \"heading3\", \"subheading\"],\n \"Used for subsections and group headings\",\n formatKeyboardShortcut(\"Mod-Alt-3\")\n ),\n\n // Command for creating an ordered list\n numberedList: new SlashMenuItem(\n \"Numbered List\",\n SlashMenuGroups.BASIC_BLOCKS,\n (editor, range) => {\n return editor\n .chain()\n .focus()\n .deleteRange(range)\n .BNCreateBlockOrSetContentType(range.from, {\n name: \"listItemContent\",\n attrs: {\n listItemType: \"ordered\",\n },\n })\n .run();\n },\n [\"li\", \"list\", \"numberedlist\", \"numbered list\"],\n \"Used to display a numbered list\",\n formatKeyboardShortcut(\"Mod-Shift-7\")\n ),\n\n // Command for creating a bullet list\n bulletList: new SlashMenuItem(\n \"Bullet List\",\n SlashMenuGroups.BASIC_BLOCKS,\n (editor, range) => {\n return editor\n .chain()\n .focus()\n .deleteRange(range)\n .BNCreateBlockOrSetContentType(range.from, {\n name: \"listItemContent\",\n attrs: {\n listItemType: \"unordered\",\n },\n })\n .run();\n },\n [\"ul\", \"list\", \"bulletlist\", \"bullet list\"],\n \"Used to display an unordered list\",\n formatKeyboardShortcut(\"Mod-Shift-8\")\n ),\n\n // Command for creating a paragraph (pretty useless)\n paragraph: new SlashMenuItem(\n \"Paragraph\",\n SlashMenuGroups.BASIC_BLOCKS,\n (editor, range) => {\n return editor\n .chain()\n .focus()\n .deleteRange(range)\n .BNCreateBlockOrSetContentType(range.from, { name: \"textContent\" })\n .run();\n },\n [\"p\"],\n \"Used for the body of your document\",\n formatKeyboardShortcut(\"Mod-Alt-0\")\n ),\n\n // replaceRangeWithNode(editor, range, node);\n\n // return true;\n // },\n // [\"ol\", \"orderedlist\"],\n // OrderedListIcon,\n // \"Used to display an ordered (enumerated) list item\"\n // ),\n\n // Command for creating a blockquote\n // blockquote: new SlashCommand(\n // \"Block Quote\",\n // CommandGroup.BASIC_BLOCKS,\n // (editor, range) => {\n // const paragraph = editor.schema.node(\"paragraph\");\n // const node = editor.schema.node(\n // \"blockquote\",\n // { \"block-id\": uniqueId.generate() },\n // paragraph\n // );\n\n // replaceRangeWithNode(editor, range, node);\n\n // return true;\n // },\n // [\"quote\", \"blockquote\"],\n // QuoteIcon,\n // \"Used to make a quote stand out\",\n // \"Ctrl+Shift+B\"\n // ),\n\n // Command for creating a horizontal rule\n // horizontalRule: new SlashCommand(\n // \"Horizontal Rule\",\n // CommandGroup.BASIC_BLOCKS,\n // (editor, range) => {\n // const node = editor.schema.node(\"horizontalRule\", {\n // \"block-id\": uniqueId.generate(),\n // });\n\n // // insert horizontal rule, create a new block after the horizontal rule if applicable\n // // and put the cursor in the block after the horizontal rule.\n // editor\n // .chain()\n // .focus()\n // .replaceRangeAndUpdateSelection(range, node)\n // .command(({ tr, dispatch }) => {\n // if (dispatch) {\n // // the node immediately after the cursor\n // const nodeAfter = tr.selection.$to.nodeAfter;\n\n // // the position of the cursor\n // const cursorPos = tr.selection.$to.pos;\n\n // // check if there is no node after the cursor (end of document)\n // if (!nodeAfter) {\n // // create a new block of the default type (probably paragraph) after the cursor\n // const { parent } = tr.selection.$to;\n // const node = parent.type.contentMatch.defaultType?.create();\n\n // if (node) {\n // tr.insert(cursorPos, node);\n // }\n // }\n\n // // try to put the cursor at the start of the node directly after the inserted horizontal rule\n // tr.doc.nodesBetween(cursorPos, cursorPos + 1, (node, pos) => {\n // if (node.type.name !== \"horizontalRule\") {\n // tr.setSelection(TextSelection.create(tr.doc, pos));\n // }\n // });\n // }\n\n // return true;\n // })\n // .scrollIntoView()\n // .run();\n // return true;\n // },\n // [\"hr\", \"horizontalrule\"],\n // SeparatorIcon,\n // \"Used to separate sections with a horizontal line\"\n // ),\n\n // Command for creating a table\n // table: new SlashCommand(\n // \"Table\",\n // CommandGroup.BASIC_BLOCKS,\n // (editor, range) => {\n // editor.chain().focus().deleteRange(range).run();\n // // TODO: add blockid, pending https://github.com/ueberdosis/tiptap/pull/1469\n // editor\n // .chain()\n // .focus()\n // .insertTable({ rows: 1, cols: 2, withHeaderRow: false })\n // .scrollIntoView()\n // .run();\n // return true;\n // },\n // [\"table\", \"database\"],\n // TableIcon,\n // \"Used to create a simple table\"\n // ),\n};\n\nexport default defaultCommands;\n","import { Extension } from \"@tiptap/core\";\nimport { PluginKey } from \"prosemirror-state\";\nimport { createSuggestionPlugin } from \"../../shared/plugins/suggestion/SuggestionPlugin\";\nimport { SuggestionsMenuFactory } from \"../../shared/plugins/suggestion/SuggestionsMenuFactoryTypes\";\nimport defaultCommands from \"./defaultCommands\";\nimport { SlashMenuItem } from \"./SlashMenuItem\";\n\nexport type SlashMenuOptions = {\n commands: { [key: string]: SlashMenuItem };\n slashMenuFactory: SuggestionsMenuFactory<any> | undefined;\n};\n\nexport const SlashMenuPluginKey = new PluginKey(\"suggestions-slash-commands\");\n\nexport const SlashMenuExtension = Extension.create<SlashMenuOptions>({\n name: \"slash-command\",\n\n addOptions() {\n return {\n commands: defaultCommands,\n slashMenuFactory: undefined, // TODO: fix undefined\n };\n },\n\n addProseMirrorPlugins() {\n if (!this.options.slashMenuFactory) {\n throw new Error(\"UI Element factory not defined for SlashMenuExtension\");\n }\n\n return [\n createSuggestionPlugin<SlashMenuItem>({\n pluginKey: SlashMenuPluginKey,\n editor: this.editor,\n char: \"/\",\n suggestionsMenuFactory: this.options.slashMenuFactory!,\n items: (query) => {\n const commands = [];\n\n for (const key in this.options.commands) {\n commands.push(this.options.commands[key]);\n }\n\n return commands.filter((cmd: SlashMenuItem) => cmd.match(query));\n },\n onSelectItem: ({ item, editor, range }) => {\n item.execute(editor, range);\n },\n }),\n ];\n },\n});\n","import { Editor } from \"@tiptap/core\";\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 { MultipleNodeSelection } from \"../Blocks/MultipleNodeSelection\";\nimport { DraggableBlocksOptions } from \"./DraggableBlocksExtension\";\nimport {\n BlockSideMenu,\n BlockSideMenuDynamicParams,\n BlockSideMenuFactory,\n BlockSideMenuStaticParams,\n} from \"./BlockSideMenuFactoryTypes\";\nimport { getBlockInfoFromPos } from \"../Blocks/helpers/getBlockInfoFromPos\";\nimport { SlashMenuPluginKey } from \"../SlashMenu/SlashMenuExtension\";\nimport styles from \"../../editor.module.css\";\n\nconst serializeForClipboard = (pv as any).__serializeForClipboard;\n// code based on https://github.com/ueberdosis/tiptap/issues/323#issuecomment-506637799\n\nlet horizontalAnchor: number;\nlet dragImageElement: Element | undefined;\n\nfunction getHorizontalAnchor() {\n if (!horizontalAnchor) {\n const firstBlockGroup = document.querySelector(\n \".ProseMirror > [class*='blockGroup']\"\n ) as HTMLElement | undefined; // first block group node\n if (firstBlockGroup) {\n horizontalAnchor = absoluteRect(firstBlockGroup).left;\n } // Anchor to the left of the first block group\n }\n return horizontalAnchor;\n}\n\nexport function createRect(rect: DOMRect) {\n let newRect = {\n left: rect.left + document.body.scrollLeft,\n top: rect.top + document.body.scrollTop,\n width: rect.width,\n height: rect.height,\n bottom: 0,\n right: 0,\n };\n newRect.bottom = newRect.top + newRect.height;\n newRect.right = newRect.left + newRect.width;\n return newRect;\n}\n\nexport function absoluteRect(element: HTMLElement) {\n return createRect(element.getBoundingClientRect());\n}\n\nfunction getDraggableBlockFromCoords(\n coords: { left: number; top: number },\n view: EditorView\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 dragImageElement = parentClone;\n dragImageElement.className = styles.dragPreview;\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(e: DragEvent, view: EditorView) {\n if (!e.dataTransfer) {\n return;\n }\n\n let coords = {\n left: view.dom.clientWidth / 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 = !selection.$anchor\n .node()\n .eq(selection.$head.node());\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 type BlockMenuViewProps = {\n editor: Editor;\n blockMenuFactory: BlockSideMenuFactory;\n horizontalPosAnchoredAtRoot: boolean;\n};\n\nexport class BlockMenuView {\n editor: Editor;\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 horizontalPosAnchoredAtRoot: boolean;\n\n blockMenu: BlockSideMenu;\n\n hoveredBlock: HTMLElement | undefined;\n\n menuOpen = false;\n menuFrozen = false;\n\n constructor({\n editor,\n blockMenuFactory,\n horizontalPosAnchoredAtRoot,\n }: BlockMenuViewProps) {\n this.editor = editor;\n this.horizontalPosAnchoredAtRoot = horizontalPosAnchoredAtRoot;\n\n this.blockMenu = blockMenuFactory(this.getStaticParams());\n\n // Shows or updates menu position whenever the cursor moves, if the menu isn't frozen.\n document.body.addEventListener(\n \"mousemove\",\n (event) => {\n if (this.menuFrozen) {\n return;\n }\n\n // Gets block at mouse cursor's vertical position.\n const coords = {\n left: this.editor.view.dom.clientWidth / 2, // take middle of editor\n top: event.clientY,\n };\n const block = getDraggableBlockFromCoords(coords, this.editor.view);\n\n // Closes the menu if the mouse cursor is beyond the editor vertically.\n if (!block) {\n if (this.menuOpen) {\n this.menuOpen = false;\n this.blockMenu.hide();\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.menuOpen &&\n this.hoveredBlock?.hasAttribute(\"data-id\") &&\n this.hoveredBlock?.getAttribute(\"data-id\") === block.id\n ) {\n return;\n }\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 this.hoveredBlock = blockContent;\n\n if (!blockContent) {\n return;\n }\n\n // Shows or updates elements.\n if (!this.menuOpen) {\n this.menuOpen = true;\n this.blockMenu.render(this.getDynamicParams(), true);\n } else {\n this.blockMenu.render(this.getDynamicParams(), false);\n }\n },\n true\n );\n\n // Hides and unfreezes the menu whenever the user selects the editor with the mouse or presses a key.\n // TODO: Better integration with suggestions menu and only editor scope?\n document.body.addEventListener(\n \"mousedown\",\n (event) => {\n if (this.blockMenu.element?.contains(event.target as HTMLElement)) {\n return;\n }\n\n if (this.menuOpen) {\n this.menuOpen = false;\n this.blockMenu.hide();\n }\n\n this.menuFrozen = false;\n },\n true\n );\n document.body.addEventListener(\n \"keydown\",\n () => {\n if (this.menuOpen) {\n this.menuOpen = false;\n this.blockMenu.hide();\n }\n\n this.menuFrozen = false;\n },\n true\n );\n }\n\n destroy() {\n if (this.menuOpen) {\n this.menuOpen = false;\n this.blockMenu.hide();\n }\n }\n\n addBlock() {\n this.menuOpen = false;\n this.menuFrozen = true;\n this.blockMenu.hide();\n\n const blockBoundingBox = this.hoveredBlock!.getBoundingClientRect();\n\n const pos = this.editor.view.posAtCoords({\n left: blockBoundingBox.left,\n top: blockBoundingBox.top,\n });\n if (!pos) {\n return;\n }\n\n const blockInfo = getBlockInfoFromPos(this.editor.state.doc, pos.pos);\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\n .chain()\n .BNCreateBlock(newBlockInsertionPos)\n .BNSetContentType(newBlockContentPos, { name: \"textContent\" })\n .setTextSelection(newBlockContentPos)\n .run();\n }\n\n // Focuses and activates the suggestion menu.\n this.editor.view.focus();\n this.editor.view.dispatch(\n this.editor.view.state.tr.scrollIntoView().setMeta(SlashMenuPluginKey, {\n // TODO import suggestion plugin key\n activate: true,\n type: \"drag\",\n })\n );\n }\n\n deleteBlock() {\n this.menuOpen = false;\n this.blockMenu.hide();\n\n const blockBoundingBox = this.hoveredBlock!.getBoundingClientRect();\n\n const pos = this.editor.view.posAtCoords({\n left: blockBoundingBox.left,\n top: blockBoundingBox.top,\n });\n if (!pos) {\n return;\n }\n\n this.editor.commands.BNDeleteBlock(pos.pos);\n }\n\n getStaticParams(): BlockSideMenuStaticParams {\n return {\n addBlock: () => this.addBlock(),\n deleteBlock: () => this.deleteBlock(),\n blockDragStart: (event: DragEvent) => dragStart(event, this.editor.view),\n blockDragEnd: () => unsetDragImage(),\n freezeMenu: () => {\n this.menuFrozen = true;\n },\n unfreezeMenu: () => {\n this.menuFrozen = false;\n },\n };\n }\n\n getDynamicParams(): BlockSideMenuDynamicParams {\n const blockBoundingBox = this.hoveredBlock!.getBoundingClientRect();\n\n return {\n blockBoundingBox: new DOMRect(\n this.horizontalPosAnchoredAtRoot\n ? getHorizontalAnchor()\n : blockBoundingBox.x,\n blockBoundingBox.y,\n blockBoundingBox.width,\n blockBoundingBox.height\n ),\n };\n }\n}\n\nexport const createDraggableBlocksPlugin = (\n options: DraggableBlocksOptions\n) => {\n return new Plugin({\n key: new PluginKey(\"DraggableBlocksPlugin\"),\n view: () =>\n new BlockMenuView({\n editor: options.editor,\n blockMenuFactory: options.blockSideMenuFactory,\n horizontalPosAnchoredAtRoot: true,\n }),\n });\n};\n","import { Editor, Extension } from \"@tiptap/core\";\nimport { BlockSideMenuFactory } from \"./BlockSideMenuFactoryTypes\";\nimport { createDraggableBlocksPlugin } from \"./DraggableBlocksPlugin\";\n\nexport type DraggableBlocksOptions = {\n editor: Editor;\n blockSideMenuFactory: BlockSideMenuFactory;\n};\n\n/**\n * This extension adds a menu to the side of blocks which features various BlockNote functions such as adding and\n * removing blocks. More importantly, it adds a drag handle which allows the user to drag and drop blocks.\n *\n * code based on https://github.com/ueberdosis/tiptap/issues/323#issuecomment-506637799\n */\nexport const DraggableBlocksExtension =\n Extension.create<DraggableBlocksOptions>({\n name: \"DraggableBlocksExtension\",\n priority: 1000, // Need to be high, in order to hide menu when typing slash\n addProseMirrorPlugins() {\n if (!this.options.blockSideMenuFactory) {\n throw new Error(\n \"UI Element factory not defined for DraggableBlocksExtension\"\n );\n }\n return [\n createDraggableBlocksPlugin({\n editor: this.editor,\n blockSideMenuFactory: this.options.blockSideMenuFactory,\n }),\n ];\n },\n });\n","import { Editor, getMarkRange, posToDOMRect, Range } from \"@tiptap/core\";\nimport { Mark } from \"prosemirror-model\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\nimport {\n HyperlinkToolbar,\n HyperlinkToolbarDynamicParams,\n HyperlinkToolbarFactory,\n HyperlinkToolbarStaticParams,\n} from \"./HyperlinkToolbarFactoryTypes\";\nconst PLUGIN_KEY = new PluginKey(\"HyperlinkToolbarPlugin\");\n\nexport type HyperlinkToolbarPluginProps = {\n hyperlinkToolbarFactory: HyperlinkToolbarFactory;\n};\n\nexport type HyperlinkToolbarViewProps = {\n editor: Editor;\n hyperlinkToolbarFactory: HyperlinkToolbarFactory;\n};\n\nclass HyperlinkToolbarView {\n editor: Editor;\n\n hyperlinkToolbar: HyperlinkToolbar;\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({ editor, hyperlinkToolbarFactory }: HyperlinkToolbarViewProps) {\n this.editor = editor;\n\n this.hyperlinkToolbar = hyperlinkToolbarFactory(this.getStaticParams());\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 editor.view.dom.addEventListener(\"mouseover\", (event) => {\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 editor.view.posAtDOM(hoveredHyperlinkElement, 0) + 1;\n const resolvedPosInHoveredHyperlinkMark = editor.state.doc.resolve(\n posInHoveredHyperlinkMark\n );\n const marksAtPos = resolvedPosInHoveredHyperlinkMark.marks();\n\n for (const mark of marksAtPos) {\n if (mark.type.name === editor.schema.mark(\"link\").type.name) {\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\n update() {\n if (!this.editor.view.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.editor.state.selection.empty) {\n const marksAtPos = this.editor.state.selection.$from.marks();\n\n for (const mark of marksAtPos) {\n if (mark.type.name === this.editor.schema.mark(\"link\").type.name) {\n this.keyboardHoveredHyperlinkMark = mark;\n this.keyboardHoveredHyperlinkMarkRange =\n getMarkRange(\n this.editor.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) {\n this.getDynamicParams();\n\n // Shows menu.\n if (!prevHyperlinkMark) {\n this.hyperlinkToolbar.render(this.getDynamicParams(), true);\n\n this.hyperlinkToolbar.element?.addEventListener(\n \"mouseleave\",\n this.startMenuUpdateTimer\n );\n this.hyperlinkToolbar.element?.addEventListener(\n \"mouseenter\",\n this.stopMenuUpdateTimer\n );\n\n return;\n }\n\n // Updates menu.\n this.hyperlinkToolbar.render(this.getDynamicParams(), false);\n }\n\n // Hides menu.\n if (!this.hyperlinkMark && prevHyperlinkMark) {\n this.hyperlinkToolbar.element?.removeEventListener(\n \"mouseleave\",\n this.startMenuUpdateTimer\n );\n this.hyperlinkToolbar.element?.removeEventListener(\n \"mouseenter\",\n this.stopMenuUpdateTimer\n );\n\n this.hyperlinkToolbar.hide();\n\n return;\n }\n }\n\n getStaticParams(): HyperlinkToolbarStaticParams {\n return {\n editHyperlink: (url: string, text: string) => {\n const tr = this.editor.view.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.editor.schema.mark(\"link\", { href: url })\n );\n this.editor.view.dispatch(tr);\n this.editor.view.focus();\n\n this.hyperlinkToolbar.hide();\n },\n deleteHyperlink: () => {\n this.editor.view.dispatch(\n this.editor.view.state.tr\n .removeMark(\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.to,\n this.hyperlinkMark!.type\n )\n .setMeta(\"preventAutolink\", true)\n );\n this.editor.view.focus();\n\n this.hyperlinkToolbar.hide();\n },\n };\n }\n\n getDynamicParams(): HyperlinkToolbarDynamicParams {\n return {\n url: this.hyperlinkMark!.attrs.href,\n text: this.editor.view.state.doc.textBetween(\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.to\n ),\n boundingBox: posToDOMRect(\n this.editor.view,\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.to\n ),\n };\n }\n}\n\nexport const createHyperlinkToolbarPlugin = (\n editor: Editor,\n options: HyperlinkToolbarPluginProps\n) => {\n return new Plugin({\n key: PLUGIN_KEY,\n view: () =>\n new HyperlinkToolbarView({\n editor: editor,\n hyperlinkToolbarFactory: options.hyperlinkToolbarFactory,\n }),\n });\n};\n","import { Link } from \"@tiptap/extension-link\";\nimport {\n createHyperlinkToolbarPlugin,\n HyperlinkToolbarPluginProps,\n} from \"./HyperlinkToolbarPlugin\";\n\n/**\n * This custom link includes a special menu for editing/deleting/opening the link.\n * The menu will be triggered by hovering over the link with the mouse,\n * or by moving the cursor inside the link text\n */\nconst Hyperlink = Link.extend<HyperlinkToolbarPluginProps>({\n priority: 500,\n addProseMirrorPlugins() {\n if (!this.options.hyperlinkToolbarFactory) {\n throw new Error(\"UI Element factory not defined for HyperlinkMark\");\n }\n\n return [\n ...(this.parent?.() || []),\n createHyperlinkToolbarPlugin(this.editor, {\n hyperlinkToolbarFactory: this.options.hyperlinkToolbarFactory,\n }),\n ];\n },\n});\n\nexport default Hyperlink;\n","import Paragraph from \"@tiptap/extension-paragraph\";\n\n// Override paragraph to disable \"Mod-Alt-0\" shortcut throw invalid content for doc type error\nexport const FixedParagraph = Paragraph.extend({\n addKeyboardShortcuts: () => {\n return {\n \"Mod-Alt-0\": () => {\n return false;\n },\n };\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/SlashMenuExtension\";\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 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?.type === \"drag\" && 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 { 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[\"block\"];\n const contentType = schema.nodes[\"textContent\"];\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 !== \"block\") {\n throw new Error(\"Expected block\");\n }\n return lastNode.nodeSize > 4; // empty <block><content/></block> is length 4\n },\n },\n }),\n ];\n },\n});\n","import {\n combineTransactionSteps,\n Extension,\n findChildren,\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 parseInt((window as any).__TEST_OPTIONS.mockID);\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 },\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","import { Extensions, extensions } from \"@tiptap/core\";\n\nimport { Node } from \"@tiptap/core\";\nimport Bold from \"@tiptap/extension-bold\";\nimport Code from \"@tiptap/extension-code\";\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 Strike from \"@tiptap/extension-strike\";\nimport Text from \"@tiptap/extension-text\";\nimport Underline from \"@tiptap/extension-underline\";\nimport { blocks } from \"./extensions/Blocks\";\nimport blockStyles from \"./extensions/Blocks/nodes/Block.module.css\";\nimport { FormattingToolbarExtension } from \"./extensions/FormattingToolbar/FormattingToolbarExtension\";\nimport { DraggableBlocksExtension } from \"./extensions/DraggableBlocks/DraggableBlocksExtension\";\nimport HyperlinkMark from \"./extensions/HyperlinkToolbar/HyperlinkMark\";\nimport { FixedParagraph } from \"./extensions/Paragraph/FixedParagraph\";\nimport { Placeholder } from \"./extensions/Placeholder/PlaceholderExtension\";\nimport SlashMenuExtension from \"./extensions/SlashMenu\";\nimport { TrailingNode } from \"./extensions/TrailingNode/TrailingNodeExtension\";\nimport UniqueID from \"./extensions/UniqueID/UniqueID\";\nimport { FormattingToolbarFactory } from \"./extensions/FormattingToolbar/FormattingToolbarFactoryTypes\";\nimport { HyperlinkToolbarFactory } from \"./extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes\";\nimport { SuggestionsMenuFactory } from \"./shared/plugins/suggestion/SuggestionsMenuFactoryTypes\";\nimport { BlockSideMenuFactory } from \"./extensions/DraggableBlocks/BlockSideMenuFactoryTypes\";\nimport { Link } from \"@tiptap/extension-link\";\nimport { SlashMenuItem } from \"./extensions/SlashMenu/SlashMenuItem\";\n\nexport const Document = Node.create({\n name: \"doc\",\n topNode: true,\n content: \"block+\",\n});\n\nexport type UiFactories = Partial<{\n formattingToolbarFactory: FormattingToolbarFactory;\n hyperlinkToolbarFactory: HyperlinkToolbarFactory;\n slashMenuFactory: SuggestionsMenuFactory<SlashMenuItem>;\n blockSideMenuFactory: BlockSideMenuFactory;\n}>;\n\n/**\n * Get all the Tiptap extensions BlockNote is configured with by default\n */\nexport const getBlockNoteExtensions = (uiFactories: UiFactories) => {\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: [\"block\"],\n }),\n HardBreak,\n // Comments,\n\n // basics:\n Text,\n\n // marks:\n Bold,\n Code,\n Italic,\n Strike,\n Underline,\n FixedParagraph,\n\n // custom blocks:\n ...blocks,\n\n DropCursor.configure({ width: 5, color: \"#ddeeff\" }),\n History,\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 (uiFactories.blockSideMenuFactory) {\n ret.push(\n DraggableBlocksExtension.configure({\n blockSideMenuFactory: uiFactories.blockSideMenuFactory,\n })\n );\n }\n\n if (uiFactories.formattingToolbarFactory) {\n ret.push(\n FormattingToolbarExtension.configure({\n formattingToolbarFactory: uiFactories.formattingToolbarFactory,\n })\n );\n }\n\n if (uiFactories.hyperlinkToolbarFactory) {\n ret.push(\n HyperlinkMark.configure({\n hyperlinkToolbarFactory: uiFactories.hyperlinkToolbarFactory,\n })\n );\n } else {\n ret.push(Link);\n }\n\n if (uiFactories.slashMenuFactory) {\n ret.push(\n SlashMenuExtension.configure({\n slashMenuFactory: uiFactories.slashMenuFactory,\n })\n );\n }\n\n return ret;\n};\n","import { Editor, EditorOptions } from \"@tiptap/core\";\n\n// import \"./blocknote.css\";\nimport { getBlockNoteExtensions, UiFactories } from \"./BlockNoteExtensions\";\nimport styles from \"./editor.module.css\";\n\nexport type BlockNoteEditorOptions = EditorOptions & {\n enableBlockNoteExtensions: boolean;\n disableHistoryExtension: boolean;\n uiFactories: UiFactories;\n};\n\nconst blockNoteOptions = {\n enableInputRules: true,\n enablePasteRules: true,\n enableCoreExtensions: false,\n};\n\nexport class BlockNoteEditor {\n public readonly tiptapEditor: Editor & { contentComponent: any };\n\n constructor(options: Partial<BlockNoteEditorOptions> = {}) {\n const blockNoteExtensions = getBlockNoteExtensions(\n options.uiFactories || {}\n );\n\n let extensions = options.disableHistoryExtension\n ? blockNoteExtensions.filter((e) => e.name !== \"history\")\n : blockNoteExtensions;\n\n const tiptapOptions = {\n ...blockNoteOptions,\n ...options,\n extensions:\n options.enableBlockNoteExtensions === false\n ? options.extensions\n : [...(options.extensions || []), ...extensions],\n editorProps: {\n attributes: {\n ...(options.editorProps?.attributes || {}),\n class: [\n styles.bnEditor,\n styles.bnRoot,\n (options.editorProps?.attributes as any)?.class || \"\",\n ].join(\" \"),\n },\n },\n };\n\n this.tiptapEditor = new Editor(tiptapOptions) as Editor & {\n contentComponent: any;\n };\n }\n}\n"],"names":["BlockAttributes","getBlockInfoFromPos","doc","posInBlock","$pos","maxDepth","node","depth","id","contentNode","contentType","numChildBlocks","startPos","endPos","PLUGIN_KEY","PluginKey","nodeAttributes","PreviousBlockTypePlugin","Plugin","_editorView","view","_prevState","_a","transaction","prev","oldState","newState","transform","combineTransactionSteps","getChangedRanges","oldNodes","findChildren","oldNodesById","newNodes","oldNode","oldContentNode","newContentNode","newAttrs","oldAttrs","indexInitialized","depthChanged","shouldUpdate","state","pluginState","decorations","pos","prevAttrs","decorationAttributes","nodeAttr","val","decoration","Decoration","DecorationSet","Block","Node","element","attrs","HTMLAttr","HTMLAttributes","mergeAttributes","styles","dispatch","newBlock","blockInfo","TextSelection","posBetweenBlocks","nextNodeIsBlock","prevNodeIsBlock","nextBlockInfo","childBlocksStart","childBlocksEnd","childBlocksRange","prevBlockEndPos","prevBlockInfo","keepType","newBlockInsertionPos","secondBlockContent","newBlockContentPos","firstBlockContent","Slice","type","chain","oldBlockContentPos","commands","selectionAtBlockStart","isTextBlock","selectionEmpty","blockAtDocStart","blockEmpty","blockIndented","BlockGroup","TextContent","HeadingContent","attributes","level","InputRule","range","OrderedListItemIndexPlugin","_transactions","_oldState","tr","modified","newIndex","isFirstBlockInDoc","prevBlockContentNode","prevBlockIndex","ListItemContent","parent","blocks","FormattingToolbarView","editor","formattingToolbarFactory","shouldShow","__publicField","from","to","selection","empty","isEmptyTextBlock","isTextSelection","event","_b","composing","isSame","ranges","isNodeSelection","posToDOMRect","url","text","mark","createFormattingToolbarPlugin","options","FormattingToolbarExtension","Extension","MultipleNodeSelection","Selection","$anchor","$head","parentNode","_pos","Fragment","i","mapping","fromResult","toResult","findBlock","findParentNode","findCommandBeforeCursor","char","regex","escapeRegExp","match","SuggestionPluginView","pluginKey","selectItemCallback","suggestionsMenuFactory","item","prevState","next","started","stopped","changed","decorationNode","createSuggestionPlugin","items","deactivate","props","_c","newDecorationId","_d","active","selectedItemIndex","decorationId","blockNode","isAppleOS","formatKeyboardShortcut","shortcut","SlashMenuGroups","SlashMenuItem","name","group","execute","aliases","hint","query","alias","defaultCommands","SlashMenuPluginKey","SlashMenuExtension","key","cmd","serializeForClipboard","pv","horizontalAnchor","dragImageElement","getHorizontalAnchor","firstBlockGroup","absoluteRect","createRect","rect","newRect","getDraggableBlockFromCoords","coords","blockPositionFromCoords","block","docView","desc","blockPositionsFromSelection","beforeFirstBlockPos","afterLastBlockPos","selectionStartInBlockContent","selectionEndInBlockContent","minDepth","startFirstBlockPos","endLastBlockPos","setDragImage","parentClone","getElementIndex","parentElement","targetElement","firstSelectedBlockIndex","lastSelectedBlockIndex","unsetDragImage","dragStart","e","draggedBlockInSelection","multipleBlocksSelected","NodeSelection","slice","dom","BlockMenuView","blockMenuFactory","horizontalPosAnchoredAtRoot","blockContent","blockBoundingBox","createDraggableBlocksPlugin","DraggableBlocksExtension","HyperlinkToolbarView","hyperlinkToolbarFactory","hoveredHyperlinkElement","posInHoveredHyperlinkMark","resolvedPosInHoveredHyperlinkMark","marksAtPos","getMarkRange","prevHyperlinkMark","createHyperlinkToolbarPlugin","Hyperlink","Link","FixedParagraph","Paragraph","Placeholder","menuState","anchor","hasAnchor","isEmpty","classes","TrailingNode","plugin","_","__","schema","shouldInsertNodeAtEnd","endPosition","_state","value","lastNode","removeDuplicates","array","by","seen","findDuplicates","filtered","el","index","UniqueID","v4","extension","types","attributeName","generateID","dragSourceElement","transformPasted","transactions","docChanges","filterTransactions","newRange","findChildrenInRange","newIds","duplicatedNewIds","deleted","handleDragstart","removeId","fragment","list","nodeWithoutId","Document","getBlockNoteExtensions","uiFactories","ret","extensions","GapCursor","blockStyles","HardBreak","Text","Bold","Code","Italic","Strike","Underline","DropCursor","History","HyperlinkMark","blockNoteOptions","BlockNoteEditor","blockNoteExtensions","tiptapOptions","Editor"],"mappings":"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"}
1
+ {"version":3,"file":"blocknote.js","sources":["../src/extensions/Blocks/helpers/getBlockInfoFromPos.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/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.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/index.ts","../src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts","../src/extensions/FormattingToolbar/FormattingToolbarExtension.ts","../src/extensions/Blocks/helpers/findBlock.ts","../src/shared/plugins/suggestion/SuggestionPlugin.ts","../src/extensions/SlashMenu/SlashMenuItem.ts","../src/extensions/SlashMenu/defaultCommands.tsx","../src/extensions/SlashMenu/SlashMenuExtension.ts","../src/extensions/DraggableBlocks/MultipleNodeSelection.ts","../src/extensions/DraggableBlocks/DraggableBlocksPlugin.ts","../src/extensions/DraggableBlocks/DraggableBlocksExtension.ts","../src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts","../src/extensions/HyperlinkToolbar/HyperlinkMark.ts","../src/extensions/Placeholder/PlaceholderExtension.ts","../src/extensions/TrailingNode/TrailingNodeExtension.ts","../src/extensions/UniqueID/UniqueID.ts","../src/extensions/BackgroundColor/BackgroundColorMark.ts","../src/extensions/TextColor/TextColorMark.ts","../src/extensions/BackgroundColor/BackgroundColorExtension.ts","../src/extensions/TextColor/TextColorExtension.ts","../src/extensions/TextAlignment/TextAlignmentExtension.ts","../src/BlockNoteExtensions.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 const $pos = doc.resolve(posInBlock);\n\n const maxDepth = $pos.depth;\n let node = $pos.node(maxDepth);\n let depth = maxDepth;\n\n while (depth >= 0) {\n // If the outermost node is not a block, it means the position does not lie within a block.\n if (depth === 0) {\n return undefined;\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 { 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 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 setTimeout(() => {\n view.dispatch(\n view.state.tr.setMeta(PLUGIN_KEY, { clearUpdate: true })\n );\n }, 0);\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, Slice } from \"prosemirror-model\";\nimport { TextSelection } from \"prosemirror-state\";\nimport { BlockUpdate } from \"../apiTypes\";\nimport { getBlockInfoFromPos } from \"../helpers/getBlockInfoFromPos\";\nimport { PreviousBlockTypePlugin } from \"../PreviousBlockTypePlugin\";\nimport styles from \"./Block.module.css\";\nimport BlockAttributes from \"./BlockAttributes\";\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: (\n posInBlock: number,\n blockUpdate: BlockUpdate\n ) => ReturnType;\n BNCreateOrUpdateBlock: (\n posInBlock: number,\n blockUpdate: BlockUpdate\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 and sets the selection to where the block was.\n BNDeleteBlock:\n (posInBlock) =>\n ({ state, view, 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 state.tr.setSelection(\n new TextSelection(state.doc.resolve(startPos + 1))\n );\n view.focus();\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 // TODO: Is there any situation where we need the whole block content, not just text? Implementation for this\n // is trickier.\n if (dispatch) {\n state.tr.deleteRange(startPos, startPos + contentNode.nodeSize);\n state.tr.insertText(contentNode.textContent, prevBlockEndPos - 1);\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 // Updates the type and attributes of a block at a given position.\n BNUpdateBlock:\n (posInBlock, blockUpdate) =>\n ({ state, dispatch }) => {\n const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);\n if (blockInfo === undefined) {\n return false;\n }\n\n const { node, startPos, contentNode } = blockInfo;\n\n if (dispatch) {\n state.tr.setBlockType(\n startPos + 1,\n startPos + contentNode.nodeSize + 1,\n state.schema.node(blockUpdate.type).type,\n {\n ...node.attrs,\n ...blockUpdate.props,\n }\n );\n }\n\n return true;\n },\n // Changes the block at a given position to a given content type if it's empty, otherwise creates a new block of\n // that type below it.\n BNCreateOrUpdateBlock:\n (posInBlock, blockUpdate) =>\n ({ state, chain }) => {\n const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);\n if (blockInfo === undefined) {\n return false;\n }\n\n const { node, startPos, endPos } = blockInfo;\n\n if (node.textContent.length === 0) {\n const oldBlockContentPos = startPos + 1;\n\n return chain()\n .BNUpdateBlock(posInBlock, blockUpdate)\n .setTextSelection(oldBlockContentPos)\n .run();\n } else {\n const newBlockInsertionPos = endPos + 1;\n const newBlockContentPos = newBlockInsertionPos + 1;\n\n return chain()\n .BNCreateBlock(newBlockInsertionPos)\n .BNUpdateBlock(newBlockContentPos, blockUpdate)\n .setTextSelection(newBlockContentPos)\n .run();\n }\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 { mergeAttributes, Node } from \"@tiptap/core\";\nimport styles from \"../../Block.module.css\";\n\nexport const ParagraphBlockContent = Node.create({\n name: \"paragraph\",\n group: \"blockContent\",\n content: \"inline*\",\n\n parseHTML() {\n return [\n {\n tag: \"p\",\n priority: 200,\n node: \"blockContainer\",\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\", 0],\n ];\n },\n});\n","import { InputRule, mergeAttributes, Node } from \"@tiptap/core\";\nimport styles from \"../../Block.module.css\";\n\nexport const HeadingBlockContent = Node.create({\n name: \"heading\",\n group: \"blockContent\",\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: \"blockContainer\",\n },\n {\n tag: \"h2\",\n attrs: { level: \"2\" },\n node: \"blockContainer\",\n },\n {\n tag: \"h3\",\n attrs: { level: \"3\" },\n node: \"blockContainer\",\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, 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, Node } from \"@tiptap/core\";\nimport styles from \"../../../Block.module.css\";\nimport { handleEnter } from \"../ListItemKeyboardShortcuts\";\n\nexport const BulletListItemBlockContent = Node.create({\n name: \"bulletListItem\",\n group: \"blockContent\",\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 {\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 // Case for BlockNote list structure.\n if (parent.getAttribute(\"data-content-type\") === \"bulletListItem\") {\n return {};\n }\n\n // Case for regular HTML list structure.\n if (parent.tagName === \"UL\") {\n return {};\n }\n\n return false;\n },\n node: \"blockContainer\",\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 [\"li\", 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, Node } from \"@tiptap/core\";\nimport { NumberedListIndexingPlugin } from \"./NumberedListIndexingPlugin\";\nimport styles from \"../../../Block.module.css\";\nimport { handleEnter } from \"../ListItemKeyboardShortcuts\";\n\nexport const NumberedListItemBlockContent = Node.create({\n name: \"numberedListItem\",\n group: \"blockContent\",\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 {\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 // Case for BlockNote list structure.\n if (parent.getAttribute(\"data-content-type\") === \"numberedListItem\") {\n return {};\n }\n\n // Case for regular HTML list structure.\n if (parent.tagName === \"OL\") {\n return {};\n }\n\n return false;\n },\n node: \"blockContainer\",\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 [\"li\", 0],\n ];\n },\n});\n","import { Node } from \"@tiptap/core\";\nimport { BlockContainer } from \"./nodes/BlockContainer\";\nimport { BlockGroup } from \"./nodes/BlockGroup\";\nimport { ParagraphBlockContent } from \"./nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent\";\nimport { HeadingBlockContent } from \"./nodes/BlockContent/HeadingBlockContent/HeadingBlockContent\";\nimport { BulletListItemBlockContent } from \"./nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent\";\nimport { NumberedListItemBlockContent } from \"./nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent\";\n\nexport const blocks: any[] = [\n ParagraphBlockContent,\n HeadingBlockContent,\n BulletListItemBlockContent,\n NumberedListItemBlockContent,\n BlockContainer,\n BlockGroup,\n Node.create({\n name: \"doc\",\n topNode: true,\n content: \"blockGroup\",\n }),\n];\n","import {\n Editor,\n isNodeSelection,\n isTextSelection,\n posToDOMRect,\n} from \"@tiptap/core\";\nimport { EditorState, Plugin, PluginKey } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\nimport { Block, BlockUpdate } from \"../Blocks/apiTypes\";\nimport { getBlockInfoFromPos } from \"../Blocks/helpers/getBlockInfoFromPos\";\nimport {\n FormattingToolbar,\n FormattingToolbarDynamicParams,\n FormattingToolbarFactory,\n FormattingToolbarStaticParams,\n} from \"./FormattingToolbarFactoryTypes\";\n\n// Same as TipTap bubblemenu plugin, but with these changes:\n// https://github.com/ueberdosis/tiptap/pull/2596/files\nexport interface FormattingToolbarPluginProps {\n pluginKey: PluginKey;\n editor: Editor;\n formattingToolbarFactory: FormattingToolbarFactory;\n shouldShow?:\n | ((props: {\n editor: Editor;\n view: EditorView;\n state: EditorState;\n oldState?: EditorState;\n from: number;\n to: number;\n }) => boolean)\n | null;\n}\n\nexport type FormattingToolbarViewProps = FormattingToolbarPluginProps & {\n view: EditorView;\n};\n\nexport class FormattingToolbarView {\n public editor: Editor;\n\n public view: EditorView;\n\n public formattingToolbar: FormattingToolbar;\n\n public preventHide = false;\n\n public preventShow = false;\n\n public toolbarIsOpen = false;\n\n public shouldShow: Exclude<FormattingToolbarPluginProps[\"shouldShow\"], null> =\n ({ 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 editor,\n formattingToolbarFactory,\n view,\n shouldShow,\n }: FormattingToolbarViewProps) {\n this.editor = editor;\n this.view = view;\n\n this.formattingToolbar = formattingToolbarFactory(this.getStaticParams());\n\n if (shouldShow) {\n this.shouldShow = shouldShow;\n }\n\n this.view.dom.addEventListener(\"mousedown\", this.viewMousedownHandler);\n this.view.dom.addEventListener(\"mouseup\", this.viewMouseupHandler);\n this.view.dom.addEventListener(\"dragstart\", this.dragstartHandler);\n\n this.editor.on(\"focus\", this.focusHandler);\n this.editor.on(\"blur\", this.blurHandler);\n }\n\n viewMousedownHandler = () => {\n this.preventShow = true;\n };\n\n viewMouseupHandler = () => {\n this.preventShow = false;\n setTimeout(() => this.update(this.editor.view));\n };\n\n dragstartHandler = () => {\n this.formattingToolbar.hide();\n this.toolbarIsOpen = false;\n };\n\n focusHandler = () => {\n // we use `setTimeout` to make sure `selection` is already updated\n setTimeout(() => this.update(this.editor.view));\n };\n\n blurHandler = ({ event }: { event: FocusEvent }) => {\n if (this.preventHide) {\n this.preventHide = false;\n\n return;\n }\n\n if (\n event?.relatedTarget &&\n this.formattingToolbar.element?.parentNode?.contains(\n event.relatedTarget as Node\n )\n ) {\n return;\n }\n\n if (this.toolbarIsOpen) {\n this.formattingToolbar.hide();\n this.toolbarIsOpen = false;\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 (composing || isSame) {\n return;\n }\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 editor: this.editor,\n view,\n state,\n oldState,\n from,\n to,\n });\n\n // Checks if menu should be shown.\n if (\n !this.toolbarIsOpen &&\n !this.preventShow &&\n (shouldShow || this.preventHide)\n ) {\n this.formattingToolbar.render(this.getDynamicParams(), true);\n this.toolbarIsOpen = true;\n\n // TODO: Is this necessary? Also for other menu plugins.\n // Listener stops focus moving to the menu on click.\n this.formattingToolbar.element!.addEventListener(\"mousedown\", (event) =>\n event.preventDefault()\n );\n\n return;\n }\n\n // Checks if menu should be updated.\n if (\n this.toolbarIsOpen &&\n !this.preventShow &&\n (shouldShow || this.preventHide)\n ) {\n this.formattingToolbar.render(this.getDynamicParams(), false);\n return;\n }\n\n // Checks if menu should be hidden.\n if (\n this.toolbarIsOpen &&\n !this.preventHide &&\n (!shouldShow || this.preventShow)\n ) {\n this.formattingToolbar.hide();\n this.toolbarIsOpen = false;\n\n // Listener stops focus moving to the menu on click.\n this.formattingToolbar.element!.removeEventListener(\n \"mousedown\",\n (event) => event.preventDefault()\n );\n\n return;\n }\n }\n\n destroy() {\n this.view.dom.removeEventListener(\"mousedown\", this.viewMousedownHandler);\n this.view.dom.removeEventListener(\"mouseup\", this.viewMouseupHandler);\n this.view.dom.removeEventListener(\"dragstart\", this.dragstartHandler);\n\n this.editor.off(\"focus\", this.focusHandler);\n this.editor.off(\"blur\", this.blurHandler);\n }\n\n getSelectionBoundingBox() {\n const { state } = this.editor.view;\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.editor.view.nodeDOM(from) as HTMLElement;\n\n if (node) {\n return node.getBoundingClientRect();\n }\n }\n\n return posToDOMRect(this.editor.view, from, to);\n }\n\n getStaticParams(): FormattingToolbarStaticParams {\n return {\n toggleBold: () => {\n this.editor.view.focus();\n this.editor.commands.toggleBold();\n },\n toggleItalic: () => {\n this.editor.view.focus();\n this.editor.commands.toggleItalic();\n },\n toggleUnderline: () => {\n this.editor.view.focus();\n this.editor.commands.toggleUnderline();\n },\n toggleStrike: () => {\n this.editor.view.focus();\n this.editor.commands.toggleStrike();\n },\n setHyperlink: (url: string, text?: string) => {\n if (url === \"\") {\n return;\n }\n\n let { from, to } = this.editor.state.selection;\n\n if (!text) {\n text = this.editor.state.doc.textBetween(from, to);\n }\n\n const mark = this.editor.schema.mark(\"link\", { href: url });\n\n this.editor.view.dispatch(\n this.editor.view.state.tr\n .insertText(text, from, to)\n .addMark(from, from + text.length, mark)\n );\n this.editor.view.focus();\n },\n setTextColor: (color: string) => {\n this.editor.view.focus();\n this.editor.commands.setTextColor(color);\n },\n setBackgroundColor: (color: string) => {\n this.editor.view.focus();\n this.editor.commands.setBackgroundColor(color);\n },\n setTextAlignment: (\n textAlignment: \"left\" | \"center\" | \"right\" | \"justify\"\n ) => {\n this.editor.view.focus();\n this.editor.commands.setTextAlignment(textAlignment);\n },\n increaseBlockIndent: () => {\n this.editor.view.focus();\n this.editor.commands.sinkListItem(\"blockContainer\");\n },\n decreaseBlockIndent: () => {\n this.editor.view.focus();\n this.editor.commands.liftListItem(\"blockContainer\");\n },\n updateBlock: (blockUpdate: BlockUpdate) => {\n this.editor.view.focus();\n this.editor.commands.BNUpdateBlock(\n this.editor.state.selection.from,\n blockUpdate\n );\n },\n };\n }\n\n getDynamicParams(): FormattingToolbarDynamicParams {\n const blockInfo = getBlockInfoFromPos(\n this.editor.state.doc,\n this.editor.state.selection.from\n )!;\n\n return {\n boldIsActive: this.editor.isActive(\"bold\"),\n italicIsActive: this.editor.isActive(\"italic\"),\n underlineIsActive: this.editor.isActive(\"underline\"),\n strikeIsActive: this.editor.isActive(\"strike\"),\n hyperlinkIsActive: this.editor.isActive(\"link\"),\n activeHyperlinkUrl: this.editor.getAttributes(\"link\").href || \"\",\n activeHyperlinkText: this.editor.state.doc.textBetween(\n this.editor.state.selection.from,\n this.editor.state.selection.to\n ),\n textColor: this.editor.getAttributes(\"textColor\").color || \"default\",\n backgroundColor:\n this.editor.getAttributes(\"backgroundColor\").color || \"default\",\n textAlignment:\n this.editor.getAttributes(blockInfo.contentType).textAlignment ||\n \"left\",\n canIncreaseBlockIndent:\n this.editor.state.doc\n .resolve(blockInfo.startPos)\n .index(blockInfo.depth - 1) > 0,\n canDecreaseBlockIndent: blockInfo.depth > 2,\n // Needs type cast as there is no way to create a type that dynamically updates based on which extensions are\n // loaded by the editor.\n block: {\n type: blockInfo.contentType.name,\n props: blockInfo.contentNode.attrs,\n } as Block,\n referenceRect: this.getSelectionBoundingBox(),\n };\n }\n}\n\nexport const createFormattingToolbarPlugin = (\n options: FormattingToolbarPluginProps\n) => {\n return new Plugin({\n key: new PluginKey(\"FormattingToolbarPlugin\"),\n view: (view) => new FormattingToolbarView({ view, ...options }),\n });\n};\n","import { Extension } from \"@tiptap/core\";\nimport { PluginKey } from \"prosemirror-state\";\nimport { FormattingToolbarFactory } from \"./FormattingToolbarFactoryTypes\";\nimport { createFormattingToolbarPlugin } from \"./FormattingToolbarPlugin\";\n\n/**\n * The menu that is displayed when selecting a piece of text.\n */\nexport const FormattingToolbarExtension = Extension.create<{\n formattingToolbarFactory: FormattingToolbarFactory;\n}>({\n name: \"FormattingToolbarExtension\",\n\n addProseMirrorPlugins() {\n if (!this.options.formattingToolbarFactory) {\n throw new Error(\n \"UI Element factory not defined for FormattingToolbarExtension\"\n );\n }\n\n return [\n createFormattingToolbarPlugin({\n editor: this.editor,\n formattingToolbarFactory: this.options.formattingToolbarFactory,\n pluginKey: new PluginKey(\"FormattingToolbarPlugin\"),\n }),\n ];\n },\n});\n","import { findParentNode } from \"@tiptap/core\";\n\nexport const findBlock = findParentNode(\n (node) => node.type.name === \"blockContainer\"\n);\n","import { Editor, Range } from \"@tiptap/core\";\nimport { EditorState, Plugin, PluginKey } from \"prosemirror-state\";\nimport { Decoration, DecorationSet, EditorView } from \"prosemirror-view\";\nimport { findBlock } from \"../../../extensions/Blocks/helpers/findBlock\";\nimport {\n SuggestionsMenu,\n SuggestionsMenuDynamicParams,\n SuggestionsMenuFactory,\n SuggestionsMenuStaticParams,\n} from \"./SuggestionsMenuFactoryTypes\";\nimport { SuggestionItem } from \"./SuggestionItem\";\n\nexport type SuggestionPluginOptions<T extends SuggestionItem> = {\n /**\n * The name of the plugin.\n *\n * Used for ensuring that the plugin key is unique when more than one instance of the SuggestionPlugin is used.\n */\n pluginKey: PluginKey;\n\n /**\n * The TipTap editor.\n */\n editor: Editor;\n\n /**\n * The character that should trigger the suggestion menu to pop up (e.g. a '/' for commands), when typed by the user.\n */\n defaultTriggerCharacter: string;\n\n suggestionsMenuFactory: SuggestionsMenuFactory<T>;\n\n /**\n * The callback that gets executed when an item is selected by the user.\n *\n * **NOTE:** The command text is not removed automatically from the editor by this plugin,\n * this should be done manually. The `editor` and `range` properties passed\n * to the callback function might come in handy when doing this.\n */\n onSelectItem?: (props: { item: T; editor: Editor; range: Range }) => void;\n\n /**\n * A function that should supply the plugin with items to suggest, based on a certain query string.\n */\n items?: (query: string) => T[];\n\n allow?: (props: { editor: Editor; range: Range }) => boolean;\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\ntype SuggestionPluginViewOptions<T extends SuggestionItem> = {\n editor: Editor;\n pluginKey: PluginKey;\n onSelectItem: (props: { item: T; editor: Editor; range: Range }) => void;\n suggestionsMenuFactory: SuggestionsMenuFactory<T>;\n};\n\nclass SuggestionPluginView<T extends SuggestionItem> {\n editor: Editor;\n pluginKey: PluginKey;\n\n suggestionsMenu: SuggestionsMenu<T>;\n\n pluginState: SuggestionPluginState<T>;\n itemCallback: (item: T) => void;\n\n constructor({\n editor,\n pluginKey,\n onSelectItem: selectItemCallback = () => {},\n suggestionsMenuFactory,\n }: SuggestionPluginViewOptions<T>) {\n this.editor = editor;\n this.pluginKey = pluginKey;\n\n this.pluginState = getDefaultPluginState<T>();\n\n this.itemCallback = (item: T) =>\n selectItemCallback({\n item: item,\n editor: editor,\n range: {\n from:\n this.pluginState.queryStartPos! -\n this.pluginState.triggerCharacter!.length,\n to: editor.state.selection.from,\n },\n });\n\n this.suggestionsMenu = suggestionsMenuFactory(this.getStaticParams());\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) {\n this.suggestionsMenu.hide();\n\n // Listener stops focus moving to the menu on click.\n this.suggestionsMenu.element!.removeEventListener(\"mousedown\", (event) =>\n event.preventDefault()\n );\n }\n\n if (changed) {\n this.suggestionsMenu.render(this.getDynamicParams(), false);\n }\n\n if (started) {\n this.suggestionsMenu.render(this.getDynamicParams(), true);\n\n // Listener stops focus moving to the menu on click.\n this.suggestionsMenu.element!.addEventListener(\"mousedown\", (event) =>\n event.preventDefault()\n );\n }\n }\n\n getStaticParams(): SuggestionsMenuStaticParams<T> {\n return {\n itemCallback: (item: T) => this.itemCallback(item),\n };\n }\n\n getDynamicParams(): SuggestionsMenuDynamicParams<T> {\n const decorationNode = document.querySelector(\n `[data-decoration-id=\"${this.pluginState.decorationId}\"]`\n );\n\n return {\n items: this.pluginState.items,\n keyboardHoveredItemIndex: this.pluginState.keyboardHoveredItemIndex!,\n referenceRect: decorationNode!.getBoundingClientRect(),\n };\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 *\n * @param options options for configuring the plugin\n * @returns the prosemirror plugin\n */\nexport function createSuggestionPlugin<T extends SuggestionItem>({\n pluginKey,\n editor,\n defaultTriggerCharacter,\n suggestionsMenuFactory,\n onSelectItem: selectItemCallback = () => {},\n items = () => [],\n}: SuggestionPluginOptions<T>) {\n // Assertions\n if (defaultTriggerCharacter.length !== 1) {\n throw new Error(\"'char' should be a single character\");\n }\n\n const deactivate = (view: EditorView) => {\n view.dispatch(view.state.tr.setMeta(pluginKey, { deactivate: true }));\n };\n\n // Plugin key is passed in as a parameter, so it can be exported and used in the DraggableBlocksPlugin.\n return new Plugin({\n key: pluginKey,\n\n view: (view: EditorView) =>\n new SuggestionPluginView({\n editor: editor,\n pluginKey: pluginKey,\n onSelectItem: (props: { item: T; editor: Editor; range: Range }) => {\n deactivate(view);\n selectItemCallback(props);\n },\n suggestionsMenuFactory: suggestionsMenuFactory,\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(prev.queryStartPos!, newState.selection.from)\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 necessary.\n if (\n transaction.getMeta(pluginKey)?.selectedItemIndexChanged !== 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 }\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 selectItemCallback({\n item: items[keyboardHoveredItemIndex],\n editor: editor,\n range: {\n from: queryStartPos - triggerCharacter.length,\n to: view.state.selection.from,\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 // Hides menu in cases where mouse click does not cause an editor state change.\n handleClick(view) {\n deactivate(view);\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}\n","import { Editor, Range } from \"@tiptap/core\";\nimport { SuggestionItem } from \"../../shared/plugins/suggestion/SuggestionItem\";\n\n/**\n * A class that defines a slash command (/<command>).\n *\n * Not to be confused with ProseMirror commands nor TipTap commands.\n */\nexport class SlashMenuItem implements SuggestionItem {\n /**\n * Constructs a new slash-command.\n *\n * @param name The name of the command\n * @param execute The callback for creating a new node\n * @param aliases Aliases for this command\n */\n constructor(\n public readonly name: string,\n public readonly execute: (editor: Editor, range: Range) => void,\n public readonly aliases: string[] = []\n ) {}\n\n match(query: string): boolean {\n return (\n this.name.toLowerCase().startsWith(query.toLowerCase()) ||\n this.aliases.filter((alias) =>\n alias.toLowerCase().startsWith(query.toLowerCase())\n ).length !== 0\n );\n }\n}\n","import { SlashMenuItem } from \"./SlashMenuItem\";\nimport { Editor, Range } from \"@tiptap/core\";\n\n/**\n * An array containing commands for creating all default blocks.\n */\nconst defaultCommands: { [key: string]: SlashMenuItem } = {\n // Command for creating a level 1 heading\n heading: new SlashMenuItem(\n \"Heading\",\n (editor: Editor, range: Range) => {\n return editor\n .chain()\n .focus()\n .deleteRange(range)\n .BNCreateOrUpdateBlock(range.from, {\n type: \"heading\",\n props: {\n level: \"1\",\n },\n })\n .run();\n },\n [\"h\", \"heading1\", \"h1\"]\n ),\n\n // Command for creating a level 2 heading\n heading2: new SlashMenuItem(\n \"Heading 2\",\n (editor: Editor, range: Range) => {\n return editor\n .chain()\n .focus()\n .deleteRange(range)\n .BNCreateOrUpdateBlock(range.from, {\n type: \"heading\",\n props: {\n level: \"2\",\n },\n })\n .run();\n },\n [\"h2\", \"heading2\", \"subheading\"]\n ),\n\n // Command for creating a level 3 heading\n heading3: new SlashMenuItem(\n \"Heading 3\",\n (editor: Editor, range: Range) => {\n return editor\n .chain()\n .focus()\n .deleteRange(range)\n .BNCreateOrUpdateBlock(range.from, {\n type: \"heading\",\n props: {\n level: \"3\",\n },\n })\n .run();\n },\n [\"h3\", \"heading3\", \"subheading\"]\n ),\n\n // Command for creating an ordered list\n numberedList: new SlashMenuItem(\n \"Numbered List\",\n (editor: Editor, range: Range) => {\n return editor\n .chain()\n .focus()\n .deleteRange(range)\n .BNCreateOrUpdateBlock(range.from, {\n type: \"numberedListItem\",\n props: {},\n })\n .run();\n },\n [\"li\", \"list\", \"numberedlist\", \"numbered list\"]\n ),\n\n // Command for creating a bullet list\n bulletList: new SlashMenuItem(\n \"Bullet List\",\n (editor: Editor, range: Range) => {\n return editor\n .chain()\n .focus()\n .deleteRange(range)\n .BNCreateOrUpdateBlock(range.from, {\n type: \"bulletListItem\",\n props: {},\n })\n .run();\n },\n [\"ul\", \"list\", \"bulletlist\", \"bullet list\"]\n ),\n\n // Command for creating a paragraph (pretty useless)\n paragraph: new SlashMenuItem(\n \"Paragraph\",\n (editor: Editor, range: Range) => {\n return editor\n .chain()\n .focus()\n .deleteRange(range)\n .BNCreateOrUpdateBlock(range.from, {\n type: \"paragraph\",\n props: {},\n })\n .run();\n },\n [\"p\"]\n ),\n\n // replaceRangeWithNode(editor, range, node);\n\n // return true;\n // },\n // [\"ol\", \"orderedlist\"],\n // OrderedListIcon,\n // \"Used to display an ordered (enumerated) list item\"\n // ),\n\n // Command for creating a blockquote\n // blockquote: new SlashCommand(\n // \"Block Quote\",\n // CommandGroup.BASIC_BLOCKS,\n // (editor, range) => {\n // const paragraph = editor.schema.node(\"paragraph\");\n // const node = editor.schema.node(\n // \"blockquote\",\n // { \"block-id\": uniqueId.generate() },\n // paragraph\n // );\n\n // replaceRangeWithNode(editor, range, node);\n\n // return true;\n // },\n // [\"quote\", \"blockquote\"],\n // QuoteIcon,\n // \"Used to make a quote stand out\",\n // \"Ctrl+Shift+B\"\n // ),\n\n // Command for creating a horizontal rule\n // horizontalRule: new SlashCommand(\n // \"Horizontal Rule\",\n // CommandGroup.BASIC_BLOCKS,\n // (editor, range) => {\n // const node = editor.schema.node(\"horizontalRule\", {\n // \"block-id\": uniqueId.generate(),\n // });\n\n // // insert horizontal rule, create a new block after the horizontal rule if applicable\n // // and put the cursor in the block after the horizontal rule.\n // editor\n // .chain()\n // .focus()\n // .replaceRangeAndUpdateSelection(range, node)\n // .command(({ tr, dispatch }) => {\n // if (dispatch) {\n // // the node immediately after the cursor\n // const nodeAfter = tr.selection.$to.nodeAfter;\n\n // // the position of the cursor\n // const cursorPos = tr.selection.$to.pos;\n\n // // check if there is no node after the cursor (end of document)\n // if (!nodeAfter) {\n // // create a new block of the default type (probably paragraph) after the cursor\n // const { parent } = tr.selection.$to;\n // const node = parent.type.contentMatch.defaultType?.create();\n\n // if (node) {\n // tr.insert(cursorPos, node);\n // }\n // }\n\n // // try to put the cursor at the start of the node directly after the inserted horizontal rule\n // tr.doc.nodesBetween(cursorPos, cursorPos + 1, (node, pos) => {\n // if (node.type.name !== \"horizontalRule\") {\n // tr.setSelection(TextSelection.create(tr.doc, pos));\n // }\n // });\n // }\n\n // return true;\n // })\n // .scrollIntoView()\n // .run();\n // return true;\n // },\n // [\"hr\", \"horizontalrule\"],\n // SeparatorIcon,\n // \"Used to separate sections with a horizontal line\"\n // ),\n\n // Command for creating a table\n // table: new SlashCommand(\n // \"Table\",\n // CommandGroup.BASIC_BLOCKS,\n // (editor, range) => {\n // editor.chain().focus().deleteRange(range).run();\n // // TODO: add blockid, pending https://github.com/ueberdosis/tiptap/pull/1469\n // editor\n // .chain()\n // .focus()\n // .insertTable({ rows: 1, cols: 2, withHeaderRow: false })\n // .scrollIntoView()\n // .run();\n // return true;\n // },\n // [\"table\", \"database\"],\n // TableIcon,\n // \"Used to create a simple table\"\n // ),\n};\n\nexport default defaultCommands;\n","import { Extension } from \"@tiptap/core\";\nimport { PluginKey } from \"prosemirror-state\";\nimport { createSuggestionPlugin } from \"../../shared/plugins/suggestion/SuggestionPlugin\";\nimport { SuggestionsMenuFactory } from \"../../shared/plugins/suggestion/SuggestionsMenuFactoryTypes\";\nimport defaultCommands from \"./defaultCommands\";\nimport { SlashMenuItem } from \"./SlashMenuItem\";\n\nexport type SlashMenuOptions = {\n commands: { [key: string]: SlashMenuItem };\n slashMenuFactory: SuggestionsMenuFactory<any> | undefined;\n};\n\nexport const SlashMenuPluginKey = new PluginKey(\"suggestions-slash-commands\");\n\nexport const SlashMenuExtension = Extension.create<SlashMenuOptions>({\n name: \"slash-command\",\n\n addOptions() {\n return {\n commands: defaultCommands,\n slashMenuFactory: undefined, // TODO: fix undefined\n };\n },\n\n addProseMirrorPlugins() {\n if (!this.options.slashMenuFactory) {\n throw new Error(\"UI Element factory not defined for SlashMenuExtension\");\n }\n\n return [\n createSuggestionPlugin<SlashMenuItem>({\n pluginKey: SlashMenuPluginKey,\n editor: this.editor,\n defaultTriggerCharacter: \"/\",\n suggestionsMenuFactory: this.options.slashMenuFactory!,\n items: (query) => {\n const commands = [];\n\n for (const key in this.options.commands) {\n commands.push(this.options.commands[key]);\n }\n\n return commands.filter((cmd: SlashMenuItem) => cmd.match(query));\n },\n onSelectItem: ({ item, editor, range }) => {\n item.execute(editor, range);\n },\n }),\n ];\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 { Editor } from \"@tiptap/core\";\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 styles from \"../../editor.module.css\";\nimport { getBlockInfoFromPos } from \"../Blocks/helpers/getBlockInfoFromPos\";\nimport { SlashMenuPluginKey } from \"../SlashMenu/SlashMenuExtension\";\nimport {\n BlockSideMenu,\n BlockSideMenuDynamicParams,\n BlockSideMenuFactory,\n BlockSideMenuStaticParams,\n} from \"./BlockSideMenuFactoryTypes\";\nimport { DraggableBlocksOptions } from \"./DraggableBlocksExtension\";\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 function createRect(rect: DOMRect) {\n let newRect = {\n left: rect.left + document.body.scrollLeft,\n top: rect.top + document.body.scrollTop,\n width: rect.width,\n height: rect.height,\n bottom: 0,\n right: 0,\n };\n newRect.bottom = newRect.top + newRect.height;\n newRect.right = newRect.left + newRect.width;\n return newRect;\n}\n\nfunction getDraggableBlockFromCoords(\n coords: { left: number; top: number },\n view: EditorView\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 dragImageElement = parentClone;\n dragImageElement.className = styles.dragPreview;\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(e: DragEvent, view: EditorView) {\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 = !selection.$anchor\n .node()\n .eq(selection.$head.node());\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 type BlockMenuViewProps = {\n editor: Editor;\n blockMenuFactory: BlockSideMenuFactory;\n horizontalPosAnchoredAtRoot: boolean;\n};\n\nexport class BlockMenuView {\n editor: Editor;\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 horizontalPosAnchoredAtRoot: boolean;\n\n horizontalPosAnchor: number;\n\n blockMenu: BlockSideMenu;\n\n hoveredBlockContent: HTMLElement | undefined;\n\n menuOpen = false;\n menuFrozen = false;\n\n constructor({\n editor,\n blockMenuFactory,\n horizontalPosAnchoredAtRoot,\n }: BlockMenuViewProps) {\n this.editor = editor;\n this.horizontalPosAnchoredAtRoot = horizontalPosAnchoredAtRoot;\n this.horizontalPosAnchor = (\n editor.view.dom.firstChild! as HTMLElement\n ).getBoundingClientRect().x;\n\n this.blockMenu = blockMenuFactory(this.getStaticParams());\n\n // Shows or updates menu position whenever the cursor moves, if the menu isn't frozen.\n document.body.addEventListener(\n \"mousemove\",\n (event) => {\n if (this.menuFrozen) {\n return;\n }\n\n // Editor itself may have padding or other styling which affects size/position, so we get the boundingRect of\n // the first child (i.e. the blockGroup that wraps all blocks in the editor) for a more accurate bounding box.\n const editorBoundingBox = (\n this.editor.view.dom.firstChild! as HTMLElement\n ).getBoundingClientRect();\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.editor.view);\n\n // Closes the menu if the mouse cursor is beyond the editor vertically.\n if (!block) {\n if (this.menuOpen) {\n this.menuOpen = false;\n this.blockMenu.hide();\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.menuOpen &&\n this.hoveredBlockContent?.hasAttribute(\"data-id\") &&\n this.hoveredBlockContent?.getAttribute(\"data-id\") === block.id\n ) {\n return;\n }\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 this.hoveredBlockContent = blockContent;\n\n if (!blockContent) {\n return;\n }\n\n // Shows or updates elements.\n if (!this.menuOpen) {\n this.menuOpen = true;\n this.blockMenu.render(this.getDynamicParams(), true);\n } else {\n this.blockMenu.render(this.getDynamicParams(), false);\n }\n },\n true\n );\n\n // Hides and unfreezes the menu whenever the user selects the editor with the mouse or presses a key.\n // TODO: Better integration with suggestions menu and only editor scope?\n document.body.addEventListener(\n \"mousedown\",\n (event) => {\n if (this.blockMenu.element?.contains(event.target as HTMLElement)) {\n return;\n }\n\n if (this.menuOpen) {\n this.menuOpen = false;\n this.blockMenu.hide();\n }\n\n this.menuFrozen = false;\n },\n true\n );\n document.body.addEventListener(\n \"keydown\",\n () => {\n if (this.menuOpen) {\n this.menuOpen = false;\n this.blockMenu.hide();\n }\n\n this.menuFrozen = false;\n },\n true\n );\n }\n\n destroy() {\n if (this.menuOpen) {\n this.menuOpen = false;\n this.blockMenu.hide();\n }\n }\n\n addBlock() {\n this.menuOpen = false;\n this.menuFrozen = true;\n this.blockMenu.hide();\n\n const blockContentBoundingBox =\n this.hoveredBlockContent!.getBoundingClientRect();\n\n const pos = this.editor.view.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(this.editor.state.doc, pos.pos);\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\n .chain()\n .BNCreateBlock(newBlockInsertionPos)\n .BNUpdateBlock(newBlockContentPos, { type: \"paragraph\", props: {} })\n .setTextSelection(newBlockContentPos)\n .run();\n } else {\n this.editor.commands.setTextSelection(endPos);\n }\n\n // Focuses and activates the suggestion menu.\n this.editor.view.focus();\n this.editor.view.dispatch(\n this.editor.view.state.tr.scrollIntoView().setMeta(SlashMenuPluginKey, {\n // TODO import suggestion plugin key\n activate: true,\n type: \"drag\",\n })\n );\n }\n\n deleteBlock() {\n this.menuOpen = false;\n this.blockMenu.hide();\n\n const blockContentBoundingBox =\n this.hoveredBlockContent!.getBoundingClientRect();\n\n const pos = this.editor.view.posAtCoords({\n left: blockContentBoundingBox.left + blockContentBoundingBox.width / 2,\n top: blockContentBoundingBox.top + blockContentBoundingBox.height / 2,\n });\n if (!pos) {\n return;\n }\n\n this.editor.commands.BNDeleteBlock(pos.pos);\n }\n\n setBlockBackgroundColor(color: string) {\n this.menuOpen = false;\n this.blockMenu.hide();\n\n const blockContentBoundingBox =\n this.hoveredBlockContent!.getBoundingClientRect();\n\n const pos = this.editor.view.posAtCoords({\n left: blockContentBoundingBox.left + blockContentBoundingBox.width / 2,\n top: blockContentBoundingBox.top + blockContentBoundingBox.height / 2,\n });\n if (!pos) {\n return;\n }\n\n this.editor.commands.setBlockBackgroundColor(pos.pos, color);\n }\n\n setBlockTextColor(color: string) {\n this.menuOpen = false;\n this.blockMenu.hide();\n\n const blockContentBoundingBox =\n this.hoveredBlockContent!.getBoundingClientRect();\n\n const pos = this.editor.view.posAtCoords({\n left: blockContentBoundingBox.left + blockContentBoundingBox.width / 2,\n top: blockContentBoundingBox.top + blockContentBoundingBox.height / 2,\n });\n if (!pos) {\n return;\n }\n\n this.editor.commands.setBlockTextColor(pos.pos, color);\n }\n\n getStaticParams(): BlockSideMenuStaticParams {\n return {\n addBlock: () => this.addBlock(),\n deleteBlock: () => this.deleteBlock(),\n blockDragStart: (event: DragEvent) => dragStart(event, this.editor.view),\n blockDragEnd: () => unsetDragImage(),\n freezeMenu: () => {\n this.menuFrozen = true;\n },\n unfreezeMenu: () => {\n this.menuFrozen = false;\n },\n setBlockBackgroundColor: (color: string) =>\n this.setBlockBackgroundColor(color),\n setBlockTextColor: (color: string) => this.setBlockTextColor(color),\n };\n }\n\n getDynamicParams(): BlockSideMenuDynamicParams {\n const blockContentBoundingBox =\n this.hoveredBlockContent!.getBoundingClientRect();\n\n return {\n blockBackgroundColor:\n this.editor.getAttributes(\"blockContainer\").backgroundColor,\n blockTextColor: this.editor.getAttributes(\"blockContainer\").textColor,\n referenceRect: new DOMRect(\n this.horizontalPosAnchoredAtRoot\n ? this.horizontalPosAnchor\n : blockContentBoundingBox.x,\n blockContentBoundingBox.y,\n blockContentBoundingBox.width,\n blockContentBoundingBox.height\n ),\n };\n }\n}\n\nexport const createDraggableBlocksPlugin = (\n options: DraggableBlocksOptions\n) => {\n return new Plugin({\n key: new PluginKey(\"DraggableBlocksPlugin\"),\n view: () =>\n new BlockMenuView({\n editor: options.editor,\n blockMenuFactory: options.blockSideMenuFactory,\n horizontalPosAnchoredAtRoot: true,\n }),\n });\n};\n","import { Editor, Extension } from \"@tiptap/core\";\nimport { BlockSideMenuFactory } from \"./BlockSideMenuFactoryTypes\";\nimport { createDraggableBlocksPlugin } from \"./DraggableBlocksPlugin\";\n\nexport type DraggableBlocksOptions = {\n editor: Editor;\n blockSideMenuFactory: BlockSideMenuFactory;\n};\n\n/**\n * This extension adds a menu to the side of blocks which features various BlockNote functions such as adding and\n * removing blocks. More importantly, it adds a drag handle which allows the user to drag and drop blocks.\n *\n * code based on https://github.com/ueberdosis/tiptap/issues/323#issuecomment-506637799\n */\nexport const DraggableBlocksExtension =\n Extension.create<DraggableBlocksOptions>({\n name: \"DraggableBlocksExtension\",\n priority: 1000, // Need to be high, in order to hide menu when typing slash\n addProseMirrorPlugins() {\n if (!this.options.blockSideMenuFactory) {\n throw new Error(\n \"UI Element factory not defined for DraggableBlocksExtension\"\n );\n }\n return [\n createDraggableBlocksPlugin({\n editor: this.editor,\n blockSideMenuFactory: this.options.blockSideMenuFactory,\n }),\n ];\n },\n });\n","import { Editor, getMarkRange, posToDOMRect, Range } from \"@tiptap/core\";\nimport { Mark } from \"prosemirror-model\";\nimport { Plugin, PluginKey } from \"prosemirror-state\";\nimport {\n HyperlinkToolbar,\n HyperlinkToolbarDynamicParams,\n HyperlinkToolbarFactory,\n HyperlinkToolbarStaticParams,\n} from \"./HyperlinkToolbarFactoryTypes\";\nconst PLUGIN_KEY = new PluginKey(\"HyperlinkToolbarPlugin\");\n\nexport type HyperlinkToolbarPluginProps = {\n hyperlinkToolbarFactory: HyperlinkToolbarFactory;\n};\n\nexport type HyperlinkToolbarViewProps = {\n editor: Editor;\n hyperlinkToolbarFactory: HyperlinkToolbarFactory;\n};\n\nclass HyperlinkToolbarView {\n editor: Editor;\n\n hyperlinkToolbar: HyperlinkToolbar;\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({ editor, hyperlinkToolbarFactory }: HyperlinkToolbarViewProps) {\n this.editor = editor;\n\n this.hyperlinkToolbar = hyperlinkToolbarFactory(this.getStaticParams());\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 editor.view.dom.addEventListener(\"mouseover\", (event) => {\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 editor.view.posAtDOM(hoveredHyperlinkElement, 0) + 1;\n const resolvedPosInHoveredHyperlinkMark = editor.state.doc.resolve(\n posInHoveredHyperlinkMark\n );\n const marksAtPos = resolvedPosInHoveredHyperlinkMark.marks();\n\n for (const mark of marksAtPos) {\n if (mark.type.name === editor.schema.mark(\"link\").type.name) {\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\n update() {\n if (!this.editor.view.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.editor.state.selection.empty) {\n const marksAtPos = this.editor.state.selection.$from.marks();\n\n for (const mark of marksAtPos) {\n if (mark.type.name === this.editor.schema.mark(\"link\").type.name) {\n this.keyboardHoveredHyperlinkMark = mark;\n this.keyboardHoveredHyperlinkMarkRange =\n getMarkRange(\n this.editor.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) {\n this.getDynamicParams();\n\n // Shows menu.\n if (!prevHyperlinkMark) {\n this.hyperlinkToolbar.render(this.getDynamicParams(), true);\n\n this.hyperlinkToolbar.element?.addEventListener(\n \"mouseleave\",\n this.startMenuUpdateTimer\n );\n this.hyperlinkToolbar.element?.addEventListener(\n \"mouseenter\",\n this.stopMenuUpdateTimer\n );\n\n return;\n }\n\n // Updates menu.\n this.hyperlinkToolbar.render(this.getDynamicParams(), false);\n\n return;\n }\n\n // Hides menu.\n if (!this.hyperlinkMark && prevHyperlinkMark) {\n this.hyperlinkToolbar.element?.removeEventListener(\n \"mouseleave\",\n this.startMenuUpdateTimer\n );\n this.hyperlinkToolbar.element?.removeEventListener(\n \"mouseenter\",\n this.stopMenuUpdateTimer\n );\n\n this.hyperlinkToolbar.hide();\n\n return;\n }\n }\n\n getStaticParams(): HyperlinkToolbarStaticParams {\n return {\n editHyperlink: (url: string, text: string) => {\n const tr = this.editor.view.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.editor.schema.mark(\"link\", { href: url })\n );\n this.editor.view.dispatch(tr);\n this.editor.view.focus();\n\n this.hyperlinkToolbar.hide();\n },\n deleteHyperlink: () => {\n this.editor.view.dispatch(\n this.editor.view.state.tr\n .removeMark(\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.to,\n this.hyperlinkMark!.type\n )\n .setMeta(\"preventAutolink\", true)\n );\n this.editor.view.focus();\n\n this.hyperlinkToolbar.hide();\n },\n };\n }\n\n getDynamicParams(): HyperlinkToolbarDynamicParams {\n return {\n url: this.hyperlinkMark!.attrs.href,\n text: this.editor.view.state.doc.textBetween(\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.to\n ),\n referenceRect: posToDOMRect(\n this.editor.view,\n this.hyperlinkMarkRange!.from,\n this.hyperlinkMarkRange!.to\n ),\n };\n }\n}\n\nexport const createHyperlinkToolbarPlugin = (\n editor: Editor,\n options: HyperlinkToolbarPluginProps\n) => {\n return new Plugin({\n key: PLUGIN_KEY,\n view: () =>\n new HyperlinkToolbarView({\n editor: editor,\n hyperlinkToolbarFactory: options.hyperlinkToolbarFactory,\n }),\n });\n};\n","import { Link } from \"@tiptap/extension-link\";\nimport {\n createHyperlinkToolbarPlugin,\n HyperlinkToolbarPluginProps,\n} from \"./HyperlinkToolbarPlugin\";\n\n/**\n * This custom link includes a special menu for editing/deleting/opening the link.\n * The menu will be triggered by hovering over the link with the mouse,\n * or by moving the cursor inside the link text\n */\nconst Hyperlink = Link.extend<HyperlinkToolbarPluginProps>({\n priority: 500,\n addProseMirrorPlugins() {\n if (!this.options.hyperlinkToolbarFactory) {\n throw new Error(\"UI Element factory not defined for HyperlinkMark\");\n }\n\n return [\n ...(this.parent?.() || []),\n createHyperlinkToolbarPlugin(this.editor, {\n hyperlinkToolbarFactory: this.options.hyperlinkToolbarFactory,\n }),\n ];\n },\n});\n\nexport default Hyperlink;\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/SlashMenuExtension\";\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 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 { 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 {\n combineTransactionSteps,\n Extension,\n findChildren,\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 parseInt((window as any).__TEST_OPTIONS.mockID);\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","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 { 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 { 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 { 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 { 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 { Extensions, extensions } from \"@tiptap/core\";\n\nimport Bold from \"@tiptap/extension-bold\";\nimport Code from \"@tiptap/extension-code\";\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 Strike from \"@tiptap/extension-strike\";\nimport Text from \"@tiptap/extension-text\";\nimport Underline from \"@tiptap/extension-underline\";\nimport { blocks } from \"./extensions/Blocks\";\nimport blockStyles from \"./extensions/Blocks/nodes/Block.module.css\";\nimport { FormattingToolbarExtension } from \"./extensions/FormattingToolbar/FormattingToolbarExtension\";\nimport { DraggableBlocksExtension } from \"./extensions/DraggableBlocks/DraggableBlocksExtension\";\nimport HyperlinkMark from \"./extensions/HyperlinkToolbar/HyperlinkMark\";\nimport { Placeholder } from \"./extensions/Placeholder/PlaceholderExtension\";\nimport SlashMenuExtension from \"./extensions/SlashMenu\";\nimport { TrailingNode } from \"./extensions/TrailingNode/TrailingNodeExtension\";\nimport UniqueID from \"./extensions/UniqueID/UniqueID\";\nimport { FormattingToolbarFactory } from \"./extensions/FormattingToolbar/FormattingToolbarFactoryTypes\";\nimport { HyperlinkToolbarFactory } from \"./extensions/HyperlinkToolbar/HyperlinkToolbarFactoryTypes\";\nimport { SuggestionsMenuFactory } from \"./shared/plugins/suggestion/SuggestionsMenuFactoryTypes\";\nimport { BlockSideMenuFactory } from \"./extensions/DraggableBlocks/BlockSideMenuFactoryTypes\";\nimport { Link } from \"@tiptap/extension-link\";\nimport { SlashMenuItem } from \"./extensions/SlashMenu/SlashMenuItem\";\nimport { BackgroundColorMark } from \"./extensions/BackgroundColor/BackgroundColorMark\";\nimport { TextColorMark } from \"./extensions/TextColor/TextColorMark\";\nimport { BackgroundColorExtension } from \"./extensions/BackgroundColor/BackgroundColorExtension\";\nimport { TextColorExtension } from \"./extensions/TextColor/TextColorExtension\";\nimport { TextAlignmentExtension } from \"./extensions/TextAlignment/TextAlignmentExtension\";\n\nexport type UiFactories = Partial<{\n formattingToolbarFactory: FormattingToolbarFactory;\n hyperlinkToolbarFactory: HyperlinkToolbarFactory;\n slashMenuFactory: SuggestionsMenuFactory<SlashMenuItem>;\n blockSideMenuFactory: BlockSideMenuFactory;\n}>;\n\n/**\n * Get all the Tiptap extensions BlockNote is configured with by default\n */\nexport const getBlockNoteExtensions = (uiFactories: UiFactories) => {\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 TextColorMark,\n TextColorExtension,\n BackgroundColorMark,\n BackgroundColorExtension,\n TextAlignmentExtension,\n\n // custom blocks:\n ...blocks,\n\n DropCursor.configure({ width: 5, color: \"#ddeeff\" }),\n History,\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 (uiFactories.blockSideMenuFactory) {\n ret.push(\n DraggableBlocksExtension.configure({\n blockSideMenuFactory: uiFactories.blockSideMenuFactory,\n })\n );\n }\n\n if (uiFactories.formattingToolbarFactory) {\n ret.push(\n FormattingToolbarExtension.configure({\n formattingToolbarFactory: uiFactories.formattingToolbarFactory,\n })\n );\n }\n\n if (uiFactories.hyperlinkToolbarFactory) {\n ret.push(\n HyperlinkMark.configure({\n hyperlinkToolbarFactory: uiFactories.hyperlinkToolbarFactory,\n })\n );\n } else {\n ret.push(Link);\n }\n\n if (uiFactories.slashMenuFactory) {\n ret.push(\n SlashMenuExtension.configure({\n slashMenuFactory: uiFactories.slashMenuFactory,\n })\n );\n }\n\n return ret;\n};\n","import { Editor, EditorOptions } from \"@tiptap/core\";\n\n// import \"./blocknote.css\";\nimport { getBlockNoteExtensions, UiFactories } from \"./BlockNoteExtensions\";\nimport styles from \"./editor.module.css\";\n\nexport type BlockNoteEditorOptions = EditorOptions & {\n enableBlockNoteExtensions: boolean;\n disableHistoryExtension: boolean;\n uiFactories: UiFactories;\n};\n\nconst blockNoteOptions = {\n enableInputRules: true,\n enablePasteRules: true,\n enableCoreExtensions: false,\n};\n\nexport class BlockNoteEditor {\n public readonly tiptapEditor: Editor & { contentComponent: any };\n\n constructor(options: Partial<BlockNoteEditorOptions> = {}) {\n const blockNoteExtensions = getBlockNoteExtensions(\n options.uiFactories || {}\n );\n\n let extensions = options.disableHistoryExtension\n ? blockNoteExtensions.filter((e) => e.name !== \"history\")\n : blockNoteExtensions;\n\n const tiptapOptions = {\n ...blockNoteOptions,\n ...options,\n extensions:\n options.enableBlockNoteExtensions === false\n ? options.extensions\n : [...(options.extensions || []), ...extensions],\n editorProps: {\n attributes: {\n ...(options.editorProps?.attributes || {}),\n class: [\n styles.bnEditor,\n styles.bnRoot,\n (options.editorProps?.attributes as any)?.class || \"\",\n ].join(\" \"),\n },\n },\n };\n\n this.tiptapEditor = new Editor(tiptapOptions) as Editor & {\n contentComponent: any;\n };\n }\n}\n"],"names":["getBlockInfoFromPos","doc","posInBlock","$pos","maxDepth","node","depth","id","contentNode","contentType","numChildBlocks","startPos","endPos","PLUGIN_KEY","PluginKey","nodeAttributes","PreviousBlockTypePlugin","Plugin","_editorView","view","_prevState","_a","transaction","prev","oldState","newState","currentTransactionOriginalOldBlockAttrs","oldNodes","findChildren","oldNodesById","newNodes","oldNode","oldContentNode","newContentNode","newAttrs","oldAttrs","state","pluginState","decorations","pos","prevAttrs","decorationAttrs","nodeAttr","val","decoration","Decoration","DecorationSet","BlockAttributes","BlockContainer","Node","element","attrs","HTMLAttr","HTMLAttributes","mergeAttributes","styles","dispatch","newBlock","blockInfo","TextSelection","posBetweenBlocks","nextNodeIsBlock","prevNodeIsBlock","nextBlockInfo","childBlocksStart","childBlocksEnd","childBlocksRange","prevBlockEndPos","prevBlockInfo","keepType","originalBlockContent","newBlockContent","newBlockInsertionPos","newBlockContentPos","Slice","Fragment","blockUpdate","chain","oldBlockContentPos","commands","selectionAtBlockStart","isParagraph","selectionEmpty","blockAtDocStart","blockEmpty","blockIndented","BlockGroup","ParagraphBlockContent","HeadingBlockContent","attributes","level","InputRule","range","handleEnter","editor","BulletListItemBlockContent","parent","NumberedListIndexingPlugin","_transactions","_oldState","tr","modified","newIndex","isFirstBlockInDoc","prevBlockContentNode","prevBlockIndex","NumberedListItemBlockContent","blocks","FormattingToolbarView","formattingToolbarFactory","shouldShow","__publicField","from","to","selection","empty","isEmptyTextBlock","isTextSelection","event","_b","composing","isSame","ranges","isNodeSelection","posToDOMRect","url","text","mark","color","textAlignment","createFormattingToolbarPlugin","options","FormattingToolbarExtension","Extension","findBlock","findParentNode","getDefaultPluginState","SuggestionPluginView","pluginKey","selectItemCallback","suggestionsMenuFactory","item","prevState","next","started","stopped","changed","decorationNode","createSuggestionPlugin","defaultTriggerCharacter","items","deactivate","props","_c","_d","menuIsActive","triggerCharacter","queryStartPos","keyboardHoveredItemIndex","active","decorationId","blockNode","SlashMenuItem","name","execute","aliases","query","alias","defaultCommands","SlashMenuPluginKey","SlashMenuExtension","key","cmd","MultipleNodeSelection","Selection","$anchor","$head","parentNode","_pos","i","mapping","fromResult","toResult","serializeForClipboard","pv","dragImageElement","getDraggableBlockFromCoords","coords","blockPositionFromCoords","block","docView","desc","blockPositionsFromSelection","beforeFirstBlockPos","afterLastBlockPos","selectionStartInBlockContent","selectionEndInBlockContent","minDepth","startFirstBlockPos","endLastBlockPos","setDragImage","parentClone","getElementIndex","parentElement","targetElement","firstSelectedBlockIndex","lastSelectedBlockIndex","unsetDragImage","dragStart","e","editorBoundingBox","draggedBlockInSelection","multipleBlocksSelected","NodeSelection","slice","dom","BlockMenuView","blockMenuFactory","horizontalPosAnchoredAtRoot","blockContent","blockContentBoundingBox","createDraggableBlocksPlugin","DraggableBlocksExtension","HyperlinkToolbarView","hyperlinkToolbarFactory","hoveredHyperlinkElement","posInHoveredHyperlinkMark","resolvedPosInHoveredHyperlinkMark","marksAtPos","getMarkRange","prevHyperlinkMark","createHyperlinkToolbarPlugin","Hyperlink","Link","Placeholder","menuState","anchor","hasAnchor","isEmpty","classes","TrailingNode","plugin","_","__","schema","shouldInsertNodeAtEnd","endPosition","type","_state","value","lastNode","removeDuplicates","array","by","seen","findDuplicates","filtered","el","index","UniqueID","v4","extension","types","attributeName","generateID","dragSourceElement","transformPasted","transactions","docChanges","filterTransactions","transform","combineTransactionSteps","getChangedRanges","newRange","findChildrenInRange","newIds","duplicatedNewIds","deleted","handleDragstart","removeId","fragment","list","nodeWithoutId","BackgroundColorMark","Mark","TextColorMark","BackgroundColorExtension","TextColorExtension","TextAlignmentExtension","positionsBeforeSelectedContent","getBlockNoteExtensions","uiFactories","ret","extensions","GapCursor","blockStyles","HardBreak","Text","Bold","Code","Italic","Strike","Underline","DropCursor","History","HyperlinkMark","blockNoteOptions","BlockNoteEditor","blockNoteExtensions","tiptapOptions","Editor"],"mappings":"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"}