@blocknote/core 0.9.6 → 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.
Files changed (367) hide show
  1. package/dist/blocknote.js +3697 -2609
  2. package/dist/blocknote.js.map +1 -1
  3. package/dist/blocknote.umd.cjs +7 -7
  4. package/dist/blocknote.umd.cjs.map +1 -1
  5. package/dist/style.css +1 -1
  6. package/dist/webpack-stats.json +1 -0
  7. package/package.json +8 -4
  8. package/src/api/README.md +8 -0
  9. package/src/api/blockManipulation/blockManipulation.test.ts +72 -10
  10. package/src/api/blockManipulation/blockManipulation.ts +38 -18
  11. package/src/api/exporters/copyExtension.ts +68 -0
  12. package/src/api/exporters/html/__snapshots__/complex/misc/external.html +1 -0
  13. package/src/api/exporters/html/__snapshots__/complex/misc/internal.html +1 -0
  14. package/src/api/exporters/html/__snapshots__/customParagraph/basic/external.html +1 -0
  15. package/src/api/exporters/html/__snapshots__/customParagraph/basic/internal.html +1 -0
  16. package/src/api/exporters/html/__snapshots__/customParagraph/nested/external.html +1 -0
  17. package/src/api/exporters/html/__snapshots__/customParagraph/nested/internal.html +1 -0
  18. package/src/api/exporters/html/__snapshots__/customParagraph/styled/external.html +1 -0
  19. package/src/api/exporters/html/__snapshots__/customParagraph/styled/internal.html +1 -0
  20. package/src/api/exporters/html/__snapshots__/fontSize/basic/external.html +1 -0
  21. package/src/api/exporters/html/__snapshots__/fontSize/basic/internal.html +1 -0
  22. package/src/api/exporters/html/__snapshots__/hardbreak/basic/external.html +1 -0
  23. package/src/api/exporters/html/__snapshots__/hardbreak/basic/internal.html +1 -0
  24. package/src/api/exporters/html/__snapshots__/hardbreak/between-links/external.html +1 -0
  25. package/src/api/exporters/html/__snapshots__/hardbreak/between-links/internal.html +1 -0
  26. package/src/api/exporters/html/__snapshots__/hardbreak/end/external.html +1 -0
  27. package/src/api/exporters/html/__snapshots__/hardbreak/end/internal.html +1 -0
  28. package/src/api/exporters/html/__snapshots__/hardbreak/link/external.html +1 -0
  29. package/src/api/exporters/html/__snapshots__/hardbreak/link/internal.html +1 -0
  30. package/src/api/exporters/html/__snapshots__/hardbreak/multiple/external.html +1 -0
  31. package/src/api/exporters/html/__snapshots__/hardbreak/multiple/internal.html +1 -0
  32. package/src/api/exporters/html/__snapshots__/hardbreak/only/external.html +1 -0
  33. package/src/api/exporters/html/__snapshots__/hardbreak/only/internal.html +1 -0
  34. package/src/api/exporters/html/__snapshots__/hardbreak/start/external.html +1 -0
  35. package/src/api/exporters/html/__snapshots__/hardbreak/start/internal.html +1 -0
  36. package/src/api/exporters/html/__snapshots__/hardbreak/styles/external.html +1 -0
  37. package/src/api/exporters/html/__snapshots__/hardbreak/styles/internal.html +1 -0
  38. package/src/api/exporters/html/__snapshots__/image/basic/external.html +1 -0
  39. package/src/api/exporters/html/__snapshots__/image/basic/internal.html +1 -0
  40. package/src/api/exporters/html/__snapshots__/image/button/external.html +1 -0
  41. package/src/api/exporters/html/__snapshots__/image/button/internal.html +1 -0
  42. package/src/api/exporters/html/__snapshots__/image/nested/external.html +1 -0
  43. package/src/api/exporters/html/__snapshots__/image/nested/internal.html +1 -0
  44. package/src/api/exporters/html/__snapshots__/link/adjacent/external.html +1 -0
  45. package/src/api/exporters/html/__snapshots__/link/adjacent/internal.html +1 -0
  46. package/src/api/exporters/html/__snapshots__/link/basic/external.html +1 -0
  47. package/src/api/exporters/html/__snapshots__/link/basic/internal.html +1 -0
  48. package/src/api/exporters/html/__snapshots__/link/styled/external.html +1 -0
  49. package/src/api/exporters/html/__snapshots__/link/styled/internal.html +1 -0
  50. package/src/api/exporters/html/__snapshots__/mention/basic/external.html +1 -0
  51. package/src/api/exporters/html/__snapshots__/mention/basic/internal.html +1 -0
  52. package/src/api/exporters/html/__snapshots__/paragraph/basic/external.html +1 -0
  53. package/src/api/exporters/html/__snapshots__/paragraph/basic/internal.html +1 -0
  54. package/src/api/exporters/html/__snapshots__/paragraph/empty/external.html +1 -0
  55. package/src/api/exporters/html/__snapshots__/paragraph/empty/internal.html +1 -0
  56. package/src/api/exporters/html/__snapshots__/paragraph/nested/external.html +1 -0
  57. package/src/api/exporters/html/__snapshots__/paragraph/nested/internal.html +1 -0
  58. package/src/api/exporters/html/__snapshots__/paragraph/styled/external.html +1 -0
  59. package/src/api/exporters/html/__snapshots__/paragraph/styled/internal.html +1 -0
  60. package/src/api/exporters/html/__snapshots__/paste/parse-basic-block-types.json +140 -0
  61. package/src/api/exporters/html/__snapshots__/paste/parse-deep-nested-content.json +240 -0
  62. package/src/api/exporters/html/__snapshots__/paste/parse-div-with-inline-content.json +91 -0
  63. package/src/api/exporters/html/__snapshots__/paste/parse-divs.json +19 -0
  64. package/src/api/exporters/html/__snapshots__/paste/parse-fake-image-caption.json +31 -0
  65. package/src/api/exporters/html/__snapshots__/paste/parse-mixed-nested-lists.json +70 -0
  66. package/src/api/exporters/html/__snapshots__/paste/parse-nested-lists-with-paragraphs.json +70 -0
  67. package/src/api/exporters/html/__snapshots__/paste/parse-nested-lists.json +70 -0
  68. package/src/api/exporters/html/__snapshots__/simpleCustomParagraph/basic/external.html +1 -0
  69. package/src/api/exporters/html/__snapshots__/simpleCustomParagraph/basic/internal.html +1 -0
  70. package/src/api/exporters/html/__snapshots__/simpleCustomParagraph/nested/external.html +1 -0
  71. package/src/api/exporters/html/__snapshots__/simpleCustomParagraph/nested/internal.html +1 -0
  72. package/src/api/exporters/html/__snapshots__/simpleCustomParagraph/styled/external.html +1 -0
  73. package/src/api/exporters/html/__snapshots__/simpleCustomParagraph/styled/internal.html +1 -0
  74. package/src/api/exporters/html/__snapshots__/simpleImage/basic/external.html +1 -0
  75. package/src/api/exporters/html/__snapshots__/simpleImage/basic/internal.html +1 -0
  76. package/src/api/exporters/html/__snapshots__/simpleImage/button/external.html +1 -0
  77. package/src/api/exporters/html/__snapshots__/simpleImage/button/internal.html +1 -0
  78. package/src/api/exporters/html/__snapshots__/simpleImage/nested/external.html +1 -0
  79. package/src/api/exporters/html/__snapshots__/simpleImage/nested/internal.html +1 -0
  80. package/src/api/exporters/html/__snapshots__/small/basic/external.html +1 -0
  81. package/src/api/exporters/html/__snapshots__/small/basic/internal.html +1 -0
  82. package/src/api/exporters/html/__snapshots__/tag/basic/external.html +1 -0
  83. package/src/api/exporters/html/__snapshots__/tag/basic/internal.html +1 -0
  84. package/src/api/exporters/html/externalHTMLExporter.ts +98 -0
  85. package/src/api/exporters/html/htmlConversion.test.ts +100 -0
  86. package/src/api/exporters/html/internalHTMLSerializer.ts +80 -0
  87. package/src/api/exporters/html/util/sharedHTMLConversion.ts +128 -0
  88. package/src/api/{formatConversions → exporters/html/util}/simplifyBlocksRehypePlugin.ts +13 -0
  89. package/src/api/exporters/markdown/__snapshots__/complex/misc/markdown.md +5 -0
  90. package/src/api/exporters/markdown/__snapshots__/customParagraph/basic/markdown.md +1 -0
  91. package/src/api/exporters/markdown/__snapshots__/customParagraph/nested/markdown.md +5 -0
  92. package/src/api/exporters/markdown/__snapshots__/customParagraph/styled/markdown.md +1 -0
  93. package/src/api/exporters/markdown/__snapshots__/fontSize/basic/markdown.md +1 -0
  94. package/src/api/exporters/markdown/__snapshots__/hardbreak/basic/markdown.md +2 -0
  95. package/src/api/exporters/markdown/__snapshots__/hardbreak/between-links/markdown.md +2 -0
  96. package/src/api/exporters/markdown/__snapshots__/hardbreak/end/markdown.md +1 -0
  97. package/src/api/exporters/markdown/__snapshots__/hardbreak/link/markdown.md +2 -0
  98. package/src/api/exporters/markdown/__snapshots__/hardbreak/multiple/markdown.md +3 -0
  99. package/src/api/exporters/markdown/__snapshots__/hardbreak/start/markdown.md +1 -0
  100. package/src/api/exporters/markdown/__snapshots__/hardbreak/styles/markdown.md +2 -0
  101. package/src/api/exporters/markdown/__snapshots__/image/basic/markdown.md +3 -0
  102. package/src/api/exporters/markdown/__snapshots__/image/button/markdown.md +1 -0
  103. package/src/api/exporters/markdown/__snapshots__/image/nested/markdown.md +7 -0
  104. package/src/api/exporters/markdown/__snapshots__/link/adjacent/markdown.md +1 -0
  105. package/src/api/exporters/markdown/__snapshots__/link/basic/markdown.md +1 -0
  106. package/src/api/exporters/markdown/__snapshots__/link/styled/markdown.md +1 -0
  107. package/src/api/exporters/markdown/__snapshots__/mention/basic/markdown.md +1 -0
  108. package/src/api/exporters/markdown/__snapshots__/paragraph/basic/markdown.md +1 -0
  109. package/src/api/exporters/markdown/__snapshots__/paragraph/empty/markdown.md +0 -0
  110. package/src/api/exporters/markdown/__snapshots__/paragraph/nested/markdown.md +5 -0
  111. package/src/api/exporters/markdown/__snapshots__/paragraph/styled/markdown.md +1 -0
  112. package/src/api/exporters/markdown/__snapshots__/simpleCustomParagraph/basic/markdown.md +1 -0
  113. package/src/api/exporters/markdown/__snapshots__/simpleCustomParagraph/nested/markdown.md +5 -0
  114. package/src/api/exporters/markdown/__snapshots__/simpleCustomParagraph/styled/markdown.md +1 -0
  115. package/src/api/exporters/markdown/__snapshots__/simpleImage/basic/markdown.md +1 -0
  116. package/src/api/exporters/markdown/__snapshots__/simpleImage/button/markdown.md +1 -0
  117. package/src/api/exporters/markdown/__snapshots__/simpleImage/nested/markdown.md +3 -0
  118. package/src/api/exporters/markdown/__snapshots__/small/basic/markdown.md +1 -0
  119. package/src/api/exporters/markdown/__snapshots__/tag/basic/markdown.md +1 -0
  120. package/src/api/exporters/markdown/markdownExporter.test.ts +85 -0
  121. package/src/api/exporters/markdown/markdownExporter.ts +42 -0
  122. package/src/api/nodeConversions/__snapshots__/nodeConversions.test.ts.snap +486 -125
  123. package/src/api/nodeConversions/nodeConversions.test.ts +67 -498
  124. package/src/api/nodeConversions/nodeConversions.ts +311 -85
  125. package/src/api/parsers/html/__snapshots__/paste/list-test.json +105 -0
  126. package/src/api/parsers/html/__snapshots__/paste/parse-basic-block-types.json +140 -0
  127. package/src/api/parsers/html/__snapshots__/paste/parse-deep-nested-content.json +240 -0
  128. package/src/api/parsers/html/__snapshots__/paste/parse-div-with-inline-content.json +91 -0
  129. package/src/api/parsers/html/__snapshots__/paste/parse-divs.json +121 -0
  130. package/src/api/parsers/html/__snapshots__/paste/parse-fake-image-caption.json +31 -0
  131. package/src/api/parsers/html/__snapshots__/paste/parse-google-docs-html.json +476 -0
  132. package/src/api/parsers/html/__snapshots__/paste/parse-mixed-nested-lists.json +140 -0
  133. package/src/api/parsers/html/__snapshots__/paste/parse-nested-lists-with-paragraphs.json +140 -0
  134. package/src/api/parsers/html/__snapshots__/paste/parse-nested-lists.json +157 -0
  135. package/src/api/parsers/html/__snapshots__/paste/parse-notion-html.json +470 -0
  136. package/src/api/parsers/html/__snapshots__/paste/parse-two-divs.json +36 -0
  137. package/src/api/parsers/html/parseHTML.test.ts +440 -0
  138. package/src/api/parsers/html/parseHTML.ts +42 -0
  139. package/src/api/parsers/html/util/__snapshots__/nestedLists.test.ts.snap +129 -0
  140. package/src/api/parsers/html/util/nestedLists.test.ts +176 -0
  141. package/src/api/parsers/html/util/nestedLists.ts +113 -0
  142. package/src/api/parsers/markdown/__snapshots__/complex.json +353 -0
  143. package/src/api/parsers/markdown/__snapshots__/issue-226-1.json +71 -0
  144. package/src/api/parsers/markdown/__snapshots__/issue-226-2.json +144 -0
  145. package/src/api/parsers/markdown/__snapshots__/nested.json +72 -0
  146. package/src/api/parsers/markdown/__snapshots__/non-nested.json +71 -0
  147. package/src/api/parsers/markdown/__snapshots__/styled.json +58 -0
  148. package/src/api/parsers/markdown/parseMarkdown.test.ts +114 -0
  149. package/src/api/parsers/markdown/parseMarkdown.ts +84 -0
  150. package/src/api/parsers/pasteExtension.ts +59 -0
  151. package/src/api/testUtil/cases/customBlocks.ts +282 -0
  152. package/src/api/testUtil/cases/customInlineContent.ts +114 -0
  153. package/src/api/testUtil/cases/customStyles.ts +100 -0
  154. package/src/api/testUtil/cases/defaultSchema.ts +399 -0
  155. package/src/api/testUtil/index.ts +17 -0
  156. package/src/api/testUtil/partialBlockTestUtil.ts +127 -0
  157. package/src/blocks/HeadingBlockContent/HeadingBlockContent.ts +136 -0
  158. package/src/{extensions/Blocks/nodes/BlockContent → blocks}/ImageBlockContent/ImageBlockContent.ts +87 -31
  159. package/src/{extensions/Blocks/nodes/BlockContent → blocks}/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +34 -47
  160. package/src/{extensions/Blocks/nodes/BlockContent → blocks}/ListItemBlockContent/ListItemKeyboardShortcuts.ts +1 -1
  161. package/src/{extensions/Blocks/nodes/BlockContent → blocks}/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts +1 -1
  162. package/src/{extensions/Blocks/nodes/BlockContent → blocks}/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +34 -56
  163. package/src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts +43 -0
  164. package/src/blocks/README.md +3 -0
  165. package/src/blocks/TableBlockContent/TableBlockContent.ts +74 -0
  166. package/src/blocks/TableBlockContent/TableExtension.ts +63 -0
  167. package/src/blocks/defaultBlockHelpers.ts +95 -0
  168. package/src/blocks/defaultBlocks.ts +60 -0
  169. package/src/blocks/defaultProps.ts +24 -0
  170. package/src/{extensions/Blocks/nodes/Block.module.css → editor/Block.css} +69 -62
  171. package/src/{BlockNoteEditor.test.ts → editor/BlockNoteEditor.test.ts} +2 -2
  172. package/src/{BlockNoteEditor.ts → editor/BlockNoteEditor.ts} +364 -153
  173. package/src/{BlockNoteExtensions.ts → editor/BlockNoteExtensions.ts} +59 -40
  174. package/src/editor/README.md +3 -0
  175. package/src/editor/cursorPositionTypes.ts +16 -0
  176. package/src/{editor.module.css → editor/editor.css} +42 -15
  177. package/src/editor/selectionTypes.ts +14 -0
  178. package/src/editor/transformPasted.ts +58 -0
  179. package/src/extensions/BackgroundColor/BackgroundColorExtension.ts +1 -36
  180. package/src/extensions/BackgroundColor/BackgroundColorMark.ts +12 -27
  181. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +16 -24
  182. package/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts +12 -10
  183. package/src/extensions/ImageToolbar/ImageToolbarPlugin.ts +35 -73
  184. package/src/extensions/Placeholder/PlaceholderExtension.ts +4 -4
  185. package/src/extensions/README.md +3 -0
  186. package/src/extensions/SideMenu/SideMenuPlugin.ts +66 -37
  187. package/src/extensions/SlashMenu/BaseSlashMenuItem.ts +7 -6
  188. package/src/extensions/SlashMenu/SlashMenuPlugin.ts +9 -7
  189. package/src/extensions/SlashMenu/defaultSlashMenuItems.ts +98 -35
  190. package/src/extensions/TableHandles/TableHandlesPlugin.ts +617 -0
  191. package/src/extensions/TextAlignment/TextAlignmentExtension.ts +3 -51
  192. package/src/extensions/TextColor/TextColorExtension.ts +1 -29
  193. package/src/extensions/TextColor/TextColorMark.ts +7 -27
  194. package/src/extensions/UniqueID/UniqueID.ts +28 -2
  195. package/src/extensions-shared/README.md +3 -0
  196. package/src/{shared/plugins → extensions-shared}/suggestion/SuggestionPlugin.ts +19 -13
  197. package/src/index.ts +21 -15
  198. package/src/{extensions/Blocks/nodes → pm-nodes}/BlockContainer.ts +161 -96
  199. package/src/pm-nodes/BlockGroup.ts +54 -0
  200. package/src/pm-nodes/Doc.ts +7 -0
  201. package/src/pm-nodes/README.md +42 -0
  202. package/src/pm-nodes/index.ts +3 -0
  203. package/src/schema/README.md +3 -0
  204. package/src/schema/blocks/createSpec.ts +220 -0
  205. package/src/schema/blocks/internal.ts +253 -0
  206. package/src/schema/blocks/types.ts +252 -0
  207. package/src/schema/index.ts +10 -0
  208. package/src/schema/inlineContent/createSpec.ts +119 -0
  209. package/src/schema/inlineContent/internal.ts +105 -0
  210. package/src/schema/inlineContent/types.ts +144 -0
  211. package/src/schema/propTypes.ts +32 -0
  212. package/src/schema/styles/createSpec.ts +85 -0
  213. package/src/schema/styles/internal.ts +96 -0
  214. package/src/schema/styles/types.ts +42 -0
  215. package/src/util/README.md +3 -0
  216. package/src/{shared/utils.ts → util/browser.ts} +4 -8
  217. package/src/util/string.ts +3 -0
  218. package/src/util/typescript.ts +5 -0
  219. package/types/src/BlockNoteEditor.d.ts +49 -36
  220. package/types/src/BlockNoteExtensions.d.ts +8 -3
  221. package/types/src/api/blockManipulation/blockManipulation.d.ts +5 -4
  222. package/types/src/api/exporters/copyExtension.d.ts +6 -0
  223. package/types/src/api/exporters/html/externalHTMLExporter.d.ts +8 -0
  224. package/types/src/api/exporters/html/internalHTMLSerializer.d.ts +8 -0
  225. package/types/src/api/exporters/html/util/sharedHTMLConversion.d.ts +7 -0
  226. package/types/src/api/exporters/markdown/markdownExporter.d.ts +5 -0
  227. package/types/src/api/exporters/markdown/markdownExporter.test.d.ts +1 -0
  228. package/types/src/api/getBlockInfoFromPos.d.ts +27 -0
  229. package/types/src/api/nodeConversions/nodeConversions.d.ts +14 -6
  230. package/types/src/api/nodeConversions/testUtil.d.ts +7 -2
  231. package/types/src/api/nodeUtil.d.ts +8 -0
  232. package/types/src/api/parsers/html/parseHTML.d.ts +3 -0
  233. package/types/src/api/parsers/html/parseHTML.test.d.ts +1 -0
  234. package/types/src/api/parsers/html/util/nestedLists.d.ts +1 -0
  235. package/types/src/api/parsers/html/util/nestedLists.test.d.ts +1 -0
  236. package/types/src/api/parsers/markdown/parseMarkdown.d.ts +3 -0
  237. package/types/src/api/parsers/markdown/parseMarkdown.test.d.ts +1 -0
  238. package/types/src/api/parsers/pasteExtension.d.ts +6 -0
  239. package/types/src/api/testCases/cases/customBlocks.d.ts +345 -0
  240. package/types/src/api/testCases/cases/customInlineContent.d.ts +29 -0
  241. package/types/src/api/testCases/cases/customStyles.d.ts +64 -0
  242. package/types/src/api/testCases/cases/defaultSchema.d.ts +3 -0
  243. package/types/src/api/testCases/index.d.ts +12 -0
  244. package/types/src/api/testUtil/cases/customBlocks.d.ts +345 -0
  245. package/types/src/api/testUtil/cases/customInlineContent.d.ts +29 -0
  246. package/types/src/api/testUtil/cases/customStyles.d.ts +64 -0
  247. package/types/src/api/testUtil/cases/defaultSchema.d.ts +3 -0
  248. package/types/src/api/testUtil/index.d.ts +12 -0
  249. package/types/src/api/testUtil/partialBlockTestUtil.d.ts +7 -0
  250. package/types/src/blocks/HeadingBlockContent/HeadingBlockContent.d.ts +58 -0
  251. package/types/src/blocks/ImageBlockContent/ImageBlockContent.d.ts +93 -0
  252. package/types/src/blocks/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.d.ts +1 -0
  253. package/types/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.d.ts +46 -0
  254. package/types/src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.d.ts +2 -0
  255. package/types/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.d.ts +2 -0
  256. package/types/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.d.ts +46 -0
  257. package/types/src/blocks/ParagraphBlockContent/ParagraphBlockContent.d.ts +52 -0
  258. package/types/src/blocks/TableBlockContent/TableBlockContent.d.ts +53 -0
  259. package/types/src/blocks/TableBlockContent/TableExtension.d.ts +2 -0
  260. package/types/src/blocks/defaultBlockHelpers.d.ts +10 -0
  261. package/types/src/blocks/defaultBlocks.d.ts +577 -0
  262. package/types/src/blocks/defaultProps.d.ts +15 -0
  263. package/types/src/editor/BlockNoteEditor.d.ts +299 -0
  264. package/types/src/editor/BlockNoteEditor.test.d.ts +1 -0
  265. package/types/src/editor/BlockNoteExtensions.d.ts +24 -0
  266. package/types/src/editor/cursorPositionTypes.d.ts +6 -0
  267. package/types/src/editor/selectionTypes.d.ts +4 -0
  268. package/types/src/editor/transformPasted.d.ts +12 -0
  269. package/types/src/extensions/BackgroundColor/BackgroundColorExtension.d.ts +0 -7
  270. package/types/src/extensions/BackgroundColor/BackgroundColorMark.d.ts +7 -9
  271. package/types/src/extensions/Blocks/api/blocks/createSpec.d.ts +35 -0
  272. package/types/src/extensions/Blocks/api/blocks/internal.d.ts +45 -0
  273. package/types/src/extensions/Blocks/api/blocks/types.d.ts +114 -0
  274. package/types/src/extensions/Blocks/api/cursorPositionTypes.d.ts +7 -5
  275. package/types/src/extensions/Blocks/api/defaultBlocks.d.ts +573 -113
  276. package/types/src/extensions/Blocks/api/defaultProps.d.ts +2 -1
  277. package/types/src/extensions/Blocks/api/inlineContent/createSpec.d.ts +21 -0
  278. package/types/src/extensions/Blocks/api/inlineContent/internal.d.ts +25 -0
  279. package/types/src/extensions/Blocks/api/inlineContent/types.d.ts +62 -0
  280. package/types/src/extensions/Blocks/api/selectionTypes.d.ts +5 -3
  281. package/types/src/extensions/Blocks/api/styles/createSpec.d.ts +13 -0
  282. package/types/src/extensions/Blocks/api/styles/internal.d.ts +22 -0
  283. package/types/src/extensions/Blocks/api/styles/types.d.ts +21 -0
  284. package/types/src/extensions/Blocks/nodes/BlockContainer.d.ts +8 -4
  285. package/types/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContent.d.ts +38 -23
  286. package/types/src/extensions/Blocks/nodes/BlockContent/ImageBlockContent/ImageBlockContent.d.ts +75 -17
  287. package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.d.ts +30 -19
  288. package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.d.ts +30 -19
  289. package/types/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.d.ts +36 -28
  290. package/types/src/extensions/Blocks/nodes/BlockContent/TableBlockContent/TableBlockContent.d.ts +53 -0
  291. package/types/src/extensions/Blocks/nodes/BlockContent/TableBlockContent/TableExtension.d.ts +2 -0
  292. package/types/src/extensions/Blocks/nodes/BlockContent/defaultBlockHelpers.d.ts +12 -0
  293. package/types/src/extensions/Blocks/nodes/BlockGroup.d.ts +1 -1
  294. package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +8 -6
  295. package/types/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.d.ts +6 -6
  296. package/types/src/extensions/ImageToolbar/ImageToolbarPlugin.d.ts +11 -16
  297. package/types/src/extensions/NonEditableBlocks/NonEditableBlockPlugin.d.ts +2 -0
  298. package/types/src/extensions/PreviousBlockType/PreviousBlockTypePlugin.d.ts +14 -0
  299. package/types/src/extensions/SideMenu/SideMenuPlugin.d.ts +18 -11
  300. package/types/src/extensions/SlashMenu/BaseSlashMenuItem.d.ts +5 -6
  301. package/types/src/extensions/SlashMenu/SlashMenuPlugin.d.ts +6 -6
  302. package/types/src/extensions/SlashMenu/defaultSlashMenuItems.d.ts +2 -1
  303. package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +74 -0
  304. package/types/src/extensions/TextAlignment/TextAlignmentExtension.d.ts +0 -7
  305. package/types/src/extensions/TextColor/TextColorExtension.d.ts +0 -7
  306. package/types/src/extensions/TextColor/TextColorMark.d.ts +7 -9
  307. package/types/src/extensions/UniqueID/UniqueID.d.ts +1 -1
  308. package/types/src/extensions-shared/BaseUiElementTypes.d.ts +7 -0
  309. package/types/src/extensions-shared/suggestion/SuggestionItem.d.ts +3 -0
  310. package/types/src/extensions-shared/suggestion/SuggestionPlugin.d.ts +36 -0
  311. package/types/src/index.d.ts +20 -15
  312. package/types/src/pm-nodes/BlockContainer.d.ts +28 -0
  313. package/types/src/pm-nodes/BlockGroup.d.ts +10 -0
  314. package/types/src/pm-nodes/Doc.d.ts +2 -0
  315. package/types/src/pm-nodes/index.d.ts +3 -0
  316. package/types/src/schema/blocks/createSpec.d.ts +35 -0
  317. package/types/src/schema/blocks/internal.d.ts +45 -0
  318. package/types/src/schema/blocks/types.d.ts +107 -0
  319. package/types/src/schema/index.d.ts +10 -0
  320. package/types/src/schema/inlineContent/createSpec.d.ts +21 -0
  321. package/types/src/schema/inlineContent/internal.d.ts +28 -0
  322. package/types/src/schema/inlineContent/types.d.ts +62 -0
  323. package/types/src/schema/propTypes.d.ts +8 -0
  324. package/types/src/schema/styles/createSpec.d.ts +13 -0
  325. package/types/src/schema/styles/internal.d.ts +22 -0
  326. package/types/src/schema/styles/types.d.ts +21 -0
  327. package/types/src/shared/plugins/suggestion/SuggestionPlugin.d.ts +4 -2
  328. package/types/src/util/EventEmitter.d.ts +11 -0
  329. package/types/src/util/browser.d.ts +3 -0
  330. package/types/src/util/string.d.ts +1 -0
  331. package/types/src/util/typescript.d.ts +3 -0
  332. package/src/api/formatConversions/__snapshots__/formatConversions.test.ts.snap +0 -346
  333. package/src/api/formatConversions/formatConversions.test.ts +0 -753
  334. package/src/api/formatConversions/formatConversions.ts +0 -133
  335. package/src/api/nodeConversions/testUtil.ts +0 -65
  336. package/src/extensions/Blocks/api/block.ts +0 -307
  337. package/src/extensions/Blocks/api/blockTypes.ts +0 -249
  338. package/src/extensions/Blocks/api/cursorPositionTypes.ts +0 -7
  339. package/src/extensions/Blocks/api/defaultBlocks.ts +0 -16
  340. package/src/extensions/Blocks/api/defaultProps.ts +0 -16
  341. package/src/extensions/Blocks/api/inlineContentTypes.ts +0 -36
  342. package/src/extensions/Blocks/api/selectionTypes.ts +0 -5
  343. package/src/extensions/Blocks/api/serialization.ts +0 -29
  344. package/src/extensions/Blocks/helpers/findBlock.ts +0 -5
  345. package/src/extensions/Blocks/index.ts +0 -8
  346. package/src/extensions/Blocks/nodes/BlockAttributes.ts +0 -10
  347. package/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContent.ts +0 -142
  348. package/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.ts +0 -62
  349. package/src/extensions/Blocks/nodes/BlockGroup.ts +0 -53
  350. package/types/src/api/formatConversions/formatConversions.d.ts +0 -6
  351. package/types/src/extensions/Blocks/api/block.d.ts +0 -20
  352. package/types/src/extensions/Blocks/api/blockTypes.d.ts +0 -103
  353. package/types/src/extensions/Blocks/api/inlineContentTypes.d.ts +0 -30
  354. package/types/src/extensions/Blocks/api/serialization.d.ts +0 -2
  355. /package/src/{shared/EditorElement.ts → api/exporters/markdown/__snapshots__/hardbreak/only/markdown.md} +0 -0
  356. /package/src/api/{formatConversions → exporters/markdown}/removeUnderlinesRehypePlugin.ts +0 -0
  357. /package/src/{extensions/Blocks/helpers → api}/getBlockInfoFromPos.ts +0 -0
  358. /package/src/api/{util/nodeUtil.ts → nodeUtil.ts} +0 -0
  359. /package/src/{extensions/Blocks/nodes/BlockContent → blocks}/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts +0 -0
  360. /package/src/extensions/{Blocks → NonEditableBlocks}/NonEditableBlockPlugin.ts +0 -0
  361. /package/src/extensions/{Blocks → PreviousBlockType}/PreviousBlockTypePlugin.ts +0 -0
  362. /package/src/{shared → extensions-shared}/BaseUiElementTypes.ts +0 -0
  363. /package/src/{shared/plugins → extensions-shared}/suggestion/SuggestionItem.ts +0 -0
  364. /package/src/{shared → util}/EventEmitter.ts +0 -0
  365. /package/types/src/api/{formatConversions/formatConversions.test.d.ts → exporters/html/htmlConversion.test.d.ts} +0 -0
  366. /package/types/src/api/{formatConversions → exporters/html/util}/simplifyBlocksRehypePlugin.d.ts +0 -0
  367. /package/types/src/api/{formatConversions → exporters/markdown}/removeUnderlinesRehypePlugin.d.ts +0 -0
