@@ -29,7 +29,6 @@ import {
29
29
BlockSchema ,
30
30
PartialBlock ,
31
31
} from "./extensions/Blocks/api/blockTypes" ;
32
- import { TextCursorPosition } from "./extensions/Blocks/api/cursorPositionTypes" ;
33
32
import {
34
33
DefaultBlockSchema ,
35
34
defaultBlockSchema ,
@@ -42,6 +41,7 @@ import {
42
41
import { Selection } from "./extensions/Blocks/api/selectionTypes" ;
43
42
import { getBlockInfoFromPos } from "./extensions/Blocks/helpers/getBlockInfoFromPos" ;
44
43
44
+ import { TextCursorPosition } from "./extensions/Blocks/api/cursorPositionTypes" ;
45
45
import { FormattingToolbarProsemirrorPlugin } from "./extensions/FormattingToolbar/FormattingToolbarPlugin" ;
46
46
import { HyperlinkToolbarProsemirrorPlugin } from "./extensions/HyperlinkToolbar/HyperlinkToolbarPlugin" ;
47
47
import { ImageToolbarProsemirrorPlugin } from "./extensions/ImageToolbar/ImageToolbarPlugin" ;
@@ -217,6 +217,12 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
217
217
218
218
this . uploadFile = newOptions . uploadFile ;
219
219
220
+ if ( newOptions . collaboration && newOptions . initialContent ) {
221
+ console . warn (
222
+ "When using Collaboration, initialContent might cause conflicts, because changes should come from the collaboration provider"
223
+ ) ;
224
+ }
225
+
220
226
const initialContent =
221
227
newOptions . initialContent ||
222
228
( options . collaboration
@@ -233,20 +239,35 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
233
239
...newOptions . _tiptapOptions ,
234
240
onBeforeCreate ( editor ) {
235
241
newOptions . _tiptapOptions ?. onBeforeCreate ?.( editor ) ;
236
- if ( ! initialContent ) {
237
- // when using collaboration
238
- return ;
239
- }
240
-
241
242
// We always set the initial content to a single paragraph block. This
242
243
// allows us to easily replace it with the actual initial content once
243
244
// the TipTap editor is initialized.
244
245
const schema = editor . editor . schema ;
246
+
247
+ // This is a hack to make "initial content detection" by y-prosemirror (and also tiptap isEmpty)
248
+ // properly detect whether or not the document has changed.
249
+ // We change the doc.createAndFill function to make sure the initial block id is set, instead of null
250
+ let cache : any ;
251
+ const oldCreateAndFill = schema . nodes . doc . createAndFill ;
252
+ ( schema . nodes . doc as any ) . createAndFill = ( ...args : any ) => {
253
+ if ( cache ) {
254
+ return cache ;
255
+ }
256
+ const ret = oldCreateAndFill . apply ( schema . nodes . doc , args ) ;
257
+
258
+ // create a copy that we can mutate (otherwise, assigning attrs is not safe and corrupts the pm state)
259
+ const jsonNode = JSON . parse ( JSON . stringify ( ret ! . toJSON ( ) ) ) ;
260
+ jsonNode . content [ 0 ] . content [ 0 ] . attrs . id = "initialBlockId" ;
261
+
262
+ cache = Node . fromJSON ( schema , jsonNode ) ;
263
+ return ret ;
264
+ } ;
265
+
245
266
const root = schema . node (
246
267
"doc" ,
247
268
undefined ,
248
269
schema . node ( "blockGroup" , undefined , [
249
- blockToNode ( { id : "initialBlock " , type : "paragraph" } , schema ) ,
270
+ blockToNode ( { id : "initialBlockId " , type : "paragraph" } , schema ) ,
250
271
] )
251
272
) ;
252
273
editor . editor . options . content = root . toJSON ( ) ;
0 commit comments