@blocknote/core 0.30.0 → 0.31.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 (245) hide show
  1. package/dist/blocknote.cjs +9 -9
  2. package/dist/blocknote.cjs.map +1 -1
  3. package/dist/blocknote.js +2771 -2245
  4. package/dist/blocknote.js.map +1 -1
  5. package/dist/comments.cjs.map +1 -1
  6. package/dist/comments.js.map +1 -1
  7. package/dist/{en-D4taoCs4.cjs → en-BXVKCwYt.cjs} +2 -2
  8. package/dist/en-BXVKCwYt.cjs.map +1 -0
  9. package/dist/{en-B7ycW7c8.js → en-qGo6sk9V.js} +2 -3
  10. package/dist/en-qGo6sk9V.js.map +1 -0
  11. package/dist/locales.cjs +1 -1
  12. package/dist/locales.cjs.map +1 -1
  13. package/dist/locales.js +20 -39
  14. package/dist/locales.js.map +1 -1
  15. package/dist/style.css +1 -1
  16. package/dist/webpack-stats.json +1 -1
  17. package/package.json +8 -7
  18. package/src/api/README.md +1 -1
  19. package/src/api/blockManipulation/commands/insertBlocks/insertBlocks.test.ts +19 -14
  20. package/src/api/blockManipulation/commands/insertBlocks/insertBlocks.ts +7 -8
  21. package/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.test.ts +3 -3
  22. package/src/api/blockManipulation/commands/mergeBlocks/mergeBlocks.ts +12 -12
  23. package/src/api/blockManipulation/commands/moveBlocks/moveBlocks.test.ts +14 -14
  24. package/src/api/blockManipulation/commands/moveBlocks/moveBlocks.ts +16 -16
  25. package/src/api/blockManipulation/commands/nestBlock/nestBlock.ts +8 -8
  26. package/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.test.ts +12 -12
  27. package/src/api/blockManipulation/commands/replaceBlocks/replaceBlocks.ts +8 -8
  28. package/src/api/blockManipulation/commands/splitBlock/splitBlock.test.ts +10 -10
  29. package/src/api/blockManipulation/commands/splitBlock/splitBlock.ts +2 -2
  30. package/src/api/blockManipulation/commands/updateBlock/__snapshots__/updateBlock.test.ts.snap +2816 -0
  31. package/src/api/blockManipulation/commands/updateBlock/updateBlock.test.ts +200 -42
  32. package/src/api/blockManipulation/commands/updateBlock/updateBlock.ts +104 -34
  33. package/src/api/blockManipulation/getBlock/getBlock.ts +9 -9
  34. package/src/api/blockManipulation/insertContentAt.ts +1 -1
  35. package/src/api/blockManipulation/selections/selection.ts +59 -12
  36. package/src/api/blockManipulation/selections/{textCursorPosition/textCursorPosition.ts → textCursorPosition.ts} +13 -13
  37. package/src/api/blockManipulation/tables/tables.test.ts +106 -106
  38. package/src/api/blockManipulation/tables/tables.ts +35 -35
  39. package/src/api/clipboard/fromClipboard/fileDropExtension.ts +2 -2
  40. package/src/api/clipboard/fromClipboard/handleFileInsertion.ts +9 -9
  41. package/src/api/clipboard/fromClipboard/handleVSCodePaste.ts +3 -3
  42. package/src/api/clipboard/fromClipboard/pasteExtension.ts +3 -3
  43. package/src/api/clipboard/toClipboard/copyExtension.ts +22 -22
  44. package/src/api/exporters/html/externalHTMLExporter.ts +6 -6
  45. package/src/api/exporters/html/internalHTMLSerializer.ts +3 -3
  46. package/src/api/exporters/html/util/serializeBlocksExternalHTML.ts +16 -16
  47. package/src/api/exporters/html/util/serializeBlocksInternalHTML.ts +14 -14
  48. package/src/api/exporters/markdown/markdownExporter.ts +3 -3
  49. package/src/api/exporters/markdown/util/addSpacesToCheckboxesRehypePlugin.ts +3 -3
  50. package/src/api/getBlockInfoFromPos.ts +6 -6
  51. package/src/api/nodeConversions/blockToNode.ts +31 -28
  52. package/src/api/nodeConversions/fragmentToBlocks.ts +1 -1
  53. package/src/api/nodeConversions/nodeToBlock.ts +240 -41
  54. package/src/api/nodeUtil.test.ts +16 -16
  55. package/src/api/nodeUtil.ts +10 -10
  56. package/src/api/parsers/html/parseHTML.ts +1 -1
  57. package/src/api/parsers/html/util/nestedLists.ts +2 -2
  58. package/src/api/parsers/markdown/parseMarkdown.ts +1 -1
  59. package/src/api/pmUtil.ts +7 -7
  60. package/src/api/positionMapping.test.ts +3 -3
  61. package/src/api/positionMapping.ts +5 -5
  62. package/src/blocks/AudioBlockContent/AudioBlockContent.ts +4 -4
  63. package/src/blocks/CodeBlockContent/CodeBlockContent.ts +18 -18
  64. package/src/blocks/FileBlockContent/FileBlockContent.ts +2 -2
  65. package/src/blocks/FileBlockContent/helpers/parse/parseFigureElement.ts +2 -2
  66. package/src/blocks/FileBlockContent/helpers/render/createAddFileButton.ts +6 -6
  67. package/src/blocks/FileBlockContent/helpers/render/createFileBlockWrapper.ts +2 -2
  68. package/src/blocks/FileBlockContent/helpers/render/createFileNameWithIcon.ts +1 -1
  69. package/src/blocks/FileBlockContent/helpers/render/createResizableFileBlockWrapper.ts +7 -7
  70. package/src/blocks/FileBlockContent/helpers/toExternalHTML/createFigureWithCaption.ts +1 -1
  71. package/src/blocks/FileBlockContent/helpers/toExternalHTML/createLinkWithCaption.ts +1 -1
  72. package/src/blocks/FileBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts +2 -2
  73. package/src/blocks/HeadingBlockContent/HeadingBlockContent.ts +6 -6
  74. package/src/blocks/ImageBlockContent/ImageBlockContent.ts +4 -4
  75. package/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +4 -4
  76. package/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts +10 -10
  77. package/src/blocks/ListItemBlockContent/ListItemKeyboardShortcuts.ts +1 -1
  78. package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListIndexingPlugin.ts +1 -1
  79. package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +4 -4
  80. package/src/blocks/ListItemBlockContent/getListItemContent.ts +5 -5
  81. package/src/blocks/PageBreakBlockContent/PageBreakBlockContent.ts +1 -1
  82. package/src/blocks/PageBreakBlockContent/getPageBreakSlashMenuItems.ts +3 -3
  83. package/src/blocks/PageBreakBlockContent/schema.ts +2 -2
  84. package/src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts +3 -3
  85. package/src/blocks/QuoteBlockContent/QuoteBlockContent.ts +4 -4
  86. package/src/blocks/README.md +1 -1
  87. package/src/blocks/TableBlockContent/TableBlockContent.ts +37 -7
  88. package/src/blocks/TableBlockContent/TableExtension.ts +3 -3
  89. package/src/blocks/VideoBlockContent/VideoBlockContent.ts +4 -4
  90. package/src/blocks/defaultBlockHelpers.ts +8 -8
  91. package/src/blocks/defaultBlockTypeGuards.ts +16 -16
  92. package/src/blocks/defaultBlocks.ts +3 -3
  93. package/src/comments/threadstore/DefaultThreadStoreAuth.ts +3 -3
  94. package/src/comments/threadstore/ThreadStore.ts +1 -1
  95. package/src/comments/threadstore/TipTapThreadStore.ts +10 -10
  96. package/src/comments/threadstore/yjs/RESTYjsThreadStore.ts +4 -4
  97. package/src/comments/threadstore/yjs/YjsThreadStore.test.ts +2 -2
  98. package/src/comments/threadstore/yjs/YjsThreadStore.ts +14 -14
  99. package/src/comments/threadstore/yjs/YjsThreadStoreBase.ts +1 -1
  100. package/src/comments/threadstore/yjs/yjsHelpers.ts +6 -6
  101. package/src/editor/Block.css +35 -1
  102. package/src/editor/BlockNoteEditor.test.ts +10 -3
  103. package/src/editor/BlockNoteEditor.ts +95 -38
  104. package/src/editor/BlockNoteExtension.ts +26 -0
  105. package/src/editor/BlockNoteExtensions.ts +38 -22
  106. package/src/editor/BlockNoteSchema.ts +4 -4
  107. package/src/editor/BlockNoteTipTapEditor.ts +33 -12
  108. package/src/editor/README.md +1 -1
  109. package/src/editor/cursorPositionTypes.ts +1 -1
  110. package/src/editor/editor.css +15 -3
  111. package/src/editor/selectionTypes.ts +1 -1
  112. package/src/editor/transformPasted.ts +2 -2
  113. package/src/exporter/Exporter.ts +5 -5
  114. package/src/exporter/mapping.ts +7 -7
  115. package/src/extensions/BackgroundColor/BackgroundColorMark.ts +1 -1
  116. package/src/extensions/Collaboration/CursorPlugin.ts +15 -9
  117. package/src/extensions/Collaboration/ForkYDocPlugin.test.ts +166 -0
  118. package/src/extensions/Collaboration/ForkYDocPlugin.ts +174 -0
  119. package/src/extensions/Collaboration/SyncPlugin.ts +7 -4
  120. package/src/extensions/Collaboration/UndoPlugin.ts +7 -4
  121. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-editor-forked.json +30 -0
  122. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-editor.json +30 -0
  123. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap-forked.html +1 -0
  124. package/src/extensions/Collaboration/__snapshots__/fork-yjs-snap.html +1 -0
  125. package/src/extensions/Comments/CommentsPlugin.ts +80 -75
  126. package/src/extensions/Comments/userstore/UserStore.ts +2 -2
  127. package/src/extensions/FilePanel/FilePanelPlugin.ts +56 -55
  128. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +60 -30
  129. package/src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts +26 -26
  130. package/src/extensions/LinkToolbar/LinkToolbarPlugin.ts +33 -32
  131. package/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.ts +45 -42
  132. package/src/extensions/Placeholder/PlaceholderPlugin.ts +113 -110
  133. package/src/extensions/PreviousBlockType/PreviousBlockTypePlugin.ts +179 -170
  134. package/src/extensions/README.md +1 -1
  135. package/src/extensions/ShowSelection/ShowSelectionPlugin.ts +22 -19
  136. package/src/extensions/SideMenu/MultipleNodeSelection.ts +1 -1
  137. package/src/extensions/SideMenu/SideMenuPlugin.ts +49 -48
  138. package/src/extensions/SideMenu/dragging.ts +8 -8
  139. package/src/extensions/SuggestionMenu/SuggestionPlugin.ts +176 -176
  140. package/src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.ts +2 -2
  141. package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +16 -16
  142. package/src/extensions/Suggestions/SuggestionMarks.ts +175 -0
  143. package/src/extensions/TableHandles/TableHandlesPlugin.ts +199 -195
  144. package/src/extensions/TrailingNode/TrailingNodeExtension.ts +1 -1
  145. package/src/extensions/UniqueID/UniqueID.ts +6 -6
  146. package/src/extensions/getDraggableBlockFromElement.ts +1 -1
  147. package/src/fonts/inter.css +18 -9
  148. package/src/i18n/locales/ar.ts +0 -1
  149. package/src/i18n/locales/de.ts +0 -1
  150. package/src/i18n/locales/en.ts +0 -1
  151. package/src/i18n/locales/es.ts +0 -1
  152. package/src/i18n/locales/fr.ts +0 -1
  153. package/src/i18n/locales/hr.ts +0 -1
  154. package/src/i18n/locales/is.ts +0 -1
  155. package/src/i18n/locales/it.ts +0 -1
  156. package/src/i18n/locales/ja.ts +0 -1
  157. package/src/i18n/locales/ko.ts +0 -1
  158. package/src/i18n/locales/nl.ts +0 -1
  159. package/src/i18n/locales/no.ts +0 -1
  160. package/src/i18n/locales/pl.ts +0 -1
  161. package/src/i18n/locales/pt.ts +0 -1
  162. package/src/i18n/locales/ru.ts +0 -1
  163. package/src/i18n/locales/sk.ts +0 -1
  164. package/src/i18n/locales/uk.ts +0 -1
  165. package/src/i18n/locales/vi.ts +0 -1
  166. package/src/i18n/locales/zh-tw.ts +0 -1
  167. package/src/i18n/locales/zh.ts +0 -1
  168. package/src/index.ts +18 -8
  169. package/src/locales.ts +1 -1
  170. package/src/pm-nodes/BlockContainer.ts +1 -1
  171. package/src/pm-nodes/BlockGroup.ts +2 -2
  172. package/src/pm-nodes/Doc.ts +5 -4
  173. package/src/schema/README.md +1 -1
  174. package/src/schema/blocks/createSpec.ts +14 -14
  175. package/src/schema/blocks/internal.ts +17 -17
  176. package/src/schema/blocks/types.ts +25 -25
  177. package/src/schema/inlineContent/createSpec.ts +16 -20
  178. package/src/schema/inlineContent/internal.ts +9 -9
  179. package/src/schema/inlineContent/types.ts +26 -26
  180. package/src/schema/propTypes.ts +8 -8
  181. package/src/schema/styles/createSpec.ts +2 -2
  182. package/src/schema/styles/internal.ts +7 -7
  183. package/src/schema/styles/types.ts +2 -2
  184. package/src/util/EventEmitter.ts +4 -4
  185. package/src/util/README.md +1 -1
  186. package/src/util/combineByGroup.ts +1 -1
  187. package/src/util/table.ts +33 -30
  188. package/types/src/api/blockManipulation/commands/insertBlocks/insertBlocks.d.ts +1 -1
  189. package/types/src/api/blockManipulation/commands/removeBlocks/removeBlocks.d.ts +4 -0
  190. package/types/src/api/blockManipulation/commands/removeBlocks/removeBlocks.test.d.ts +1 -0
  191. package/types/src/api/blockManipulation/commands/updateBlock/updateBlock.d.ts +3 -1
  192. package/types/src/api/blockManipulation/selections/selection.d.ts +10 -0
  193. package/types/src/api/blockManipulation/selections/textCursorPosition.d.ts +5 -0
  194. package/types/src/api/blockManipulation/transactions.test.d.ts +0 -0
  195. package/types/src/api/clipboard/clipboardExternal.test.d.ts +1 -0
  196. package/types/src/api/clipboard/clipboardInternal.test.d.ts +1 -0
  197. package/types/src/api/clipboard/testUtil.d.ts +541 -0
  198. package/types/src/api/exporters/html/htmlConversion.test.d.ts +1 -0
  199. package/types/src/api/exporters/markdown/markdownExporter.test.d.ts +1 -0
  200. package/types/src/api/nodeConversions/nodeConversions.test.d.ts +1 -0
  201. package/types/src/api/nodeConversions/nodeToBlock.d.ts +39 -2
  202. package/types/src/api/parsers/html/parseHTML.test.d.ts +1 -0
  203. package/types/src/api/parsers/markdown/parseMarkdown.test.d.ts +1 -0
  204. package/types/src/api/pmUtil.d.ts +3 -3
  205. package/types/src/api/testUtil/cases/customBlocks.d.ts +670 -0
  206. package/types/src/api/testUtil/cases/customInlineContent.d.ts +558 -0
  207. package/types/src/api/testUtil/cases/customStyles.d.ts +552 -0
  208. package/types/src/api/testUtil/cases/defaultSchema.d.ts +4 -0
  209. package/types/src/api/testUtil/index.d.ts +14 -0
  210. package/types/src/api/testUtil/partialBlockTestUtil.d.ts +9 -0
  211. package/types/src/api/testUtil/paste.d.ts +2 -0
  212. package/types/src/blocks/CodeBlockContent/defaultSupportedLanguages.d.ts +6 -0
  213. package/types/src/blocks/TableBlockContent/TableBlockContent.d.ts +9 -1
  214. package/types/src/editor/BlockNoteEditor.d.ts +58 -10
  215. package/types/src/editor/BlockNoteExtension.d.ts +9 -0
  216. package/types/src/editor/BlockNoteExtensions.d.ts +2 -2
  217. package/types/src/editor/BlockNoteTipTapEditor.d.ts +2 -2
  218. package/types/src/extensions/Collaboration/CursorPlugin.d.ts +3 -3
  219. package/types/src/extensions/Collaboration/ForkYDocPlugin.d.ts +41 -0
  220. package/types/src/extensions/Collaboration/ForkYDocPlugin.test.d.ts +1 -0
  221. package/types/src/extensions/Collaboration/SyncPlugin.d.ts +3 -3
  222. package/types/src/extensions/Collaboration/UndoPlugin.d.ts +3 -3
  223. package/types/src/extensions/Collaboration/createCollaborationExtensions.d.ts +17 -0
  224. package/types/src/extensions/Comments/CommentsPlugin.d.ts +2 -4
  225. package/types/src/extensions/FilePanel/FilePanelPlugin.d.ts +3 -4
  226. package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +5 -5
  227. package/types/src/extensions/LinkToolbar/LinkToolbarPlugin.d.ts +3 -4
  228. package/types/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.d.ts +2 -3
  229. package/types/src/extensions/Placeholder/PlaceholderPlugin.d.ts +2 -3
  230. package/types/src/extensions/PreviousBlockType/PreviousBlockTypePlugin.d.ts +2 -3
  231. package/types/src/extensions/ShowSelection/ShowSelectionPlugin.d.ts +2 -3
  232. package/types/src/extensions/SideMenu/SideMenuPlugin.d.ts +3 -4
  233. package/types/src/extensions/SuggestionMenu/SuggestionPlugin.d.ts +2 -4
  234. package/types/src/extensions/Suggestions/SuggestionMarks.d.ts +4 -0
  235. package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +5 -6
  236. package/types/src/i18n/locales/en.d.ts +0 -1
  237. package/types/src/i18n/locales/sk.d.ts +0 -1
  238. package/types/src/index.d.ts +15 -8
  239. package/dist/en-B7ycW7c8.js.map +0 -1
  240. package/dist/en-D4taoCs4.cjs.map +0 -1
  241. package/dist/tsconfig.tsbuildinfo +0 -1
  242. package/src/api/blockManipulation/selections/__snapshots__/selection.test.ts.snap +0 -844
  243. package/src/api/blockManipulation/selections/selection.test.ts +0 -72
  244. package/src/api/blockManipulation/selections/textCursorPosition/__snapshots__/textCursorPosition.test.ts.snap +0 -316
  245. package/src/api/blockManipulation/selections/textCursorPosition/textCursorPosition.test.ts +0 -74