@@ -0,0 +1,70 @@
1
+ [
2
+ {
3
+ "id": "1",
4
+ "type": "bulletListItem",
5
+ "props": {
6
+ "textColor": "default",
7
+ "backgroundColor": "default",
8
+ "textAlignment": "left"
9
+ },
10
+ "content": [
11
+ {
12
+ "type": "text",
13
+ "text": "Bullet List Item",
14
+ "styles": {}
15
+ }
16
+ ],
17
+ "children": []
18
+ },
19
+ {
20
+ "id": "2",
21
+ "type": "bulletListItem",
22
+ "props": {
23
+ "textColor": "default",
24
+ "backgroundColor": "default",
25
+ "textAlignment": "left"
26
+ },
27
+ "content": [
28
+ {
29
+ "type": "text",
30
+ "text": "Nested Bullet List Item",
31
+ "styles": {}
32
+ }
33
+ ],
34
+ "children": []
35
+ },
36
+ {
37
+ "id": "3",
38
+ "type": "bulletListItem",
39
+ "props": {
40
+ "textColor": "default",
41
+ "backgroundColor": "default",
42
+ "textAlignment": "left"
43
+ },
44
+ "content": [
45
+ {
46
+ "type": "text",
47
+ "text": "Nested Bullet List Item",
48
+ "styles": {}
49
+ }
50
+ ],
51
+ "children": []
52
+ },
53
+ {
54
+ "id": "4",
55
+ "type": "bulletListItem",
56
+ "props": {
57
+ "textColor": "default",
58
+ "backgroundColor": "default",
59
+ "textAlignment": "left"
60
+ },
61
+ "content": [
62
+ {
63
+ "type": "text",
64
+ "text": "Bullet List Item",
65
+ "styles": {}
66
+ }
67
+ ],
68
+ "children": []
69
+ }
70
+ ]
@@ -0,0 +1 @@
1
+ <p class="bn-inline-content simple-custom-paragraph" data-editable="">Custom Paragraph</p>
@@ -0,0 +1 @@
1
+ <div class="bn-block-group" data-node-type="blockGroup"><div class="bn-block-outer" data-node-type="blockOuter" data-id="1"><div class="bn-block" data-node-type="blockContainer" data-id="1"><div class="bn-block-content" data-content-type="simpleCustomParagraph"><p class="bn-inline-content simple-custom-paragraph" data-editable="">Custom Paragraph</p></div></div></div></div>
@@ -0,0 +1 @@
1
+ <p class="bn-inline-content simple-custom-paragraph" data-editable="">Custom Paragraph</p><p class="bn-inline-content simple-custom-paragraph" data-editable="">Nested Custom Paragraph 1</p><p class="bn-inline-content simple-custom-paragraph" data-editable="">Nested Custom Paragraph 2</p>
@@ -0,0 +1 @@
1
+ <div class="bn-block-group" data-node-type="blockGroup"><div class="bn-block-outer" data-node-type="blockOuter" data-id="1"><div class="bn-block" data-node-type="blockContainer" data-id="1"><div class="bn-block-content" data-content-type="simpleCustomParagraph"><p class="bn-inline-content simple-custom-paragraph" data-editable="">Custom Paragraph</p></div><div class="bn-block-group" data-node-type="blockGroup"><div class="bn-block-outer" data-node-type="blockOuter" data-id="2"><div class="bn-block" data-node-type="blockContainer" data-id="2"><div class="bn-block-content" data-content-type="simpleCustomParagraph"><p class="bn-inline-content simple-custom-paragraph" data-editable="">Nested Custom Paragraph 1</p></div></div></div><div class="bn-block-outer" data-node-type="blockOuter" data-id="3"><div class="bn-block" data-node-type="blockContainer" data-id="3"><div class="bn-block-content" data-content-type="simpleCustomParagraph"><p class="bn-inline-content simple-custom-paragraph" data-editable="">Nested Custom Paragraph 2</p></div></div></div></div></div></div></div>
@@ -0,0 +1 @@
1
+ <p class="bn-inline-content simple-custom-paragraph" data-editable="">Plain <span data-text-color="red">Red Text </span><span data-background-color="blue">Blue Background </span><span data-text-color="red"><span data-background-color="blue">Mixed Colors</span></span></p>
@@ -0,0 +1 @@
1
+ <div class="bn-block-group" data-node-type="blockGroup"><div class="bn-block-outer" data-node-type="blockOuter" data-id="1" data-text-color="orange" data-background-color="pink"><div class="bn-block" data-node-type="blockContainer" data-id="1" data-text-color="orange" data-background-color="pink"><div class="bn-block-content" data-content-type="simpleCustomParagraph" data-text-alignment="center"><p class="bn-inline-content simple-custom-paragraph" data-editable="">Plain <span data-text-color="red">Red Text </span><span data-background-color="blue">Blue Background </span><span data-text-color="red"><span data-background-color="blue">Mixed Colors</span></span></p></div></div></div></div>
@@ -0,0 +1 @@
1
+ <div class="bn-image-block-content-wrapper" style="align-items: flex-start;"><div class="bn-add-image-button" style="display: none;"><div class="bn-add-image-button-icon"></div><p class="bn-add-image-button-text"></p></div><div class="bn-image-and-caption-wrapper"><div class="bn-image-wrapper"><img class="bn-image" src="exampleURL" alt="placeholder" draggable="false" style="width: 0px;"><div class="bn-image-resize-handle" style="left: 4px;"></div><div class="bn-image-resize-handle" style="right: 4px;"></div></div><p class="bn-image-caption" style="padding: 4px;"></p></div></div>
@@ -0,0 +1 @@
1
+ <div class="bn-block-group" data-node-type="blockGroup"><div class="bn-block-outer" data-node-type="blockOuter" data-id="1"><div class="bn-block" data-node-type="blockContainer" data-id="1"><div class="bn-block-content" data-content-type="simpleImage" data-url="exampleURL" data-caption="Caption" data-width="256"><div class="bn-image-block-content-wrapper" style="align-items: flex-start;"><div class="bn-add-image-button" style="display: none;"><div class="bn-add-image-button-icon"></div><p class="bn-add-image-button-text"></p></div><div class="bn-image-and-caption-wrapper"><div class="bn-image-wrapper"><img class="bn-image" src="exampleURL" alt="placeholder" draggable="false" style="width: 0px;"><div class="bn-image-resize-handle" style="left: 4px;"></div><div class="bn-image-resize-handle" style="right: 4px;"></div></div><p class="bn-image-caption" style="padding: 4px;"></p></div></div></div></div></div></div>
@@ -0,0 +1 @@
1
+ <div class="bn-image-block-content-wrapper" style="align-items: flex-start;"><div class="bn-add-image-button"><div class="bn-add-image-button-icon"></div><p class="bn-add-image-button-text"></p></div><div class="bn-image-and-caption-wrapper" style="display: none;"><div class="bn-image-wrapper" style="display: none;"><img class="bn-image" src="" alt="placeholder" draggable="false" style="width: 0px;"><div class="bn-image-resize-handle" style="left: 4px;"></div><div class="bn-image-resize-handle" style="right: 4px;"></div></div><p class="bn-image-caption"></p></div></div>
@@ -0,0 +1 @@
1
+ <div class="bn-block-group" data-node-type="blockGroup"><div class="bn-block-outer" data-node-type="blockOuter" data-id="1"><div class="bn-block" data-node-type="blockContainer" data-id="1"><div class="bn-block-content" data-content-type="simpleImage"><div class="bn-image-block-content-wrapper" style="align-items: flex-start;"><div class="bn-add-image-button"><div class="bn-add-image-button-icon"></div><p class="bn-add-image-button-text"></p></div><div class="bn-image-and-caption-wrapper" style="display: none;"><div class="bn-image-wrapper" style="display: none;"><img class="bn-image" src="" alt="placeholder" draggable="false" style="width: 0px;"><div class="bn-image-resize-handle" style="left: 4px;"></div><div class="bn-image-resize-handle" style="right: 4px;"></div></div><p class="bn-image-caption"></p></div></div></div></div></div></div>
@@ -0,0 +1 @@
1
+ <div class="bn-image-block-content-wrapper" style="align-items: flex-start;"><div class="bn-add-image-button" style="display: none;"><div class="bn-add-image-button-icon"></div><p class="bn-add-image-button-text"></p></div><div class="bn-image-and-caption-wrapper"><div class="bn-image-wrapper"><img class="bn-image" src="exampleURL" alt="placeholder" draggable="false" style="width: 0px;"><div class="bn-image-resize-handle" style="left: 4px;"></div><div class="bn-image-resize-handle" style="right: 4px;"></div></div><p class="bn-image-caption" style="padding: 4px;"></p></div></div><div class="bn-image-block-content-wrapper" style="align-items: flex-start;"><div class="bn-add-image-button" style="display: none;"><div class="bn-add-image-button-icon"></div><p class="bn-add-image-button-text"></p></div><div class="bn-image-and-caption-wrapper"><div class="bn-image-wrapper"><img class="bn-image" src="exampleURL" alt="placeholder" draggable="false" style="width: 0px;"><div class="bn-image-resize-handle" style="left: 4px;"></div><div class="bn-image-resize-handle" style="right: 4px;"></div></div><p class="bn-image-caption" style="padding: 4px;"></p></div></div>
@@ -0,0 +1 @@
1
+ <div class="bn-block-group" data-node-type="blockGroup"><div class="bn-block-outer" data-node-type="blockOuter" data-id="1"><div class="bn-block" data-node-type="blockContainer" data-id="1"><div class="bn-block-content" data-content-type="simpleImage" data-url="exampleURL" data-caption="Caption" data-width="256"><div class="bn-image-block-content-wrapper" style="align-items: flex-start;"><div class="bn-add-image-button" style="display: none;"><div class="bn-add-image-button-icon"></div><p class="bn-add-image-button-text"></p></div><div class="bn-image-and-caption-wrapper"><div class="bn-image-wrapper"><img class="bn-image" src="exampleURL" alt="placeholder" draggable="false" style="width: 0px;"><div class="bn-image-resize-handle" style="left: 4px;"></div><div class="bn-image-resize-handle" style="right: 4px;"></div></div><p class="bn-image-caption" style="padding: 4px;"></p></div></div></div><div class="bn-block-group" data-node-type="blockGroup"><div class="bn-block-outer" data-node-type="blockOuter" data-id="2"><div class="bn-block" data-node-type="blockContainer" data-id="2"><div class="bn-block-content" data-content-type="simpleImage" data-url="exampleURL" data-caption="Caption" data-width="256"><div class="bn-image-block-content-wrapper" style="align-items: flex-start;"><div class="bn-add-image-button" style="display: none;"><div class="bn-add-image-button-icon"></div><p class="bn-add-image-button-text"></p></div><div class="bn-image-and-caption-wrapper"><div class="bn-image-wrapper"><img class="bn-image" src="exampleURL" alt="placeholder" draggable="false" style="width: 0px;"><div class="bn-image-resize-handle" style="left: 4px;"></div><div class="bn-image-resize-handle" style="right: 4px;"></div></div><p class="bn-image-caption" style="padding: 4px;"></p></div></div></div></div></div></div></div></div></div>
@@ -0,0 +1 @@
1
+ <p class="bn-inline-content"><small data-style-type="small" data-editable="">This is a small text</small></p>
@@ -0,0 +1 @@
1
+ <div class="bn-block-group" data-node-type="blockGroup"><div class="bn-block-outer" data-node-type="blockOuter" data-id="1"><div class="bn-block" data-node-type="blockContainer" data-id="1"><div class="bn-block-content" data-content-type="paragraph"><p class="bn-inline-content"><small data-style-type="small" data-editable="">This is a small text</small></p></div></div></div></div>
@@ -0,0 +1 @@
1
+ <p class="bn-inline-content">I love <span data-inline-content-type="tag">#<span data-editable="">BlockNote</span></span></p>
@@ -0,0 +1 @@
1
+ <div class="bn-block-group" data-node-type="blockGroup"><div class="bn-block-outer" data-node-type="blockOuter" data-id="1"><div class="bn-block" data-node-type="blockContainer" data-id="1"><div class="bn-block-content" data-content-type="paragraph"><p class="bn-inline-content">I love <span data-inline-content-type="tag">#<span data-editable="">BlockNote</span></span></p></div></div></div></div>
@@ -0,0 +1,98 @@
1
+ import { DOMSerializer, Fragment, Node, Schema } from "prosemirror-model";
2
+ import rehypeParse from "rehype-parse";
3
+ import rehypeStringify from "rehype-stringify";
4
+ import { unified } from "unified";
5
+
6
+ import type { BlockNoteEditor } from "../../../editor/BlockNoteEditor";
7
+ import {
8
+ BlockSchema,
9
+ InlineContentSchema,
10
+ PartialBlock,
11
+ StyleSchema,
12
+ } from "../../../schema";
13
+ import { blockToNode } from "../../nodeConversions/nodeConversions";
14
+ import {
15
+ serializeNodeInner,
16
+ serializeProseMirrorFragment,
17
+ } from "./util/sharedHTMLConversion";
18
+ import { simplifyBlocks } from "./util/simplifyBlocksRehypePlugin";
19
+
20
+ // Used to export BlockNote blocks and ProseMirror nodes to HTML for use outside
21
+ // the editor. Blocks are exported using the `toExternalHTML` method in their
22
+ // `blockSpec`, or `toInternalHTML` if `toExternalHTML` is not defined.
23
+ //
24
+ // The HTML created by this serializer is different to what's rendered by the
25
+ // editor to the DOM. This also means that data is likely to be lost when
26
+ // converting back to original blocks. The differences in the output HTML are:
27
+ // 1. It doesn't include the `blockGroup` and `blockContainer` wrappers meaning
28
+ // that nesting is not preserved for non-list-item blocks.
29
+ // 2. `li` items in the output HTML are wrapped in `ul` or `ol` elements.
30
+ // 3. While nesting for list items is preserved, other types of blocks nested
31
+ // inside a list are un-nested and a new list is created after them.
32
+ // 4. The HTML is wrapped in a single `div` element.
33
+ //
34
+ // The serializer has 2 main methods:
35
+ // `exportBlocks`: Exports an array of blocks to HTML.
36
+ // `exportFragment`: Exports a ProseMirror fragment to HTML. This is mostly
37
+ // useful if you want to export a selection which may not start/end at the
38
+ // start/end of a block.
39
+ export interface ExternalHTMLExporter<
40
+ BSchema extends BlockSchema,
41
+ I extends InlineContentSchema,
42
+ S extends StyleSchema
43
+ > {
44
+ exportBlocks: (blocks: PartialBlock<BSchema, I, S>[]) => string;
45
+ exportProseMirrorFragment: (fragment: Fragment) => string;
46
+ }
47
+
48
+ export const createExternalHTMLExporter = <
49
+ BSchema extends BlockSchema,
50
+ I extends InlineContentSchema,
51
+ S extends StyleSchema
52
+ >(
53
+ schema: Schema,
54
+ editor: BlockNoteEditor<BSchema, I, S>
55
+ ): ExternalHTMLExporter<BSchema, I, S> => {
56
+ const serializer = DOMSerializer.fromSchema(schema) as DOMSerializer & {
57
+ serializeNodeInner: (
58
+ node: Node,
59
+ options: { document?: Document }
60
+ ) => HTMLElement;
61
+ // TODO: Should not be async, but is since we're using a rehype plugin to
62
+ // convert internal HTML to external HTML.
63
+ exportProseMirrorFragment: (fragment: Fragment) => string;
64
+ exportBlocks: (blocks: PartialBlock<BSchema, I, S>[]) => string;
65
+ };
66
+
67
+ serializer.serializeNodeInner = (
68
+ node: Node,
69
+ options: { document?: Document }
70
+ ) => serializeNodeInner(node, options, serializer, editor, true);
71
+
72
+ // Like the `internalHTMLSerializer`, also uses `serializeProseMirrorFragment`
73
+ // but additionally runs it through the `simplifyBlocks` rehype plugin to
74
+ // convert the internal HTML to external.
75
+ serializer.exportProseMirrorFragment = (fragment) => {
76
+ const externalHTML = unified()
77
+ .use(rehypeParse, { fragment: true })
78
+ .use(simplifyBlocks, {
79
+ orderedListItemBlockTypes: new Set<string>(["numberedListItem"]),
80
+ unorderedListItemBlockTypes: new Set<string>(["bulletListItem"]),
81
+ })
82
+ .use(rehypeStringify)
83
+ .processSync(serializeProseMirrorFragment(fragment, serializer));
84
+
85
+ return externalHTML.value as string;
86
+ };
87
+
88
+ serializer.exportBlocks = (blocks: PartialBlock<BSchema, I, S>[]) => {
89
+ const nodes = blocks.map((block) =>
90
+ blockToNode(block, schema, editor.styleSchema)
91
+ );
92
+ const blockGroup = schema.nodes["blockGroup"].create(null, nodes);
93
+
94
+ return serializer.exportProseMirrorFragment(Fragment.from(blockGroup));
95
+ };
96
+
97
+ return serializer;
98
+ };
@@ -0,0 +1,100 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
2
+ import { BlockNoteEditor } from "../../../editor/BlockNoteEditor";
3
+
4
+ import { addIdsToBlocks, partialBlocksToBlocksForTesting } from "../../..";
5
+ import { BlockSchema, PartialBlock } from "../../../schema/blocks/types";
6
+ import { InlineContentSchema } from "../../../schema/inlineContent/types";
7
+ import { StyleSchema } from "../../../schema/styles/types";
8
+ import { customBlocksTestCases } from "../../testUtil/cases/customBlocks";
9
+ import { customInlineContentTestCases } from "../../testUtil/cases/customInlineContent";
10
+ import { customStylesTestCases } from "../../testUtil/cases/customStyles";
11
+ import { defaultSchemaTestCases } from "../../testUtil/cases/defaultSchema";
12
+ import { createExternalHTMLExporter } from "./externalHTMLExporter";
13
+ import { createInternalHTMLSerializer } from "./internalHTMLSerializer";
14
+
15
+ async function convertToHTMLAndCompareSnapshots<
16
+ B extends BlockSchema,
17
+ I extends InlineContentSchema,
18
+ S extends StyleSchema
19
+ >(
20
+ editor: BlockNoteEditor<B, I, S>,
21
+ blocks: PartialBlock<B, I, S>[],
22
+ snapshotDirectory: string,
23
+ snapshotName: string
24
+ ) {
25
+ addIdsToBlocks(blocks);
26
+ const serializer = createInternalHTMLSerializer(
27
+ editor._tiptapEditor.schema,
28
+ editor
29
+ );
30
+ const internalHTML = serializer.serializeBlocks(blocks);
31
+ const internalHTMLSnapshotPath =
32
+ "./__snapshots__/" +
33
+ snapshotDirectory +
34
+ "/" +
35
+ snapshotName +
36
+ "/internal.html";
37
+ expect(internalHTML).toMatchFileSnapshot(internalHTMLSnapshotPath);
38
+
39
+ // turn the internalHTML back into blocks, and make sure no data was lost
40
+ const fullBlocks = partialBlocksToBlocksForTesting(
41
+ editor.blockSchema,
42
+ blocks
43
+ );
44
+ const parsed = await editor.tryParseHTMLToBlocks(internalHTML);
45
+
46
+ expect(parsed).toStrictEqual(fullBlocks);
47
+
48
+ // Create the "external" HTML, which is a cleaned up HTML representation, but lossy
49
+ const exporter = createExternalHTMLExporter(
50
+ editor._tiptapEditor.schema,
51
+ editor
52
+ );
53
+ const externalHTML = exporter.exportBlocks(blocks);
54
+ const externalHTMLSnapshotPath =
55
+ "./__snapshots__/" +
56
+ snapshotDirectory +
57
+ "/" +
58
+ snapshotName +
59
+ "/external.html";
60
+ expect(externalHTML).toMatchFileSnapshot(externalHTMLSnapshotPath);
61
+ }
62
+
63
+ const testCases = [
64
+ defaultSchemaTestCases,
65
+ customBlocksTestCases,
66
+ customStylesTestCases,
67
+ customInlineContentTestCases,
68
+ ];
69
+
70
+ describe("Test HTML conversion", () => {
71
+ for (const testCase of testCases) {
72
+ describe("Case: " + testCase.name, () => {
73
+ let editor: BlockNoteEditor<any, any, any>;
74
+
75
+ beforeEach(() => {
76
+ editor = testCase.createEditor();
77
+ });
78
+
79
+ afterEach(() => {
80
+ editor._tiptapEditor.destroy();
81
+ editor = undefined as any;
82
+
83
+ delete (window as Window & { __TEST_OPTIONS?: any }).__TEST_OPTIONS;
84
+ });
85
+
86
+ for (const document of testCase.documents) {
87
+ // eslint-disable-next-line no-loop-func
88
+ it("Convert " + document.name + " to HTML", async () => {
89
+ const nameSplit = document.name.split("/");
90
+ await convertToHTMLAndCompareSnapshots(
91
+ editor,
92
+ document.blocks,
93
+ nameSplit[0],
94
+ nameSplit[1]
95
+ );
96
+ });
97
+ }
98
+ });
99
+ }
100
+ });
@@ -0,0 +1,80 @@
1
+ import { DOMSerializer, Fragment, Node, Schema } from "prosemirror-model";
2
+ import type { BlockNoteEditor } from "../../../editor/BlockNoteEditor";
3
+ import {
4
+ BlockSchema,
5
+ InlineContentSchema,
6
+ PartialBlock,
7
+ StyleSchema,
8
+ } from "../../../schema";
9
+ import { blockToNode } from "../../nodeConversions/nodeConversions";
10
+ import {
11
+ serializeNodeInner,
12
+ serializeProseMirrorFragment,
13
+ } from "./util/sharedHTMLConversion";
14
+
15
+ // Used to serialize BlockNote blocks and ProseMirror nodes to HTML without
16
+ // losing data. Blocks are exported using the `toInternalHTML` method in their
17
+ // `blockSpec`.
18
+ //
19
+ // The HTML created by this serializer is the same as what's rendered by the
20
+ // editor to the DOM. This means that it retains the same structure as the
21
+ // editor, including the `blockGroup` and `blockContainer` wrappers. This also
22
+ // means that it can be converted back to the original blocks without any data
23
+ // loss.
24
+ //
25
+ // The serializer has 2 main methods:
26
+ // `serializeFragment`: Serializes a ProseMirror fragment to HTML. This is
27
+ // mostly useful if you want to serialize a selection which may not start/end at
28
+ // the start/end of a block.
29
+ // `serializeBlocks`: Serializes an array of blocks to HTML.
30
+ export interface InternalHTMLSerializer<
31
+ BSchema extends BlockSchema,
32
+ I extends InlineContentSchema,
33
+ S extends StyleSchema
34
+ > {
35
+ // TODO: Ideally we would expand the BlockNote API to support partial
36
+ // selections so we don't need this.
37
+ serializeProseMirrorFragment: (fragment: Fragment) => string;
38
+ serializeBlocks: (blocks: PartialBlock<BSchema, I, S>[]) => string;
39
+ }
40
+
41
+ export const createInternalHTMLSerializer = <
42
+ BSchema extends BlockSchema,
43
+ I extends InlineContentSchema,
44
+ S extends StyleSchema
45
+ >(
46
+ schema: Schema,
47
+ editor: BlockNoteEditor<BSchema, I, S>
48
+ ): InternalHTMLSerializer<BSchema, I, S> => {
49
+ const serializer = DOMSerializer.fromSchema(schema) as DOMSerializer & {
50
+ serializeNodeInner: (
51
+ node: Node,
52
+ options: { document?: Document }
53
+ ) => HTMLElement;
54
+ serializeBlocks: (blocks: PartialBlock<BSchema, I, S>[]) => string;
55
+ serializeProseMirrorFragment: (
56
+ fragment: Fragment,
57
+ options?: { document?: Document | undefined } | undefined,
58
+ target?: HTMLElement | DocumentFragment | undefined
59
+ ) => string;
60
+ };
61
+
62
+ serializer.serializeNodeInner = (
63
+ node: Node,
64
+ options: { document?: Document }
65
+ ) => serializeNodeInner(node, options, serializer, editor, false);
66
+
67
+ serializer.serializeProseMirrorFragment = (fragment: Fragment) =>
68
+ serializeProseMirrorFragment(fragment, serializer);
69
+
70
+ serializer.serializeBlocks = (blocks: PartialBlock<BSchema, I, S>[]) => {
71
+ const nodes = blocks.map((block) =>
72
+ blockToNode(block, schema, editor.styleSchema)
73
+ );
74
+ const blockGroup = schema.nodes["blockGroup"].create(null, nodes);
75
+
76
+ return serializer.serializeProseMirrorFragment(Fragment.from(blockGroup));
77
+ };
78
+
79
+ return serializer;
80
+ };
@@ -0,0 +1,128 @@
1
+ import { DOMSerializer, Fragment, Node } from "prosemirror-model";
2
+
3
+ import type { BlockNoteEditor } from "../../../../editor/BlockNoteEditor";
4
+ import {
5
+ BlockSchema,
6
+ InlineContentSchema,
7
+ StyleSchema,
8
+ } from "../../../../schema";
9
+ import { nodeToBlock } from "../../../nodeConversions/nodeConversions";
10
+
11
+ function doc(options: { document?: Document }) {
12
+ return options.document || window.document;
13
+ }
14
+
15
+ // Used to implement `serializeNodeInner` for the `internalHTMLSerializer` and
16
+ // `externalHTMLExporter`. Changes how the content of `blockContainer` nodes is
17
+ // serialized vs the default `DOMSerializer` implementation. For the
18
+ // `blockContent` node, the `toInternalHTML` or `toExternalHTML` function of its
19
+ // corresponding block is used for serialization instead of the node's
20
+ // `renderHTML` method.
21
+ export const serializeNodeInner = <
22
+ BSchema extends BlockSchema,
23
+ I extends InlineContentSchema,
24
+ S extends StyleSchema
25
+ >(
26
+ node: Node,
27
+ options: { document?: Document },
28
+ serializer: DOMSerializer,
29
+ editor: BlockNoteEditor<BSchema, I, S>,
30
+ toExternalHTML: boolean
31
+ ) => {
32
+ if (!serializer.nodes[node.type.name]) {
33
+ throw new Error("Serializer is missing a node type: " + node.type.name);
34
+ }
35
+ const { dom, contentDOM } = DOMSerializer.renderSpec(
36
+ doc(options),
37
+ serializer.nodes[node.type.name](node)
38
+ );
39
+
40
+ if (contentDOM) {
41
+ if (node.isLeaf) {
42
+ throw new RangeError("Content hole not allowed in a leaf node spec");
43
+ }
44
+
45
+ // Handles converting `blockContainer` nodes to HTML.
46
+ if (node.type.name === "blockContainer") {
47
+ const blockContentNode =
48
+ node.childCount > 0 &&
49
+ node.firstChild!.type.spec.group === "blockContent"
50
+ ? node.firstChild!
51
+ : undefined;
52
+ const blockGroupNode =
53
+ node.childCount > 0 && node.lastChild!.type.spec.group === "blockGroup"
54
+ ? node.lastChild!
55
+ : undefined;
56
+
57
+ // Converts `blockContent` node using the custom `blockSpec`'s
58
+ // `toExternalHTML` or `toInternalHTML` function.
59
+ // Note: While `blockContainer` nodes should always contain a
60
+ // `blockContent` node according to the schema, PM Fragments don't always
61
+ // conform to the schema. This is unintuitive but important as it occurs
62
+ // when copying only nested blocks.
63
+ if (blockContentNode !== undefined) {
64
+ const impl =
65
+ editor.blockImplementations[blockContentNode.type.name]
66
+ .implementation;
67
+ const toHTML = toExternalHTML
68
+ ? impl.toExternalHTML
69
+ : impl.toInternalHTML;
70
+ const blockContent = toHTML(
71
+ nodeToBlock(
72
+ node,
73
+ editor.blockSchema,
74
+ editor.inlineContentSchema,
75
+ editor.styleSchema,
76
+ editor.blockCache
77
+ ),
78
+ editor as any
79
+ );
80
+
81
+ // Converts inline nodes in the `blockContent` node's content to HTML
82
+ // using their `renderHTML` methods.
83
+ if (blockContent.contentDOM !== undefined) {
84
+ if (node.isLeaf) {
85
+ throw new RangeError(
86
+ "Content hole not allowed in a leaf node spec"
87
+ );
88
+ }
89
+
90
+ blockContent.contentDOM.appendChild(
91
+ serializer.serializeFragment(blockContentNode.content, options)
92
+ );
93
+ }
94
+
95
+ contentDOM.appendChild(blockContent.dom);
96
+ }
97
+
98
+ // Converts `blockGroup` node to HTML using its `renderHTML` method.
99
+ if (blockGroupNode !== undefined) {
100
+ serializer.serializeFragment(
101
+ Fragment.from(blockGroupNode),
102
+ options,
103
+ contentDOM
104
+ );
105
+ }
106
+ } else {
107
+ // Converts the node normally, i.e. using its `renderHTML method`.
108
+ serializer.serializeFragment(node.content, options, contentDOM);
109
+ }
110
+ }
111
+
112
+ return dom as HTMLElement;
113
+ };
114
+
115
+ // Used to implement `serializeProseMirrorFragment` for the
116
+ // `internalHTMLSerializer` and `externalHTMLExporter`. Does basically the same
117
+ // thing as `serializer.serializeFragment`, but takes fewer arguments and
118
+ // returns a string instead, to make it easier to use.
119
+ export const serializeProseMirrorFragment = (
120
+ fragment: Fragment,
121
+ serializer: DOMSerializer
122
+ ) => {
123
+ const internalHTML = serializer.serializeFragment(fragment);
124
+ const parent = document.createElement("div");
125
+ parent.appendChild(internalHTML);
126
+
127
+ return parent.innerHTML;
128
+ };
@@ -22,6 +22,19 @@ export function simplifyBlocks(options: SimplifyBlocksOptions) {
22
22
  ]);
