@blocknote/core 0.16.0 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/dist/blocknote.js +3292 -2755
  2. package/dist/blocknote.js.map +1 -1
  3. package/dist/blocknote.umd.cjs +6 -6
  4. package/dist/blocknote.umd.cjs.map +1 -1
  5. package/dist/webpack-stats.json +1 -1
  6. package/package.json +5 -2
  7. package/src/api/blockManipulation/commands/insertBlocks/__snapshots__/insertBlocks.test.ts.snap +3087 -0
  8. package/src/api/blockManipulation/commands/insertBlocks/insertBlocks.test.ts +132 -0
  9. package/src/api/blockManipulation/commands/insertBlocks/insertBlocks.ts +71 -0
  10. package/src/api/blockManipulation/commands/mergeBlocks/__snapshots__/mergeBlocks.test.ts.snap +2276 -0
  11. package/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.test.ts +131 -0
  12. package/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.ts +103 -0
  13. package/src/api/blockManipulation/commands/moveBlock/__snapshots__/moveBlock.test.ts.snap +3767 -0
  14. package/src/api/blockManipulation/commands/moveBlock/moveBlock.test.ts +192 -0
  15. package/src/api/blockManipulation/commands/moveBlock/moveBlock.ts +178 -0
  16. package/src/api/blockManipulation/commands/removeBlocks/__snapshots__/removeBlocks.test.ts.snap +1136 -0
  17. package/src/api/blockManipulation/commands/removeBlocks/removeBlocks.test.ts +34 -0
  18. package/src/api/blockManipulation/commands/removeBlocks/removeBlocks.ts +100 -0
  19. package/src/api/blockManipulation/commands/replaceBlocks/__snapshots__/replaceBlocks.test.ts.snap +4931 -0
  20. package/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.test.ts +222 -0
  21. package/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts +70 -0
  22. package/src/api/blockManipulation/commands/splitBlock/__snapshots__/splitBlock.test.ts.snap +2924 -0
  23. package/src/api/blockManipulation/commands/splitBlock/splitBlock.test.ts +136 -0
  24. package/src/api/blockManipulation/commands/splitBlock/splitBlock.ts +48 -0
  25. package/src/api/blockManipulation/commands/updateBlock/__snapshots__/updateBlock.test.ts.snap +8376 -0
  26. package/src/api/blockManipulation/commands/updateBlock/updateBlock.test.ts +300 -0
  27. package/src/api/blockManipulation/commands/updateBlock/updateBlock.ts +199 -0
  28. package/src/api/blockManipulation/insertContentAt.ts +96 -0
  29. package/src/api/blockManipulation/selections/textCursorPosition/__snapshots__/textCursorPosition.test.ts.snap +316 -0
  30. package/src/api/blockManipulation/selections/textCursorPosition/textCursorPosition.test.ts +53 -0
  31. package/src/api/blockManipulation/selections/textCursorPosition/textCursorPosition.ts +130 -0
  32. package/src/api/blockManipulation/setupTestEnv.ts +179 -0
  33. package/src/api/clipboard/__snapshots__/tableAllCells.html +1 -1
  34. package/src/api/clipboard/clipboard.test.ts +5 -6
  35. package/src/api/clipboard/fromClipboard/fileDropExtension.ts +8 -4
  36. package/src/api/clipboard/fromClipboard/handleFileInsertion.ts +11 -6
  37. package/src/api/clipboard/fromClipboard/pasteExtension.ts +8 -4
  38. package/src/api/clipboard/toClipboard/copyExtension.ts +113 -61
  39. package/src/api/exporters/html/__snapshots__/complex/misc/external.html +1 -1
  40. package/src/api/exporters/html/__snapshots__/lists/basic/external.html +1 -1
  41. package/src/api/exporters/html/__snapshots__/lists/nested/external.html +1 -1
  42. package/src/api/exporters/html/externalHTMLExporter.ts +42 -94
  43. package/src/api/exporters/html/htmlConversion.test.ts +19 -13
  44. package/src/api/exporters/html/internalHTMLSerializer.ts +21 -72
  45. package/src/api/exporters/html/util/serializeBlocksExternalHTML.ts +263 -0
  46. package/src/api/exporters/html/util/serializeBlocksInternalHTML.ts +158 -0
  47. package/src/api/exporters/markdown/markdownExporter.test.ts +10 -10
  48. package/src/api/exporters/markdown/markdownExporter.ts +11 -7
  49. package/src/api/exporters/markdown/util/addSpacesToCheckboxesRehypePlugin.ts +2 -2
  50. package/src/api/getBlockInfoFromPos.ts +172 -90
  51. package/src/api/nodeConversions/blockToNode.ts +257 -0
  52. package/src/api/nodeConversions/fragmentToBlocks.ts +60 -0
  53. package/src/api/nodeConversions/nodeConversions.test.ts +9 -8
  54. package/src/api/nodeConversions/{nodeConversions.ts → nodeToBlock.ts} +20 -262
  55. package/src/api/parsers/html/parseHTML.test.ts +2 -2
  56. package/src/api/parsers/html/parseHTML.ts +8 -4
  57. package/src/api/parsers/html/util/nestedLists.test.ts +2 -2
  58. package/src/api/parsers/markdown/parseMarkdown.test.ts +2 -2
  59. package/src/api/parsers/markdown/parseMarkdown.ts +8 -4
  60. package/src/api/testUtil/cases/customBlocks.ts +11 -11
  61. package/src/api/testUtil/cases/customInlineContent.ts +6 -6
  62. package/src/api/testUtil/cases/customStyles.ts +6 -6
  63. package/src/api/testUtil/cases/defaultSchema.ts +4 -4
  64. package/src/api/testUtil/index.ts +6 -6
  65. package/src/api/testUtil/partialBlockTestUtil.ts +5 -5
  66. package/src/blocks/AudioBlockContent/AudioBlockContent.ts +5 -5
  67. package/src/blocks/FileBlockContent/FileBlockContent.ts +4 -4
  68. package/src/blocks/FileBlockContent/fileBlockHelpers.ts +2 -2
  69. package/src/blocks/HeadingBlockContent/HeadingBlockContent.ts +61 -39
  70. package/src/blocks/ImageBlockContent/ImageBlockContent.ts +5 -5
  71. package/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +30 -18
  72. package/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts +67 -33
  73. package/src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts +23 -19
  74. package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts +22 -24
  75. package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +31 -19
  76. package/src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts +16 -11
  77. package/src/blocks/TableBlockContent/TableBlockContent.ts +4 -4
  78. package/src/blocks/VideoBlockContent/VideoBlockContent.ts +5 -5
  79. package/src/blocks/defaultBlockHelpers.ts +4 -4
  80. package/src/blocks/defaultBlockTypeGuards.ts +5 -5
  81. package/src/blocks/defaultBlocks.ts +13 -13
  82. package/src/blocks/defaultProps.ts +1 -1
  83. package/src/editor/BlockNoteEditor.test.ts +14 -7
  84. package/src/editor/BlockNoteEditor.ts +82 -149
  85. package/src/editor/BlockNoteExtensions.ts +15 -11
  86. package/src/editor/BlockNoteSchema.ts +7 -7
  87. package/src/editor/BlockNoteTipTapEditor.ts +5 -3
  88. package/src/editor/cursorPositionTypes.ts +7 -2
  89. package/src/editor/selectionTypes.ts +6 -2
  90. package/src/extensions/BackgroundColor/BackgroundColorExtension.ts +1 -1
  91. package/src/extensions/BackgroundColor/BackgroundColorMark.ts +1 -1
  92. package/src/extensions/FilePanel/FilePanelPlugin.ts +4 -4
  93. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +8 -4
  94. package/src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts +334 -0
  95. package/src/extensions/LinkToolbar/LinkToolbarPlugin.ts +9 -4
  96. package/src/extensions/{NonEditableBlocks/NonEditableBlockPlugin.ts → NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.ts} +2 -2
  97. package/src/extensions/Placeholder/PlaceholderPlugin.ts +1 -1
  98. package/src/extensions/SideMenu/SideMenuPlugin.ts +72 -401
  99. package/src/extensions/SideMenu/dragging.ts +251 -0
  100. package/src/extensions/SuggestionMenu/DefaultSuggestionItem.ts +1 -1
  101. package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +8 -4
  102. package/src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.ts +8 -4
  103. package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +19 -15
  104. package/src/extensions/TableHandles/TableHandlesPlugin.ts +11 -7
  105. package/src/extensions/TextColor/TextColorExtension.ts +1 -1
  106. package/src/extensions/TextColor/TextColorMark.ts +1 -1
  107. package/src/i18n/dictionary.ts +1 -1
  108. package/src/i18n/locales/ar.ts +1 -1
  109. package/src/i18n/locales/fr.ts +1 -1
  110. package/src/i18n/locales/hr.ts +308 -0
  111. package/src/i18n/locales/index.ts +15 -14
  112. package/src/i18n/locales/is.ts +1 -1
  113. package/src/i18n/locales/ja.ts +1 -1
  114. package/src/i18n/locales/ko.ts +1 -1
  115. package/src/i18n/locales/nl.ts +1 -1
  116. package/src/i18n/locales/pl.ts +1 -1
  117. package/src/i18n/locales/pt.ts +1 -1
  118. package/src/i18n/locales/ru.ts +1 -1
  119. package/src/i18n/locales/vi.ts +1 -1
  120. package/src/i18n/locales/zh.ts +1 -1
  121. package/src/index.ts +45 -44
  122. package/src/pm-nodes/BlockContainer.ts +3 -647
  123. package/src/pm-nodes/BlockGroup.ts +2 -2
  124. package/src/pm-nodes/index.ts +3 -3
  125. package/src/schema/blocks/createSpec.ts +8 -7
  126. package/src/schema/blocks/internal.ts +9 -9
  127. package/src/schema/blocks/types.ts +4 -4
  128. package/src/schema/index.ts +10 -10
  129. package/src/schema/inlineContent/createSpec.ts +9 -10
  130. package/src/schema/inlineContent/internal.ts +3 -3
  131. package/src/schema/inlineContent/types.ts +2 -2
  132. package/src/schema/styles/createSpec.ts +4 -3
  133. package/src/schema/styles/internal.ts +1 -1
  134. package/types/src/api/blockManipulation/commands/insertBlocks/insertBlocks.d.ts +4 -0
  135. package/types/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.d.ts +7 -0
  136. package/types/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.test.d.ts +1 -0
  137. package/types/src/api/blockManipulation/commands/moveBlock/moveBlock.d.ts +5 -0
  138. package/types/src/api/blockManipulation/commands/moveBlock/moveBlock.test.d.ts +1 -0
  139. package/types/src/api/blockManipulation/commands/removeBlocks/removeBlocks.d.ts +7 -0
  140. package/types/src/api/blockManipulation/commands/removeBlocks/removeBlocks.test.d.ts +1 -0
  141. package/types/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.d.ts +7 -0
  142. package/types/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.test.d.ts +1 -0
  143. package/types/src/api/blockManipulation/commands/splitBlock/splitBlock.d.ts +5 -0
  144. package/types/src/api/blockManipulation/commands/splitBlock/splitBlock.test.d.ts +1 -0
  145. package/types/src/api/blockManipulation/commands/updateBlock/updateBlock.d.ts +11 -0
  146. package/types/src/api/blockManipulation/commands/updateBlock/updateBlock.test.d.ts +1 -0
  147. package/types/src/api/blockManipulation/insertContentAt.d.ts +6 -0
  148. package/types/src/api/blockManipulation/selections/textCursorPosition/textCursorPosition.d.ts +5 -0
  149. package/types/src/api/blockManipulation/selections/textCursorPosition/textCursorPosition.test.d.ts +1 -0
  150. package/types/src/api/blockManipulation/setupTestEnv.d.ts +492 -0
  151. package/types/src/api/clipboard/fromClipboard/fileDropExtension.d.ts +3 -3
  152. package/types/src/api/clipboard/fromClipboard/handleFileInsertion.d.ts +1 -1
  153. package/types/src/api/clipboard/fromClipboard/pasteExtension.d.ts +2 -2
  154. package/types/src/api/clipboard/toClipboard/copyExtension.d.ts +5 -5
  155. package/types/src/api/exporters/html/externalHTMLExporter.d.ts +7 -9
  156. package/types/src/api/exporters/html/internalHTMLSerializer.d.ts +6 -10
  157. package/types/src/api/exporters/html/util/serializeBlocksExternalHTML.d.ts +10 -0
  158. package/types/src/api/exporters/html/util/serializeBlocksInternalHTML.d.ts +11 -0
  159. package/types/src/api/exporters/markdown/markdownExporter.d.ts +3 -3
  160. package/types/src/api/getBlockInfoFromPos.d.ts +63 -20
  161. package/types/src/api/nodeConversions/blockToNode.d.ts +15 -0
  162. package/types/src/api/nodeConversions/fragmentToBlocks.d.ts +7 -0
  163. package/types/src/api/nodeConversions/nodeToBlock.d.ts +16 -0
  164. package/types/src/api/parsers/html/parseHTML.d.ts +2 -2
  165. package/types/src/api/parsers/markdown/parseMarkdown.d.ts +2 -2
  166. package/types/src/api/testUtil/cases/customBlocks.d.ts +39 -39
  167. package/types/src/api/testUtil/cases/customInlineContent.d.ts +35 -35
  168. package/types/src/api/testUtil/cases/customStyles.d.ts +35 -35
  169. package/types/src/api/testUtil/cases/defaultSchema.d.ts +2 -2
  170. package/types/src/api/testUtil/index.d.ts +6 -6
  171. package/types/src/api/testUtil/partialBlockTestUtil.d.ts +4 -4
  172. package/types/src/blocks/AudioBlockContent/AudioBlockContent.d.ts +4 -4
  173. package/types/src/blocks/FileBlockContent/FileBlockContent.d.ts +4 -4
  174. package/types/src/blocks/FileBlockContent/fileBlockHelpers.d.ts +2 -2
  175. package/types/src/blocks/HeadingBlockContent/HeadingBlockContent.d.ts +2 -2
  176. package/types/src/blocks/ImageBlockContent/ImageBlockContent.d.ts +4 -4
  177. package/types/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.d.ts +2 -2
  178. package/types/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.d.ts +2 -2
  179. package/types/src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.d.ts +2 -2
  180. package/types/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.d.ts +2 -2
  181. package/types/src/blocks/ParagraphBlockContent/ParagraphBlockContent.d.ts +2 -2
  182. package/types/src/blocks/TableBlockContent/TableBlockContent.d.ts +2 -2
  183. package/types/src/blocks/VideoBlockContent/VideoBlockContent.d.ts +4 -4
  184. package/types/src/blocks/defaultBlockHelpers.d.ts +3 -3
  185. package/types/src/blocks/defaultBlockTypeGuards.d.ts +4 -4
  186. package/types/src/blocks/defaultBlocks.d.ts +38 -38
  187. package/types/src/blocks/defaultProps.d.ts +1 -1
  188. package/types/src/editor/BlockNoteEditor.d.ts +28 -16
  189. package/types/src/editor/BlockNoteExtensions.d.ts +3 -3
  190. package/types/src/editor/BlockNoteSchema.d.ts +4 -4
  191. package/types/src/editor/BlockNoteTipTapEditor.d.ts +2 -2
  192. package/types/src/editor/cursorPositionTypes.d.ts +3 -2
  193. package/types/src/editor/selectionTypes.d.ts +2 -2
  194. package/types/src/extensions/BackgroundColor/BackgroundColorMark.d.ts +1 -1
  195. package/types/src/extensions/FilePanel/FilePanelPlugin.d.ts +4 -4
  196. package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +4 -4
  197. package/types/src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.d.ts +5 -0
  198. package/types/src/extensions/LinkToolbar/LinkToolbarPlugin.d.ts +4 -4
  199. package/types/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.d.ts +2 -0
  200. package/types/src/extensions/Placeholder/PlaceholderPlugin.d.ts +1 -1
  201. package/types/src/extensions/SideMenu/SideMenuPlugin.d.ts +12 -28
  202. package/types/src/extensions/SideMenu/dragging.d.ts +17 -0
  203. package/types/src/extensions/SuggestionMenu/DefaultSuggestionItem.d.ts +1 -1
  204. package/types/src/extensions/SuggestionMenu/SuggestionPlugin.d.ts +4 -4
  205. package/types/src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.d.ts +3 -3
  206. package/types/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.d.ts +4 -4
  207. package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +4 -4
  208. package/types/src/extensions/TextColor/TextColorMark.d.ts +1 -1
  209. package/types/src/i18n/dictionary.d.ts +1 -1
  210. package/types/src/i18n/locales/ar.d.ts +1 -1
  211. package/types/src/i18n/locales/fr.d.ts +1 -1
  212. package/types/src/i18n/locales/hr.d.ts +239 -0
  213. package/types/src/i18n/locales/index.d.ts +15 -14
  214. package/types/src/i18n/locales/is.d.ts +1 -1
  215. package/types/src/i18n/locales/ja.d.ts +1 -1
  216. package/types/src/i18n/locales/ko.d.ts +1 -1
  217. package/types/src/i18n/locales/nl.d.ts +1 -1
  218. package/types/src/i18n/locales/pl.d.ts +1 -1
  219. package/types/src/i18n/locales/pt.d.ts +1 -1
  220. package/types/src/i18n/locales/ru.d.ts +1 -1
  221. package/types/src/i18n/locales/vi.d.ts +1 -1
  222. package/types/src/i18n/locales/zh.d.ts +1 -1
  223. package/types/src/index.d.ts +45 -44
  224. package/types/src/pm-nodes/BlockContainer.d.ts +2 -16
  225. package/types/src/pm-nodes/BlockGroup.d.ts +1 -1
  226. package/types/src/pm-nodes/index.d.ts +3 -3
  227. package/types/src/schema/blocks/createSpec.d.ts +5 -5
  228. package/types/src/schema/blocks/internal.d.ts +5 -5
  229. package/types/src/schema/blocks/types.d.ts +4 -4
  230. package/types/src/schema/index.d.ts +10 -10
  231. package/types/src/schema/inlineContent/createSpec.d.ts +3 -3
  232. package/types/src/schema/inlineContent/internal.d.ts +2 -2
  233. package/types/src/schema/inlineContent/types.d.ts +2 -2
  234. package/types/src/schema/styles/createSpec.d.ts +1 -1
  235. package/types/src/schema/styles/internal.d.ts +1 -1
  236. package/src/api/blockManipulation/__snapshots__/blockManipulation.test.ts.snap +0 -714
  237. package/src/api/blockManipulation/blockManipulation.test.ts +0 -292
  238. package/src/api/blockManipulation/blockManipulation.ts +0 -350
  239. package/src/api/exporters/html/util/sharedHTMLConversion.ts +0 -130
  240. package/src/api/exporters/html/util/simplifyBlocksRehypePlugin.ts +0 -218
  241. package/src/api/getCurrentBlockContentType.ts +0 -14
  242. package/types/src/api/blockManipulation/blockManipulation.d.ts +0 -14
  243. package/types/src/api/exporters/html/util/sharedHTMLConversion.d.ts +0 -9
  244. package/types/src/api/exporters/html/util/simplifyBlocksRehypePlugin.d.ts +0 -16
  245. package/types/src/api/getCurrentBlockContentType.d.ts +0 -2
  246. package/types/src/api/nodeConversions/nodeConversions.d.ts +0 -24
  247. package/types/src/extensions/NonEditableBlocks/NonEditableBlockPlugin.d.ts +0 -2
  248. /package/types/src/api/blockManipulation/{blockManipulation.test.d.ts → commands/insertBlocks/insertBlocks.test.d.ts} +0 -0
