@blocknote/core 0.23.1 → 0.23.2

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 (28) hide show
  1. package/dist/blocknote.js +2819 -2500
  2. package/dist/blocknote.js.map +1 -1
  3. package/dist/blocknote.umd.cjs +6 -6
  4. package/dist/blocknote.umd.cjs.map +1 -1
  5. package/dist/tsconfig.tsbuildinfo +1 -1
  6. package/dist/webpack-stats.json +1 -1
  7. package/package.json +2 -2
  8. package/src/api/blockManipulation/commands/updateBlock/updateBlock.ts +4 -2
  9. package/src/api/exporters/html/__snapshots__/codeBlock/contains-newlines/external.html +1 -0
  10. package/src/api/exporters/html/__snapshots__/codeBlock/contains-newlines/internal.html +3 -0
  11. package/src/api/exporters/html/util/serializeBlocksInternalHTML.ts +6 -2
  12. package/src/api/exporters/markdown/__snapshots__/codeBlock/contains-newlines/markdown.md +4 -0
  13. package/src/api/nodeConversions/__snapshots__/nodeConversions.test.ts.snap +27 -0
  14. package/src/api/nodeConversions/blockToNode.ts +35 -9
  15. package/src/api/testUtil/cases/defaultSchema.ts +9 -0
  16. package/src/editor/BlockNoteExtensions.ts +4 -128
  17. package/src/extensions/Collaboration/createCollaborationExtensions.ts +151 -0
  18. package/src/extensions/SideMenu/SideMenuPlugin.ts +76 -28
  19. package/src/i18n/locales/fr.ts +2 -2
  20. package/src/i18n/locales/index.ts +2 -1
  21. package/src/i18n/locales/uk.ts +289 -0
  22. package/types/src/api/exporters/html/util/serializeBlocksInternalHTML.d.ts +1 -1
  23. package/types/src/api/nodeConversions/blockToNode.d.ts +1 -1
  24. package/types/src/editor/BlockNoteExtensions.d.ts +1 -1
  25. package/types/src/extensions/Collaboration/createCollaborationExtensions.d.ts +17 -0
  26. package/types/src/extensions/SideMenu/SideMenuPlugin.d.ts +0 -5
  27. package/types/src/i18n/locales/index.d.ts +2 -1
  28. package/types/src/i18n/locales/uk.d.ts +2 -0