23
23
 
24
24
  const simplifyBlocksHelper = (tree: HASTParent) => {
25
+ // Checks whether blocks in the tree are wrapped by a parent `blockGroup`
26
+ // element, in which case the `blockGroup`'s children are lifted out, and it
27
+ // is removed.
28
+ if (
29
+ tree.children.length === 1 &&
30
+ (tree.children[0] as HASTElement).properties?.["dataNodeType"] ===
31
+ "blockGroup"
32
+ ) {
33
+ const blockGroup = tree.children[0] as HASTElement;
34
+ tree.children.pop();
35
+ tree.children.push(...blockGroup.children);
36
+ }
37
+
25
38
  let numChildElements = tree.children.length;
26
39
  let activeList: HASTElement | undefined;
27
40
 
@@ -0,0 +1,5 @@
1
+ ## **Heading ***~~2~~*
2
+
3
+ Paragraph
4
+
5
+ *
@@ -0,0 +1,5 @@
1
+ Hello World
2
+
3
+ Hello World
4
+
5
+ Hello World
@@ -0,0 +1 @@
1
+ This is text with a custom fontSize
@@ -0,0 +1,2 @@
1
+ [Link1](https://www.website.com)\
2
+ [Link2](https://www.website2.com)
@@ -0,0 +1,2 @@
1
+ [Link1](https://www.website.com)\
2
+ [Link1](https://www.website.com)
@@ -0,0 +1,3 @@
1
+ ![](exampleURL)
2
+
3
+ Caption
@@ -0,0 +1,7 @@
1
+ ![](exampleURL)
2
+
3
+ Caption
4
+
5
+ ![](exampleURL)
6
+
7
+ Caption
@@ -0,0 +1 @@
1
+ [Website](https://www.website.com)[Website2](https://www.website2.com)
@@ -0,0 +1 @@
1
+ [Website](https://www.website.com)