@@ -26,13 +26,13 @@ export class YjsThreadStore extends YjsThreadStoreBase {
26
26
  constructor(
27
27
  private readonly userId: string,
28
28
  threadsYMap: Y.Map<any>,
29
- auth: ThreadStoreAuth
29
+ auth: ThreadStoreAuth,
30
30
  ) {
31
31
  super(threadsYMap, auth);
32
32
  }
33
33
 
34
34
  private transact = <T, R>(
35
- fn: (options: T) => R
35
+ fn: (options: T) => R,
36
36
  ): ((options: T) => Promise<R>) => {
37
37
  return async (options: T) => {
38
38
  return this.threadsYMap.doc!.transact(() => {
@@ -79,7 +79,7 @@ export class YjsThreadStore extends YjsThreadStoreBase {
79
79
  this.threadsYMap.set(thread.id, threadToYMap(thread));
80
80
 
81
81
  return thread;
82
- }
82
+ },
83
83
  );
84
84
 
85
85
  // YjsThreadStore does not support addThreadToDocument
@@ -121,7 +121,7 @@ export class YjsThreadStore extends YjsThreadStoreBase {
121
121
 
122
122
  yThread.set("updatedAt", new Date().getTime());
123
123
  return comment;
124
- }
124
+ },
125
125
  );
126
126
 
127
127
  public updateComment = this.transact(
@@ -140,7 +140,7 @@ export class YjsThreadStore extends YjsThreadStoreBase {
140
140
 
141
141
  const yCommentIndex = yArrayFindIndex(
142
142
  yThread.get("comments"),
143
- (comment) => comment.get("id") === options.commentId
143
+ (comment) => comment.get("id") === options.commentId,
144
144
  );
145
145
 
146
146
  if (yCommentIndex === -1) {
@@ -156,7 +156,7 @@ export class YjsThreadStore extends YjsThreadStoreBase {
156
156
  yComment.set("body", options.comment.body);
157
157
  yComment.set("updatedAt", new Date().getTime());
158
158
  yComment.set("metadata", options.comment.metadata);
159
- }
159
+ },
160
160
  );
161
161
 
162
162
  public deleteComment = this.transact(
@@ -172,7 +172,7 @@ export class YjsThreadStore extends YjsThreadStoreBase {
172
172
 
173
173
  const yCommentIndex = yArrayFindIndex(
174
174
  yThread.get("comments"),
175
- (comment) => comment.get("id") === options.commentId
175
+ (comment) => comment.get("id") === options.commentId,
176
176
  );
177
177
 
178
178
  if (yCommentIndex === -1) {
@@ -210,13 +210,13 @@ export class YjsThreadStore extends YjsThreadStoreBase {
210
210
  }
211
211
 
212
212
  yThread.set("updatedAt", new Date().getTime());
213
- }
213
+ },
214
214
  );
215
215
 
216
216
  public deleteThread = this.transact((options: { threadId: string }) => {
217
217
  if (
218
218
  !this.auth.canDeleteThread(
219
- yMapToThread(this.threadsYMap.get(options.threadId))
219
+ yMapToThread(this.threadsYMap.get(options.threadId)),
220
220
  )
221
221
  ) {
222
222
  throw new Error("Not authorized");
@@ -263,7 +263,7 @@ export class YjsThreadStore extends YjsThreadStoreBase {
263
263
 
264
264
  const yCommentIndex = yArrayFindIndex(
265
265
  yThread.get("comments"),
266
- (comment) => comment.get("id") === options.commentId
266
+ (comment) => comment.get("id") === options.commentId,
267
267
  );
268
268
 
269
269
  if (yCommentIndex === -1) {
@@ -292,7 +292,7 @@ export class YjsThreadStore extends YjsThreadStoreBase {
292
292
  reaction.set("userId", this.userId);
293
293
  reactionsByUser.set(key, reaction);
294
294
  }
295
- }
295
+ },
296
296
  );
297
297
 
298
298
  public deleteReaction = this.transact(
@@ -304,7 +304,7 @@ export class YjsThreadStore extends YjsThreadStoreBase {
304
304
 
305
305
  const yCommentIndex = yArrayFindIndex(
306
306
  yThread.get("comments"),
307
- (comment) => comment.get("id") === options.commentId
307
+ (comment) => comment.get("id") === options.commentId,
308
308
  );
309
309
 
310
310
  if (yCommentIndex === -1) {
@@ -324,13 +324,13 @@ export class YjsThreadStore extends YjsThreadStoreBase {
324
324
  const reactionsByUser = yComment.get("reactionsByUser");
325
325
 
326
326
  reactionsByUser.delete(key);
327
- }
327
+ },
328
328
  );
329
329
  }
330
330
 
331
331
  function yArrayFindIndex(
332
332
  yArray: Y.Array<any>,
333
- predicate: (item: any) => boolean
333
+ predicate: (item: any) => boolean,
334
334
  ) {
335
335
  for (let i = 0; i < yArray.length; i++) {
336
336
  if (predicate(yArray.get(i))) {
@@ -11,7 +11,7 @@ import { yMapToThread } from "./yjsHelpers.js";
11
11
  export abstract class YjsThreadStoreBase extends ThreadStore {
12
12
  constructor(
13
13
  protected readonly threadsYMap: Y.Map<any>,
14
- auth: ThreadStoreAuth
14
+ auth: ThreadStoreAuth,
15
15
  ) {
16
16
  super(auth);
17
17
  }
@@ -52,7 +52,7 @@ type SingleUserCommentReactionData = {
52
52
  };
53
53
 
54
54
  export function yMapToReaction(
55
- yMap: Y.Map<any>
55
+ yMap: Y.Map<any>,
56
56
  ): SingleUserCommentReactionData {
57
57
  return {
58
58
  emoji: yMap.get("emoji"),
@@ -63,7 +63,7 @@ export function yMapToReaction(
63
63
 
64
64
  function yMapToReactions(yMap: Y.Map<any>): CommentReactionData[] {
65
65
  const flatReactions = [...yMap.values()].map((reaction: Y.Map<any>) =>
66
- yMapToReaction(reaction)
66
+ yMapToReaction(reaction),
67
67
  );
68
68
  // combine reactions by the same emoji
69
69
  return flatReactions.reduce(
@@ -74,8 +74,8 @@ function yMapToReactions(yMap: Y.Map<any>): CommentReactionData[] {
74
74
  existingReaction.createdAt = new Date(
75
75
  Math.min(
76
76
  existingReaction.createdAt.getTime(),
77
- reaction.createdAt.getTime()
78
- )
77
+ reaction.createdAt.getTime(),
78
+ ),
79
79
  );
80
80
  } else {
81
81
  acc.push({
@@ -86,7 +86,7 @@ function yMapToReactions(yMap: Y.Map<any>): CommentReactionData[] {
86
86
  }
87
87
  return acc;
88
88
  },
89
- [] as CommentReactionData[]
89
+ [] as CommentReactionData[],
90
90
  );
91
91
  }
92
92
 
@@ -113,7 +113,7 @@ export function yMapToThread(yMap: Y.Map<any>): ThreadData {
113
113
  createdAt: new Date(yMap.get("createdAt")),
114
114
  updatedAt: new Date(yMap.get("updatedAt")),
115
115
  comments: ((yMap.get("comments") as Y.Array<Y.Map<any>>) || []).map(
116
- (comment) => yMapToComment(comment)
116
+ (comment) => yMapToComment(comment),
117
117
  ),
118
118
  resolved: yMap.get("resolved"),
119
119
  resolvedUpdatedAt: new Date(yMap.get("resolvedUpdatedAt")),
@@ -23,6 +23,14 @@ BASIC STYLES
23
23
  */
24
24
  }
25
25
 
26
+ /* We can't set `display: flex` on `.bn-block-content` while it has inline
27
+ content (see #1629). However, it's necessary to set alignment of blocks
28
+ without content as these can't use `text-align`, so this additional rule is
29
+ used. */
30
+ .bn-block-content:not(:has(.bn-inline-content)) {
31
+ display: flex;
32
+ }
33
+
26
34
  .bn-block-content::before {
27
35
  /* content: ""; */
28
36
  transition: all 0.2s;
@@ -144,6 +152,11 @@ NESTED BLOCKS
144
152
 
145
153
  .bn-block-outer:not([data-prev-type])
146
154
  > .bn-block
155
+ > .bn-block-content[data-content-type="heading"],
156
+ .bn-block-outer:not([data-prev-type])
157
+ > .bn-block
158
+ > div[data-type="modification"]
159
+ > div[data-type="modification"]
147
160
  > .bn-block-content[data-content-type="heading"] {
148
161
  font-size: var(--level);
149
162
  font-weight: bold;
@@ -187,6 +200,10 @@ NESTED BLOCKS
187
200
 
188
201
  .bn-block-outer:not([data-prev-type])
189
202
  > .bn-block
203
+ > .bn-block-content[data-content-type="numberedListItem"]::before,
204
+ .bn-block-outer:not([data-prev-type])
205
+ > .bn-block
206
+ > div[data-type="modification"]
190
207
  > .bn-block-content[data-content-type="numberedListItem"]::before {
191
208
  content: var(--index) ".";
192
209
  }
@@ -231,6 +248,10 @@ NESTED BLOCKS
231
248
 
232
249
  .bn-block-outer:not([data-prev-type])
233
250
  > .bn-block
251
+ > .bn-block-content[data-content-type="bulletListItem"]::before,
252
+ .bn-block-outer:not([data-prev-type])
253
+ > .bn-block
254
+ > div[data-type="modification"]
234
255
  > .bn-block-content[data-content-type="bulletListItem"]::before {
235
256
  content: "•";
236
257
  }
@@ -248,6 +269,12 @@ NESTED BLOCKS
248
269
  ~ .bn-block-group
249
270
  > .bn-block-outer:not([data-prev-type])
250
271
  > .bn-block
272
+ > .bn-block-content[data-content-type="bulletListItem"]::before,
273
+ [data-content-type="bulletListItem"]
274
+ ~ .bn-block-group
275
+ > .bn-block-outer:not([data-prev-type])
276
+ > .bn-block
277
+ > div[data-type="modification"]
251
278
  > .bn-block-content[data-content-type="bulletListItem"]::before {
252
279
  content: "◦";
253
280
  }
@@ -269,6 +296,14 @@ NESTED BLOCKS
269
296
  ~ .bn-block-group
270
297
  > .bn-block-outer:not([data-prev-type])
271
298
  > .bn-block
299
+ > .bn-block-content[data-content-type="bulletListItem"]::before,
300
+ [data-content-type="bulletListItem"]
301
+ ~ .bn-block-group
302
+ [data-content-type="bulletListItem"]
303
+ ~ .bn-block-group
304
+ > .bn-block-outer:not([data-prev-type])
305
+ > .bn-block
306
+ > div[data-type="modification"]
272
307
  > .bn-block-content[data-content-type="bulletListItem"]::before {
273
308
  content: "▪";
274
309
  }
@@ -434,7 +469,6 @@ NESTED BLOCKS
434
469
  position: absolute;
435
470
  font-style: italic;
436
471
  }
437
-
438
472
  /* TODO: should this be here? */
439
473
 
440
474
  /* TEXT COLORS */
@@ -18,7 +18,7 @@ it("creates an editor", () => {
18
18
  it("immediately replaces doc", async () => {
19
19
  const editor = BlockNoteEditor.create();
20
20
  const blocks = await editor.tryParseMarkdownToBlocks(
21
- "This is a normal text\n\n# And this is a large heading"
21
+ "This is a normal text\n\n# And this is a large heading",
22
22
  );
23
23
  editor.replaceBlocks(editor.document, blocks);
24
24
  expect(editor.document).toMatchInlineSnapshot(`
@@ -67,14 +67,21 @@ it("adds id attribute when requested", async () => {
67
67
  setIdAttribute: true,
68
68
  });
69
69
  const blocks = await editor.tryParseMarkdownToBlocks(
70
- "This is a normal text\n\n# And this is a large heading"
70
+ "This is a normal text\n\n# And this is a large heading",
71
71
  );
72
72
  editor.replaceBlocks(editor.document, blocks);
73
73
  expect(await editor.blocksToFullHTML(editor.document)).toMatchInlineSnapshot(
74
- `"<div class="bn-block-group" data-node-type="blockGroup"><div class="bn-block-outer" data-node-type="blockOuter" data-id="1" id="1"><div class="bn-block" data-node-type="blockContainer" data-id="1" id="1"><div class="bn-block-content" data-content-type="paragraph"><p class="bn-inline-content">This is a normal text</p></div></div></div><div class="bn-block-outer" data-node-type="blockOuter" data-id="2" id="2"><div class="bn-block" data-node-type="blockContainer" data-id="2" id="2"><div class="bn-block-content" data-content-type="heading"><h1 class="bn-inline-content">And this is a large heading</h1></div></div></div></div>"`
74
+ `"<div class="bn-block-group" data-node-type="blockGroup"><div class="bn-block-outer" data-node-type="blockOuter" data-id="1" id="1"><div class="bn-block" data-node-type="blockContainer" data-id="1" id="1"><div class="bn-block-content" data-content-type="paragraph"><p class="bn-inline-content">This is a normal text</p></div></div></div><div class="bn-block-outer" data-node-type="blockOuter" data-id="2" id="2"><div class="bn-block" data-node-type="blockContainer" data-id="2" id="2"><div class="bn-block-content" data-content-type="heading"><h1 class="bn-inline-content">And this is a large heading</h1></div></div></div></div>"`,
75
75
  );
76
76
  });
77
77
 
78
+ it("updates block", () => {
79
+ const editor = BlockNoteEditor.create();
80
+ editor.updateBlock(editor.document[0], {
81
+ content: "hello",
82
+ });
83
+ });
84
+
78
85
  it("block prop types", () => {
79
86
  // this test checks whether the block props are correctly typed in typescript
80
87
  const editor = BlockNoteEditor.create();
@@ -33,12 +33,13 @@ import {
33
33
  import { insertContentAt } from "../api/blockManipulation/insertContentAt.js";
34
34
  import {
35
35
  getSelection,
36
+ getSelectionCutBlocks,
36
37
  setSelection,
37
38
  } from "../api/blockManipulation/selections/selection.js";
38
39
  import {
39
40
  getTextCursorPosition,
40
41
  setTextCursorPosition,
41
- } from "../api/blockManipulation/selections/textCursorPosition/textCursorPosition.js";
42
+ } from "../api/blockManipulation/selections/textCursorPosition.js";
42
43
  import { createExternalHTMLExporter } from "../api/exporters/html/externalHTMLExporter.js";
43
44
  import { blocksToMarkdown } from "../api/exporters/markdown/markdownExporter.js";
44
45
  import { HTMLToBlocks } from "../api/parsers/html/parseHTML.js";
@@ -93,6 +94,7 @@ import {
93
94
  import { Dictionary } from "../i18n/dictionary.js";
94
95
  import { en } from "../i18n/locales/index.js";
95
96
 
97
+ import { redo, undo } from "@tiptap/pm/history";
96
98
  import {
97
99
  TextSelection,
98
100
  type Command,
@@ -101,11 +103,10 @@ import {
101
103
  } from "@tiptap/pm/state";
102
104
  import { dropCursor } from "prosemirror-dropcursor";
103
105
  import { EditorView } from "prosemirror-view";
104
- import { undoCommand, redoCommand, ySyncPluginKey } from "y-prosemirror";
105
- import { undo, redo } from "@tiptap/pm/history";
106
+ import { redoCommand, undoCommand, ySyncPluginKey } from "y-prosemirror";
106
107
  import { createInternalHTMLSerializer } from "../api/exporters/html/internalHTMLSerializer.js";
107
108
  import { inlineContentToNodes } from "../api/nodeConversions/blockToNode.js";
108
- import { nodeToBlock } from "../api/nodeConversions/nodeToBlock.js";
109
+ import { docToBlocks } from "../api/nodeConversions/nodeToBlock.js";
109
110
  import {
110
111
  BlocksChanged,
111
112
  getBlocksChangedByTransaction,
@@ -113,20 +114,26 @@ import {
113
114
  import { nestedListsToBlockNoteStructure } from "../api/parsers/html/util/nestedLists.js";
114
115
  import { CodeBlockOptions } from "../blocks/CodeBlockContent/CodeBlockContent.js";
115
116
  import type { ThreadStore, User } from "../comments/index.js";
116
- import "../style.css";
117
+ import type { CursorPlugin } from "../extensions/Collaboration/CursorPlugin.js";
118
+ import type { ForkYDocPlugin } from "../extensions/Collaboration/ForkYDocPlugin.js";
117
119
  import { EventEmitter } from "../util/EventEmitter.js";
118
- import { CursorPlugin } from "../extensions/Collaboration/CursorPlugin.js";
120
+ import { BlockNoteExtension } from "./BlockNoteExtension.js";
121
+
122
+ import "../style.css";
119
123
 
124
+ /**
125
+ * A factory function that returns a BlockNoteExtension
126
+ * This is useful so we can create extensions that require an editor instance
127
+ * in the constructor
128
+ */
120
129
  export type BlockNoteExtensionFactory = (
121
130
  editor: BlockNoteEditor<any, any, any>,
122
131
  ) => BlockNoteExtension;
123
132
 
124
- export type BlockNoteExtension =
125
- | AnyExtension
126
- | {
127
- plugin: Plugin;
128
- priority?: number;
129
- };
133
+ /**
134
+ * We support Tiptap extensions and BlockNoteExtension based extensions
135
+ */
136
+ export type SupportedExtension = AnyExtension | BlockNoteExtension;
130
137
 
131
138
  export type BlockCache<
132
139
  BSchema extends BlockSchema = any,
@@ -369,10 +376,17 @@ export type BlockNoteEditorOptions<
369
376
  _tiptapOptions: Partial<EditorOptions>;
370
377
 
371
378
  /**
372
- * (experimental) add extra prosemirror plugins or tiptap extensions to the editor
379
+ * (experimental) add extra extensions to the editor
380
+ *
381
+ * @deprecated, should use `extensions` instead
373
382
  */
374
383
  _extensions: Record<string, BlockNoteExtension | BlockNoteExtensionFactory>;
375
384
 
385
+ /**
386
+ * Register
387
+ */
388
+ extensions: Array<BlockNoteExtension | BlockNoteExtensionFactory>;
389
+
376
390
  /**
377
391
  * Boolean indicating whether the editor is in headless mode.
378
392
  * Headless mode means we can use features like importing / exporting blocks,
@@ -404,7 +418,7 @@ export class BlockNoteEditor<
404
418
  /**
405
419
  * extensions that are added to the editor, can be tiptap extensions or prosemirror plugins
406
420
  */
407
- public readonly extensions: Record<string, BlockNoteExtension> = {};
421
+ public extensions: Record<string, SupportedExtension> = {};
408
422
 
409
423
  /**
410
424
  * Boolean indicating whether the editor is in headless mode.
@@ -473,8 +487,10 @@ export class BlockNoteEditor<
473
487
 
474
488
  private readonly showSelectionPlugin: ShowSelectionPlugin;
475
489
 
476
- private readonly cursorPlugin: CursorPlugin;
477
-
490
+ /**
491
+ * The plugin for forking a document, only defined if in collaboration mode
492
+ */
493
+ public readonly forkYDocPlugin?: ForkYDocPlugin;
478
494
  /**
479
495
  * The `uploadFile` method is what the editor uses when files need to be uploaded (for example when selecting an image to upload).
480
496
  * This method should set when creating the editor as this is application-specific.
@@ -609,6 +625,16 @@ export class BlockNoteEditor<
609
625
  });
610
626
 
611
627
  // add extensions from options
628
+ for (let ext of newOptions.extensions || []) {
629
+ if (typeof ext === "function") {
630
+ // factory
631
+ ext = ext(this);
632
+ }
633
+ const key = (ext.constructor as any).name();
634
+ this.extensions[key] = ext;
635
+ }
636
+
637
+ // (when passed in via the deprecated `_extensions` option)
612
638
  Object.entries(newOptions._extensions || {}).forEach(([key, ext]) => {
613
639
  if (typeof ext === "function") {
614
640
  // factory
@@ -625,7 +651,7 @@ export class BlockNoteEditor<
625
651
  this.tableHandles = this.extensions["tableHandles"] as any;
626
652
  this.comments = this.extensions["comments"] as any;
627
653
  this.showSelectionPlugin = this.extensions["showSelection"] as any;
628
- this.cursorPlugin = this.extensions["yCursorPlugin"] as any;
654
+ this.forkYDocPlugin = this.extensions["forkYDocPlugin"] as any;
629
655
 
630
656
  if (newOptions.uploadFile) {
631
657
  const uploadFile = newOptions.uploadFile;
@@ -691,20 +717,19 @@ export class BlockNoteEditor<
691
717
  return ext;
692
718
  }
693
719
 
694
- if (!ext.plugin) {
695
- throw new Error(
696
- "Extension should either be a TipTap extension or a ProseMirror plugin in a plugin property",
697
- );
720
+ if (ext instanceof BlockNoteExtension && !ext.plugins.length) {
721
+ return undefined;
698
722
  }
699
723
 
700
724
  // "blocknote" extensions (prosemirror plugins)
701
725
  return Extension.create({
702
726
  name: key,
703
727
  priority: ext.priority,
704
- addProseMirrorPlugins: () => [ext.plugin],
728
+ addProseMirrorPlugins: () => ext.plugins,
705
729
  });
706
730
  }),
707
- ];
731
+ ].filter((ext): ext is Extension => ext !== undefined);
732
+
708
733
  const tiptapOptions: BlockNoteTipTapEditorOptions = {
709
734
  ...blockNoteTipTapOptions,
710
735
  ...newOptions._tiptapOptions,
@@ -865,6 +890,26 @@ export class BlockNoteEditor<
865
890
  }
866
891
  }
867
892
 
893
+ // TO DISCUSS
894
+ /**
895
+ * Shorthand to get a typed extension from the editor, by
896
+ * just passing in the extension class.
897
+ *
898
+ * @param ext - The extension class to get
899
+ * @param key - optional, the key of the extension in the extensions object (defaults to the extension name)
900
+ * @returns The extension instance
901
+ */
902
+ public extension<T extends BlockNoteExtension>(
903
+ ext: { new (...args: any[]): T } & typeof BlockNoteExtension,
904
+ key = ext.name(),
905
+ ): T {
906
+ const extension = this.extensions[key] as T;
907
+ if (!extension) {
908
+ throw new Error(`Extension ${key} not found`);
909
+ }
910
+ return extension;
911
+ }
912
+
868
913
  /**
869
914
  * Mount the editor to a parent DOM element. Call mount(undefined) to clean up
870
915
  *
@@ -946,15 +991,7 @@ export class BlockNoteEditor<
946
991
  */
947
992
  public get document(): Block<BSchema, ISchema, SSchema>[] {
948
993
  return this.transact((tr) => {
949
- const blocks: Block<BSchema, ISchema, SSchema>[] = [];
950
-
951
- tr.doc.firstChild!.descendants((node) => {
952
- blocks.push(nodeToBlock(node, this.pmSchema));
953
-
954
- return false;
955
- });
956
-
957
- return blocks;
994
+ return docToBlocks(tr.doc, this.pmSchema);
958
995
  });
959
996
  }
960
997
 
@@ -1099,12 +1136,26 @@ export class BlockNoteEditor<
1099
1136
  }
1100
1137
 
1101
1138
  /**
1102
- * Gets a snapshot of the current selection.
1139
+ * Gets a snapshot of the current selection. This contains all blocks (included nested blocks)
1140
+ * that the selection spans across.
1141
+ *
1142
+ * If the selection starts / ends halfway through a block, the returned data will contain the entire block.
1103
1143
  */
1104
1144
  public getSelection(): Selection<BSchema, ISchema, SSchema> | undefined {
1105
1145
  return this.transact((tr) => getSelection(tr));
1106
1146
  }
1107
1147
 
1148
+ /**
1149
+ * Gets a snapshot of the current selection. This contains all blocks (included nested blocks)
1150
+ * that the selection spans across.
1151
+ *
1152
+ * If the selection starts / ends halfway through a block, the returned block will be
1153
+ * only the part of the block that is included in the selection.
1154
+ */
1155
+ public getSelectionCutBlocks() {
1156
+ return this.transact((tr) => getSelectionCutBlocks(tr));
1157
+ }
1158
+
1108
1159
  /**
1109
1160
  * Sets the selection to a range of blocks.
1110
1161
  * @param startBlock The identifier of the block that should be the start of the selection.
@@ -1231,7 +1282,10 @@ export class BlockNoteEditor<
1231
1282
  *
1232
1283
  * @param content can be a string, or array of partial inline content elements
1233
1284
  */
1234
- public insertInlineContent(content: PartialInlineContent<ISchema, SSchema>) {
1285
+ public insertInlineContent(
1286
+ content: PartialInlineContent<ISchema, SSchema>,
1287
+ { updateSelection = false }: { updateSelection?: boolean } = {},
1288
+ ) {
1235
1289
  const nodes = inlineContentToNodes(content, this.pmSchema);
1236
1290
 
1237
1291
  this.transact((tr) => {
@@ -1242,6 +1296,9 @@ export class BlockNoteEditor<
1242
1296
  to: tr.selection.to,
1243
1297
  },
1244
1298
  nodes,
1299
+ {
1300
+ updateSelection,
1301
+ },
1245
1302
  );
1246
1303
  });
1247
1304
  }
@@ -1494,7 +1551,7 @@ export class BlockNoteEditor<
1494
1551
  );
1495
1552
  }
1496
1553
 
1497
- this.cursorPlugin.updateUser(user);
1554
+ (this.extensions["yCursorPlugin"] as CursorPlugin).updateUser(user);
1498
1555
  }
1499
1556
 
1500
1557
  /**
@@ -1589,8 +1646,8 @@ export class BlockNoteEditor<
1589
1646
  if (!this.prosemirrorView) {
1590
1647
  return undefined;
1591
1648
  }
1592
- const state = this.prosemirrorView?.state;
1593
- const { selection } = state;
1649
+
1650
+ const { selection } = this.prosemirrorState;
1594
1651
 
1595
1652
  // support for CellSelections
1596
1653
  const { ranges } = selection;
@@ -1635,7 +1692,7 @@ export class BlockNoteEditor<
1635
1692
  if (pluginState?.deleteTriggerCharacter) {
1636
1693
  tr.insertText(triggerCharacter);
1637
1694
  }
1638
- tr.scrollIntoView().setMeta(this.suggestionMenus.plugin, {
1695
+ tr.scrollIntoView().setMeta(this.suggestionMenus.plugins[0], {
1639
1696
  triggerCharacter: triggerCharacter,
1640
1697
  deleteTriggerCharacter: pluginState?.deleteTriggerCharacter || false,
1641
1698
  ignoreQueryLength: pluginState?.ignoreQueryLength || false,
@@ -0,0 +1,26 @@
1
+ import { Plugin } from "prosemirror-state";
2
+ import { EventEmitter } from "../util/EventEmitter.js";
3
+
4
+ export abstract class BlockNoteExtension<
5
+ TEvent extends Record<string, any> = any,
6
+ > extends EventEmitter<TEvent> {
7
+ public static name(): string {
8
+ throw new Error("You must implement the name method in your extension");
9
+ }
10
+
11
+ protected addProsemirrorPlugin(plugin: Plugin) {
12
+ this.plugins.push(plugin);
13
+ }
14
+
15
+ public readonly plugins: Plugin[] = [];
16
+ public get priority(): number | undefined {
17
+ return undefined;
18
+ }
19
+
20
+ // eslint-disable-next-line
21
+ constructor(..._args: any[]) {
22
+ super();
23
+ // Allow subclasses to have constructors with parameters
24
+ // without this, we can't easily implement BlockNoteEditor.extension(MyExtension) pattern
25
+ }
26
+ }