@blocknote/core 0.9.5 → 0.10.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 +3699 -2600
- package/dist/blocknote.js.map +1 -1
- package/dist/blocknote.umd.cjs +7 -7
- package/dist/blocknote.umd.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/dist/webpack-stats.json +1 -0
- package/package.json +8 -4
- package/src/api/README.md +8 -0
- package/src/api/blockManipulation/blockManipulation.test.ts +72 -10
- package/src/api/blockManipulation/blockManipulation.ts +38 -18
- package/src/api/exporters/copyExtension.ts +68 -0
- package/src/api/exporters/html/__snapshots__/complex/misc/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/complex/misc/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/customParagraph/basic/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/customParagraph/basic/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/customParagraph/nested/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/customParagraph/nested/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/customParagraph/styled/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/customParagraph/styled/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/fontSize/basic/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/fontSize/basic/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/hardbreak/basic/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/hardbreak/basic/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/hardbreak/between-links/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/hardbreak/between-links/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/hardbreak/end/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/hardbreak/end/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/hardbreak/link/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/hardbreak/link/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/hardbreak/multiple/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/hardbreak/multiple/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/hardbreak/only/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/hardbreak/only/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/hardbreak/start/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/hardbreak/start/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/hardbreak/styles/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/hardbreak/styles/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/image/basic/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/image/basic/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/image/button/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/image/button/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/image/nested/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/image/nested/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/link/adjacent/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/link/adjacent/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/link/basic/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/link/basic/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/link/styled/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/link/styled/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/mention/basic/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/mention/basic/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/paragraph/basic/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/paragraph/basic/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/paragraph/empty/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/paragraph/empty/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/paragraph/nested/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/paragraph/nested/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/paragraph/styled/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/paragraph/styled/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/paste/parse-basic-block-types.json +140 -0
- package/src/api/exporters/html/__snapshots__/paste/parse-deep-nested-content.json +240 -0
- package/src/api/exporters/html/__snapshots__/paste/parse-div-with-inline-content.json +91 -0
- package/src/api/exporters/html/__snapshots__/paste/parse-divs.json +19 -0
- package/src/api/exporters/html/__snapshots__/paste/parse-fake-image-caption.json +31 -0
- package/src/api/exporters/html/__snapshots__/paste/parse-mixed-nested-lists.json +70 -0
- package/src/api/exporters/html/__snapshots__/paste/parse-nested-lists-with-paragraphs.json +70 -0
- package/src/api/exporters/html/__snapshots__/paste/parse-nested-lists.json +70 -0
- package/src/api/exporters/html/__snapshots__/simpleCustomParagraph/basic/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/simpleCustomParagraph/basic/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/simpleCustomParagraph/nested/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/simpleCustomParagraph/nested/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/simpleCustomParagraph/styled/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/simpleCustomParagraph/styled/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/simpleImage/basic/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/simpleImage/basic/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/simpleImage/button/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/simpleImage/button/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/simpleImage/nested/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/simpleImage/nested/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/small/basic/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/small/basic/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/tag/basic/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/tag/basic/internal.html +1 -0
- package/src/api/exporters/html/externalHTMLExporter.ts +98 -0
- package/src/api/exporters/html/htmlConversion.test.ts +100 -0
- package/src/api/exporters/html/internalHTMLSerializer.ts +80 -0
- package/src/api/exporters/html/util/sharedHTMLConversion.ts +128 -0
- package/src/api/{formatConversions → exporters/html/util}/simplifyBlocksRehypePlugin.ts +13 -0
- package/src/api/exporters/markdown/__snapshots__/complex/misc/markdown.md +5 -0
- package/src/api/exporters/markdown/__snapshots__/customParagraph/basic/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/customParagraph/nested/markdown.md +5 -0
- package/src/api/exporters/markdown/__snapshots__/customParagraph/styled/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/fontSize/basic/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/hardbreak/basic/markdown.md +2 -0
- package/src/api/exporters/markdown/__snapshots__/hardbreak/between-links/markdown.md +2 -0
- package/src/api/exporters/markdown/__snapshots__/hardbreak/end/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/hardbreak/link/markdown.md +2 -0
- package/src/api/exporters/markdown/__snapshots__/hardbreak/multiple/markdown.md +3 -0
- package/src/api/exporters/markdown/__snapshots__/hardbreak/start/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/hardbreak/styles/markdown.md +2 -0
- package/src/api/exporters/markdown/__snapshots__/image/basic/markdown.md +3 -0
- package/src/api/exporters/markdown/__snapshots__/image/button/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/image/nested/markdown.md +7 -0
- package/src/api/exporters/markdown/__snapshots__/link/adjacent/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/link/basic/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/link/styled/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/mention/basic/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/paragraph/basic/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/paragraph/empty/markdown.md +0 -0
- package/src/api/exporters/markdown/__snapshots__/paragraph/nested/markdown.md +5 -0
- package/src/api/exporters/markdown/__snapshots__/paragraph/styled/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/simpleCustomParagraph/basic/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/simpleCustomParagraph/nested/markdown.md +5 -0
- package/src/api/exporters/markdown/__snapshots__/simpleCustomParagraph/styled/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/simpleImage/basic/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/simpleImage/button/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/simpleImage/nested/markdown.md +3 -0
- package/src/api/exporters/markdown/__snapshots__/small/basic/markdown.md +1 -0
- package/src/api/exporters/markdown/__snapshots__/tag/basic/markdown.md +1 -0
- package/src/api/exporters/markdown/markdownExporter.test.ts +85 -0
- package/src/api/exporters/markdown/markdownExporter.ts +42 -0
- package/src/api/nodeConversions/__snapshots__/nodeConversions.test.ts.snap +486 -125
- package/src/api/nodeConversions/nodeConversions.test.ts +67 -498
- package/src/api/nodeConversions/nodeConversions.ts +311 -98
- package/src/api/parsers/html/__snapshots__/paste/list-test.json +105 -0
- package/src/api/parsers/html/__snapshots__/paste/parse-basic-block-types.json +140 -0
- package/src/api/parsers/html/__snapshots__/paste/parse-deep-nested-content.json +240 -0
- package/src/api/parsers/html/__snapshots__/paste/parse-div-with-inline-content.json +91 -0
- package/src/api/parsers/html/__snapshots__/paste/parse-divs.json +121 -0
- package/src/api/parsers/html/__snapshots__/paste/parse-fake-image-caption.json +31 -0
- package/src/api/parsers/html/__snapshots__/paste/parse-google-docs-html.json +476 -0
- package/src/api/parsers/html/__snapshots__/paste/parse-mixed-nested-lists.json +140 -0
- package/src/api/parsers/html/__snapshots__/paste/parse-nested-lists-with-paragraphs.json +140 -0
- package/src/api/parsers/html/__snapshots__/paste/parse-nested-lists.json +157 -0
- package/src/api/parsers/html/__snapshots__/paste/parse-notion-html.json +470 -0
- package/src/api/parsers/html/__snapshots__/paste/parse-two-divs.json +36 -0
- package/src/api/parsers/html/parseHTML.test.ts +440 -0
- package/src/api/parsers/html/parseHTML.ts +42 -0
- package/src/api/parsers/html/util/__snapshots__/nestedLists.test.ts.snap +129 -0
- package/src/api/parsers/html/util/nestedLists.test.ts +176 -0
- package/src/api/parsers/html/util/nestedLists.ts +113 -0
- package/src/api/parsers/markdown/__snapshots__/complex.json +353 -0
- package/src/api/parsers/markdown/__snapshots__/issue-226-1.json +71 -0
- package/src/api/parsers/markdown/__snapshots__/issue-226-2.json +144 -0
- package/src/api/parsers/markdown/__snapshots__/nested.json +72 -0
- package/src/api/parsers/markdown/__snapshots__/non-nested.json +71 -0
- package/src/api/parsers/markdown/__snapshots__/styled.json +58 -0
- package/src/api/parsers/markdown/parseMarkdown.test.ts +114 -0
- package/src/api/parsers/markdown/parseMarkdown.ts +84 -0
- package/src/api/parsers/pasteExtension.ts +59 -0
- package/src/api/testUtil/cases/customBlocks.ts +282 -0
- package/src/api/testUtil/cases/customInlineContent.ts +114 -0
- package/src/api/testUtil/cases/customStyles.ts +100 -0
- package/src/api/testUtil/cases/defaultSchema.ts +399 -0
- package/src/api/testUtil/index.ts +17 -0
- package/src/api/testUtil/partialBlockTestUtil.ts +127 -0
- package/src/blocks/HeadingBlockContent/HeadingBlockContent.ts +136 -0
- package/src/{extensions/Blocks/nodes/BlockContent → blocks}/ImageBlockContent/ImageBlockContent.ts +117 -31
- package/src/{extensions/Blocks/nodes/BlockContent → blocks}/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +34 -47
- package/src/{extensions/Blocks/nodes/BlockContent → blocks}/ListItemBlockContent/ListItemKeyboardShortcuts.ts +1 -1
- package/src/{extensions/Blocks/nodes/BlockContent → blocks}/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts +1 -1
- package/src/{extensions/Blocks/nodes/BlockContent → blocks}/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +34 -56
- package/src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts +43 -0
- package/src/blocks/README.md +3 -0
- package/src/blocks/TableBlockContent/TableBlockContent.ts +74 -0
- package/src/blocks/TableBlockContent/TableExtension.ts +63 -0
- package/src/blocks/defaultBlockHelpers.ts +95 -0
- package/src/blocks/defaultBlocks.ts +60 -0
- package/src/blocks/defaultProps.ts +24 -0
- package/src/{extensions/Blocks/nodes/Block.module.css → editor/Block.css} +70 -66
- package/src/{BlockNoteEditor.test.ts → editor/BlockNoteEditor.test.ts} +2 -2
- package/src/{BlockNoteEditor.ts → editor/BlockNoteEditor.ts} +382 -159
- package/src/{BlockNoteExtensions.ts → editor/BlockNoteExtensions.ts} +59 -40
- package/src/editor/README.md +3 -0
- package/src/editor/cursorPositionTypes.ts +16 -0
- package/src/{editor.module.css → editor/editor.css} +42 -15
- package/src/editor/selectionTypes.ts +14 -0
- package/src/editor/transformPasted.ts +58 -0
- package/src/extensions/BackgroundColor/BackgroundColorExtension.ts +1 -36
- package/src/extensions/BackgroundColor/BackgroundColorMark.ts +12 -27
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +16 -24
- package/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts +12 -10
- package/src/extensions/ImageToolbar/ImageToolbarPlugin.ts +35 -73
- package/src/extensions/Placeholder/PlaceholderExtension.ts +4 -4
- package/src/extensions/README.md +3 -0
- package/src/extensions/SideMenu/SideMenuPlugin.ts +77 -37
- package/src/extensions/SlashMenu/BaseSlashMenuItem.ts +7 -6
- package/src/extensions/SlashMenu/SlashMenuPlugin.ts +9 -7
- package/src/extensions/SlashMenu/defaultSlashMenuItems.ts +98 -35
- package/src/extensions/TableHandles/TableHandlesPlugin.ts +617 -0
- package/src/extensions/TextAlignment/TextAlignmentExtension.ts +3 -51
- package/src/extensions/TextColor/TextColorExtension.ts +1 -29
- package/src/extensions/TextColor/TextColorMark.ts +7 -27
- package/src/extensions/UniqueID/UniqueID.ts +28 -2
- package/src/extensions-shared/README.md +3 -0
- package/src/{shared/plugins → extensions-shared}/suggestion/SuggestionPlugin.ts +19 -13
- package/src/index.ts +21 -15
- package/src/{extensions/Blocks/nodes → pm-nodes}/BlockContainer.ts +161 -96
- package/src/pm-nodes/BlockGroup.ts +54 -0
- package/src/pm-nodes/Doc.ts +7 -0
- package/src/pm-nodes/README.md +42 -0
- package/src/pm-nodes/index.ts +3 -0
- package/src/schema/README.md +3 -0
- package/src/schema/blocks/createSpec.ts +220 -0
- package/src/schema/blocks/internal.ts +253 -0
- package/src/schema/blocks/types.ts +252 -0
- package/src/schema/index.ts +10 -0
- package/src/schema/inlineContent/createSpec.ts +119 -0
- package/src/schema/inlineContent/internal.ts +105 -0
- package/src/schema/inlineContent/types.ts +144 -0
- package/src/schema/propTypes.ts +32 -0
- package/src/schema/styles/createSpec.ts +85 -0
- package/src/schema/styles/internal.ts +96 -0
- package/src/schema/styles/types.ts +42 -0
- package/src/util/README.md +3 -0
- package/src/{shared/utils.ts → util/browser.ts} +4 -8
- package/src/util/string.ts +3 -0
- package/src/util/typescript.ts +5 -0
- package/types/src/BlockNoteEditor.d.ts +51 -37
- package/types/src/BlockNoteExtensions.d.ts +8 -3
- package/types/src/api/blockManipulation/blockManipulation.d.ts +5 -4
- package/types/src/api/exporters/copyExtension.d.ts +6 -0
- package/types/src/api/exporters/html/externalHTMLExporter.d.ts +8 -0
- package/types/src/api/exporters/html/internalHTMLSerializer.d.ts +8 -0
- package/types/src/api/exporters/html/util/sharedHTMLConversion.d.ts +7 -0
- package/types/src/api/exporters/markdown/markdownExporter.d.ts +5 -0
- package/types/src/api/exporters/markdown/markdownExporter.test.d.ts +1 -0
- package/types/src/api/getBlockInfoFromPos.d.ts +27 -0
- package/types/src/api/nodeConversions/nodeConversions.d.ts +14 -6
- package/types/src/api/nodeConversions/testUtil.d.ts +7 -2
- package/types/src/api/nodeUtil.d.ts +8 -0
- package/types/src/api/parsers/html/parseHTML.d.ts +3 -0
- package/types/src/api/parsers/html/parseHTML.test.d.ts +1 -0
- package/types/src/api/parsers/html/util/nestedLists.d.ts +1 -0
- package/types/src/api/parsers/html/util/nestedLists.test.d.ts +1 -0
- package/types/src/api/parsers/markdown/parseMarkdown.d.ts +3 -0
- package/types/src/api/parsers/markdown/parseMarkdown.test.d.ts +1 -0
- package/types/src/api/parsers/pasteExtension.d.ts +6 -0
- package/types/src/api/testCases/cases/customBlocks.d.ts +345 -0
- package/types/src/api/testCases/cases/customInlineContent.d.ts +29 -0
- package/types/src/api/testCases/cases/customStyles.d.ts +64 -0
- package/types/src/api/testCases/cases/defaultSchema.d.ts +3 -0
- package/types/src/api/testCases/index.d.ts +12 -0
- package/types/src/api/testUtil/cases/customBlocks.d.ts +345 -0
- package/types/src/api/testUtil/cases/customInlineContent.d.ts +29 -0
- package/types/src/api/testUtil/cases/customStyles.d.ts +64 -0
- package/types/src/api/testUtil/cases/defaultSchema.d.ts +3 -0
- package/types/src/api/testUtil/index.d.ts +12 -0
- package/types/src/api/testUtil/partialBlockTestUtil.d.ts +7 -0
- package/types/src/blocks/HeadingBlockContent/HeadingBlockContent.d.ts +58 -0
- package/types/src/blocks/ImageBlockContent/ImageBlockContent.d.ts +93 -0
- package/types/src/blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.d.ts +1 -0
- package/types/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.d.ts +46 -0
- package/types/src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.d.ts +2 -0
- package/types/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.d.ts +2 -0
- package/types/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.d.ts +46 -0
- package/types/src/blocks/ParagraphBlockContent/ParagraphBlockContent.d.ts +52 -0
- package/types/src/blocks/TableBlockContent/TableBlockContent.d.ts +53 -0
- package/types/src/blocks/TableBlockContent/TableExtension.d.ts +2 -0
- package/types/src/blocks/defaultBlockHelpers.d.ts +10 -0
- package/types/src/blocks/defaultBlocks.d.ts +577 -0
- package/types/src/blocks/defaultProps.d.ts +15 -0
- package/types/src/editor/BlockNoteEditor.d.ts +299 -0
- package/types/src/editor/BlockNoteEditor.test.d.ts +1 -0
- package/types/src/editor/BlockNoteExtensions.d.ts +24 -0
- package/types/src/editor/cursorPositionTypes.d.ts +6 -0
- package/types/src/editor/selectionTypes.d.ts +4 -0
- package/types/src/editor/transformPasted.d.ts +12 -0
- package/types/src/extensions/BackgroundColor/BackgroundColorExtension.d.ts +0 -7
- package/types/src/extensions/BackgroundColor/BackgroundColorMark.d.ts +7 -9
- package/types/src/extensions/Blocks/api/blocks/createSpec.d.ts +35 -0
- package/types/src/extensions/Blocks/api/blocks/internal.d.ts +45 -0
- package/types/src/extensions/Blocks/api/blocks/types.d.ts +114 -0
- package/types/src/extensions/Blocks/api/cursorPositionTypes.d.ts +7 -5
- package/types/src/extensions/Blocks/api/defaultBlocks.d.ts +573 -113
- package/types/src/extensions/Blocks/api/defaultProps.d.ts +2 -1
- package/types/src/extensions/Blocks/api/inlineContent/createSpec.d.ts +21 -0
- package/types/src/extensions/Blocks/api/inlineContent/internal.d.ts +25 -0
- package/types/src/extensions/Blocks/api/inlineContent/types.d.ts +62 -0
- package/types/src/extensions/Blocks/api/selectionTypes.d.ts +5 -3
- package/types/src/extensions/Blocks/api/styles/createSpec.d.ts +13 -0
- package/types/src/extensions/Blocks/api/styles/internal.d.ts +22 -0
- package/types/src/extensions/Blocks/api/styles/types.d.ts +21 -0
- package/types/src/extensions/Blocks/nodes/BlockContainer.d.ts +8 -4
- package/types/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContent.d.ts +38 -23
- package/types/src/extensions/Blocks/nodes/BlockContent/ImageBlockContent/ImageBlockContent.d.ts +75 -17
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.d.ts +30 -19
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.d.ts +30 -19
- package/types/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.d.ts +36 -28
- package/types/src/extensions/Blocks/nodes/BlockContent/TableBlockContent/TableBlockContent.d.ts +53 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/TableBlockContent/TableExtension.d.ts +2 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/defaultBlockHelpers.d.ts +12 -0
- package/types/src/extensions/Blocks/nodes/BlockGroup.d.ts +1 -1
- package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +8 -6
- package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.d.ts +6 -6
- package/types/src/extensions/ImageToolbar/ImageToolbarPlugin.d.ts +11 -16
- package/types/src/extensions/NonEditableBlocks/NonEditableBlockPlugin.d.ts +2 -0
- package/types/src/extensions/PreviousBlockType/PreviousBlockTypePlugin.d.ts +14 -0
- package/types/src/extensions/SideMenu/SideMenuPlugin.d.ts +19 -11
- package/types/src/extensions/SlashMenu/BaseSlashMenuItem.d.ts +5 -6
- package/types/src/extensions/SlashMenu/SlashMenuPlugin.d.ts +6 -6
- package/types/src/extensions/SlashMenu/defaultSlashMenuItems.d.ts +2 -1
- package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +74 -0
- package/types/src/extensions/TextAlignment/TextAlignmentExtension.d.ts +0 -7
- package/types/src/extensions/TextColor/TextColorExtension.d.ts +0 -7
- package/types/src/extensions/TextColor/TextColorMark.d.ts +7 -9
- package/types/src/extensions/UniqueID/UniqueID.d.ts +1 -1
- package/types/src/extensions-shared/BaseUiElementTypes.d.ts +7 -0
- package/types/src/extensions-shared/suggestion/SuggestionItem.d.ts +3 -0
- package/types/src/extensions-shared/suggestion/SuggestionPlugin.d.ts +36 -0
- package/types/src/index.d.ts +20 -15
- package/types/src/pm-nodes/BlockContainer.d.ts +28 -0
- package/types/src/pm-nodes/BlockGroup.d.ts +10 -0
- package/types/src/pm-nodes/Doc.d.ts +2 -0
- package/types/src/pm-nodes/index.d.ts +3 -0
- package/types/src/schema/blocks/createSpec.d.ts +35 -0
- package/types/src/schema/blocks/internal.d.ts +45 -0
- package/types/src/schema/blocks/types.d.ts +107 -0
- package/types/src/schema/index.d.ts +10 -0
- package/types/src/schema/inlineContent/createSpec.d.ts +21 -0
- package/types/src/schema/inlineContent/internal.d.ts +28 -0
- package/types/src/schema/inlineContent/types.d.ts +62 -0
- package/types/src/schema/propTypes.d.ts +8 -0
- package/types/src/schema/styles/createSpec.d.ts +13 -0
- package/types/src/schema/styles/internal.d.ts +22 -0
- package/types/src/schema/styles/types.d.ts +21 -0
- package/types/src/shared/plugins/suggestion/SuggestionPlugin.d.ts +4 -2
- package/types/src/util/EventEmitter.d.ts +11 -0
- package/types/src/util/browser.d.ts +3 -0
- package/types/src/util/string.d.ts +1 -0
- package/types/src/util/typescript.d.ts +3 -0
- package/src/api/formatConversions/__snapshots__/formatConversions.test.ts.snap +0 -346
- package/src/api/formatConversions/formatConversions.test.ts +0 -753
- package/src/api/formatConversions/formatConversions.ts +0 -133
- package/src/api/nodeConversions/testUtil.ts +0 -65
- package/src/extensions/Blocks/api/block.ts +0 -307
- package/src/extensions/Blocks/api/blockTypes.ts +0 -249
- package/src/extensions/Blocks/api/cursorPositionTypes.ts +0 -7
- package/src/extensions/Blocks/api/defaultBlocks.ts +0 -16
- package/src/extensions/Blocks/api/defaultProps.ts +0 -16
- package/src/extensions/Blocks/api/inlineContentTypes.ts +0 -36
- package/src/extensions/Blocks/api/selectionTypes.ts +0 -5
- package/src/extensions/Blocks/api/serialization.ts +0 -29
- package/src/extensions/Blocks/helpers/findBlock.ts +0 -5
- package/src/extensions/Blocks/index.ts +0 -8
- package/src/extensions/Blocks/nodes/BlockAttributes.ts +0 -10
- package/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContent.ts +0 -142
- package/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.ts +0 -62
- package/src/extensions/Blocks/nodes/BlockGroup.ts +0 -53
- package/types/src/api/formatConversions/formatConversions.d.ts +0 -6
- package/types/src/extensions/Blocks/api/block.d.ts +0 -20
- package/types/src/extensions/Blocks/api/blockTypes.d.ts +0 -103
- package/types/src/extensions/Blocks/api/inlineContentTypes.d.ts +0 -30
- package/types/src/extensions/Blocks/api/serialization.d.ts +0 -2
- /package/src/{shared/EditorElement.ts → api/exporters/markdown/__snapshots__/hardbreak/only/markdown.md} +0 -0
- /package/src/api/{formatConversions → exporters/markdown}/removeUnderlinesRehypePlugin.ts +0 -0
- /package/src/{extensions/Blocks/helpers → api}/getBlockInfoFromPos.ts +0 -0
- /package/src/api/{util/nodeUtil.ts → nodeUtil.ts} +0 -0
- /package/src/{extensions/Blocks/nodes/BlockContent → blocks}/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts +0 -0
- /package/src/extensions/{Blocks → NonEditableBlocks}/NonEditableBlockPlugin.ts +0 -0
- /package/src/extensions/{Blocks → PreviousBlockType}/PreviousBlockTypePlugin.ts +0 -0
- /package/src/{shared → extensions-shared}/BaseUiElementTypes.ts +0 -0
- /package/src/{shared/plugins → extensions-shared}/suggestion/SuggestionItem.ts +0 -0
- /package/src/{shared → util}/EventEmitter.ts +0 -0
- /package/types/src/api/{formatConversions/formatConversions.test.d.ts → exporters/html/htmlConversion.test.d.ts} +0 -0
- /package/types/src/api/{formatConversions → exporters/html/util}/simplifyBlocksRehypePlugin.d.ts +0 -0
- /package/types/src/api/{formatConversions → exporters/markdown}/removeUnderlinesRehypePlugin.d.ts +0 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Node } from "@tiptap/core";
|
|
2
|
+
import { BlockNoteDOMAttributes } from "../schema";
|
|
3
|
+
import { mergeCSSClasses } from "../util/browser";
|
|
4
|
+
|
|
5
|
+
export const BlockGroup = Node.create<{
|
|
6
|
+
domAttributes?: BlockNoteDOMAttributes;
|
|
7
|
+
}>({
|
|
8
|
+
name: "blockGroup",
|
|
9
|
+
group: "blockGroup",
|
|
10
|
+
content: "blockContainer+",
|
|
11
|
+
|
|
12
|
+
parseHTML() {
|
|
13
|
+
return [
|
|
14
|
+
{
|
|
15
|
+
tag: "div",
|
|
16
|
+
getAttrs: (element) => {
|
|
17
|
+
if (typeof element === "string") {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (element.getAttribute("data-node-type") === "blockGroup") {
|
|
22
|
+
// Null means the element matches, but we don't want to add any attributes to the node.
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return false;
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
renderHTML({ HTMLAttributes }) {
|
|
33
|
+
const blockGroupHTMLAttributes = {
|
|
34
|
+
...(this.options.domAttributes?.blockGroup || {}),
|
|
35
|
+
...HTMLAttributes,
|
|
36
|
+
};
|
|
37
|
+
const blockGroup = document.createElement("div");
|
|
38
|
+
blockGroup.className = mergeCSSClasses(
|
|
39
|
+
"bn-block-group",
|
|
40
|
+
blockGroupHTMLAttributes.class
|
|
41
|
+
);
|
|
42
|
+
blockGroup.setAttribute("data-node-type", "blockGroup");
|
|
43
|
+
for (const [attribute, value] of Object.entries(blockGroupHTMLAttributes)) {
|
|
44
|
+
if (attribute !== "class") {
|
|
45
|
+
blockGroup.setAttribute(attribute, value);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
dom: blockGroup,
|
|
51
|
+
contentDOM: blockGroup,
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
### @blocknote/core/src/pm-nodes
|
|
2
|
+
|
|
3
|
+
Defines the prosemirror nodes and base node structure. See below:
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# Node structure
|
|
7
|
+
|
|
8
|
+
We use a Prosemirror document structure where every element is a `block` with 1 `content` element and one optional group of children (`blockgroup`).
|
|
9
|
+
|
|
10
|
+
- A `block` can only appear in a `blockgroup` (which is also the type of the root node)
|
|
11
|
+
- Every `block` element can have attributes (e.g.: is it a heading or a list item)
|
|
12
|
+
- Every `block` element can contain a `blockgroup` as second child. In this case the `blockgroup` is considered nested (indented in the UX)
|
|
13
|
+
|
|
14
|
+
This architecture is different from the "default" Prosemirror / Tiptap implementation which would use more semantic HTML node types (`p`, `li`, etc.). We have designed this block structure instead to more easily:
|
|
15
|
+
|
|
16
|
+
- support indentation of any node (without complex wrapping logic)
|
|
17
|
+
- supporting animations (nodes stay the same type, only attrs are changed)
|
|
18
|
+
|
|
19
|
+
## Example
|
|
20
|
+
|
|
21
|
+
```xml
|
|
22
|
+
<blockgroup>
|
|
23
|
+
<block>
|
|
24
|
+
<content>Parent element 1</content>
|
|
25
|
+
<blockgroup>
|
|
26
|
+
<block>
|
|
27
|
+
<content>Nested / child / indented item</content>
|
|
28
|
+
</block>
|
|
29
|
+
</blockgroup>
|
|
30
|
+
</block>
|
|
31
|
+
<block>
|
|
32
|
+
<content>Parent element 2</content>
|
|
33
|
+
<blockgroup>
|
|
34
|
+
<block>...</block>
|
|
35
|
+
<block>...</block>
|
|
36
|
+
</blockgroup>
|
|
37
|
+
</block>
|
|
38
|
+
<block>
|
|
39
|
+
<content>Element 3 without children</content>
|
|
40
|
+
</block>
|
|
41
|
+
</blockgroup>
|
|
42
|
+
```
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { ParseRule } from "@tiptap/pm/model";
|
|
2
|
+
import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
|
|
3
|
+
import { InlineContentSchema } from "../inlineContent/types";
|
|
4
|
+
import { StyleSchema } from "../styles/types";
|
|
5
|
+
import {
|
|
6
|
+
createInternalBlockSpec,
|
|
7
|
+
createStronglyTypedTiptapNode,
|
|
8
|
+
getBlockFromPos,
|
|
9
|
+
propsToAttributes,
|
|
10
|
+
wrapInBlockStructure,
|
|
11
|
+
} from "./internal";
|
|
12
|
+
import {
|
|
13
|
+
BlockConfig,
|
|
14
|
+
BlockFromConfig,
|
|
15
|
+
BlockSchemaWithBlock,
|
|
16
|
+
PartialBlockFromConfig,
|
|
17
|
+
} from "./types";
|
|
18
|
+
|
|
19
|
+
// restrict content to "inline" and "none" only
|
|
20
|
+
export type CustomBlockConfig = BlockConfig & {
|
|
21
|
+
content: "inline" | "none";
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type CustomBlockImplementation<
|
|
25
|
+
T extends CustomBlockConfig,
|
|
26
|
+
I extends InlineContentSchema,
|
|
27
|
+
S extends StyleSchema
|
|
28
|
+
> = {
|
|
29
|
+
render: (
|
|
30
|
+
/**
|
|
31
|
+
* The custom block to render
|
|
32
|
+
*/
|
|
33
|
+
block: BlockFromConfig<T, I, S>,
|
|
34
|
+
/**
|
|
35
|
+
* The BlockNote editor instance
|
|
36
|
+
* This is typed generically. If you want an editor with your custom schema, you need to
|
|
37
|
+
* cast it manually, e.g.: `const e = editor as BlockNoteEditor<typeof mySchema>;`
|
|
38
|
+
*/
|
|
39
|
+
editor: BlockNoteEditor<BlockSchemaWithBlock<T["type"], T>, I, S>
|
|
40
|
+
// (note) if we want to fix the manual cast, we need to prevent circular references and separate block definition and render implementations
|
|
41
|
+
// or allow manually passing <BSchema>, but that's not possible without passing the other generics because Typescript doesn't support partial inferred generics
|
|
42
|
+
) => {
|
|
43
|
+
dom: HTMLElement;
|
|
44
|
+
contentDOM?: HTMLElement;
|
|
45
|
+
destroy?: () => void;
|
|
46
|
+
};
|
|
47
|
+
// Exports block to external HTML. If not defined, the output will be the same
|
|
48
|
+
// as `render(...).dom`. Used to create clipboard data when pasting outside
|
|
49
|
+
// BlockNote.
|
|
50
|
+
// TODO: Maybe can return undefined to ignore when serializing?
|
|
51
|
+
toExternalHTML?: (
|
|
52
|
+
block: BlockFromConfig<T, I, S>,
|
|
53
|
+
editor: BlockNoteEditor<BlockSchemaWithBlock<T["type"], T>, I, S>
|
|
54
|
+
) => {
|
|
55
|
+
dom: HTMLElement;
|
|
56
|
+
contentDOM?: HTMLElement;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
parse?: (
|
|
60
|
+
el: HTMLElement
|
|
61
|
+
) => PartialBlockFromConfig<T, I, S>["props"] | undefined;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Function that uses the 'parse' function of a blockConfig to create a
|
|
65
|
+
// TipTap node's `parseHTML` property. This is only used for parsing content
|
|
66
|
+
// from the clipboard.
|
|
67
|
+
export function getParseRules(
|
|
68
|
+
config: BlockConfig,
|
|
69
|
+
customParseFunction: CustomBlockImplementation<any, any, any>["parse"]
|
|
70
|
+
) {
|
|
71
|
+
const rules: ParseRule[] = [
|
|
72
|
+
{
|
|
73
|
+
tag: "[data-content-type=" + config.type + "]",
|
|
74
|
+
contentElement: "[data-editable]",
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
if (customParseFunction) {
|
|
79
|
+
rules.push({
|
|
80
|
+
tag: "*",
|
|
81
|
+
getAttrs(node: string | HTMLElement) {
|
|
82
|
+
if (typeof node === "string") {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const props = customParseFunction?.(node);
|
|
87
|
+
|
|
88
|
+
if (props === undefined) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return props;
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
// getContent(node, schema) {
|
|
97
|
+
// const block = blockConfig.parse?.(node as HTMLElement);
|
|
98
|
+
//
|
|
99
|
+
// if (block !== undefined && block.content !== undefined) {
|
|
100
|
+
// return Fragment.from(
|
|
101
|
+
// typeof block.content === "string"
|
|
102
|
+
// ? schema.text(block.content)
|
|
103
|
+
// : inlineContentToNodes(block.content, schema)
|
|
104
|
+
// );
|
|
105
|
+
// }
|
|
106
|
+
//
|
|
107
|
+
// return Fragment.empty;
|
|
108
|
+
// },
|
|
109
|
+
// });
|
|
110
|
+
// }
|
|
111
|
+
|
|
112
|
+
return rules;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// A function to create custom block for API consumers
|
|
116
|
+
// we want to hide the tiptap node from API consumers and provide a simpler API surface instead
|
|
117
|
+
export function createBlockSpec<
|
|
118
|
+
T extends CustomBlockConfig,
|
|
119
|
+
I extends InlineContentSchema,
|
|
120
|
+
S extends StyleSchema
|
|
121
|
+
>(blockConfig: T, blockImplementation: CustomBlockImplementation<T, I, S>) {
|
|
122
|
+
const node = createStronglyTypedTiptapNode({
|
|
123
|
+
name: blockConfig.type as T["type"],
|
|
124
|
+
content: (blockConfig.content === "inline"
|
|
125
|
+
? "inline*"
|
|
126
|
+
: "") as T["content"] extends "inline" ? "inline*" : "",
|
|
127
|
+
group: "blockContent",
|
|
128
|
+
selectable: true,
|
|
129
|
+
|
|
130
|
+
addAttributes() {
|
|
131
|
+
return propsToAttributes(blockConfig.propSchema);
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
parseHTML() {
|
|
135
|
+
return getParseRules(blockConfig, blockImplementation.parse);
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
renderHTML() {
|
|
139
|
+
// renderHTML is not really used, as we always use a nodeView, and we use toExternalHTML / toInternalHTML for serialization
|
|
140
|
+
// There's an edge case when this gets called nevertheless; before the nodeviews have been mounted
|
|
141
|
+
// this is why we implement it with a temporary placeholder
|
|
142
|
+
const div = document.createElement("div");
|
|
143
|
+
div.setAttribute("data-tmp-placeholder", "true");
|
|
144
|
+
return {
|
|
145
|
+
dom: div,
|
|
146
|
+
};
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
addNodeView() {
|
|
150
|
+
return ({ getPos }) => {
|
|
151
|
+
// Gets the BlockNote editor instance
|
|
152
|
+
const editor = this.options.editor;
|
|
153
|
+
// Gets the block
|
|
154
|
+
const block = getBlockFromPos(
|
|
155
|
+
getPos,
|
|
156
|
+
editor,
|
|
157
|
+
this.editor,
|
|
158
|
+
blockConfig.type
|
|
159
|
+
);
|
|
160
|
+
// Gets the custom HTML attributes for `blockContent` nodes
|
|
161
|
+
const blockContentDOMAttributes =
|
|
162
|
+
this.options.domAttributes?.blockContent || {};
|
|
163
|
+
|
|
164
|
+
const output = blockImplementation.render(block as any, editor);
|
|
165
|
+
|
|
166
|
+
return wrapInBlockStructure(
|
|
167
|
+
output,
|
|
168
|
+
block.type,
|
|
169
|
+
block.props,
|
|
170
|
+
blockConfig.propSchema,
|
|
171
|
+
blockContentDOMAttributes
|
|
172
|
+
);
|
|
173
|
+
};
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
if (node.name !== blockConfig.type) {
|
|
178
|
+
throw new Error(
|
|
179
|
+
"Node name does not match block type. This is a bug in BlockNote."
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return createInternalBlockSpec(blockConfig, {
|
|
184
|
+
node,
|
|
185
|
+
toInternalHTML: (block, editor) => {
|
|
186
|
+
const blockContentDOMAttributes =
|
|
187
|
+
node.options.domAttributes?.blockContent || {};
|
|
188
|
+
|
|
189
|
+
const output = blockImplementation.render(block as any, editor as any);
|
|
190
|
+
|
|
191
|
+
return wrapInBlockStructure(
|
|
192
|
+
output,
|
|
193
|
+
block.type,
|
|
194
|
+
block.props,
|
|
195
|
+
blockConfig.propSchema,
|
|
196
|
+
blockContentDOMAttributes
|
|
197
|
+
);
|
|
198
|
+
},
|
|
199
|
+
toExternalHTML: (block, editor) => {
|
|
200
|
+
const blockContentDOMAttributes =
|
|
201
|
+
node.options.domAttributes?.blockContent || {};
|
|
202
|
+
|
|
203
|
+
let output = blockImplementation.toExternalHTML?.(
|
|
204
|
+
block as any,
|
|
205
|
+
editor as any
|
|
206
|
+
);
|
|
207
|
+
if (output === undefined) {
|
|
208
|
+
output = blockImplementation.render(block as any, editor as any);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return wrapInBlockStructure(
|
|
212
|
+
output,
|
|
213
|
+
block.type,
|
|
214
|
+
block.props,
|
|
215
|
+
blockConfig.propSchema,
|
|
216
|
+
blockContentDOMAttributes
|
|
217
|
+
);
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Attribute,
|
|
3
|
+
Attributes,
|
|
4
|
+
Editor,
|
|
5
|
+
Extension,
|
|
6
|
+
Node,
|
|
7
|
+
NodeConfig,
|
|
8
|
+
} from "@tiptap/core";
|
|
9
|
+
import { defaultBlockToHTML } from "../../blocks/defaultBlockHelpers";
|
|
10
|
+
import { inheritedProps } from "../../blocks/defaultProps";
|
|
11
|
+
import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
|
|
12
|
+
import { mergeCSSClasses } from "../../util/browser";
|
|
13
|
+
import { camelToDataKebab } from "../../util/string";
|
|
14
|
+
import { InlineContentSchema } from "../inlineContent/types";
|
|
15
|
+
import { PropSchema, Props } from "../propTypes";
|
|
16
|
+
import { StyleSchema } from "../styles/types";
|
|
17
|
+
import {
|
|
18
|
+
BlockConfig,
|
|
19
|
+
BlockSchemaFromSpecs,
|
|
20
|
+
BlockSchemaWithBlock,
|
|
21
|
+
BlockSpec,
|
|
22
|
+
BlockSpecs,
|
|
23
|
+
SpecificBlock,
|
|
24
|
+
TiptapBlockImplementation,
|
|
25
|
+
} from "./types";
|
|
26
|
+
|
|
27
|
+
// Function that uses the 'propSchema' of a blockConfig to create a TipTap
|
|
28
|
+
// node's `addAttributes` property.
|
|
29
|
+
// TODO: extract function
|
|
30
|
+
export function propsToAttributes(propSchema: PropSchema): Attributes {
|
|
31
|
+
const tiptapAttributes: Record<string, Attribute> = {};
|
|
32
|
+
|
|
33
|
+
Object.entries(propSchema)
|
|
34
|
+
.filter(([name, _spec]) => !inheritedProps.includes(name))
|
|
35
|
+
.forEach(([name, spec]) => {
|
|
36
|
+
tiptapAttributes[name] = {
|
|
37
|
+
default: spec.default,
|
|
38
|
+
keepOnSplit: true,
|
|
39
|
+
// Props are displayed in kebab-case as HTML attributes. If a prop's
|
|
40
|
+
// value is the same as its default, we don't display an HTML
|
|
41
|
+
// attribute for it.
|
|
42
|
+
parseHTML: (element) => {
|
|
43
|
+
const value = element.getAttribute(camelToDataKebab(name));
|
|
44
|
+
|
|
45
|
+
if (value === null) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (typeof spec.default === "boolean") {
|
|
50
|
+
if (value === "true") {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (value === "false") {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (typeof spec.default === "number") {
|
|
62
|
+
const asNumber = parseFloat(value);
|
|
63
|
+
const isNumeric =
|
|
64
|
+
!Number.isNaN(asNumber) && Number.isFinite(asNumber);
|
|
65
|
+
|
|
66
|
+
if (isNumeric) {
|
|
67
|
+
return asNumber;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return value;
|
|
74
|
+
},
|
|
75
|
+
renderHTML: (attributes) =>
|
|
76
|
+
attributes[name] !== spec.default
|
|
77
|
+
? {
|
|
78
|
+
[camelToDataKebab(name)]: attributes[name],
|
|
79
|
+
}
|
|
80
|
+
: {},
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
return tiptapAttributes;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Used to figure out which block should be rendered. This block is then used to
|
|
88
|
+
// create the node view.
|
|
89
|
+
export function getBlockFromPos<
|
|
90
|
+
BType extends string,
|
|
91
|
+
Config extends BlockConfig,
|
|
92
|
+
BSchema extends BlockSchemaWithBlock<BType, Config>,
|
|
93
|
+
I extends InlineContentSchema,
|
|
94
|
+
S extends StyleSchema
|
|
95
|
+
>(
|
|
96
|
+
getPos: (() => number) | boolean,
|
|
97
|
+
editor: BlockNoteEditor<BSchema, I, S>,
|
|
98
|
+
tipTapEditor: Editor,
|
|
99
|
+
type: BType
|
|
100
|
+
) {
|
|
101
|
+
// Gets position of the node
|
|
102
|
+
if (typeof getPos === "boolean") {
|
|
103
|
+
throw new Error(
|
|
104
|
+
"Cannot find node position as getPos is a boolean, not a function."
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
const pos = getPos();
|
|
108
|
+
// Gets parent blockContainer node
|
|
109
|
+
const blockContainer = tipTapEditor.state.doc.resolve(pos!).node();
|
|
110
|
+
// Gets block identifier
|
|
111
|
+
const blockIdentifier = blockContainer.attrs.id;
|
|
112
|
+
// Gets the block
|
|
113
|
+
const block = editor.getBlock(blockIdentifier)! as SpecificBlock<
|
|
114
|
+
BSchema,
|
|
115
|
+
BType,
|
|
116
|
+
I,
|
|
117
|
+
S
|
|
118
|
+
>;
|
|
119
|
+
if (block.type !== type) {
|
|
120
|
+
throw new Error("Block type does not match");
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return block;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Function that wraps the `dom` element returned from 'blockConfig.render' in a
|
|
127
|
+
// `blockContent` div, which contains the block type and props as HTML
|
|
128
|
+
// attributes. If `blockConfig.render` also returns a `contentDOM`, it also adds
|
|
129
|
+
// an `inlineContent` class to it.
|
|
130
|
+
export function wrapInBlockStructure<
|
|
131
|
+
BType extends string,
|
|
132
|
+
PSchema extends PropSchema
|
|
133
|
+
>(
|
|
134
|
+
element: {
|
|
135
|
+
dom: HTMLElement;
|
|
136
|
+
contentDOM?: HTMLElement;
|
|
137
|
+
destroy?: () => void;
|
|
138
|
+
},
|
|
139
|
+
blockType: BType,
|
|
140
|
+
blockProps: Props<PSchema>,
|
|
141
|
+
propSchema: PSchema,
|
|
142
|
+
domAttributes?: Record<string, string>
|
|
143
|
+
): {
|
|
144
|
+
dom: HTMLElement;
|
|
145
|
+
contentDOM?: HTMLElement;
|
|
146
|
+
destroy?: () => void;
|
|
147
|
+
} {
|
|
148
|
+
// Creates `blockContent` element
|
|
149
|
+
const blockContent = document.createElement("div");
|
|
150
|
+
|
|
151
|
+
// Adds custom HTML attributes
|
|
152
|
+
if (domAttributes !== undefined) {
|
|
153
|
+
for (const [attr, value] of Object.entries(domAttributes)) {
|
|
154
|
+
if (attr !== "class") {
|
|
155
|
+
blockContent.setAttribute(attr, value);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// Sets blockContent class
|
|
160
|
+
blockContent.className = mergeCSSClasses(
|
|
161
|
+
"bn-block-content",
|
|
162
|
+
domAttributes?.class || ""
|
|
163
|
+
);
|
|
164
|
+
// Sets content type attribute
|
|
165
|
+
blockContent.setAttribute("data-content-type", blockType);
|
|
166
|
+
// Adds props as HTML attributes in kebab-case with "data-" prefix. Skips props
|
|
167
|
+
// which are already added as HTML attributes to the parent `blockContent`
|
|
168
|
+
// element (inheritedProps) and props set to their default values.
|
|
169
|
+
for (const [prop, value] of Object.entries(blockProps)) {
|
|
170
|
+
if (!inheritedProps.includes(prop) && value !== propSchema[prop].default) {
|
|
171
|
+
blockContent.setAttribute(camelToDataKebab(prop), value);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
blockContent.appendChild(element.dom);
|
|
176
|
+
|
|
177
|
+
if (element.contentDOM !== undefined) {
|
|
178
|
+
element.contentDOM.className = mergeCSSClasses(
|
|
179
|
+
"bn-inline-content",
|
|
180
|
+
element.contentDOM.className
|
|
181
|
+
);
|
|
182
|
+
element.contentDOM.setAttribute("data-editable", "");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
...element,
|
|
187
|
+
dom: blockContent,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Helper type to keep track of the `name` and `content` properties after calling Node.create.
|
|
192
|
+
type StronglyTypedTipTapNode<
|
|
193
|
+
Name extends string,
|
|
194
|
+
Content extends "inline*" | "tableRow+" | ""
|
|
195
|
+
> = Node & { name: Name; config: { content: Content } };
|
|
196
|
+
|
|
197
|
+
export function createStronglyTypedTiptapNode<
|
|
198
|
+
Name extends string,
|
|
199
|
+
Content extends "inline*" | "tableRow+" | ""
|
|
200
|
+
>(config: NodeConfig & { name: Name; content: Content }) {
|
|
201
|
+
return Node.create(config) as StronglyTypedTipTapNode<Name, Content>; // force re-typing (should be safe as it's type-checked from the config)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// This helper function helps to instantiate a blockspec with a
|
|
205
|
+
// config and implementation that conform to the type of Config
|
|
206
|
+
export function createInternalBlockSpec<T extends BlockConfig>(
|
|
207
|
+
config: T,
|
|
208
|
+
implementation: TiptapBlockImplementation<
|
|
209
|
+
T,
|
|
210
|
+
any,
|
|
211
|
+
InlineContentSchema,
|
|
212
|
+
StyleSchema
|
|
213
|
+
>
|
|
214
|
+
) {
|
|
215
|
+
return {
|
|
216
|
+
config,
|
|
217
|
+
implementation,
|
|
218
|
+
} satisfies BlockSpec<T, any, InlineContentSchema, StyleSchema>;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export function createBlockSpecFromStronglyTypedTiptapNode<
|
|
222
|
+
T extends Node,
|
|
223
|
+
P extends PropSchema
|
|
224
|
+
>(node: T, propSchema: P, requiredExtensions?: Array<Extension | Node>) {
|
|
225
|
+
return createInternalBlockSpec(
|
|
226
|
+
{
|
|
227
|
+
type: node.name as T["name"],
|
|
228
|
+
content: (node.config.content === "inline*"
|
|
229
|
+
? "inline"
|
|
230
|
+
: node.config.content === "tableRow+"
|
|
231
|
+
? "table"
|
|
232
|
+
: "none") as T["config"]["content"] extends "inline*"
|
|
233
|
+
? "inline"
|
|
234
|
+
: T["config"]["content"] extends "tableRow+"
|
|
235
|
+
? "table"
|
|
236
|
+
: "none",
|
|
237
|
+
propSchema,
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
node,
|
|
241
|
+
requiredExtensions,
|
|
242
|
+
toInternalHTML: defaultBlockToHTML,
|
|
243
|
+
toExternalHTML: defaultBlockToHTML,
|
|
244
|
+
// parse: () => undefined, // parse rules are in node already
|
|
245
|
+
}
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export function getBlockSchemaFromSpecs<T extends BlockSpecs>(specs: T) {
|
|
250
|
+
return Object.fromEntries(
|
|
251
|
+
Object.entries(specs).map(([key, value]) => [key, value.config])
|
|
252
|
+
) as BlockSchemaFromSpecs<T>;
|
|
253
|
+
}
|