@@ -1,292 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, it } from "vitest";
2
- import {
3
- Block,
4
- defaultBlockSpecs,
5
- DefaultInlineContentSchema,
6
- DefaultStyleSchema,
7
- PartialBlock,
8
- } from "../../blocks/defaultBlocks";
9
- import { BlockNoteEditor } from "../../editor/BlockNoteEditor";
10
- import { createBlockSpec } from "../../schema";
11
- import { BlockNoteSchema } from "../../editor/BlockNoteSchema";
12
-
13
- const CustomBlock = createBlockSpec(
14
- {
15
- type: "customBlock",
16
- propSchema: {},
17
- content: "inline",
18
- } as const,
19
- {
20
- render: () => {
21
- const dom = document.createElement("div");
22
- dom.className = "custom-block";
23
-
24
- return {
25
- dom: dom,
26
- contentDOM: dom,
27
- };
28
- },
29
- }
30
- );
31
-
32
- const schema = BlockNoteSchema.create({
33
- blockSpecs: {
34
- ...defaultBlockSpecs,
35
- customBlock: CustomBlock,
36
- },
37
- });
38
-
39
- let editor: BlockNoteEditor<typeof schema.blockSchema>;
40
- const div = document.createElement("div");
41
-
42
- let singleBlock: PartialBlock<
43
- typeof schema.blockSchema,
44
- DefaultInlineContentSchema,
45
- DefaultStyleSchema
46
- >;
47
-
48
- let multipleBlocks: PartialBlock<
49
- typeof schema.blockSchema,
50
- DefaultInlineContentSchema,
51
- DefaultStyleSchema
52
- >[];
53
-
54
- let blocksWithLineBreaks: PartialBlock<
55
- typeof schema.blockSchema,
56
- DefaultInlineContentSchema,
57
- DefaultStyleSchema
58
- >[];
59
-
60
- let insert: (
61
- placement: "before" | "nested" | "after"
62
- ) => Block<
63
- typeof schema.blockSchema,
64
- DefaultInlineContentSchema,
65
- DefaultStyleSchema
66
- >[];
67
-
68
- beforeEach(() => {
69
- editor = BlockNoteEditor.create<typeof schema.blockSchema>({
70
- schema: schema,
71
- });
72
-
73
- editor.mount(div);
74
-
75
- singleBlock = {
76
- type: "paragraph",
77
- content: "Paragraph",
78
- };
79
-
80
- multipleBlocks = [
81
- {
82
- type: "heading",
83
- props: {
84
- level: 1,
85
- },
86
- content: "Heading 1",
87
- children: [
88
- {
89
- type: "heading",
90
- props: {
91
- level: 1,
92
- },
93
- content: "Nested Heading 1",
94
- },
95
- ],
96
- },
97
- {
98
- type: "heading",
99
- props: {
100
- level: 2,
101
- },
102
- content: "Heading 2",
103
- children: [
104
- {
105
- type: "heading",
106
- props: {
107
- level: 2,
108
- },
109
- content: "Nested Heading 2",
110
- },
111
- ],
112
- },
113
- ];
114
-
115
- blocksWithLineBreaks = [
116
- {
117
- type: "paragraph",
118
- content: "Line1\nLine2",
119
- },
120
- {
121
- type: "customBlock",
122
- content: "Line1\nLine2",
123
- },
124
- ];
125
-
126
- insert = (placement) => {
127
- const existingBlock = editor.document[0];
128
- editor.insertBlocks(multipleBlocks, existingBlock, placement);
129
-
130
- return editor.document;
131
- };
132
- });
133
-
134
- afterEach(() => {
135
- editor.mount(undefined);
136
- editor._tiptapEditor.destroy();
137
- editor = undefined as any;
138
- });
139
-
140
- describe("Test strong typing", () => {
141
- it("checks that block types are inferred correctly", () => {
142
- try {
143
- editor.updateBlock(
144
- { id: "sdf" },
145
- {
146
- // @ts-expect-error invalid type
147
- type: "non-existing",
148
- }
149
- );
150
- } catch (e) {
151
- // id doesn't exists, which is fine, this is a compile-time check
152
- }
153
- });
154
-
155
- it("checks that block props are inferred correctly", () => {
156
- try {
157
- editor.updateBlock(
158
- { id: "sdf" },
159
- {
160
- type: "paragraph",
161
- props: {
162
- // @ts-expect-error invalid type
163
- level: 1,
164
- },
165
- }
166
- );
167
- } catch (e) {
168
- // id doesn't exists, which is fine, this is a compile-time check
169
- }
170
- try {
171
- editor.updateBlock(
172
- { id: "sdf" },
173
- {
174
- type: "heading",
175
- props: {
176
- level: 1,
177
- },
178
- }
179
- );
180
- } catch (e) {
181
- // id doesn't exists, which is fine, this is a compile-time check
182
- }
183
- });
184
- });
185
-
186
- describe("Inserting Blocks with Different Placements", () => {
187
- it("Insert before existing block", () => {
188
- const output = insert("before");
189
-
190
- expect(output).toMatchSnapshot();
191
- });
192
-
193
- it("Insert nested inside existing block", () => {
194
- const output = insert("nested");
195
-
196
- expect(output).toMatchSnapshot();
197
- });
198
-
199
- it("Insert after existing block", () => {
200
- const output = insert("after");
201
-
202
- expect(output).toMatchSnapshot();
203
- });
204
- });
205
-
206
- describe("Insert, Update, & Delete Blocks", () => {
207
- it("Insert, update, & delete single block", () => {
208
- const existingBlock = editor.document[0];
209
- editor.insertBlocks([singleBlock], existingBlock);
210
-
211
- expect(editor.document).toMatchSnapshot();
212
-
213
- const newBlock = editor.document[0];
214
- editor.updateBlock(newBlock, {
215
- type: "heading",
216
- props: {
217
- textAlignment: "right",
218
- level: 3,
219
- },
220
- content: [
221
- {
222
- type: "text",
223
- text: "Heading ",
224
- styles: {
225
- textColor: "red",
226
- },
227
- },
228
- {
229
- type: "text",
230
- text: "3",
231
- styles: {
232
- backgroundColor: "red",
233
- },
234
- },
235
- ],
236
- children: [singleBlock],
237
- });
238
-
239
- expect(editor.document).toMatchSnapshot();
240
-
241
- const updatedBlock = editor.document[0];
242
- editor.removeBlocks([updatedBlock]);
243
-
244
- expect(editor.document).toMatchSnapshot();
245
- });
246
-
247
- it("Insert, update, & delete multiple blocks", () => {
248
- const existingBlock = editor.document[0];
249
- editor.insertBlocks(multipleBlocks, existingBlock);
250
-
251
- expect(editor.document).toMatchSnapshot();
252
-
253
- const newBlock = editor.document[0];
254
- editor.updateBlock(newBlock, {
255
- type: "paragraph",
256
- });
257
-
258
- expect(editor.document).toMatchSnapshot();
259
-
260
- const updatedBlocks = editor.document.slice(0, 2);
261
- editor.removeBlocks([updatedBlocks[0].children[0], updatedBlocks[1]]);
262
-
263
- expect(editor.document).toMatchSnapshot();
264
- });
265
- });
266
-
267
- describe("Update Line Breaks", () => {
268
- it("Update paragraph with line break", () => {
269
- const existingBlock = editor.document[0];
270
- editor.insertBlocks(blocksWithLineBreaks, existingBlock);
271
-
272
- const newBlock = editor.document[0];
273
- editor.updateBlock(newBlock, {
274
- type: "paragraph",
275
- content: "Updated Custom Block with \nline \nbreak",
276
- });
277
-
278
- expect(editor.document).toMatchSnapshot();
279
- });
280
- it("Update custom block with line break", () => {
281
- const existingBlock = editor.document[0];
282
- editor.insertBlocks(blocksWithLineBreaks, existingBlock);
283
-
284
- const newBlock = editor.document[1];
285
- editor.updateBlock(newBlock, {
286
- type: "customBlock",
287
- content: "Updated Custom Block with \nline \nbreak",
288
- });
289
-
290
- expect(editor.document).toMatchSnapshot();
291
- });
292
- });
@@ -1,350 +0,0 @@
1
- import { Node } from "prosemirror-model";
2
-
3
- import { selectionToInsertionEnd } from "@tiptap/core";
4
- import { Transaction } from "prosemirror-state";
5
- import { Block, PartialBlock } from "../../blocks/defaultBlocks";
6
- import type { BlockNoteEditor } from "../../editor/BlockNoteEditor";
7
- import {
8
- BlockIdentifier,
9
- BlockSchema,
10
- InlineContentSchema,
11
- StyleSchema,
12
- } from "../../schema";
13
- import { blockToNode, nodeToBlock } from "../nodeConversions/nodeConversions";
14
- import { getNodeById } from "../nodeUtil";
15
-
16
- export function insertBlocks<
17
- BSchema extends BlockSchema,
18
- I extends InlineContentSchema,
19
- S extends StyleSchema
20
- >(
21
- blocksToInsert: PartialBlock<BSchema, I, S>[],
22
- referenceBlock: BlockIdentifier,
23
- placement: "before" | "after" | "nested" = "before",
24
- editor: BlockNoteEditor<BSchema, I, S>
25
- ): Block<BSchema, I, S>[] {
26
- const id =
27
- typeof referenceBlock === "string" ? referenceBlock : referenceBlock.id;
28
-
29
- const nodesToInsert: Node[] = [];
30
- for (const blockSpec of blocksToInsert) {
31
- nodesToInsert.push(
32
- blockToNode(blockSpec, editor.pmSchema, editor.schema.styleSchema)
33
- );
34
- }
35
-
36
- const { node, posBeforeNode } = getNodeById(
37
- id,
38
- editor._tiptapEditor.state.doc
39
- );
40
-
41
- if (placement === "before") {
42
- editor.dispatch(
43
- editor._tiptapEditor.state.tr.insert(posBeforeNode, nodesToInsert)
44
- );
45
- }
46
-
47
- if (placement === "after") {
48
- editor.dispatch(
49
- editor._tiptapEditor.state.tr.insert(
50
- posBeforeNode + node.nodeSize,
51
- nodesToInsert
52
- )
53
- );
54
- }
55
-
56
- if (placement === "nested") {
57
- // Case if block doesn't already have children.
58
- if (node.childCount < 2) {
59
- const blockGroupNode = editor._tiptapEditor.state.schema.nodes[
60
- "blockGroup"
61
- ].create({}, nodesToInsert);
62
-
63
- editor.dispatch(
64
- editor._tiptapEditor.state.tr.insert(
65
- posBeforeNode + node.firstChild!.nodeSize + 1,
66
- blockGroupNode
67
- )
68
- );
69
- }
70
- }
71
-
72
- // Now that the `PartialBlock`s have been converted to nodes, we can
73
- // re-convert them into full `Block`s.
74
- const insertedBlocks: Block<BSchema, I, S>[] = [];
75
- for (const node of nodesToInsert) {
76
- insertedBlocks.push(
77
- nodeToBlock(
78
- node,
79
- editor.schema.blockSchema,
80
- editor.schema.inlineContentSchema,
81
- editor.schema.styleSchema,
82
- editor.blockCache
83
- )
84
- );
85
- }
86
-
87
- return insertedBlocks;
88
- }
89
-
90
- export function updateBlock<
91
- BSchema extends BlockSchema,
92
- I extends InlineContentSchema,
93
- S extends StyleSchema
94
- >(
95
- blockToUpdate: BlockIdentifier,
96
- update: PartialBlock<BSchema, I, S>,
97
- editor: BlockNoteEditor<BSchema, I, S>
98
- ): Block<BSchema, I, S> {
99
- const ttEditor = editor._tiptapEditor;
100
-
101
- const id =
102
- typeof blockToUpdate === "string" ? blockToUpdate : blockToUpdate.id;
103
- const { posBeforeNode } = getNodeById(id, ttEditor.state.doc);
104
-
105
- ttEditor.commands.BNUpdateBlock(posBeforeNode + 1, update);
106
-
107
- const blockContainerNode = ttEditor.state.doc
108
- .resolve(posBeforeNode + 1)
109
- .node();
110
-
111
- return nodeToBlock(
112
- blockContainerNode,
113
- editor.schema.blockSchema,
114
- editor.schema.inlineContentSchema,
115
- editor.schema.styleSchema,
116
- editor.blockCache
117
- );
118
- }
119
-
120
- function removeBlocksWithCallback<
121
- BSchema extends BlockSchema,
122
- I extends InlineContentSchema,
123
- S extends StyleSchema
124
- >(
125
- blocksToRemove: BlockIdentifier[],
126
- editor: BlockNoteEditor<BSchema, I, S>,
127
- // Should return new removedSize.
128
- callback?: (
129
- node: Node,
130
- pos: number,
131
- tr: Transaction,
132
- removedSize: number
133
- ) => number
134
- ): Block<BSchema, I, S>[] {
135
- const ttEditor = editor._tiptapEditor;
136
- const tr = ttEditor.state.tr;
137
-
138
- const idsOfBlocksToRemove = new Set<string>(
139
- blocksToRemove.map((block) =>
140
- typeof block === "string" ? block : block.id
141
- )
142
- );
143
- const removedBlocks: Block<BSchema, I, S>[] = [];
144
- let removedSize = 0;
145
-
146
- ttEditor.state.doc.descendants((node, pos) => {
147
- // Skips traversing nodes after all target blocks have been removed.
148
- if (idsOfBlocksToRemove.size === 0) {
149
- return false;
150
- }
151
-
152
- // Keeps traversing nodes if block with target ID has not been found.
153
- if (
154
- node.type.name !== "blockContainer" ||
155
- !idsOfBlocksToRemove.has(node.attrs.id)
156
- ) {
157
- return true;
158
- }
159
-
160
- // Saves the block that is being deleted.
161
- removedBlocks.push(
162
- nodeToBlock(
163
- node,
164
- editor.schema.blockSchema,
165
- editor.schema.inlineContentSchema,
166
- editor.schema.styleSchema,
167
- editor.blockCache
168
- )
169
- );
170
- idsOfBlocksToRemove.delete(node.attrs.id);
171
-
172
- // Removes the block and calculates the change in document size.
173
- removedSize = callback?.(node, pos, tr, removedSize) || removedSize;
174
- const oldDocSize = tr.doc.nodeSize;
175
- tr.delete(pos - removedSize - 1, pos - removedSize + node.nodeSize + 1);
176
- const newDocSize = tr.doc.nodeSize;
177
- removedSize += oldDocSize - newDocSize;
178
-
179
- return false;
180
- });
181
-
182
- // Throws an error if now all blocks could be found.
183
- if (idsOfBlocksToRemove.size > 0) {
184
- const notFoundIds = [...idsOfBlocksToRemove].join("\n");
185
-
186
- throw Error(
187
- "Blocks with the following IDs could not be found in the editor: " +
188
- notFoundIds
189
- );
190
- }
191
-
192
- editor.dispatch(tr);
193
-
194
- return removedBlocks;
195
- }
196
-
197
- export function removeBlocks<
198
- BSchema extends BlockSchema,
199
- I extends InlineContentSchema,
200
- S extends StyleSchema
201
- >(
202
- blocksToRemove: BlockIdentifier[],
203
- editor: BlockNoteEditor<BSchema, I, S>
204
- ): Block<BSchema, I, S>[] {
205
- return removeBlocksWithCallback(blocksToRemove, editor);
206
- }
207
-
208
- export function replaceBlocks<
209
- BSchema extends BlockSchema,
210
- I extends InlineContentSchema,
211
- S extends StyleSchema
212
- >(
213
- blocksToRemove: BlockIdentifier[],
214
- blocksToInsert: PartialBlock<BSchema, I, S>[],
215
- editor: BlockNoteEditor<BSchema, I, S>
216
- ): {
217
- insertedBlocks: Block<BSchema, I, S>[];
218
- removedBlocks: Block<BSchema, I, S>[];
219
- } {
220
- const nodesToInsert: Node[] = [];
221
- for (const block of blocksToInsert) {
222
- nodesToInsert.push(
223
- blockToNode(block, editor.pmSchema, editor.schema.styleSchema)
224
- );
225
- }
226
-
227
- const idOfFirstBlock =
228
- typeof blocksToRemove[0] === "string"
229
- ? blocksToRemove[0]
230
- : blocksToRemove[0].id;
231
- const removedBlocks = removeBlocksWithCallback(
232
- blocksToRemove,
233
- editor,
234
- (node, pos, tr, removedSize) => {
235
- if (node.attrs.id === idOfFirstBlock) {
236
- const oldDocSize = tr.doc.nodeSize;
237
- tr.insert(pos, nodesToInsert);
238
- const newDocSize = tr.doc.nodeSize;
239
-
240
- return removedSize + oldDocSize - newDocSize;
241
- }
242
-
243
- return removedSize;
244
- }
245
- );
246
-
247
- // Now that the `PartialBlock`s have been converted to nodes, we can
248
- // re-convert them into full `Block`s.
249
- const insertedBlocks: Block<BSchema, I, S>[] = [];
250
- for (const node of nodesToInsert) {
251
- insertedBlocks.push(
252
- nodeToBlock(
253
- node,
254
- editor.schema.blockSchema,
255
- editor.schema.inlineContentSchema,
256
- editor.schema.styleSchema,
257
- editor.blockCache
258
- )
259
- );
260
- }
261
-
262
- return { insertedBlocks, removedBlocks };
263
- }
264
-
265
- // similar to tiptap insertContentAt
266
- export function insertContentAt<
267
- BSchema extends BlockSchema,
268
- I extends InlineContentSchema,
269
- S extends StyleSchema
270
- >(
271
- position: any,
272
- nodes: Node[],
273
- editor: BlockNoteEditor<BSchema, I, S>,
274
- options: {
275
- updateSelection: boolean;
276
- } = { updateSelection: true }
277
- ) {
278
- const tr = editor._tiptapEditor.state.tr;
279
-
280
- // don’t dispatch an empty fragment because this can lead to strange errors
281
- // if (content.toString() === "<>") {
282
- // return true;
283
- // }
284
-
285
- let { from, to } =
286
- typeof position === "number"
287
- ? { from: position, to: position }
288
- : { from: position.from, to: position.to };
289
-
290
- let isOnlyTextContent = true;
291
- let isOnlyBlockContent = true;
292
- // const nodes = isFragment(content) ? content : [content];
293
-
294
- let text = "";
295
-
296
- nodes.forEach((node) => {
297
- // check if added node is valid
298
- node.check();
299
-
300
- if (isOnlyTextContent && node.isText && node.marks.length === 0) {
301
- text += node.text;
302
- } else {
303
- isOnlyTextContent = false;
304
- }
305
-
306
- isOnlyBlockContent = isOnlyBlockContent ? node.isBlock : false;
307
- });
308
-
309
- // check if we can replace the wrapping node by
310
- // the newly inserted content
311
- // example:
312
- // replace an empty paragraph by an inserted image
313
- // instead of inserting the image below the paragraph
314
- if (from === to && isOnlyBlockContent) {
315
- const { parent } = tr.doc.resolve(from);
316
- const isEmptyTextBlock =
317
- parent.isTextblock && !parent.type.spec.code && !parent.childCount;
318
-
319
- if (isEmptyTextBlock) {
320
- from -= 1;
321
- to += 1;
322
- }
323
- }
324
-
325
- // if there is only plain text we have to use `insertText`
326
- // because this will keep the current marks
327
- if (isOnlyTextContent) {
328
- // if value is string, we can use it directly
329
- // otherwise if it is an array, we have to join it
330
- // if (Array.isArray(value)) {
331
- // tr.insertText(value.map((v) => v.text || "").join(""), from, to);
332
- // } else if (typeof value === "object" && !!value && !!value.text) {
333
- // tr.insertText(value.text, from, to);
334
- // } else {
335
- // tr.insertText(value as string, from, to);
336
- // }
337
- tr.insertText(text, from, to);
338
- } else {
339
- tr.replaceWith(from, to, nodes);
340
- }
341
-
342
- // set cursor at end of inserted content
343
- if (options.updateSelection) {
344
- selectionToInsertionEnd(tr, tr.steps.length - 1, -1);
345
- }
346
-
347
- editor.dispatch(tr);
348
-
349
- return true;
350
- }