@blocknote/core 0.15.11 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/blocknote.js +3349 -2773
- package/dist/blocknote.js.map +1 -1
- package/dist/blocknote.umd.cjs +6 -6
- package/dist/blocknote.umd.cjs.map +1 -1
- package/dist/webpack-stats.json +1 -1
- package/package.json +5 -2
- package/src/api/blockManipulation/commands/insertBlocks/__snapshots__/insertBlocks.test.ts.snap +3087 -0
- package/src/api/blockManipulation/commands/insertBlocks/insertBlocks.test.ts +132 -0
- package/src/api/blockManipulation/commands/insertBlocks/insertBlocks.ts +71 -0
- package/src/api/blockManipulation/commands/mergeBlocks/__snapshots__/mergeBlocks.test.ts.snap +2276 -0
- package/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.test.ts +131 -0
- package/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.ts +103 -0
- package/src/api/blockManipulation/commands/moveBlock/__snapshots__/moveBlock.test.ts.snap +3767 -0
- package/src/api/blockManipulation/commands/moveBlock/moveBlock.test.ts +192 -0
- package/src/api/blockManipulation/commands/moveBlock/moveBlock.ts +178 -0
- package/src/api/blockManipulation/commands/removeBlocks/__snapshots__/removeBlocks.test.ts.snap +1136 -0
- package/src/api/blockManipulation/commands/removeBlocks/removeBlocks.test.ts +34 -0
- package/src/api/blockManipulation/commands/removeBlocks/removeBlocks.ts +100 -0
- package/src/api/blockManipulation/commands/replaceBlocks/__snapshots__/replaceBlocks.test.ts.snap +4931 -0
- package/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.test.ts +222 -0
- package/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts +70 -0
- package/src/api/blockManipulation/commands/splitBlock/__snapshots__/splitBlock.test.ts.snap +2924 -0
- package/src/api/blockManipulation/commands/splitBlock/splitBlock.test.ts +136 -0
- package/src/api/blockManipulation/commands/splitBlock/splitBlock.ts +48 -0
- package/src/api/blockManipulation/commands/updateBlock/__snapshots__/updateBlock.test.ts.snap +8376 -0
- package/src/api/blockManipulation/commands/updateBlock/updateBlock.test.ts +300 -0
- package/src/api/blockManipulation/commands/updateBlock/updateBlock.ts +199 -0
- package/src/api/blockManipulation/insertContentAt.ts +96 -0
- package/src/api/blockManipulation/selections/textCursorPosition/__snapshots__/textCursorPosition.test.ts.snap +316 -0
- package/src/api/blockManipulation/selections/textCursorPosition/textCursorPosition.test.ts +53 -0
- package/src/api/blockManipulation/selections/textCursorPosition/textCursorPosition.ts +130 -0
- package/src/api/blockManipulation/setupTestEnv.ts +179 -0
- package/src/api/clipboard/__snapshots__/childToParent.html +1 -0
- package/src/api/clipboard/__snapshots__/childrenToNextParent.html +1 -0
- package/src/api/clipboard/__snapshots__/childrenToNextParentsChildren.html +1 -0
- package/src/api/clipboard/__snapshots__/image.html +1 -0
- package/src/api/clipboard/__snapshots__/multipleStyledText.html +1 -0
- package/src/api/clipboard/__snapshots__/nestedImage.html +1 -0
- package/src/api/clipboard/__snapshots__/partialChildToParent.html +1 -0
- package/src/api/clipboard/__snapshots__/styledText.html +1 -0
- package/src/api/clipboard/__snapshots__/tableAllCells.html +1 -0
- package/src/api/clipboard/__snapshots__/tableCell.html +1 -0
- package/src/api/clipboard/__snapshots__/tableCellText.html +1 -0
- package/src/api/clipboard/__snapshots__/tableRow.html +1 -0
- package/src/api/clipboard/__snapshots__/unstyledText.html +1 -0
- package/src/api/clipboard/clipboard.test.ts +283 -0
- package/src/api/{parsers → clipboard/fromClipboard}/fileDropExtension.ts +8 -4
- package/src/api/{parsers → clipboard/fromClipboard}/handleFileInsertion.ts +12 -7
- package/src/api/{parsers → clipboard/fromClipboard}/pasteExtension.ts +19 -8
- package/src/api/clipboard/toClipboard/copyExtension.ts +243 -0
- package/src/api/exporters/html/__snapshots__/complex/misc/external.html +1 -1
- package/src/api/exporters/html/__snapshots__/lists/basic/external.html +1 -1
- package/src/api/exporters/html/__snapshots__/lists/nested/external.html +1 -1
- package/src/api/exporters/html/externalHTMLExporter.ts +42 -87
- package/src/api/exporters/html/htmlConversion.test.ts +19 -156
- package/src/api/exporters/html/internalHTMLSerializer.ts +21 -69
- package/src/api/exporters/html/util/serializeBlocksExternalHTML.ts +263 -0
- package/src/api/exporters/html/util/serializeBlocksInternalHTML.ts +158 -0
- package/src/api/exporters/markdown/markdownExporter.test.ts +10 -10
- package/src/api/exporters/markdown/markdownExporter.ts +11 -7
- package/src/api/exporters/markdown/util/addSpacesToCheckboxesRehypePlugin.ts +2 -2
- package/src/api/getBlockInfoFromPos.ts +172 -90
- package/src/api/nodeConversions/blockToNode.ts +257 -0
- package/src/api/nodeConversions/fragmentToBlocks.ts +60 -0
- package/src/api/nodeConversions/nodeConversions.test.ts +9 -8
- package/src/api/nodeConversions/{nodeConversions.ts → nodeToBlock.ts} +20 -262
- package/src/api/parsers/html/parseHTML.test.ts +5 -8
- package/src/api/parsers/html/parseHTML.ts +8 -4
- package/src/api/parsers/html/util/nestedLists.test.ts +2 -2
- package/src/api/parsers/markdown/__snapshots__/pasted/complex.json +319 -0
- package/src/api/parsers/markdown/__snapshots__/pasted/issue-226-1.json +81 -0
- package/src/api/parsers/{html/__snapshots__/paste/parse-deep-nested-content.json → markdown/__snapshots__/pasted/issue-226-2.json} +35 -110
- package/src/api/parsers/markdown/__snapshots__/pasted/nested.json +81 -0
- package/src/api/parsers/markdown/__snapshots__/pasted/non-nested.json +81 -0
- package/src/api/parsers/markdown/__snapshots__/pasted/styled.json +61 -0
- package/src/api/parsers/markdown/parseMarkdown.test.ts +16 -1
- package/src/api/parsers/markdown/parseMarkdown.ts +8 -4
- package/src/api/testUtil/cases/customBlocks.ts +11 -11
- package/src/api/testUtil/cases/customInlineContent.ts +6 -6
- package/src/api/testUtil/cases/customStyles.ts +6 -6
- package/src/api/testUtil/cases/defaultSchema.ts +4 -4
- package/src/api/testUtil/index.ts +6 -6
- package/src/api/testUtil/partialBlockTestUtil.ts +5 -5
- package/src/api/testUtil/paste.ts +46 -0
- package/src/blocks/AudioBlockContent/AudioBlockContent.ts +5 -5
- package/src/blocks/FileBlockContent/FileBlockContent.ts +4 -4
- package/src/blocks/FileBlockContent/fileBlockHelpers.ts +2 -2
- package/src/blocks/HeadingBlockContent/HeadingBlockContent.ts +61 -39
- package/src/blocks/ImageBlockContent/ImageBlockContent.ts +5 -5
- package/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +30 -18
- package/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts +67 -33
- package/src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts +23 -19
- package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts +22 -24
- package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +31 -19
- package/src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts +16 -11
- package/src/blocks/TableBlockContent/TableBlockContent.ts +4 -5
- package/src/blocks/VideoBlockContent/VideoBlockContent.ts +5 -5
- package/src/blocks/defaultBlockHelpers.ts +4 -4
- package/src/blocks/defaultBlockTypeGuards.ts +5 -5
- package/src/blocks/defaultBlocks.ts +13 -13
- package/src/blocks/defaultProps.ts +1 -1
- package/src/editor/BlockNoteEditor.test.ts +14 -7
- package/src/editor/BlockNoteEditor.ts +82 -149
- package/src/editor/BlockNoteExtensions.ts +15 -11
- package/src/editor/BlockNoteSchema.ts +7 -7
- package/src/editor/BlockNoteTipTapEditor.ts +5 -3
- package/src/editor/cursorPositionTypes.ts +7 -2
- package/src/editor/selectionTypes.ts +6 -2
- package/src/editor/transformPasted.ts +34 -2
- package/src/extensions/BackgroundColor/BackgroundColorExtension.ts +1 -1
- package/src/extensions/BackgroundColor/BackgroundColorMark.ts +1 -1
- package/src/extensions/FilePanel/FilePanelPlugin.ts +4 -4
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +8 -4
- package/src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts +333 -0
- package/src/extensions/LinkToolbar/LinkToolbarPlugin.ts +9 -4
- package/src/extensions/{NonEditableBlocks/NonEditableBlockPlugin.ts → NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.ts} +2 -2
- package/src/extensions/Placeholder/PlaceholderPlugin.ts +1 -1
- package/src/extensions/SideMenu/SideMenuPlugin.ts +72 -402
- package/src/extensions/SideMenu/dragging.ts +251 -0
- package/src/extensions/SuggestionMenu/DefaultSuggestionItem.ts +1 -1
- package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +8 -4
- package/src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.ts +8 -4
- package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +19 -15
- package/src/extensions/TableHandles/TableHandlesPlugin.ts +11 -7
- package/src/extensions/TextColor/TextColorExtension.ts +1 -1
- package/src/extensions/TextColor/TextColorMark.ts +1 -1
- package/src/i18n/dictionary.ts +1 -1
- package/src/i18n/locales/ar.ts +1 -1
- package/src/i18n/locales/fr.ts +1 -1
- package/src/i18n/locales/hr.ts +308 -0
- package/src/i18n/locales/index.ts +15 -14
- package/src/i18n/locales/is.ts +1 -1
- package/src/i18n/locales/ja.ts +1 -1
- package/src/i18n/locales/ko.ts +1 -1
- package/src/i18n/locales/nl.ts +1 -1
- package/src/i18n/locales/pl.ts +1 -1
- package/src/i18n/locales/pt.ts +1 -1
- package/src/i18n/locales/ru.ts +1 -1
- package/src/i18n/locales/vi.ts +1 -1
- package/src/i18n/locales/zh.ts +1 -1
- package/src/index.ts +45 -44
- package/src/pm-nodes/BlockContainer.ts +3 -647
- package/src/pm-nodes/BlockGroup.ts +2 -2
- package/src/pm-nodes/index.ts +3 -3
- package/src/schema/blocks/createSpec.ts +24 -14
- package/src/schema/blocks/internal.ts +9 -9
- package/src/schema/blocks/types.ts +4 -4
- package/src/schema/index.ts +10 -10
- package/src/schema/inlineContent/createSpec.ts +9 -10
- package/src/schema/inlineContent/internal.ts +3 -3
- package/src/schema/inlineContent/types.ts +2 -2
- package/src/schema/styles/createSpec.ts +4 -3
- package/src/schema/styles/internal.ts +1 -1
- package/types/src/api/blockManipulation/commands/insertBlocks/insertBlocks.d.ts +4 -0
- package/types/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.d.ts +7 -0
- package/types/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.test.d.ts +1 -0
- package/types/src/api/blockManipulation/commands/moveBlock/moveBlock.d.ts +5 -0
- package/types/src/api/blockManipulation/commands/moveBlock/moveBlock.test.d.ts +1 -0
- package/types/src/api/blockManipulation/commands/removeBlocks/removeBlocks.d.ts +7 -0
- package/types/src/api/blockManipulation/commands/removeBlocks/removeBlocks.test.d.ts +1 -0
- package/types/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.d.ts +7 -0
- package/types/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.test.d.ts +1 -0
- package/types/src/api/blockManipulation/commands/splitBlock/splitBlock.d.ts +5 -0
- package/types/src/api/blockManipulation/commands/splitBlock/splitBlock.test.d.ts +1 -0
- package/types/src/api/blockManipulation/commands/updateBlock/updateBlock.d.ts +11 -0
- package/types/src/api/blockManipulation/commands/updateBlock/updateBlock.test.d.ts +1 -0
- package/types/src/api/blockManipulation/insertContentAt.d.ts +6 -0
- package/types/src/api/blockManipulation/selections/textCursorPosition/textCursorPosition.d.ts +5 -0
- package/types/src/api/blockManipulation/selections/textCursorPosition/textCursorPosition.test.d.ts +1 -0
- package/types/src/api/blockManipulation/setupTestEnv.d.ts +492 -0
- package/types/src/api/clipboard/clipboard.test.d.ts +1 -0
- package/types/src/api/clipboard/fromClipboard/fileDropExtension.d.ts +6 -0
- package/types/src/api/{parsers → clipboard/fromClipboard}/handleFileInsertion.d.ts +2 -2
- package/types/src/api/clipboard/fromClipboard/pasteExtension.d.ts +6 -0
- package/types/src/api/clipboard/toClipboard/copyExtension.d.ts +12 -0
- package/types/src/api/exporters/html/externalHTMLExporter.d.ts +7 -8
- package/types/src/api/exporters/html/internalHTMLSerializer.d.ts +6 -10
- package/types/src/api/exporters/html/util/serializeBlocksExternalHTML.d.ts +10 -0
- package/types/src/api/exporters/html/util/serializeBlocksInternalHTML.d.ts +11 -0
- package/types/src/api/exporters/markdown/markdownExporter.d.ts +3 -3
- package/types/src/api/getBlockInfoFromPos.d.ts +63 -20
- package/types/src/api/nodeConversions/blockToNode.d.ts +15 -0
- package/types/src/api/nodeConversions/fragmentToBlocks.d.ts +7 -0
- package/types/src/api/nodeConversions/nodeToBlock.d.ts +16 -0
- package/types/src/api/parsers/html/parseHTML.d.ts +2 -2
- package/types/src/api/parsers/markdown/parseMarkdown.d.ts +2 -2
- package/types/src/api/testUtil/cases/customBlocks.d.ts +39 -39
- package/types/src/api/testUtil/cases/customInlineContent.d.ts +35 -35
- package/types/src/api/testUtil/cases/customStyles.d.ts +35 -35
- package/types/src/api/testUtil/cases/defaultSchema.d.ts +2 -2
- package/types/src/api/testUtil/index.d.ts +6 -6
- package/types/src/api/testUtil/partialBlockTestUtil.d.ts +4 -4
- package/types/src/api/testUtil/paste.d.ts +2 -0
- package/types/src/blocks/AudioBlockContent/AudioBlockContent.d.ts +4 -4
- package/types/src/blocks/FileBlockContent/FileBlockContent.d.ts +4 -4
- package/types/src/blocks/FileBlockContent/fileBlockHelpers.d.ts +2 -2
- package/types/src/blocks/HeadingBlockContent/HeadingBlockContent.d.ts +2 -2
- package/types/src/blocks/ImageBlockContent/ImageBlockContent.d.ts +4 -4
- package/types/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.d.ts +2 -2
- package/types/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.d.ts +2 -2
- package/types/src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.d.ts +2 -2
- package/types/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.d.ts +2 -2
- package/types/src/blocks/ParagraphBlockContent/ParagraphBlockContent.d.ts +2 -2
- package/types/src/blocks/TableBlockContent/TableBlockContent.d.ts +2 -2
- package/types/src/blocks/VideoBlockContent/VideoBlockContent.d.ts +4 -4
- package/types/src/blocks/defaultBlockHelpers.d.ts +3 -3
- package/types/src/blocks/defaultBlockTypeGuards.d.ts +4 -4
- package/types/src/blocks/defaultBlocks.d.ts +38 -38
- package/types/src/blocks/defaultProps.d.ts +1 -1
- package/types/src/editor/BlockNoteEditor.d.ts +28 -16
- package/types/src/editor/BlockNoteExtensions.d.ts +3 -3
- package/types/src/editor/BlockNoteSchema.d.ts +4 -4
- package/types/src/editor/BlockNoteTipTapEditor.d.ts +2 -2
- package/types/src/editor/cursorPositionTypes.d.ts +3 -2
- package/types/src/editor/selectionTypes.d.ts +2 -2
- package/types/src/editor/transformPasted.d.ts +8 -1
- package/types/src/extensions/BackgroundColor/BackgroundColorMark.d.ts +1 -1
- package/types/src/extensions/FilePanel/FilePanelPlugin.d.ts +4 -4
- package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +4 -4
- package/types/src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.d.ts +5 -0
- package/types/src/extensions/LinkToolbar/LinkToolbarPlugin.d.ts +4 -4
- package/types/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.d.ts +2 -0
- package/types/src/extensions/Placeholder/PlaceholderPlugin.d.ts +1 -1
- package/types/src/extensions/SideMenu/SideMenuPlugin.d.ts +12 -28
- package/types/src/extensions/SideMenu/dragging.d.ts +17 -0
- package/types/src/extensions/SuggestionMenu/DefaultSuggestionItem.d.ts +1 -1
- package/types/src/extensions/SuggestionMenu/SuggestionPlugin.d.ts +4 -4
- package/types/src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.d.ts +3 -3
- package/types/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.d.ts +4 -4
- package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +4 -4
- package/types/src/extensions/TextColor/TextColorMark.d.ts +1 -1
- package/types/src/i18n/dictionary.d.ts +1 -1
- package/types/src/i18n/locales/ar.d.ts +1 -1
- package/types/src/i18n/locales/fr.d.ts +1 -1
- package/types/src/i18n/locales/hr.d.ts +239 -0
- package/types/src/i18n/locales/index.d.ts +15 -14
- package/types/src/i18n/locales/is.d.ts +1 -1
- package/types/src/i18n/locales/ja.d.ts +1 -1
- package/types/src/i18n/locales/ko.d.ts +1 -1
- package/types/src/i18n/locales/nl.d.ts +1 -1
- package/types/src/i18n/locales/pl.d.ts +1 -1
- package/types/src/i18n/locales/pt.d.ts +1 -1
- package/types/src/i18n/locales/ru.d.ts +1 -1
- package/types/src/i18n/locales/vi.d.ts +1 -1
- package/types/src/i18n/locales/zh.d.ts +1 -1
- package/types/src/index.d.ts +45 -44
- package/types/src/pm-nodes/BlockContainer.d.ts +2 -16
- package/types/src/pm-nodes/BlockGroup.d.ts +1 -1
- package/types/src/pm-nodes/index.d.ts +3 -3
- package/types/src/schema/blocks/createSpec.d.ts +5 -5
- package/types/src/schema/blocks/internal.d.ts +5 -5
- package/types/src/schema/blocks/types.d.ts +4 -4
- package/types/src/schema/index.d.ts +10 -10
- package/types/src/schema/inlineContent/createSpec.d.ts +3 -3
- package/types/src/schema/inlineContent/internal.d.ts +2 -2
- package/types/src/schema/inlineContent/types.d.ts +2 -2
- package/types/src/schema/styles/createSpec.d.ts +1 -1
- package/types/src/schema/styles/internal.d.ts +1 -1
- package/src/api/blockManipulation/__snapshots__/blockManipulation.test.ts.snap +0 -714
- package/src/api/blockManipulation/blockManipulation.test.ts +0 -292
- package/src/api/blockManipulation/blockManipulation.ts +0 -350
- package/src/api/exporters/copyExtension.ts +0 -164
- package/src/api/exporters/html/__snapshots_fragment_edge_cases__/selectionLeavesBlockChildren.html +0 -1
- package/src/api/exporters/html/__snapshots_fragment_edge_cases__/selectionSpansBlocksChildren.html +0 -1
- package/src/api/exporters/html/util/sharedHTMLConversion.ts +0 -130
- package/src/api/exporters/html/util/simplifyBlocksRehypePlugin.ts +0 -218
- package/src/api/getCurrentBlockContentType.ts +0 -14
- package/src/api/parsers/html/__snapshots__/paste/parse-google-docs-html.json +0 -476
- package/types/src/api/blockManipulation/blockManipulation.d.ts +0 -14
- package/types/src/api/exporters/copyExtension.d.ts +0 -6
- package/types/src/api/exporters/html/util/sharedHTMLConversion.d.ts +0 -9
- package/types/src/api/exporters/html/util/simplifyBlocksRehypePlugin.d.ts +0 -16
- package/types/src/api/getCurrentBlockContentType.d.ts +0 -2
- package/types/src/api/nodeConversions/nodeConversions.d.ts +0 -24
- package/types/src/api/parsers/fileDropExtension.d.ts +0 -6
- package/types/src/api/parsers/pasteExtension.d.ts +0 -6
- package/types/src/extensions/NonEditableBlocks/NonEditableBlockPlugin.d.ts +0 -2
- /package/src/api/{exporters/html/__snapshots_fragment_edge_cases__/selectionWithinBlockChildren.html → clipboard/__snapshots__/multipleChildren.html} +0 -0
- /package/src/api/{parsers → clipboard/fromClipboard}/acceptedMIMETypes.ts +0 -0
- /package/src/api/parsers/html/__snapshots__/{paste/list-test.json → list-test.json} +0 -0
- /package/src/api/parsers/html/__snapshots__/{paste/parse-basic-block-types.json → parse-basic-block-types.json} +0 -0
- /package/src/api/parsers/html/__snapshots__/{paste/parse-div-with-inline-content.json → parse-div-with-inline-content.json} +0 -0
- /package/src/api/parsers/html/__snapshots__/{paste/parse-divs.json → parse-divs.json} +0 -0
- /package/src/api/parsers/html/__snapshots__/{paste/parse-fake-image-caption.json → parse-fake-image-caption.json} +0 -0
- /package/src/api/parsers/html/__snapshots__/{paste/parse-image-in-paragraph.json → parse-image-in-paragraph.json} +0 -0
- /package/src/api/parsers/html/__snapshots__/{paste/parse-mixed-nested-lists.json → parse-mixed-nested-lists.json} +0 -0
- /package/src/api/parsers/html/__snapshots__/{paste/parse-nested-lists-with-paragraphs.json → parse-nested-lists-with-paragraphs.json} +0 -0
- /package/src/api/parsers/html/__snapshots__/{paste/parse-nested-lists.json → parse-nested-lists.json} +0 -0
- /package/src/api/parsers/html/__snapshots__/{paste/parse-notion-html.json → parse-notion-html.json} +0 -0
- /package/src/api/parsers/html/__snapshots__/{paste/parse-two-divs.json → parse-two-divs.json} +0 -0
- /package/types/src/api/blockManipulation/{blockManipulation.test.d.ts → commands/insertBlocks/insertBlocks.test.d.ts} +0 -0
- /package/types/src/api/{parsers → clipboard/fromClipboard}/acceptedMIMETypes.d.ts +0 -0
|
@@ -1,24 +1,8 @@
|
|
|
1
1
|
import { Node } from "@tiptap/core";
|
|
2
|
-
import { Fragment, Node as PMNode, Slice } from "prosemirror-model";
|
|
3
|
-
import { NodeSelection, TextSelection } from "prosemirror-state";
|
|
4
2
|
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
inlineContentToNodes,
|
|
9
|
-
tableContentToNodes,
|
|
10
|
-
} from "../api/nodeConversions/nodeConversions";
|
|
11
|
-
import { PartialBlock } from "../blocks/defaultBlocks";
|
|
12
|
-
import type { BlockNoteEditor } from "../editor/BlockNoteEditor";
|
|
13
|
-
import { NonEditableBlockPlugin } from "../extensions/NonEditableBlocks/NonEditableBlockPlugin";
|
|
14
|
-
import {
|
|
15
|
-
BlockNoteDOMAttributes,
|
|
16
|
-
BlockSchema,
|
|
17
|
-
InlineContentSchema,
|
|
18
|
-
StyleSchema,
|
|
19
|
-
} from "../schema";
|
|
20
|
-
import { mergeCSSClasses } from "../util/browser";
|
|
21
|
-
import { UnreachableCaseError } from "../util/typescript";
|
|
3
|
+
import type { BlockNoteEditor } from "../editor/BlockNoteEditor.js";
|
|
4
|
+
import { BlockNoteDOMAttributes } from "../schema/index.js";
|
|
5
|
+
import { mergeCSSClasses } from "../util/browser.js";
|
|
22
6
|
|
|
23
7
|
// Object containing all possible block attributes.
|
|
24
8
|
const BlockAttributes: Record<string, string> = {
|
|
@@ -29,37 +13,6 @@ const BlockAttributes: Record<string, string> = {
|
|
|
29
13
|
depthChange: "data-depth-change",
|
|
30
14
|
};
|
|
31
15
|
|
|
32
|
-
declare module "@tiptap/core" {
|
|
33
|
-
interface Commands<ReturnType> {
|
|
34
|
-
block: {
|
|
35
|
-
BNCreateBlock: (pos: number) => ReturnType;
|
|
36
|
-
BNDeleteBlock: (posInBlock: number) => ReturnType;
|
|
37
|
-
BNMergeBlocks: (posBetweenBlocks: number) => ReturnType;
|
|
38
|
-
BNSplitBlock: (
|
|
39
|
-
posInBlock: number,
|
|
40
|
-
keepType?: boolean,
|
|
41
|
-
keepProps?: boolean
|
|
42
|
-
) => ReturnType;
|
|
43
|
-
BNUpdateBlock: <
|
|
44
|
-
BSchema extends BlockSchema,
|
|
45
|
-
I extends InlineContentSchema,
|
|
46
|
-
S extends StyleSchema
|
|
47
|
-
>(
|
|
48
|
-
posInBlock: number,
|
|
49
|
-
block: PartialBlock<BSchema, I, S>
|
|
50
|
-
) => ReturnType;
|
|
51
|
-
BNCreateOrUpdateBlock: <
|
|
52
|
-
BSchema extends BlockSchema,
|
|
53
|
-
I extends InlineContentSchema,
|
|
54
|
-
S extends StyleSchema
|
|
55
|
-
>(
|
|
56
|
-
posInBlock: number,
|
|
57
|
-
block: PartialBlock<BSchema, I, S>
|
|
58
|
-
) => ReturnType;
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
16
|
/**
|
|
64
17
|
* The main "Block node" documents consist of
|
|
65
18
|
*/
|
|
@@ -131,601 +84,4 @@ export const BlockContainer = Node.create<{
|
|
|
131
84
|
contentDOM: block,
|
|
132
85
|
};
|
|
133
86
|
},
|
|
134
|
-
|
|
135
|
-
addCommands() {
|
|
136
|
-
return {
|
|
137
|
-
// Creates a new text block at a given position.
|
|
138
|
-
BNCreateBlock:
|
|
139
|
-
(pos) =>
|
|
140
|
-
({ state, dispatch }) => {
|
|
141
|
-
const newBlock =
|
|
142
|
-
state.schema.nodes["blockContainer"].createAndFill()!;
|
|
143
|
-
|
|
144
|
-
if (dispatch) {
|
|
145
|
-
state.tr.insert(pos, newBlock).scrollIntoView();
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return true;
|
|
149
|
-
},
|
|
150
|
-
// Deletes a block at a given position.
|
|
151
|
-
BNDeleteBlock:
|
|
152
|
-
(posInBlock) =>
|
|
153
|
-
({ state, dispatch }) => {
|
|
154
|
-
const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);
|
|
155
|
-
if (blockInfo === undefined) {
|
|
156
|
-
return false;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const { startPos, endPos } = blockInfo;
|
|
160
|
-
|
|
161
|
-
if (dispatch) {
|
|
162
|
-
state.tr.deleteRange(startPos, endPos);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return true;
|
|
166
|
-
},
|
|
167
|
-
// Updates a block at a given position.
|
|
168
|
-
BNUpdateBlock:
|
|
169
|
-
(posInBlock, block) =>
|
|
170
|
-
({ state, dispatch }) => {
|
|
171
|
-
const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);
|
|
172
|
-
if (blockInfo === undefined) {
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const { startPos, endPos, node, contentNode } = blockInfo;
|
|
177
|
-
|
|
178
|
-
if (dispatch) {
|
|
179
|
-
// Adds blockGroup node with child blocks if necessary.
|
|
180
|
-
if (block.children !== undefined) {
|
|
181
|
-
const childNodes = [];
|
|
182
|
-
|
|
183
|
-
// Creates ProseMirror nodes for each child block, including their descendants.
|
|
184
|
-
for (const child of block.children) {
|
|
185
|
-
childNodes.push(
|
|
186
|
-
blockToNode(
|
|
187
|
-
child,
|
|
188
|
-
state.schema,
|
|
189
|
-
this.options.editor.schema.styleSchema
|
|
190
|
-
)
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Checks if a blockGroup node already exists.
|
|
195
|
-
if (node.childCount === 2) {
|
|
196
|
-
// Replaces all child nodes in the existing blockGroup with the ones created earlier.
|
|
197
|
-
state.tr.replace(
|
|
198
|
-
startPos + contentNode.nodeSize + 1,
|
|
199
|
-
endPos - 1,
|
|
200
|
-
new Slice(Fragment.from(childNodes), 0, 0)
|
|
201
|
-
);
|
|
202
|
-
} else {
|
|
203
|
-
// Inserts a new blockGroup containing the child nodes created earlier.
|
|
204
|
-
state.tr.insert(
|
|
205
|
-
startPos + contentNode.nodeSize,
|
|
206
|
-
state.schema.nodes["blockGroup"].create({}, childNodes)
|
|
207
|
-
);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const oldType = contentNode.type.name;
|
|
212
|
-
const newType = block.type || oldType;
|
|
213
|
-
|
|
214
|
-
// The code below determines the new content of the block.
|
|
215
|
-
// or "keep" to keep as-is
|
|
216
|
-
let content: PMNode[] | "keep" = "keep";
|
|
217
|
-
|
|
218
|
-
// Has there been any custom content provided?
|
|
219
|
-
if (block.content) {
|
|
220
|
-
if (typeof block.content === "string") {
|
|
221
|
-
// Adds a single text node with no marks to the content.
|
|
222
|
-
content = inlineContentToNodes(
|
|
223
|
-
[block.content],
|
|
224
|
-
state.schema,
|
|
225
|
-
this.options.editor.schema.styleSchema
|
|
226
|
-
);
|
|
227
|
-
} else if (Array.isArray(block.content)) {
|
|
228
|
-
// Adds a text node with the provided styles converted into marks to the content,
|
|
229
|
-
// for each InlineContent object.
|
|
230
|
-
content = inlineContentToNodes(
|
|
231
|
-
block.content,
|
|
232
|
-
state.schema,
|
|
233
|
-
this.options.editor.schema.styleSchema
|
|
234
|
-
);
|
|
235
|
-
} else if (block.content.type === "tableContent") {
|
|
236
|
-
content = tableContentToNodes(
|
|
237
|
-
block.content,
|
|
238
|
-
state.schema,
|
|
239
|
-
this.options.editor.schema.styleSchema
|
|
240
|
-
);
|
|
241
|
-
} else {
|
|
242
|
-
throw new UnreachableCaseError(block.content.type);
|
|
243
|
-
}
|
|
244
|
-
} else {
|
|
245
|
-
// no custom content has been provided, use existing content IF possible
|
|
246
|
-
|
|
247
|
-
// Since some block types contain inline content and others don't,
|
|
248
|
-
// we either need to call setNodeMarkup to just update type &
|
|
249
|
-
// attributes, or replaceWith to replace the whole blockContent.
|
|
250
|
-
const oldContentType = state.schema.nodes[oldType].spec.content;
|
|
251
|
-
const newContentType = state.schema.nodes[newType].spec.content;
|
|
252
|
-
|
|
253
|
-
if (oldContentType === "") {
|
|
254
|
-
// keep old content, because it's empty anyway and should be compatible with
|
|
255
|
-
// any newContentType
|
|
256
|
-
} else if (newContentType !== oldContentType) {
|
|
257
|
-
// the content type changed, replace the previous content
|
|
258
|
-
content = [];
|
|
259
|
-
} else {
|
|
260
|
-
// keep old content, because the content type is the same and should be compatible
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// Now, changes the blockContent node type and adds the provided props
|
|
265
|
-
// as attributes. Also preserves all existing attributes that are
|
|
266
|
-
// compatible with the new type.
|
|
267
|
-
//
|
|
268
|
-
// Use either setNodeMarkup or replaceWith depending on whether the
|
|
269
|
-
// content is being replaced or not.
|
|
270
|
-
if (content === "keep") {
|
|
271
|
-
// use setNodeMarkup to only update the type and attributes
|
|
272
|
-
state.tr.setNodeMarkup(
|
|
273
|
-
startPos,
|
|
274
|
-
block.type === undefined
|
|
275
|
-
? undefined
|
|
276
|
-
: state.schema.nodes[block.type],
|
|
277
|
-
{
|
|
278
|
-
...contentNode.attrs,
|
|
279
|
-
...block.props,
|
|
280
|
-
}
|
|
281
|
-
);
|
|
282
|
-
} else {
|
|
283
|
-
// use replaceWith to replace the content and the block itself
|
|
284
|
-
// also reset the selection since replacing the block content
|
|
285
|
-
// sets it to the next block.
|
|
286
|
-
state.tr
|
|
287
|
-
.replaceWith(
|
|
288
|
-
startPos,
|
|
289
|
-
endPos,
|
|
290
|
-
state.schema.nodes[newType].create(
|
|
291
|
-
{
|
|
292
|
-
...contentNode.attrs,
|
|
293
|
-
...block.props,
|
|
294
|
-
},
|
|
295
|
-
content
|
|
296
|
-
)
|
|
297
|
-
)
|
|
298
|
-
// If the node doesn't contain editable content, we want to
|
|
299
|
-
// select the whole node. But if it does have editable content,
|
|
300
|
-
// we want to set the selection to the start of it.
|
|
301
|
-
.setSelection(
|
|
302
|
-
state.schema.nodes[newType].spec.content === ""
|
|
303
|
-
? new NodeSelection(state.tr.doc.resolve(startPos))
|
|
304
|
-
: state.schema.nodes[newType].spec.content === "inline*"
|
|
305
|
-
? new TextSelection(state.tr.doc.resolve(startPos))
|
|
306
|
-
: // Need to offset the position as we have to get through the
|
|
307
|
-
// `tableRow` and `tableCell` nodes to get to the
|
|
308
|
-
// `tableParagraph` node we want to set the selection in.
|
|
309
|
-
new TextSelection(state.tr.doc.resolve(startPos + 4))
|
|
310
|
-
);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// Adds all provided props as attributes to the parent blockContainer node too, and also preserves existing
|
|
314
|
-
// attributes.
|
|
315
|
-
state.tr.setNodeMarkup(startPos - 1, undefined, {
|
|
316
|
-
...node.attrs,
|
|
317
|
-
...block.props,
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
return true;
|
|
322
|
-
},
|
|
323
|
-
// Appends the text contents of a block to the nearest previous block, given a position between them. Children of
|
|
324
|
-
// the merged block are moved out of it first, rather than also being merged.
|
|
325
|
-
//
|
|
326
|
-
// In the example below, the position passed into the function is between Block1 and Block2.
|
|
327
|
-
//
|
|
328
|
-
// Block1
|
|
329
|
-
// Block2
|
|
330
|
-
// Block3
|
|
331
|
-
// Block4
|
|
332
|
-
// Block5
|
|
333
|
-
//
|
|
334
|
-
// Becomes:
|
|
335
|
-
//
|
|
336
|
-
// Block1
|
|
337
|
-
// Block2Block3
|
|
338
|
-
// Block4
|
|
339
|
-
// Block5
|
|
340
|
-
BNMergeBlocks:
|
|
341
|
-
(posBetweenBlocks) =>
|
|
342
|
-
({ state, dispatch }) => {
|
|
343
|
-
const nextNodeIsBlock =
|
|
344
|
-
state.doc.resolve(posBetweenBlocks + 1).node().type.name ===
|
|
345
|
-
"blockContainer";
|
|
346
|
-
const prevNodeIsBlock =
|
|
347
|
-
state.doc.resolve(posBetweenBlocks - 1).node().type.name ===
|
|
348
|
-
"blockContainer";
|
|
349
|
-
|
|
350
|
-
if (!nextNodeIsBlock || !prevNodeIsBlock) {
|
|
351
|
-
return false;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
const nextBlockInfo = getBlockInfoFromPos(
|
|
355
|
-
state.doc,
|
|
356
|
-
posBetweenBlocks + 1
|
|
357
|
-
);
|
|
358
|
-
|
|
359
|
-
const { node, contentNode, startPos, endPos, depth } = nextBlockInfo!;
|
|
360
|
-
|
|
361
|
-
// Removes a level of nesting all children of the next block by 1 level, if it contains both content and block
|
|
362
|
-
// group nodes.
|
|
363
|
-
if (node.childCount === 2) {
|
|
364
|
-
const childBlocksStart = state.doc.resolve(
|
|
365
|
-
startPos + contentNode.nodeSize + 1
|
|
366
|
-
);
|
|
367
|
-
const childBlocksEnd = state.doc.resolve(endPos - 1);
|
|
368
|
-
const childBlocksRange =
|
|
369
|
-
childBlocksStart.blockRange(childBlocksEnd);
|
|
370
|
-
|
|
371
|
-
// Moves the block group node inside the block into the block group node that the current block is in.
|
|
372
|
-
if (dispatch) {
|
|
373
|
-
state.tr.lift(childBlocksRange!, depth - 1);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
let prevBlockEndPos = posBetweenBlocks - 1;
|
|
378
|
-
let prevBlockInfo = getBlockInfoFromPos(state.doc, prevBlockEndPos);
|
|
379
|
-
|
|
380
|
-
// Finds the nearest previous block, regardless of nesting level.
|
|
381
|
-
while (prevBlockInfo!.numChildBlocks > 0) {
|
|
382
|
-
prevBlockEndPos--;
|
|
383
|
-
prevBlockInfo = getBlockInfoFromPos(state.doc, prevBlockEndPos);
|
|
384
|
-
if (prevBlockInfo === undefined) {
|
|
385
|
-
return false;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// Deletes next block and adds its text content to the nearest previous block.
|
|
390
|
-
|
|
391
|
-
if (dispatch) {
|
|
392
|
-
dispatch(
|
|
393
|
-
state.tr
|
|
394
|
-
.deleteRange(startPos, startPos + contentNode.nodeSize)
|
|
395
|
-
.replace(
|
|
396
|
-
prevBlockEndPos - 1,
|
|
397
|
-
startPos,
|
|
398
|
-
new Slice(contentNode.content, 0, 0)
|
|
399
|
-
)
|
|
400
|
-
.scrollIntoView()
|
|
401
|
-
);
|
|
402
|
-
|
|
403
|
-
state.tr.setSelection(
|
|
404
|
-
new TextSelection(state.doc.resolve(prevBlockEndPos - 1))
|
|
405
|
-
);
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
return true;
|
|
409
|
-
},
|
|
410
|
-
// Splits a block at a given position. Content after the position is moved to a new block below, at the same
|
|
411
|
-
// nesting level.
|
|
412
|
-
// - `keepType` is usually false, unless the selection is at the start of
|
|
413
|
-
// a block.
|
|
414
|
-
// - `keepProps` is usually true when `keepType` is true, except for when
|
|
415
|
-
// creating new list item blocks with Enter.
|
|
416
|
-
BNSplitBlock:
|
|
417
|
-
(posInBlock, keepType, keepProps) =>
|
|
418
|
-
({ state, dispatch }) => {
|
|
419
|
-
const blockInfo = getBlockInfoFromPos(state.doc, posInBlock);
|
|
420
|
-
if (blockInfo === undefined) {
|
|
421
|
-
return false;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
const { contentNode, contentType, startPos, endPos, depth } =
|
|
425
|
-
blockInfo;
|
|
426
|
-
|
|
427
|
-
const originalBlockContent = state.doc.cut(startPos + 1, posInBlock);
|
|
428
|
-
const newBlockContent = state.doc.cut(posInBlock, endPos - 1);
|
|
429
|
-
|
|
430
|
-
const newBlock =
|
|
431
|
-
state.schema.nodes["blockContainer"].createAndFill()!;
|
|
432
|
-
|
|
433
|
-
const newBlockInsertionPos = endPos + 1;
|
|
434
|
-
const newBlockContentPos = newBlockInsertionPos + 2;
|
|
435
|
-
|
|
436
|
-
if (dispatch) {
|
|
437
|
-
// Creates a new block. Since the schema requires it to have a content node, a paragraph node is created
|
|
438
|
-
// automatically, spanning newBlockContentPos to newBlockContentPos + 1.
|
|
439
|
-
state.tr.insert(newBlockInsertionPos, newBlock);
|
|
440
|
-
|
|
441
|
-
// Replaces the content of the newly created block's content node. Doesn't replace the whole content node so
|
|
442
|
-
// its type doesn't change.
|
|
443
|
-
state.tr.replace(
|
|
444
|
-
newBlockContentPos,
|
|
445
|
-
newBlockContentPos + 1,
|
|
446
|
-
newBlockContent.content.size > 0
|
|
447
|
-
? new Slice(
|
|
448
|
-
Fragment.from(newBlockContent),
|
|
449
|
-
depth + 2,
|
|
450
|
-
depth + 2
|
|
451
|
-
)
|
|
452
|
-
: undefined
|
|
453
|
-
);
|
|
454
|
-
|
|
455
|
-
// Changes the type of the content node. The range doesn't matter as long as both from and to positions are
|
|
456
|
-
// within the content node.
|
|
457
|
-
if (keepType) {
|
|
458
|
-
state.tr.setBlockType(
|
|
459
|
-
newBlockContentPos,
|
|
460
|
-
newBlockContentPos,
|
|
461
|
-
state.schema.node(contentType).type,
|
|
462
|
-
keepProps ? contentNode.attrs : undefined
|
|
463
|
-
);
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
// Sets the selection to the start of the new block's content node.
|
|
467
|
-
state.tr.setSelection(
|
|
468
|
-
new TextSelection(state.doc.resolve(newBlockContentPos))
|
|
469
|
-
);
|
|
470
|
-
|
|
471
|
-
// Replaces the content of the original block's content node. Doesn't replace the whole content node so its
|
|
472
|
-
// type doesn't change.
|
|
473
|
-
state.tr.replace(
|
|
474
|
-
startPos + 1,
|
|
475
|
-
endPos - 1,
|
|
476
|
-
originalBlockContent.content.size > 0
|
|
477
|
-
? new Slice(
|
|
478
|
-
Fragment.from(originalBlockContent),
|
|
479
|
-
depth + 2,
|
|
480
|
-
depth + 2
|
|
481
|
-
)
|
|
482
|
-
: undefined
|
|
483
|
-
);
|
|
484
|
-
|
|
485
|
-
state.tr.scrollIntoView();
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
return true;
|
|
489
|
-
},
|
|
490
|
-
};
|
|
491
|
-
},
|
|
492
|
-
|
|
493
|
-
addProseMirrorPlugins() {
|
|
494
|
-
return [NonEditableBlockPlugin()];
|
|
495
|
-
},
|
|
496
|
-
|
|
497
|
-
addKeyboardShortcuts() {
|
|
498
|
-
// handleBackspace is partially adapted from https://github.com/ueberdosis/tiptap/blob/ed56337470efb4fd277128ab7ef792b37cfae992/packages/core/src/extensions/keymap.ts
|
|
499
|
-
const handleBackspace = () =>
|
|
500
|
-
this.editor.commands.first(({ commands }) => [
|
|
501
|
-
// Deletes the selection if it's not empty.
|
|
502
|
-
() => commands.deleteSelection(),
|
|
503
|
-
// Undoes an input rule if one was triggered in the last editor state change.
|
|
504
|
-
() => commands.undoInputRule(),
|
|
505
|
-
// Reverts block content type to a paragraph if the selection is at the start of the block.
|
|
506
|
-
() =>
|
|
507
|
-
commands.command(({ state }) => {
|
|
508
|
-
const { contentType, startPos } = getBlockInfoFromPos(
|
|
509
|
-
state.doc,
|
|
510
|
-
state.selection.from
|
|
511
|
-
)!;
|
|
512
|
-
|
|
513
|
-
const selectionAtBlockStart = state.selection.from === startPos + 1;
|
|
514
|
-
const isParagraph = contentType.name === "paragraph";
|
|
515
|
-
|
|
516
|
-
if (selectionAtBlockStart && !isParagraph) {
|
|
517
|
-
return commands.BNUpdateBlock(state.selection.from, {
|
|
518
|
-
type: "paragraph",
|
|
519
|
-
props: {},
|
|
520
|
-
});
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
return false;
|
|
524
|
-
}),
|
|
525
|
-
// Removes a level of nesting if the block is indented if the selection is at the start of the block.
|
|
526
|
-
() =>
|
|
527
|
-
commands.command(({ state }) => {
|
|
528
|
-
const { startPos } = getBlockInfoFromPos(
|
|
529
|
-
state.doc,
|
|
530
|
-
state.selection.from
|
|
531
|
-
)!;
|
|
532
|
-
|
|
533
|
-
const selectionAtBlockStart = state.selection.from === startPos + 1;
|
|
534
|
-
|
|
535
|
-
if (selectionAtBlockStart) {
|
|
536
|
-
return commands.liftListItem("blockContainer");
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
return false;
|
|
540
|
-
}),
|
|
541
|
-
// Merges block with the previous one if it isn't indented, isn't the first block in the doc, and the selection
|
|
542
|
-
// is at the start of the block.
|
|
543
|
-
() =>
|
|
544
|
-
commands.command(({ state }) => {
|
|
545
|
-
const { depth, startPos } = getBlockInfoFromPos(
|
|
546
|
-
state.doc,
|
|
547
|
-
state.selection.from
|
|
548
|
-
)!;
|
|
549
|
-
|
|
550
|
-
const selectionAtBlockStart = state.selection.from === startPos + 1;
|
|
551
|
-
const selectionEmpty = state.selection.empty;
|
|
552
|
-
const blockAtDocStart = startPos === 2;
|
|
553
|
-
|
|
554
|
-
const posBetweenBlocks = startPos - 1;
|
|
555
|
-
|
|
556
|
-
if (
|
|
557
|
-
!blockAtDocStart &&
|
|
558
|
-
selectionAtBlockStart &&
|
|
559
|
-
selectionEmpty &&
|
|
560
|
-
depth === 2
|
|
561
|
-
) {
|
|
562
|
-
return commands.BNMergeBlocks(posBetweenBlocks);
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
return false;
|
|
566
|
-
}),
|
|
567
|
-
]);
|
|
568
|
-
|
|
569
|
-
const handleDelete = () =>
|
|
570
|
-
this.editor.commands.first(({ commands }) => [
|
|
571
|
-
// Deletes the selection if it's not empty.
|
|
572
|
-
() => commands.deleteSelection(),
|
|
573
|
-
// Merges block with the next one (at the same nesting level or lower),
|
|
574
|
-
// if one exists, the block has no children, and the selection is at the
|
|
575
|
-
// end of the block.
|
|
576
|
-
() =>
|
|
577
|
-
commands.command(({ state }) => {
|
|
578
|
-
const { node, depth, endPos } = getBlockInfoFromPos(
|
|
579
|
-
state.doc,
|
|
580
|
-
state.selection.from
|
|
581
|
-
)!;
|
|
582
|
-
|
|
583
|
-
const blockAtDocEnd = endPos === state.doc.nodeSize - 4;
|
|
584
|
-
const selectionAtBlockEnd = state.selection.from === endPos - 1;
|
|
585
|
-
const selectionEmpty = state.selection.empty;
|
|
586
|
-
const hasChildBlocks = node.childCount === 2;
|
|
587
|
-
|
|
588
|
-
if (
|
|
589
|
-
!blockAtDocEnd &&
|
|
590
|
-
selectionAtBlockEnd &&
|
|
591
|
-
selectionEmpty &&
|
|
592
|
-
!hasChildBlocks
|
|
593
|
-
) {
|
|
594
|
-
let oldDepth = depth;
|
|
595
|
-
let newPos = endPos + 2;
|
|
596
|
-
let newDepth = state.doc.resolve(newPos).depth;
|
|
597
|
-
|
|
598
|
-
while (newDepth < oldDepth) {
|
|
599
|
-
oldDepth = newDepth;
|
|
600
|
-
newPos += 2;
|
|
601
|
-
newDepth = state.doc.resolve(newPos).depth;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
return commands.BNMergeBlocks(newPos - 1);
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
return false;
|
|
608
|
-
}),
|
|
609
|
-
]);
|
|
610
|
-
|
|
611
|
-
const handleEnter = () =>
|
|
612
|
-
this.editor.commands.first(({ commands }) => [
|
|
613
|
-
// Removes a level of nesting if the block is empty & indented, while the selection is also empty & at the start
|
|
614
|
-
// of the block.
|
|
615
|
-
() =>
|
|
616
|
-
commands.command(({ state }) => {
|
|
617
|
-
const { contentNode, depth } = getBlockInfoFromPos(
|
|
618
|
-
state.doc,
|
|
619
|
-
state.selection.from
|
|
620
|
-
)!;
|
|
621
|
-
|
|
622
|
-
const selectionAtBlockStart =
|
|
623
|
-
state.selection.$anchor.parentOffset === 0;
|
|
624
|
-
const selectionEmpty =
|
|
625
|
-
state.selection.anchor === state.selection.head;
|
|
626
|
-
const blockEmpty = contentNode.childCount === 0;
|
|
627
|
-
const blockIndented = depth > 2;
|
|
628
|
-
|
|
629
|
-
if (
|
|
630
|
-
selectionAtBlockStart &&
|
|
631
|
-
selectionEmpty &&
|
|
632
|
-
blockEmpty &&
|
|
633
|
-
blockIndented
|
|
634
|
-
) {
|
|
635
|
-
return commands.liftListItem("blockContainer");
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
return false;
|
|
639
|
-
}),
|
|
640
|
-
// Creates a new block and moves the selection to it if the current one is empty, while the selection is also
|
|
641
|
-
// empty & at the start of the block.
|
|
642
|
-
() =>
|
|
643
|
-
commands.command(({ state, chain }) => {
|
|
644
|
-
const { contentNode, endPos } = getBlockInfoFromPos(
|
|
645
|
-
state.doc,
|
|
646
|
-
state.selection.from
|
|
647
|
-
)!;
|
|
648
|
-
|
|
649
|
-
const selectionAtBlockStart =
|
|
650
|
-
state.selection.$anchor.parentOffset === 0;
|
|
651
|
-
const selectionEmpty =
|
|
652
|
-
state.selection.anchor === state.selection.head;
|
|
653
|
-
const blockEmpty = contentNode.childCount === 0;
|
|
654
|
-
|
|
655
|
-
if (selectionAtBlockStart && selectionEmpty && blockEmpty) {
|
|
656
|
-
const newBlockInsertionPos = endPos + 1;
|
|
657
|
-
const newBlockContentPos = newBlockInsertionPos + 2;
|
|
658
|
-
|
|
659
|
-
chain()
|
|
660
|
-
.BNCreateBlock(newBlockInsertionPos)
|
|
661
|
-
.setTextSelection(newBlockContentPos)
|
|
662
|
-
.run();
|
|
663
|
-
|
|
664
|
-
return true;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
return false;
|
|
668
|
-
}),
|
|
669
|
-
// Splits the current block, moving content inside that's after the cursor to a new text block below. Also
|
|
670
|
-
// deletes the selection beforehand, if it's not empty.
|
|
671
|
-
() =>
|
|
672
|
-
commands.command(({ state, chain }) => {
|
|
673
|
-
const { contentNode } = getBlockInfoFromPos(
|
|
674
|
-
state.doc,
|
|
675
|
-
state.selection.from
|
|
676
|
-
)!;
|
|
677
|
-
|
|
678
|
-
const selectionAtBlockStart =
|
|
679
|
-
state.selection.$anchor.parentOffset === 0;
|
|
680
|
-
const blockEmpty = contentNode.childCount === 0;
|
|
681
|
-
|
|
682
|
-
if (!blockEmpty) {
|
|
683
|
-
chain()
|
|
684
|
-
.deleteSelection()
|
|
685
|
-
.BNSplitBlock(
|
|
686
|
-
state.selection.from,
|
|
687
|
-
selectionAtBlockStart,
|
|
688
|
-
selectionAtBlockStart
|
|
689
|
-
)
|
|
690
|
-
.run();
|
|
691
|
-
|
|
692
|
-
return true;
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
return false;
|
|
696
|
-
}),
|
|
697
|
-
]);
|
|
698
|
-
|
|
699
|
-
return {
|
|
700
|
-
Backspace: handleBackspace,
|
|
701
|
-
Delete: handleDelete,
|
|
702
|
-
Enter: handleEnter,
|
|
703
|
-
// Always returning true for tab key presses ensures they're not captured by the browser. Otherwise, they blur the
|
|
704
|
-
// editor since the browser will try to use tab for keyboard navigation.
|
|
705
|
-
Tab: () => {
|
|
706
|
-
if (
|
|
707
|
-
this.options.editor.formattingToolbar?.shown ||
|
|
708
|
-
this.options.editor.linkToolbar?.shown ||
|
|
709
|
-
this.options.editor.filePanel?.shown
|
|
710
|
-
) {
|
|
711
|
-
// don't handle tabs if a toolbar is shown, so we can tab into / out of it
|
|
712
|
-
return false;
|
|
713
|
-
}
|
|
714
|
-
this.editor.commands.sinkListItem("blockContainer");
|
|
715
|
-
return true;
|
|
716
|
-
},
|
|
717
|
-
"Shift-Tab": () => {
|
|
718
|
-
if (
|
|
719
|
-
this.options.editor.formattingToolbar?.shown ||
|
|
720
|
-
this.options.editor.linkToolbar?.shown ||
|
|
721
|
-
this.options.editor.filePanel?.shown
|
|
722
|
-
) {
|
|
723
|
-
// don't handle tabs if a toolbar is shown, so we can tab into / out of it
|
|
724
|
-
return false;
|
|
725
|
-
}
|
|
726
|
-
this.editor.commands.liftListItem("blockContainer");
|
|
727
|
-
return true;
|
|
728
|
-
},
|
|
729
|
-
};
|
|
730
|
-
},
|
|
731
87
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Node } from "@tiptap/core";
|
|
2
|
-
import { BlockNoteDOMAttributes } from "../schema";
|
|
3
|
-
import { mergeCSSClasses } from "../util/browser";
|
|
2
|
+
import { BlockNoteDOMAttributes } from "../schema/index.js";
|
|
3
|
+
import { mergeCSSClasses } from "../util/browser.js";
|
|
4
4
|
|
|
5
5
|
export const BlockGroup = Node.create<{
|
|
6
6
|
domAttributes?: BlockNoteDOMAttributes;
|
package/src/pm-nodes/index.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { BlockContainer } from "./BlockContainer";
|
|
2
|
-
export { BlockGroup } from "./BlockGroup";
|
|
3
|
-
export { Doc } from "./Doc";
|
|
1
|
+
export { BlockContainer } from "./BlockContainer.js";
|
|
2
|
+
export { BlockGroup } from "./BlockGroup.js";
|
|
3
|
+
export { Doc } from "./Doc.js";
|