@@ -1 +1 @@
1
- {"builtAt":1738020155335,"assets":[{"name":"blocknote.umd.cjs","size":246763},{"name":"blocknote.umd.cjs.map","size":912979}],"chunks":[{"id":"a1ee98a","entry":true,"initial":true,"files":["blocknote.umd.cjs"],"names":["index"]}],"modules":[{"name":"./src/i18n/locales/ar.ts","size":6919,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/de.ts","size":7549,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/en.ts","size":6990,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/es.ts","size":7421,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/fr.ts","size":8126,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/hr.ts","size":7328,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/is.ts","size":7210,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/ja.ts","size":6639,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/ko.ts","size":6437,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/nl.ts","size":7426,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/pl.ts","size":7129,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/pt.ts","size":7349,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/ru.ts","size":8013,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/vi.ts","size":7264,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/zh.ts","size":6381,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/it.ts","size":7338,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/index.ts","size":0,"chunks":["a1ee98a"]},{"name":"./src/util/typescript.ts","size":331,"chunks":["a1ee98a"]},{"name":"./src/extensions/UniqueID/UniqueID.ts","size":8887,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/types.ts","size":302,"chunks":["a1ee98a"]},{"name":"./src/api/nodeConversions/blockToNode.ts","size":5714,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/util/serializeBlocksExternalHTML.ts","size":5122,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/externalHTMLExporter.ts","size":886,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/util/serializeBlocksInternalHTML.ts","size":3201,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/internalHTMLSerializer.ts","size":288,"chunks":["a1ee98a"]},{"name":"./src/api/getBlockInfoFromPos.ts","size":3648,"chunks":["a1ee98a"]},{"name":"./src/api/nodeUtil.ts","size":490,"chunks":["a1ee98a"]},{"name":"./src/util/browser.ts","size":536,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultBlockHelpers.ts","size":1755,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultProps.ts","size":269,"chunks":["a1ee98a"]},{"name":"./src/util/string.ts","size":299,"chunks":["a1ee98a"]},{"name":"./src/schema/blocks/internal.ts","size":4130,"chunks":["a1ee98a"]},{"name":"./src/schema/blocks/createSpec.ts","size":3609,"chunks":["a1ee98a"]},{"name":"./src/api/nodeConversions/nodeToBlock.ts","size":7706,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/internal.ts","size":1398,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/createSpec.ts","size":2739,"chunks":["a1ee98a"]},{"name":"./src/schema/styles/internal.ts","size":1162,"chunks":["a1ee98a"]},{"name":"./src/schema/styles/createSpec.ts","size":1263,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/helpers/parse/parseFigureElement.ts","size":342,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/helpers/render/createAddFileButton.ts","size":1725,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/helpers/render/createFileNameWithIcon.ts","size":753,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/helpers/render/createFileBlockWrapper.ts","size":1428,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/helpers/toExternalHTML/createFigureWithCaption.ts","size":307,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/helpers/toExternalHTML/createLinkWithCaption.ts","size":294,"chunks":["a1ee98a"]},{"name":"./src/blocks/AudioBlockContent/parseAudioElement.ts","size":108,"chunks":["a1ee98a"]},{"name":"./src/blocks/AudioBlockContent/AudioBlockContent.ts","size":3155,"chunks":["a1ee98a"]},{"name":"./src/blocks/CodeBlockContent/defaultSupportedLanguages.ts","size":1707,"chunks":["a1ee98a"]},{"name":"./src/blocks/CodeBlockContent/CodeBlockContent.ts","size":9104,"chunks":["a1ee98a"]},{"name":"./src/blocks/PageBreakBlockContent/PageBreakBlockContent.ts","size":854,"chunks":["a1ee98a"]},{"name":"./src/extensions/BackgroundColor/BackgroundColorMark.ts","size":946,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextColor/TextColorMark.ts","size":866,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/helpers/parse/parseEmbedElement.ts","size":108,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/FileBlockContent.ts","size":1460,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/commands/updateBlock/updateBlock.ts","size":4673,"chunks":["a1ee98a"]},{"name":"./src/blocks/HeadingBlockContent/HeadingBlockContent.ts","size":3418,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/helpers/render/createResizableFileBlockWrapper.ts","size":4637,"chunks":["a1ee98a"]},{"name":"./src/blocks/ImageBlockContent/parseImageElement.ts","size":175,"chunks":["a1ee98a"]},{"name":"./src/blocks/ImageBlockContent/ImageBlockContent.ts","size":3243,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/commands/splitBlock/splitBlock.ts","size":868,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts","size":1429,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts","size":3415,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts","size":7148,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts","size":2207,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts","size":4427,"chunks":["a1ee98a"]},{"name":"./src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts","size":1434,"chunks":["a1ee98a"]},{"name":"./src/blocks/TableBlockContent/TableExtension.ts","size":2275,"chunks":["a1ee98a"]},{"name":"./src/blocks/TableBlockContent/TableBlockContent.ts","size":4223,"chunks":["a1ee98a"]},{"name":"./src/blocks/VideoBlockContent/parseVideoElement.ts","size":175,"chunks":["a1ee98a"]},{"name":"./src/blocks/VideoBlockContent/VideoBlockContent.ts","size":3162,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultBlocks.ts","size":1147,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultBlockTypeGuards.ts","size":1580,"chunks":["a1ee98a"]},{"name":"./src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts","size":6735,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteSchema.ts","size":1044,"chunks":["a1ee98a"]},{"name":"./src/blocks/PageBreakBlockContent/schema.ts","size":350,"chunks":["a1ee98a"]},{"name":"./src/blocks/PageBreakBlockContent/getPageBreakSlashMenuItems.ts","size":534,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts","size":316,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/commands/insertBlocks/insertBlocks.ts","size":1141,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts","size":5693,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/commands/nestBlock/nestBlock.ts","size":2324,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts","size":2533,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/commands/removeBlocks/removeBlocks.ts","size":123,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/getBlock/getBlock.ts","size":2452,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/insertContentAt.ts","size":1120,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/selections/selection.ts","size":4698,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/selections/textCursorPosition/textCursorPosition.ts","size":2880,"chunks":["a1ee98a"]},{"name":"./src/util/esmDependencies.ts","size":820,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/markdown/removeUnderlinesRehypePlugin.ts","size":752,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/markdown/util/addSpacesToCheckboxesRehypePlugin.ts","size":969,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/markdown/markdownExporter.ts","size":837,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/html/util/nestedLists.ts","size":2174,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/html/parseHTML.ts","size":503,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/markdown/parseMarkdown.ts","size":1097,"chunks":["a1ee98a"]},{"name":"./src/api/clipboard/fromClipboard/acceptedMIMETypes.ts","size":115,"chunks":["a1ee98a"]},{"name":"./src/api/clipboard/fromClipboard/handleFileInsertion.ts","size":3576,"chunks":["a1ee98a"]},{"name":"./src/api/clipboard/fromClipboard/fileDropExtension.ts","size":884,"chunks":["a1ee98a"]},{"name":"./src/api/clipboard/fromClipboard/handleVSCodePaste.ts","size":661,"chunks":["a1ee98a"]},{"name":"./src/api/clipboard/fromClipboard/pasteExtension.ts","size":1552,"chunks":["a1ee98a"]},{"name":"./src/api/nodeConversions/fragmentToBlocks.ts","size":859,"chunks":["a1ee98a"]},{"name":"./src/api/clipboard/toClipboard/copyExtension.ts","size":4666,"chunks":["a1ee98a"]},{"name":"./src/extensions/BackgroundColor/BackgroundColorExtension.ts","size":791,"chunks":["a1ee98a"]},{"name":"./src/util/EventEmitter.ts","size":744,"chunks":["a1ee98a"]},{"name":"./src/extensions/FilePanel/FilePanelPlugin.ts","size":3584,"chunks":["a1ee98a"]},{"name":"./src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts","size":5240,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.ts","size":3228,"chunks":["a1ee98a"]},{"name":"./src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts","size":14774,"chunks":["a1ee98a"]},{"name":"./src/extensions/LinkToolbar/LinkToolbarPlugin.ts","size":7557,"chunks":["a1ee98a"]},{"name":"./src/extensions/LinkToolbar/protocols.ts","size":172,"chunks":["a1ee98a"]},{"name":"./src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.ts","size":1195,"chunks":["a1ee98a"]},{"name":"./src/extensions/Placeholder/PlaceholderPlugin.ts","size":3316,"chunks":["a1ee98a"]},{"name":"./src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts","size":4802,"chunks":["a1ee98a"]},{"name":"./src/extensions/getDraggableBlockFromElement.ts","size":404,"chunks":["a1ee98a"]},{"name":"./src/extensions/SideMenu/MultipleNodeSelection.ts","size":1616,"chunks":["a1ee98a"]},{"name":"./src/extensions/SideMenu/dragging.ts","size":4521,"chunks":["a1ee98a"]},{"name":"./src/extensions/SideMenu/SideMenuPlugin.ts","size":13295,"chunks":["a1ee98a"]},{"name":"./src/extensions/SuggestionMenu/SuggestionPlugin.ts","size":8034,"chunks":["a1ee98a"]},{"name":"./src/extensions/TableHandles/TableHandlesPlugin.ts","size":19364,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextAlignment/TextAlignmentExtension.ts","size":928,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextColor/TextColorExtension.ts","size":725,"chunks":["a1ee98a"]},{"name":"./src/extensions/TrailingNode/TrailingNodeExtension.ts","size":1563,"chunks":["a1ee98a"]},{"name":"./src/pm-nodes/BlockContainer.ts","size":2038,"chunks":["a1ee98a"]},{"name":"./src/pm-nodes/BlockGroup.ts","size":1102,"chunks":["a1ee98a"]},{"name":"./src/pm-nodes/Doc.ts","size":90,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteExtensions.ts","size":7869,"chunks":["a1ee98a"]},{"name":"./src/editor/transformPasted.ts","size":2604,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteTipTapEditor.ts","size":3599,"chunks":["a1ee98a"]},{"name":"./src/style.css","size":0,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteEditor.ts","size":26432,"chunks":["a1ee98a"]},{"name":"./src/editor/defaultColors.ts","size":1193,"chunks":["a1ee98a"]},{"name":"./src/exporter/Exporter.ts","size":1075,"chunks":["a1ee98a"]},{"name":"./src/exporter/mapping.ts","size":197,"chunks":["a1ee98a"]},{"name":"./src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.ts","size":700,"chunks":["a1ee98a"]},{"name":"./src/util/combineByGroup.ts","size":550,"chunks":["a1ee98a"]},{"name":"./src/api/testUtil/partialBlockTestUtil.ts","size":3149,"chunks":["a1ee98a"]},{"name":"./src/index.ts","size":0,"chunks":["a1ee98a"]}]}
1
+ {"builtAt":1738934513601,"assets":[{"name":"blocknote.umd.cjs","size":254712},{"name":"blocknote.umd.cjs.map","size":931549}],"chunks":[{"id":"a1ee98a","entry":true,"initial":true,"files":["blocknote.umd.cjs"],"names":["index"]}],"modules":[{"name":"./src/i18n/locales/ar.ts","size":6919,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/de.ts","size":7549,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/en.ts","size":6990,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/es.ts","size":7421,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/fr.ts","size":8147,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/hr.ts","size":7328,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/is.ts","size":7210,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/it.ts","size":7338,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/ja.ts","size":6639,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/ko.ts","size":6437,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/nl.ts","size":7426,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/pl.ts","size":7129,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/pt.ts","size":7349,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/ru.ts","size":8013,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/uk.ts","size":7519,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/vi.ts","size":7264,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/zh.ts","size":6381,"chunks":["a1ee98a"]},{"name":"./src/i18n/locales/index.ts","size":0,"chunks":["a1ee98a"]},{"name":"./src/util/typescript.ts","size":331,"chunks":["a1ee98a"]},{"name":"./src/extensions/UniqueID/UniqueID.ts","size":8887,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/types.ts","size":302,"chunks":["a1ee98a"]},{"name":"./src/api/nodeConversions/blockToNode.ts","size":6071,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/util/serializeBlocksExternalHTML.ts","size":5122,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/externalHTMLExporter.ts","size":886,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/util/serializeBlocksInternalHTML.ts","size":3264,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/html/internalHTMLSerializer.ts","size":288,"chunks":["a1ee98a"]},{"name":"./src/api/getBlockInfoFromPos.ts","size":3648,"chunks":["a1ee98a"]},{"name":"./src/api/nodeUtil.ts","size":490,"chunks":["a1ee98a"]},{"name":"./src/util/browser.ts","size":536,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultBlockHelpers.ts","size":1755,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultProps.ts","size":269,"chunks":["a1ee98a"]},{"name":"./src/util/string.ts","size":299,"chunks":["a1ee98a"]},{"name":"./src/schema/blocks/internal.ts","size":4130,"chunks":["a1ee98a"]},{"name":"./src/schema/blocks/createSpec.ts","size":3609,"chunks":["a1ee98a"]},{"name":"./src/api/nodeConversions/nodeToBlock.ts","size":7706,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/internal.ts","size":1398,"chunks":["a1ee98a"]},{"name":"./src/schema/inlineContent/createSpec.ts","size":2739,"chunks":["a1ee98a"]},{"name":"./src/schema/styles/internal.ts","size":1162,"chunks":["a1ee98a"]},{"name":"./src/schema/styles/createSpec.ts","size":1263,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/helpers/parse/parseFigureElement.ts","size":342,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/helpers/render/createAddFileButton.ts","size":1725,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/helpers/render/createFileNameWithIcon.ts","size":753,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/helpers/render/createFileBlockWrapper.ts","size":1428,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/helpers/toExternalHTML/createFigureWithCaption.ts","size":307,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/helpers/toExternalHTML/createLinkWithCaption.ts","size":294,"chunks":["a1ee98a"]},{"name":"./src/blocks/AudioBlockContent/parseAudioElement.ts","size":108,"chunks":["a1ee98a"]},{"name":"./src/blocks/AudioBlockContent/AudioBlockContent.ts","size":3155,"chunks":["a1ee98a"]},{"name":"./src/blocks/CodeBlockContent/defaultSupportedLanguages.ts","size":1707,"chunks":["a1ee98a"]},{"name":"./src/blocks/CodeBlockContent/CodeBlockContent.ts","size":9104,"chunks":["a1ee98a"]},{"name":"./src/blocks/PageBreakBlockContent/PageBreakBlockContent.ts","size":854,"chunks":["a1ee98a"]},{"name":"./src/extensions/BackgroundColor/BackgroundColorMark.ts","size":946,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextColor/TextColorMark.ts","size":866,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/helpers/parse/parseEmbedElement.ts","size":108,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/FileBlockContent.ts","size":1460,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/commands/updateBlock/updateBlock.ts","size":4725,"chunks":["a1ee98a"]},{"name":"./src/blocks/HeadingBlockContent/HeadingBlockContent.ts","size":3418,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/helpers/render/createResizableFileBlockWrapper.ts","size":4637,"chunks":["a1ee98a"]},{"name":"./src/blocks/ImageBlockContent/parseImageElement.ts","size":175,"chunks":["a1ee98a"]},{"name":"./src/blocks/ImageBlockContent/ImageBlockContent.ts","size":3243,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/commands/splitBlock/splitBlock.ts","size":868,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts","size":1429,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts","size":3415,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts","size":7148,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts","size":2207,"chunks":["a1ee98a"]},{"name":"./src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts","size":4427,"chunks":["a1ee98a"]},{"name":"./src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts","size":1434,"chunks":["a1ee98a"]},{"name":"./src/blocks/TableBlockContent/TableExtension.ts","size":2275,"chunks":["a1ee98a"]},{"name":"./src/blocks/TableBlockContent/TableBlockContent.ts","size":4223,"chunks":["a1ee98a"]},{"name":"./src/blocks/VideoBlockContent/parseVideoElement.ts","size":175,"chunks":["a1ee98a"]},{"name":"./src/blocks/VideoBlockContent/VideoBlockContent.ts","size":3162,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultBlocks.ts","size":1147,"chunks":["a1ee98a"]},{"name":"./src/blocks/defaultBlockTypeGuards.ts","size":1580,"chunks":["a1ee98a"]},{"name":"./src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts","size":6735,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteSchema.ts","size":1044,"chunks":["a1ee98a"]},{"name":"./src/blocks/PageBreakBlockContent/schema.ts","size":350,"chunks":["a1ee98a"]},{"name":"./src/blocks/PageBreakBlockContent/getPageBreakSlashMenuItems.ts","size":534,"chunks":["a1ee98a"]},{"name":"./src/blocks/FileBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts","size":316,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/commands/insertBlocks/insertBlocks.ts","size":1141,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts","size":5693,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/commands/nestBlock/nestBlock.ts","size":2324,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts","size":2533,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/commands/removeBlocks/removeBlocks.ts","size":123,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/getBlock/getBlock.ts","size":2452,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/insertContentAt.ts","size":1120,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/selections/selection.ts","size":4698,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/selections/textCursorPosition/textCursorPosition.ts","size":2880,"chunks":["a1ee98a"]},{"name":"./src/util/esmDependencies.ts","size":820,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/markdown/removeUnderlinesRehypePlugin.ts","size":752,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/markdown/util/addSpacesToCheckboxesRehypePlugin.ts","size":969,"chunks":["a1ee98a"]},{"name":"./src/api/exporters/markdown/markdownExporter.ts","size":837,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/html/util/nestedLists.ts","size":2174,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/html/parseHTML.ts","size":503,"chunks":["a1ee98a"]},{"name":"./src/api/parsers/markdown/parseMarkdown.ts","size":1097,"chunks":["a1ee98a"]},{"name":"./src/api/clipboard/fromClipboard/acceptedMIMETypes.ts","size":115,"chunks":["a1ee98a"]},{"name":"./src/api/clipboard/fromClipboard/handleFileInsertion.ts","size":3576,"chunks":["a1ee98a"]},{"name":"./src/api/clipboard/fromClipboard/fileDropExtension.ts","size":884,"chunks":["a1ee98a"]},{"name":"./src/api/clipboard/fromClipboard/handleVSCodePaste.ts","size":661,"chunks":["a1ee98a"]},{"name":"./src/api/clipboard/fromClipboard/pasteExtension.ts","size":1552,"chunks":["a1ee98a"]},{"name":"./src/api/nodeConversions/fragmentToBlocks.ts","size":859,"chunks":["a1ee98a"]},{"name":"./src/api/clipboard/toClipboard/copyExtension.ts","size":4666,"chunks":["a1ee98a"]},{"name":"./src/extensions/BackgroundColor/BackgroundColorExtension.ts","size":791,"chunks":["a1ee98a"]},{"name":"./src/util/EventEmitter.ts","size":744,"chunks":["a1ee98a"]},{"name":"./src/extensions/FilePanel/FilePanelPlugin.ts","size":3584,"chunks":["a1ee98a"]},{"name":"./src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts","size":5240,"chunks":["a1ee98a"]},{"name":"./src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.ts","size":3228,"chunks":["a1ee98a"]},{"name":"./src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts","size":14774,"chunks":["a1ee98a"]},{"name":"./src/extensions/LinkToolbar/LinkToolbarPlugin.ts","size":7557,"chunks":["a1ee98a"]},{"name":"./src/extensions/LinkToolbar/protocols.ts","size":172,"chunks":["a1ee98a"]},{"name":"./src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.ts","size":1195,"chunks":["a1ee98a"]},{"name":"./src/extensions/Placeholder/PlaceholderPlugin.ts","size":3316,"chunks":["a1ee98a"]},{"name":"./src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts","size":4802,"chunks":["a1ee98a"]},{"name":"./src/extensions/getDraggableBlockFromElement.ts","size":404,"chunks":["a1ee98a"]},{"name":"./src/extensions/SideMenu/MultipleNodeSelection.ts","size":1616,"chunks":["a1ee98a"]},{"name":"./src/extensions/SideMenu/dragging.ts","size":4521,"chunks":["a1ee98a"]},{"name":"./src/extensions/SideMenu/SideMenuPlugin.ts","size":13634,"chunks":["a1ee98a"]},{"name":"./src/extensions/SuggestionMenu/SuggestionPlugin.ts","size":8034,"chunks":["a1ee98a"]},{"name":"./src/extensions/TableHandles/TableHandlesPlugin.ts","size":19364,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextAlignment/TextAlignmentExtension.ts","size":928,"chunks":["a1ee98a"]},{"name":"./src/extensions/TextColor/TextColorExtension.ts","size":725,"chunks":["a1ee98a"]},{"name":"./src/extensions/TrailingNode/TrailingNodeExtension.ts","size":1563,"chunks":["a1ee98a"]},{"name":"./src/pm-nodes/BlockContainer.ts","size":2038,"chunks":["a1ee98a"]},{"name":"./src/pm-nodes/BlockGroup.ts","size":1102,"chunks":["a1ee98a"]},{"name":"./src/pm-nodes/Doc.ts","size":90,"chunks":["a1ee98a"]},{"name":"./src/extensions/Collaboration/createCollaborationExtensions.ts","size":3607,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteExtensions.ts","size":4367,"chunks":["a1ee98a"]},{"name":"./src/editor/transformPasted.ts","size":2604,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteTipTapEditor.ts","size":3599,"chunks":["a1ee98a"]},{"name":"./src/style.css","size":0,"chunks":["a1ee98a"]},{"name":"./src/editor/BlockNoteEditor.ts","size":26432,"chunks":["a1ee98a"]},{"name":"./src/editor/defaultColors.ts","size":1193,"chunks":["a1ee98a"]},{"name":"./src/exporter/Exporter.ts","size":1075,"chunks":["a1ee98a"]},{"name":"./src/exporter/mapping.ts","size":197,"chunks":["a1ee98a"]},{"name":"./src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.ts","size":700,"chunks":["a1ee98a"]},{"name":"./src/util/combineByGroup.ts","size":550,"chunks":["a1ee98a"]},{"name":"./src/api/testUtil/partialBlockTestUtil.ts","size":3149,"chunks":["a1ee98a"]},{"name":"./src/index.ts","size":0,"chunks":["a1ee98a"]}]}
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "*.css"
7
7
  ],
8
8
  "license": "MPL-2.0",
9
- "version": "0.23.1",
9
+ "version": "0.23.2",
10
10
  "files": [
11
11
  "dist",
12
12
  "types",
@@ -124,5 +124,5 @@
124
124
  "access": "public",
125
125
  "registry": "https://registry.npmjs.org/"
126
126
  },
127
- "gitHead": "50bc584ee7fe5b7f3e010d43f61e872063cfeeb3"
127
+ "gitHead": "8433d2e54ea0aefc01633ef2edc56e7c234f42d1"
128
128
  }
@@ -141,7 +141,8 @@ function updateBlockContentNode<
141
141
  content = inlineContentToNodes(
142
142
  [block.content],
143
143
  state.schema,
144
- editor.schema.styleSchema
144
+ editor.schema.styleSchema,
145
+ newNodeType.name
145
146
  );
146
147
  } else if (Array.isArray(block.content)) {
147
148
  // Adds a text node with the provided styles converted into marks to the content,
@@ -149,7 +150,8 @@ function updateBlockContentNode<
149
150
  content = inlineContentToNodes(
150
151
  block.content,
151
152
  state.schema,
152
- editor.schema.styleSchema
153
+ editor.schema.styleSchema,
154
+ newNodeType.name
153
155
  );
154
156
  } else if (block.content.type === "tableContent") {
155
157
  content = tableContentToNodes(
@@ -0,0 +1 @@
1
+ <pre><code class="bn-inline-content language-javascript">const hello = 'world';<br>console.log(hello);<br></code></pre>
@@ -0,0 +1,3 @@
1
+ <div class="bn-block-group" data-node-type="blockGroup"><div class="bn-block-outer" data-node-type="blockOuter" data-id="1"><div class="bn-block" data-node-type="blockContainer" data-id="1"><div class="bn-block-content" data-content-type="codeBlock"><pre><code class="bn-inline-content language-javascript">const hello = 'world';
2
+ console.log(hello);
3
+ </code></pre></div></div></div></div>
@@ -21,6 +21,7 @@ export function serializeInlineContentInternalHTML<
21
21
  editor: BlockNoteEditor<any, I, S>,
22
22
  blockContent: PartialBlock<BSchema, I, S>["content"],
23
23
  serializer: DOMSerializer,
24
+ blockType?: string,
24
25
  options?: { document?: Document }
25
26
  ) {
26
27
  let nodes: any;
@@ -32,13 +33,15 @@ export function serializeInlineContentInternalHTML<
32
33
  nodes = inlineContentToNodes(
33
34
  [blockContent],
34
35
  editor.pmSchema,
35
- editor.schema.styleSchema
36
+ editor.schema.styleSchema,
37
+ blockType
36
38
  );
37
39
  } else if (Array.isArray(blockContent)) {
38
40
  nodes = inlineContentToNodes(
39
41
  blockContent,
40
42
  editor.pmSchema,
41
- editor.schema.styleSchema
43
+ editor.schema.styleSchema,
44
+ blockType
42
45
  );
43
46
  } else if (blockContent.type === "tableContent") {
44
47
  nodes = tableContentToNodes(
@@ -102,6 +105,7 @@ function serializeBlock<
102
105
  editor,
103
106
  block.content as any, // TODO
104
107
  serializer,
108
+ block.type,
105
109
  options
106
110
  );
107
111
  ret.contentDOM.appendChild(ic);
@@ -0,0 +1,4 @@
1
+ ```javascript
2
+ const hello = 'world';
3
+ console.log(hello);
4
+ ```
@@ -662,6 +662,33 @@ exports[`Test BlockNote-Prosemirror conversion > Case: custom style schema > Con
662
662
  }
663
663
  `;
664
664
 
665
+ exports[`Test BlockNote-Prosemirror conversion > Case: default schema > Convert codeBlock/contains-newlines to/from prosemirror 1`] = `
666
+ {
667
+ "attrs": {
668
+ "backgroundColor": "default",
669
+ "id": "1",
670
+ "textColor": "default",
671
+ },
672
+ "content": [
673
+ {
674
+ "attrs": {
675
+ "language": "javascript",
676
+ },
677
+ "content": [
678
+ {
679
+ "text": "const hello = 'world';
680
+ console.log(hello);
681
+ ",
682
+ "type": "text",
683
+ },
684
+ ],
685
+ "type": "codeBlock",
686
+ },
687
+ ],
688
+ "type": "blockContainer",
689
+ }
690
+ `;
691
+
665
692
  exports[`Test BlockNote-Prosemirror conversion > Case: default schema > Convert codeBlock/defaultLanguage to/from prosemirror 1`] = `
666
693
  {
667
694
  "attrs": {
@@ -25,7 +25,8 @@ import { UnreachableCaseError } from "../../util/typescript.js";
25
25
  function styledTextToNodes<T extends StyleSchema>(
26
26
  styledText: StyledText<T>,
27
27
  schema: Schema,
28
- styleSchema: T
28
+ styleSchema: T,
29
+ blockType?: string
29
30
  ): Node[] {
30
31
  const marks: Mark[] = [];
31
32
 
@@ -44,6 +45,12 @@ function styledTextToNodes<T extends StyleSchema>(
44
45
  }
45
46
  }
46
47
 
48
+ const parseHardBreaks = !blockType || !schema.nodes[blockType].spec.code;
49
+
50
+ if (!parseHardBreaks) {
51
+ return [schema.text(styledText.text, marks)];
52
+ }
53
+
47
54
  return (
48
55
  styledText.text
49
56
  // Splits text & line breaks.
@@ -96,7 +103,8 @@ function linkToNodes(
96
103
  function styledTextArrayToNodes<S extends StyleSchema>(
97
104
  content: string | StyledText<S>[],
98
105
  schema: Schema,
99
- styleSchema: S
106
+ styleSchema: S,
107
+ blockType?: string
100
108
  ): Node[] {
101
109
  const nodes: Node[] = [];
102
110
 
@@ -105,14 +113,17 @@ function styledTextArrayToNodes<S extends StyleSchema>(
105
113
  ...styledTextToNodes(
106
114
  { type: "text", text: content, styles: {} },
107
115
  schema,
108
- styleSchema
116
+ styleSchema,
117
+ blockType
109
118
  )
110
119
  );
111
120
  return nodes;
112
121
  }
113
122
 
114
123
  for (const styledText of content) {
115
- nodes.push(...styledTextToNodes(styledText, schema, styleSchema));
124
+ nodes.push(
125
+ ...styledTextToNodes(styledText, schema, styleSchema, blockType)
126
+ );
116
127
  }
117
128
  return nodes;
118
129
  }
@@ -126,17 +137,22 @@ export function inlineContentToNodes<
126
137
  >(
127
138
  blockContent: PartialInlineContent<I, S>,
128
139
  schema: Schema,
129
- styleSchema: S
140
+ styleSchema: S,
141
+ blockType?: string
130
142
  ): Node[] {
131
143
  const nodes: Node[] = [];
132
144
 
133
145
  for (const content of blockContent) {
134
146
  if (typeof content === "string") {
135
- nodes.push(...styledTextArrayToNodes(content, schema, styleSchema));
147
+ nodes.push(
148
+ ...styledTextArrayToNodes(content, schema, styleSchema, blockType)
149
+ );
136
150
  } else if (isPartialLinkInlineContent(content)) {
137
151
  nodes.push(...linkToNodes(content, schema, styleSchema));
138
152
  } else if (isStyledTextInlineContent(content)) {
139
- nodes.push(...styledTextArrayToNodes([content], schema, styleSchema));
153
+ nodes.push(
154
+ ...styledTextArrayToNodes([content], schema, styleSchema, blockType)
155
+ );
140
156
  } else {
141
157
  nodes.push(
142
158
  blockOrInlineContentToContentNode(content, schema, styleSchema)
@@ -217,10 +233,20 @@ function blockOrInlineContentToContentNode(
217
233
  if (!block.content) {
218
234
  contentNode = schema.nodes[type].createChecked(block.props);
219
235
  } else if (typeof block.content === "string") {
220
- const nodes = inlineContentToNodes([block.content], schema, styleSchema);
236
+ const nodes = inlineContentToNodes(
237
+ [block.content],
238
+ schema,
239
+ styleSchema,
240
+ type
241
+ );
221
242
  contentNode = schema.nodes[type].createChecked(block.props, nodes);
222
243
  } else if (Array.isArray(block.content)) {
223
- const nodes = inlineContentToNodes(block.content, schema, styleSchema);
244
+ const nodes = inlineContentToNodes(
245
+ block.content,
246
+ schema,
247
+ styleSchema,
248
+ type
249
+ );
224
250
  contentNode = schema.nodes[type].createChecked(block.props, nodes);
225
251
  } else if (block.content.type === "tableContent") {
226
252
  const nodes = tableContentToNodes(block.content, schema, styleSchema);
@@ -208,6 +208,15 @@ export const defaultSchemaTestCases: EditorTestCases<
208
208
  },
209
209
  ],
210
210
  },
211
+ {
212
+ name: "codeBlock/contains-newlines",
213
+ blocks: [
214
+ {
215
+ type: "codeBlock",
216
+ content: "const hello = 'world';\nconsole.log(hello);\n",
217
+ },
218
+ ],
219
+ },
211
220
  {
212
221
  name: "pageBreak/basic",
213
222
  blocks: [
@@ -1,10 +1,4 @@
1
1
  import { AnyExtension, Extension, extensions } from "@tiptap/core";
2
- import { Awareness } from "y-protocols/awareness";
3
-
4
- import type { BlockNoteEditor, BlockNoteExtension } from "./BlockNoteEditor.js";
5
-
6
- import Collaboration from "@tiptap/extension-collaboration";
7
- import CollaborationCursor from "@tiptap/extension-collaboration-cursor";
8
2
  import { Gapcursor } from "@tiptap/extension-gapcursor";
9
3
  import { HardBreak } from "@tiptap/extension-hard-break";
10
4
  import { History } from "@tiptap/extension-history";
@@ -12,6 +6,8 @@ import { Link } from "@tiptap/extension-link";
12
6
  import { Text } from "@tiptap/extension-text";
13
7
  import { Plugin } from "prosemirror-state";
14
8
  import * as Y from "yjs";
9
+
10
+ import type { BlockNoteEditor, BlockNoteExtension } from "./BlockNoteEditor.js";
15
11
  import { createDropFileExtension } from "../api/clipboard/fromClipboard/fileDropExtension.js";
16
12
  import { createPasteFromClipboardExtension } from "../api/clipboard/fromClipboard/pasteExtension.js";
17
13
  import { createCopyToClipboardExtension } from "../api/clipboard/toClipboard/copyExtension.js";
@@ -44,6 +40,7 @@ import {
44
40
  StyleSchema,
45
41
  StyleSpecs,
46
42
  } from "../schema/index.js";
43
+ import { createCollaborationExtensions } from "../extensions/Collaboration/createCollaborationExtensions.js";
47
44
 
48
45
  type ExtensionOptions<
49
46
  BSchema extends BlockSchema,
@@ -247,128 +244,7 @@ const getTipTapExtensions = <
247
244
  ];
248
245
 
249
246
  if (opts.collaboration) {
250
- tiptapExtensions.push(
251
- Collaboration.configure({
252
- fragment: opts.collaboration.fragment,
253
- })
254
- );
255
-
256
- const awareness = opts.collaboration?.provider.awareness as Awareness;
257
-
258
- if (awareness) {
259
- const cursors = new Map<
260
- number,
261
- { element: HTMLElement; hideTimeout: NodeJS.Timeout | undefined }
262
- >();
263
-
264
- if (opts.collaboration.showCursorLabels !== "always") {
265
- awareness.on(
266
- "change",
267
- ({
268
- updated,
269
- }: {
270
- added: Array<number>;
271
- updated: Array<number>;
272
- removed: Array<number>;
273
- }) => {
274
- for (const clientID of updated) {
275
- const cursor = cursors.get(clientID);
276
-
277
- if (cursor) {
278
- cursor.element.setAttribute("data-active", "");
279
-
280
- if (cursor.hideTimeout) {
281
- clearTimeout(cursor.hideTimeout);
282
- }
283
-
284
- cursors.set(clientID, {
285
- element: cursor.element,
286
- hideTimeout: setTimeout(() => {
287
- cursor.element.removeAttribute("data-active");
288
- }, 2000),
289
- });
290
- }
291
- }
292
- }
293
- );
294
- }
295
-
296
- const createCursor = (clientID: number, name: string, color: string) => {
297
- const cursorElement = document.createElement("span");
298
-
299
- cursorElement.classList.add("collaboration-cursor__caret");
300
- cursorElement.setAttribute("style", `border-color: ${color}`);
301
- if (opts.collaboration?.showCursorLabels === "always") {
302
- cursorElement.setAttribute("data-active", "");
303
- }
304
-
305
- const labelElement = document.createElement("span");
306
-
307
- labelElement.classList.add("collaboration-cursor__label");
308
- labelElement.setAttribute("style", `background-color: ${color}`);
309
- labelElement.insertBefore(document.createTextNode(name), null);
310
-
311
- cursorElement.insertBefore(document.createTextNode("\u2060"), null); // Non-breaking space
312
- cursorElement.insertBefore(labelElement, null);
313
- cursorElement.insertBefore(document.createTextNode("\u2060"), null); // Non-breaking space
314
-
315
- cursors.set(clientID, {
316
- element: cursorElement,
317
- hideTimeout: undefined,
318
- });
319
-
320
- if (opts.collaboration?.showCursorLabels !== "always") {
321
- cursorElement.addEventListener("mouseenter", () => {
322
- const cursor = cursors.get(clientID)!;
323
- cursor.element.setAttribute("data-active", "");
324
-
325
- if (cursor.hideTimeout) {
326
- clearTimeout(cursor.hideTimeout);
327
- cursors.set(clientID, {
328
- element: cursor.element,
329
- hideTimeout: undefined,
330
- });
331
- }
332
- });
333
-
334
- cursorElement.addEventListener("mouseleave", () => {
335
- const cursor = cursors.get(clientID)!;
336
-
337
- cursors.set(clientID, {
338
- element: cursor.element,
339
- hideTimeout: setTimeout(() => {
340
- cursor.element.removeAttribute("data-active");
341
- }, 2000),
342
- });
343
- });
344
- }
345
-
346
- return cursors.get(clientID)!;
347
- };
348
-
349
- const defaultRender = (user: { color: string; name: string }) => {
350
- const clientState = [...awareness.getStates().entries()].find(
351
- (state) => state[1].user === user
352
- );
353
-
354
- if (!clientState) {
355
- throw new Error("Could not find client state for user");
356
- }
357
-
358
- const clientID = clientState[0];
359
-
360
- return (
361
- cursors.get(clientID) || createCursor(clientID, user.name, user.color)
362
- ).element;
363
- };
364
- tiptapExtensions.push(
365
- CollaborationCursor.configure({
366
- user: opts.collaboration.user,
367
- render: opts.collaboration.renderCursor || defaultRender,
368
- provider: opts.collaboration.provider,
369
- })
370
- );
371
- }
247
+ tiptapExtensions.push(...createCollaborationExtensions(opts.collaboration));
372
248
  } else {
373
249
  // disable history extension when collaboration is enabled as Yjs takes care of undo / redo
374
250
  tiptapExtensions.push(History);
@@ -0,0 +1,151 @@
1
+ import Collaboration from "@tiptap/extension-collaboration";
2
+ import { Awareness } from "y-protocols/awareness";
3
+ import CollaborationCursor from "@tiptap/extension-collaboration-cursor";
4
+ import * as Y from "yjs";
5
+
6
+ export const createCollaborationExtensions = (collaboration: {
7
+ fragment: Y.XmlFragment;
8
+ user: {
9
+ name: string;
10
+ color: string;
11
+ [key: string]: string;
12
+ };
13
+ provider: any;
14
+ renderCursor?: (user: any) => HTMLElement;
15
+ showCursorLabels?: "always" | "activity";
16
+ }) => {
17
+ const tiptapExtensions = [];
18
+
19
+ tiptapExtensions.push(
20
+ Collaboration.configure({
21
+ fragment: collaboration.fragment,
22
+ })
23
+ );
24
+
25
+ const awareness = collaboration.provider?.awareness as Awareness | undefined;
26
+
27
+ if (awareness) {
28
+ const cursors = new Map<
29
+ number,
30
+ { element: HTMLElement; hideTimeout: NodeJS.Timeout | undefined }
31
+ >();
32
+
33
+ if (collaboration.showCursorLabels !== "always") {
34
+ awareness.on(
35
+ "change",
36
+ ({
37
+ updated,
38
+ }: {
39
+ added: Array<number>;
40
+ updated: Array<number>;
41
+ removed: Array<number>;
42
+ }) => {
43
+ for (const clientID of updated) {
44
+ const cursor = cursors.get(clientID);
45
+
46
+ if (cursor) {
47
+ cursor.element.setAttribute("data-active", "");
48
+
49
+ if (cursor.hideTimeout) {
50
+ clearTimeout(cursor.hideTimeout);
51
+ }
52
+
53
+ cursors.set(clientID, {
54
+ element: cursor.element,
55
+ hideTimeout: setTimeout(() => {
56
+ cursor.element.removeAttribute("data-active");
57
+ }, 2000),
58
+ });
59
+ }
60
+ }
61
+ }
62
+ );
63
+ }
64
+
65
+ const renderCursor = (user: { name: string; color: string }) => {
66
+ const cursorElement = document.createElement("span");
67
+
68
+ cursorElement.classList.add("collaboration-cursor__caret");
69
+ cursorElement.setAttribute("style", `border-color: ${user.color}`);
70
+ if (collaboration?.showCursorLabels === "always") {
71
+ cursorElement.setAttribute("data-active", "");
72
+ }
73
+
74
+ const labelElement = document.createElement("span");
75
+
76
+ labelElement.classList.add("collaboration-cursor__label");
77
+ labelElement.setAttribute("style", `background-color: ${user.color}`);
78
+ labelElement.insertBefore(document.createTextNode(user.name), null);
79
+
80
+ cursorElement.insertBefore(document.createTextNode("\u2060"), null); // Non-breaking space
81
+ cursorElement.insertBefore(labelElement, null);
82
+ cursorElement.insertBefore(document.createTextNode("\u2060"), null); // Non-breaking space
83
+
84
+ return cursorElement;
85
+ };
86
+
87
+ const render = (user: { color: string; name: string }) => {
88
+ const clientState = [...awareness.getStates().entries()].find(
89
+ (state) => state[1].user === user
90
+ );
91
+
92
+ if (!clientState) {
93
+ throw new Error("Could not find client state for user");
94
+ }
95
+
96
+ const clientID = clientState[0];
97
+
98
+ let cursorData = cursors.get(clientID);
99
+
100
+ if (!cursorData) {
101
+ const cursorElement =
102
+ collaboration?.renderCursor?.(user) || renderCursor(user);
103
+
104
+ if (collaboration?.showCursorLabels !== "always") {
105
+ cursorElement.addEventListener("mouseenter", () => {
106
+ const cursor = cursors.get(clientID)!;
107
+ cursor.element.setAttribute("data-active", "");
108
+
109
+ if (cursor.hideTimeout) {
110
+ clearTimeout(cursor.hideTimeout);
111
+ cursors.set(clientID, {
112
+ element: cursor.element,
113
+ hideTimeout: undefined,
114
+ });
115
+ }
116
+ });
117
+
118
+ cursorElement.addEventListener("mouseleave", () => {
119
+ const cursor = cursors.get(clientID)!;
120
+
121
+ cursors.set(clientID, {
122
+ element: cursor.element,
123
+ hideTimeout: setTimeout(() => {
124
+ cursor.element.removeAttribute("data-active");
125
+ }, 2000),
126
+ });
127
+ });
128
+ }
129
+
130
+ cursorData = {
131
+ element: cursorElement,
132
+ hideTimeout: undefined,
133
+ };
134
+
135
+ cursors.set(clientID, cursorData);
136
+ }
137
+
138
+ return cursorData.element;
139
+ };
140
+
141
+ tiptapExtensions.push(
142
+ CollaborationCursor.configure({
143
+ user: collaboration.user,
144
+ render,
145
+ provider: collaboration.provider,
146
+ })
147
+ );
148
+ }
149
+
150
+ return tiptapExtensions;
151
+ };