@blocknote/core 0.29.1 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +125 -0
- package/dist/blocknote.cjs +9 -9
- package/dist/blocknote.cjs.map +1 -1
- package/dist/blocknote.js +1479 -1339
- package/dist/blocknote.js.map +1 -1
- package/dist/locales.cjs +1 -1
- package/dist/locales.cjs.map +1 -1
- package/dist/locales.js +751 -9
- package/dist/locales.js.map +1 -1
- package/dist/style.css +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/webpack-stats.json +1 -1
- package/package.json +3 -6
- package/src/api/blockManipulation/commands/insertBlocks/__snapshots__/insertBlocks.test.ts.snap +0 -7
- package/src/api/blockManipulation/commands/mergeBlocks/__snapshots__/mergeBlocks.test.ts.snap +0 -5
- package/src/api/blockManipulation/commands/moveBlocks/__snapshots__/moveBlocks.test.ts.snap +0 -20
- package/src/api/blockManipulation/commands/replaceBlocks/__snapshots__/replaceBlocks.test.ts.snap +0 -12
- package/src/api/blockManipulation/commands/splitBlock/__snapshots__/splitBlock.test.ts.snap +0 -6
- package/src/api/blockManipulation/commands/updateBlock/__snapshots__/updateBlock.test.ts.snap +0 -17
- package/src/api/clipboard/fromClipboard/pasteExtension.ts +19 -1
- package/src/blocks/AudioBlockContent/AudioBlockContent.ts +5 -0
- package/src/blocks/CodeBlockContent/CodeBlockContent.ts +32 -18
- package/src/blocks/FileBlockContent/FileBlockContent.ts +5 -0
- package/src/blocks/FileBlockContent/helpers/render/createResizableFileBlockWrapper.ts +9 -2
- package/src/blocks/HeadingBlockContent/HeadingBlockContent.ts +3 -0
- package/src/blocks/ImageBlockContent/ImageBlockContent.ts +10 -2
- package/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +9 -25
- package/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts +14 -3
- package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +9 -26
- package/src/blocks/ListItemBlockContent/getListItemContent.ts +115 -0
- package/src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts +6 -2
- package/src/blocks/QuoteBlockContent/QuoteBlockContent.ts +6 -1
- package/src/blocks/TableBlockContent/TableBlockContent.ts +71 -14
- package/src/blocks/VideoBlockContent/VideoBlockContent.ts +10 -2
- package/src/blocks/defaultBlockHelpers.ts +16 -0
- package/src/editor/Block.css +2 -1
- package/src/editor/BlockNoteEditor.ts +103 -60
- package/src/editor/BlockNoteExtensions.ts +14 -5
- package/src/extensions/Collaboration/CursorPlugin.ts +152 -0
- package/src/extensions/Collaboration/SyncPlugin.ts +15 -0
- package/src/extensions/Collaboration/UndoPlugin.ts +14 -0
- package/src/extensions/FilePanel/FilePanelPlugin.ts +31 -22
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +2 -4
- package/src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts +3 -0
- package/src/i18n/locales/index.ts +2 -0
- package/src/i18n/locales/ru.ts +2 -2
- package/src/i18n/locales/sk.ts +355 -0
- package/src/i18n/locales/zh-tw.ts +390 -0
- package/src/pm-nodes/BlockContainer.ts +7 -6
- package/src/schema/blocks/createSpec.ts +1 -1
- package/src/schema/blocks/internal.ts +0 -1
- package/src/schema/blocks/types.ts +2 -1
- package/types/src/api/blockManipulation/setupTestEnv.d.ts +8 -4
- package/types/src/blocks/ImageBlockContent/ImageBlockContent.d.ts +8 -4
- package/types/src/blocks/ListItemBlockContent/getListItemContent.d.ts +28 -0
- package/types/src/blocks/VideoBlockContent/VideoBlockContent.d.ts +8 -4
- package/types/src/blocks/defaultBlockHelpers.d.ts +1 -0
- package/types/src/blocks/defaultBlocks.d.ts +16 -8
- package/types/src/editor/BlockNoteEditor.d.ts +18 -1
- package/types/src/extensions/Collaboration/CursorPlugin.d.ts +31 -0
- package/types/src/extensions/Collaboration/SyncPlugin.d.ts +7 -0
- package/types/src/extensions/Collaboration/UndoPlugin.d.ts +6 -0
- package/types/src/extensions/FilePanel/FilePanelPlugin.d.ts +1 -1
- package/types/src/i18n/locales/index.d.ts +2 -0
- package/types/src/i18n/locales/sk.d.ts +313 -0
- package/types/src/i18n/locales/zh-tw.d.ts +2 -0
- package/types/src/schema/blocks/types.d.ts +2 -1
- package/src/extensions/Collaboration/createCollaborationExtensions.ts +0 -147
- package/types/src/extensions/Collaboration/createCollaborationExtensions.d.ts +0 -17
|
@@ -101,7 +101,8 @@ import {
|
|
|
101
101
|
} from "@tiptap/pm/state";
|
|
102
102
|
import { dropCursor } from "prosemirror-dropcursor";
|
|
103
103
|
import { EditorView } from "prosemirror-view";
|
|
104
|
-
import { ySyncPluginKey } from "y-prosemirror";
|
|
104
|
+
import { undoCommand, redoCommand, ySyncPluginKey } from "y-prosemirror";
|
|
105
|
+
import { undo, redo } from "@tiptap/pm/history";
|
|
105
106
|
import { createInternalHTMLSerializer } from "../api/exporters/html/internalHTMLSerializer.js";
|
|
106
107
|
import { inlineContentToNodes } from "../api/nodeConversions/blockToNode.js";
|
|
107
108
|
import { nodeToBlock } from "../api/nodeConversions/nodeToBlock.js";
|
|
@@ -114,27 +115,29 @@ import { CodeBlockOptions } from "../blocks/CodeBlockContent/CodeBlockContent.js
|
|
|
114
115
|
import type { ThreadStore, User } from "../comments/index.js";
|
|
115
116
|
import "../style.css";
|
|
116
117
|
import { EventEmitter } from "../util/EventEmitter.js";
|
|
118
|
+
import { CursorPlugin } from "../extensions/Collaboration/CursorPlugin.js";
|
|
117
119
|
|
|
118
120
|
export type BlockNoteExtensionFactory = (
|
|
119
|
-
editor: BlockNoteEditor<any, any, any
|
|
121
|
+
editor: BlockNoteEditor<any, any, any>,
|
|
120
122
|
) => BlockNoteExtension;
|
|
121
123
|
|
|
122
124
|
export type BlockNoteExtension =
|
|
123
125
|
| AnyExtension
|
|
124
126
|
| {
|
|
125
127
|
plugin: Plugin;
|
|
128
|
+
priority?: number;
|
|
126
129
|
};
|
|
127
130
|
|
|
128
131
|
export type BlockCache<
|
|
129
132
|
BSchema extends BlockSchema = any,
|
|
130
133
|
ISchema extends InlineContentSchema = any,
|
|
131
|
-
SSchema extends StyleSchema = any
|
|
134
|
+
SSchema extends StyleSchema = any,
|
|
132
135
|
> = WeakMap<Node, Block<BSchema, ISchema, SSchema>>;
|
|
133
136
|
|
|
134
137
|
export type BlockNoteEditorOptions<
|
|
135
138
|
BSchema extends BlockSchema,
|
|
136
139
|
ISchema extends InlineContentSchema,
|
|
137
|
-
SSchema extends StyleSchema
|
|
140
|
+
SSchema extends StyleSchema,
|
|
138
141
|
> = {
|
|
139
142
|
/**
|
|
140
143
|
* Whether changes to blocks (like indentation, creating lists, changing headings) should be animated or not. Defaults to `true`.
|
|
@@ -357,7 +360,7 @@ export type BlockNoteEditorOptions<
|
|
|
357
360
|
*/
|
|
358
361
|
uploadFile: (
|
|
359
362
|
file: File,
|
|
360
|
-
blockId?: string
|
|
363
|
+
blockId?: string,
|
|
361
364
|
) => Promise<string | Record<string, any>>;
|
|
362
365
|
|
|
363
366
|
/**
|
|
@@ -389,7 +392,7 @@ const blockNoteTipTapOptions = {
|
|
|
389
392
|
export class BlockNoteEditor<
|
|
390
393
|
BSchema extends BlockSchema = DefaultBlockSchema,
|
|
391
394
|
ISchema extends InlineContentSchema = DefaultInlineContentSchema,
|
|
392
|
-
SSchema extends StyleSchema = DefaultStyleSchema
|
|
395
|
+
SSchema extends StyleSchema = DefaultStyleSchema,
|
|
393
396
|
> extends EventEmitter<{
|
|
394
397
|
create: void;
|
|
395
398
|
}> {
|
|
@@ -412,11 +415,10 @@ export class BlockNoteEditor<
|
|
|
412
415
|
*/
|
|
413
416
|
public readonly headless: boolean = false;
|
|
414
417
|
|
|
415
|
-
public readonly _tiptapEditor:
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
} = undefined as any; // TODO: Type should actually reflect that it can be `undefined` in headless mode
|
|
418
|
+
public readonly _tiptapEditor: Omit<BlockNoteTipTapEditor, "view"> & {
|
|
419
|
+
view: EditorView | undefined;
|
|
420
|
+
contentComponent: any;
|
|
421
|
+
} = undefined as any; // TODO: Type should actually reflect that it can be `undefined` in headless mode
|
|
420
422
|
|
|
421
423
|
/**
|
|
422
424
|
* Used by React to store a reference to an `ElementRenderer` helper utility to make sure we can render React elements
|
|
@@ -471,6 +473,8 @@ export class BlockNoteEditor<
|
|
|
471
473
|
|
|
472
474
|
private readonly showSelectionPlugin: ShowSelectionPlugin;
|
|
473
475
|
|
|
476
|
+
private readonly cursorPlugin: CursorPlugin;
|
|
477
|
+
|
|
474
478
|
/**
|
|
475
479
|
* The `uploadFile` method is what the editor uses when files need to be uploaded (for example when selecting an image to upload).
|
|
476
480
|
* This method should set when creating the editor as this is application-specific.
|
|
@@ -505,37 +509,37 @@ export class BlockNoteEditor<
|
|
|
505
509
|
public static create<
|
|
506
510
|
BSchema extends BlockSchema = DefaultBlockSchema,
|
|
507
511
|
ISchema extends InlineContentSchema = DefaultInlineContentSchema,
|
|
508
|
-
SSchema extends StyleSchema = DefaultStyleSchema
|
|
512
|
+
SSchema extends StyleSchema = DefaultStyleSchema,
|
|
509
513
|
>(options: Partial<BlockNoteEditorOptions<BSchema, ISchema, SSchema>> = {}) {
|
|
510
514
|
return new BlockNoteEditor<BSchema, ISchema, SSchema>(options);
|
|
511
515
|
}
|
|
512
516
|
|
|
513
517
|
protected constructor(
|
|
514
|
-
protected readonly options: Partial<BlockNoteEditorOptions<any, any, any
|
|
518
|
+
protected readonly options: Partial<BlockNoteEditorOptions<any, any, any>>,
|
|
515
519
|
) {
|
|
516
520
|
super();
|
|
517
521
|
const anyOpts = options as any;
|
|
518
522
|
if (anyOpts.onEditorContentChange) {
|
|
519
523
|
throw new Error(
|
|
520
|
-
"onEditorContentChange initialization option is deprecated, use <BlockNoteView onChange={...} />, the useEditorChange(...) hook, or editor.onChange(...)"
|
|
524
|
+
"onEditorContentChange initialization option is deprecated, use <BlockNoteView onChange={...} />, the useEditorChange(...) hook, or editor.onChange(...)",
|
|
521
525
|
);
|
|
522
526
|
}
|
|
523
527
|
|
|
524
528
|
if (anyOpts.onTextCursorPositionChange) {
|
|
525
529
|
throw new Error(
|
|
526
|
-
"onTextCursorPositionChange initialization option is deprecated, use <BlockNoteView onSelectionChange={...} />, the useEditorSelectionChange(...) hook, or editor.onSelectionChange(...)"
|
|
530
|
+
"onTextCursorPositionChange initialization option is deprecated, use <BlockNoteView onSelectionChange={...} />, the useEditorSelectionChange(...) hook, or editor.onSelectionChange(...)",
|
|
527
531
|
);
|
|
528
532
|
}
|
|
529
533
|
|
|
530
534
|
if (anyOpts.onEditorReady) {
|
|
531
535
|
throw new Error(
|
|
532
|
-
"onEditorReady is deprecated. Editor is immediately ready for use after creation."
|
|
536
|
+
"onEditorReady is deprecated. Editor is immediately ready for use after creation.",
|
|
533
537
|
);
|
|
534
538
|
}
|
|
535
539
|
|
|
536
540
|
if (anyOpts.editable) {
|
|
537
541
|
throw new Error(
|
|
538
|
-
"editable initialization option is deprecated, use <BlockNoteView editable={true/false} />, or alternatively editor.isEditable = true/false"
|
|
542
|
+
"editable initialization option is deprecated, use <BlockNoteView editable={true/false} />, or alternatively editor.isEditable = true/false",
|
|
539
543
|
);
|
|
540
544
|
}
|
|
541
545
|
|
|
@@ -621,18 +625,19 @@ export class BlockNoteEditor<
|
|
|
621
625
|
this.tableHandles = this.extensions["tableHandles"] as any;
|
|
622
626
|
this.comments = this.extensions["comments"] as any;
|
|
623
627
|
this.showSelectionPlugin = this.extensions["showSelection"] as any;
|
|
628
|
+
this.cursorPlugin = this.extensions["yCursorPlugin"] as any;
|
|
624
629
|
|
|
625
630
|
if (newOptions.uploadFile) {
|
|
626
631
|
const uploadFile = newOptions.uploadFile;
|
|
627
|
-
this.uploadFile = async (file,
|
|
632
|
+
this.uploadFile = async (file, blockId) => {
|
|
628
633
|
this.onUploadStartCallbacks.forEach((callback) =>
|
|
629
|
-
callback.apply(this, [
|
|
634
|
+
callback.apply(this, [blockId]),
|
|
630
635
|
);
|
|
631
636
|
try {
|
|
632
|
-
return await uploadFile(file,
|
|
637
|
+
return await uploadFile(file, blockId);
|
|
633
638
|
} finally {
|
|
634
639
|
this.onUploadEndCallbacks.forEach((callback) =>
|
|
635
|
-
callback.apply(this, [
|
|
640
|
+
callback.apply(this, [blockId]),
|
|
636
641
|
);
|
|
637
642
|
}
|
|
638
643
|
};
|
|
@@ -642,13 +647,13 @@ export class BlockNoteEditor<
|
|
|
642
647
|
this.headless = newOptions._headless;
|
|
643
648
|
|
|
644
649
|
const collaborationEnabled =
|
|
645
|
-
"
|
|
650
|
+
"ySyncPlugin" in this.extensions ||
|
|
646
651
|
"liveblocksExtension" in this.extensions;
|
|
647
652
|
|
|
648
653
|
if (collaborationEnabled && newOptions.initialContent) {
|
|
649
654
|
// eslint-disable-next-line no-console
|
|
650
655
|
console.warn(
|
|
651
|
-
"When using Collaboration, initialContent might cause conflicts, because changes should come from the collaboration provider"
|
|
656
|
+
"When using Collaboration, initialContent might cause conflicts, because changes should come from the collaboration provider",
|
|
652
657
|
);
|
|
653
658
|
}
|
|
654
659
|
|
|
@@ -671,7 +676,7 @@ export class BlockNoteEditor<
|
|
|
671
676
|
if (!Array.isArray(initialContent) || initialContent.length === 0) {
|
|
672
677
|
throw new Error(
|
|
673
678
|
"initialContent must be a non-empty array of blocks, received: " +
|
|
674
|
-
initialContent
|
|
679
|
+
initialContent,
|
|
675
680
|
);
|
|
676
681
|
}
|
|
677
682
|
|
|
@@ -688,13 +693,14 @@ export class BlockNoteEditor<
|
|
|
688
693
|
|
|
689
694
|
if (!ext.plugin) {
|
|
690
695
|
throw new Error(
|
|
691
|
-
"Extension should either be a TipTap extension or a ProseMirror plugin in a plugin property"
|
|
696
|
+
"Extension should either be a TipTap extension or a ProseMirror plugin in a plugin property",
|
|
692
697
|
);
|
|
693
698
|
}
|
|
694
699
|
|
|
695
700
|
// "blocknote" extensions (prosemirror plugins)
|
|
696
701
|
return Extension.create({
|
|
697
702
|
name: key,
|
|
703
|
+
priority: ext.priority,
|
|
698
704
|
addProseMirrorPlugins: () => [ext.plugin],
|
|
699
705
|
});
|
|
700
706
|
}),
|
|
@@ -716,7 +722,7 @@ export class BlockNoteEditor<
|
|
|
716
722
|
class: mergeCSSClasses(
|
|
717
723
|
"bn-editor",
|
|
718
724
|
newOptions.defaultStyles ? "bn-default-styles" : "",
|
|
719
|
-
newOptions.domAttributes?.editor?.class || ""
|
|
725
|
+
newOptions.domAttributes?.editor?.class || "",
|
|
720
726
|
),
|
|
721
727
|
},
|
|
722
728
|
transformPasted,
|
|
@@ -726,7 +732,7 @@ export class BlockNoteEditor<
|
|
|
726
732
|
if (!this.headless) {
|
|
727
733
|
this._tiptapEditor = BlockNoteTipTapEditor.create(
|
|
728
734
|
tiptapOptions,
|
|
729
|
-
this.schema.styleSchema
|
|
735
|
+
this.schema.styleSchema,
|
|
730
736
|
) as BlockNoteTipTapEditor & {
|
|
731
737
|
view: any;
|
|
732
738
|
contentComponent: any;
|
|
@@ -761,7 +767,7 @@ export class BlockNoteEditor<
|
|
|
761
767
|
public exec(command: Command) {
|
|
762
768
|
if (this.activeTransaction) {
|
|
763
769
|
throw new Error(
|
|
764
|
-
"`exec` should not be called within a `transact` call, move the `exec` call outside of the `transact` call"
|
|
770
|
+
"`exec` should not be called within a `transact` call, move the `exec` call outside of the `transact` call",
|
|
765
771
|
);
|
|
766
772
|
}
|
|
767
773
|
const state = this._tiptapEditor.state;
|
|
@@ -786,7 +792,7 @@ export class BlockNoteEditor<
|
|
|
786
792
|
public canExec(command: Command): boolean {
|
|
787
793
|
if (this.activeTransaction) {
|
|
788
794
|
throw new Error(
|
|
789
|
-
"`canExec` should not be called within a `transact` call, move the `canExec` call outside of the `transact` call"
|
|
795
|
+
"`canExec` should not be called within a `transact` call, move the `canExec` call outside of the `transact` call",
|
|
790
796
|
);
|
|
791
797
|
}
|
|
792
798
|
const state = this._tiptapEditor.state;
|
|
@@ -820,8 +826,8 @@ export class BlockNoteEditor<
|
|
|
820
826
|
* The current active transaction, this will automatically be dispatched to the editor when the callback is complete
|
|
821
827
|
* If another `transact` call is made within the callback, it will be passed the same transaction as the parent call.
|
|
822
828
|
*/
|
|
823
|
-
tr: Transaction
|
|
824
|
-
) => T
|
|
829
|
+
tr: Transaction,
|
|
830
|
+
) => T,
|
|
825
831
|
): T {
|
|
826
832
|
if (this.activeTransaction) {
|
|
827
833
|
// Already in a transaction, so we can just callback immediately
|
|
@@ -866,13 +872,28 @@ export class BlockNoteEditor<
|
|
|
866
872
|
*/
|
|
867
873
|
public mount = (
|
|
868
874
|
parentElement?: HTMLElement | null,
|
|
869
|
-
contentComponent?: any
|
|
875
|
+
contentComponent?: any,
|
|
870
876
|
) => {
|
|
871
877
|
this._tiptapEditor.mount(this, parentElement, contentComponent);
|
|
872
878
|
};
|
|
873
879
|
|
|
880
|
+
/**
|
|
881
|
+
* Get the underlying prosemirror state
|
|
882
|
+
* @note Prefer using `editor.transact` to read the current editor state, as that will ensure the state is up to date
|
|
883
|
+
* @see https://prosemirror.net/docs/ref/#state.EditorState
|
|
884
|
+
*/
|
|
885
|
+
public get prosemirrorState() {
|
|
886
|
+
if (this.activeTransaction) {
|
|
887
|
+
throw new Error(
|
|
888
|
+
"`prosemirrorState` should not be called within a `transact` call, move the `prosemirrorState` call outside of the `transact` call or use `editor.transact` to read the current editor state",
|
|
889
|
+
);
|
|
890
|
+
}
|
|
891
|
+
return this._tiptapEditor.state;
|
|
892
|
+
}
|
|
893
|
+
|
|
874
894
|
/**
|
|
875
895
|
* Get the underlying prosemirror view
|
|
896
|
+
* @see https://prosemirror.net/docs/ref/#view.EditorView
|
|
876
897
|
*/
|
|
877
898
|
public get prosemirrorView() {
|
|
878
899
|
return this._tiptapEditor.view;
|
|
@@ -945,7 +966,7 @@ export class BlockNoteEditor<
|
|
|
945
966
|
* matching block was found.
|
|
946
967
|
*/
|
|
947
968
|
public getBlock(
|
|
948
|
-
blockIdentifier: BlockIdentifier
|
|
969
|
+
blockIdentifier: BlockIdentifier,
|
|
949
970
|
): Block<BSchema, ISchema, SSchema> | undefined {
|
|
950
971
|
return this.transact((tr) => getBlock(tr.doc, blockIdentifier));
|
|
951
972
|
}
|
|
@@ -960,7 +981,7 @@ export class BlockNoteEditor<
|
|
|
960
981
|
* in the document.
|
|
961
982
|
*/
|
|
962
983
|
public getPrevBlock(
|
|
963
|
-
blockIdentifier: BlockIdentifier
|
|
984
|
+
blockIdentifier: BlockIdentifier,
|
|
964
985
|
): Block<BSchema, ISchema, SSchema> | undefined {
|
|
965
986
|
return this.transact((tr) => getPrevBlock(tr.doc, blockIdentifier));
|
|
966
987
|
}
|
|
@@ -974,7 +995,7 @@ export class BlockNoteEditor<
|
|
|
974
995
|
* the document.
|
|
975
996
|
*/
|
|
976
997
|
public getNextBlock(
|
|
977
|
-
blockIdentifier: BlockIdentifier
|
|
998
|
+
blockIdentifier: BlockIdentifier,
|
|
978
999
|
): Block<BSchema, ISchema, SSchema> | undefined {
|
|
979
1000
|
return this.transact((tr) => getNextBlock(tr.doc, blockIdentifier));
|
|
980
1001
|
}
|
|
@@ -987,7 +1008,7 @@ export class BlockNoteEditor<
|
|
|
987
1008
|
* if no matching block was found, or the block isn't nested.
|
|
988
1009
|
*/
|
|
989
1010
|
public getParentBlock(
|
|
990
|
-
blockIdentifier: BlockIdentifier
|
|
1011
|
+
blockIdentifier: BlockIdentifier,
|
|
991
1012
|
): Block<BSchema, ISchema, SSchema> | undefined {
|
|
992
1013
|
return this.transact((tr) => getParentBlock(tr.doc, blockIdentifier));
|
|
993
1014
|
}
|
|
@@ -999,7 +1020,7 @@ export class BlockNoteEditor<
|
|
|
999
1020
|
*/
|
|
1000
1021
|
public forEachBlock(
|
|
1001
1022
|
callback: (block: Block<BSchema, ISchema, SSchema>) => boolean,
|
|
1002
|
-
reverse = false
|
|
1023
|
+
reverse = false,
|
|
1003
1024
|
): void {
|
|
1004
1025
|
const blocks = this.document.slice();
|
|
1005
1026
|
|
|
@@ -1008,7 +1029,7 @@ export class BlockNoteEditor<
|
|
|
1008
1029
|
}
|
|
1009
1030
|
|
|
1010
1031
|
function traverseBlockArray(
|
|
1011
|
-
blockArray: Block<BSchema, ISchema, SSchema>[]
|
|
1032
|
+
blockArray: Block<BSchema, ISchema, SSchema>[],
|
|
1012
1033
|
): boolean {
|
|
1013
1034
|
for (const block of blockArray) {
|
|
1014
1035
|
if (callback(block) === false) {
|
|
@@ -1034,7 +1055,7 @@ export class BlockNoteEditor<
|
|
|
1034
1055
|
* Executes a callback whenever the editor's contents change.
|
|
1035
1056
|
* @param callback The callback to execute.
|
|
1036
1057
|
*
|
|
1037
|
-
* @deprecated use
|
|
1058
|
+
* @deprecated use {@link BlockNoteEditor.onChange} instead
|
|
1038
1059
|
*/
|
|
1039
1060
|
public onEditorContentChange(callback: () => void) {
|
|
1040
1061
|
this._tiptapEditor.on("update", callback);
|
|
@@ -1070,10 +1091,10 @@ export class BlockNoteEditor<
|
|
|
1070
1091
|
*/
|
|
1071
1092
|
public setTextCursorPosition(
|
|
1072
1093
|
targetBlock: BlockIdentifier,
|
|
1073
|
-
placement: "start" | "end" = "start"
|
|
1094
|
+
placement: "start" | "end" = "start",
|
|
1074
1095
|
) {
|
|
1075
1096
|
return this.transact((tr) =>
|
|
1076
|
-
setTextCursorPosition(tr, targetBlock, placement)
|
|
1097
|
+
setTextCursorPosition(tr, targetBlock, placement),
|
|
1077
1098
|
);
|
|
1078
1099
|
}
|
|
1079
1100
|
|
|
@@ -1137,10 +1158,10 @@ export class BlockNoteEditor<
|
|
|
1137
1158
|
public insertBlocks(
|
|
1138
1159
|
blocksToInsert: PartialBlock<BSchema, ISchema, SSchema>[],
|
|
1139
1160
|
referenceBlock: BlockIdentifier,
|
|
1140
|
-
placement: "before" | "after" = "before"
|
|
1161
|
+
placement: "before" | "after" = "before",
|
|
1141
1162
|
) {
|
|
1142
1163
|
return this.transact((tr) =>
|
|
1143
|
-
insertBlocks(tr, blocksToInsert, referenceBlock, placement)
|
|
1164
|
+
insertBlocks(tr, blocksToInsert, referenceBlock, placement),
|
|
1144
1165
|
);
|
|
1145
1166
|
}
|
|
1146
1167
|
|
|
@@ -1153,7 +1174,7 @@ export class BlockNoteEditor<
|
|
|
1153
1174
|
*/
|
|
1154
1175
|
public updateBlock(
|
|
1155
1176
|
blockToUpdate: BlockIdentifier,
|
|
1156
|
-
update: PartialBlock<BSchema, ISchema, SSchema
|
|
1177
|
+
update: PartialBlock<BSchema, ISchema, SSchema>,
|
|
1157
1178
|
) {
|
|
1158
1179
|
return this.transact((tr) => updateBlock(tr, blockToUpdate, update));
|
|
1159
1180
|
}
|
|
@@ -1164,7 +1185,7 @@ export class BlockNoteEditor<
|
|
|
1164
1185
|
*/
|
|
1165
1186
|
public removeBlocks(blocksToRemove: BlockIdentifier[]) {
|
|
1166
1187
|
return this.transact(
|
|
1167
|
-
(tr) => removeAndInsertBlocks(tr, blocksToRemove, []).removedBlocks
|
|
1188
|
+
(tr) => removeAndInsertBlocks(tr, blocksToRemove, []).removedBlocks,
|
|
1168
1189
|
);
|
|
1169
1190
|
}
|
|
1170
1191
|
|
|
@@ -1177,13 +1198,34 @@ export class BlockNoteEditor<
|
|
|
1177
1198
|
*/
|
|
1178
1199
|
public replaceBlocks(
|
|
1179
1200
|
blocksToRemove: BlockIdentifier[],
|
|
1180
|
-
blocksToInsert: PartialBlock<BSchema, ISchema, SSchema>[]
|
|
1201
|
+
blocksToInsert: PartialBlock<BSchema, ISchema, SSchema>[],
|
|
1181
1202
|
) {
|
|
1182
1203
|
return this.transact((tr) =>
|
|
1183
|
-
removeAndInsertBlocks(tr, blocksToRemove, blocksToInsert)
|
|
1204
|
+
removeAndInsertBlocks(tr, blocksToRemove, blocksToInsert),
|
|
1184
1205
|
);
|
|
1185
1206
|
}
|
|
1186
1207
|
|
|
1208
|
+
/**
|
|
1209
|
+
* Undo the last action.
|
|
1210
|
+
*/
|
|
1211
|
+
public undo() {
|
|
1212
|
+
if (this.options.collaboration) {
|
|
1213
|
+
return this.exec(undoCommand);
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
return this.exec(undo);
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
/**
|
|
1220
|
+
* Redo the last action.
|
|
1221
|
+
*/
|
|
1222
|
+
public redo() {
|
|
1223
|
+
if (this.options.collaboration) {
|
|
1224
|
+
return this.exec(redoCommand);
|
|
1225
|
+
}
|
|
1226
|
+
return this.exec(redo);
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1187
1229
|
/**
|
|
1188
1230
|
* Insert a piece of content at the current cursor position.
|
|
1189
1231
|
*
|
|
@@ -1199,7 +1241,7 @@ export class BlockNoteEditor<
|
|
|
1199
1241
|
from: tr.selection.from,
|
|
1200
1242
|
to: tr.selection.to,
|
|
1201
1243
|
},
|
|
1202
|
-
nodes
|
|
1244
|
+
nodes,
|
|
1203
1245
|
);
|
|
1204
1246
|
});
|
|
1205
1247
|
}
|
|
@@ -1323,7 +1365,7 @@ export class BlockNoteEditor<
|
|
|
1323
1365
|
tr.setSelection(TextSelection.create(tr.doc, to)).addMark(
|
|
1324
1366
|
from,
|
|
1325
1367
|
to,
|
|
1326
|
-
mark
|
|
1368
|
+
mark,
|
|
1327
1369
|
);
|
|
1328
1370
|
}
|
|
1329
1371
|
});
|
|
@@ -1383,7 +1425,7 @@ export class BlockNoteEditor<
|
|
|
1383
1425
|
* @returns The blocks, serialized as an HTML string.
|
|
1384
1426
|
*/
|
|
1385
1427
|
public async blocksToHTMLLossy(
|
|
1386
|
-
blocks: PartialBlock<BSchema, ISchema, SSchema>[] = this.document
|
|
1428
|
+
blocks: PartialBlock<BSchema, ISchema, SSchema>[] = this.document,
|
|
1387
1429
|
): Promise<string> {
|
|
1388
1430
|
const exporter = createExternalHTMLExporter(this.pmSchema, this);
|
|
1389
1431
|
return exporter.exportBlocks(blocks, {});
|
|
@@ -1399,7 +1441,7 @@ export class BlockNoteEditor<
|
|
|
1399
1441
|
* @returns The blocks, serialized as an HTML string.
|
|
1400
1442
|
*/
|
|
1401
1443
|
public async blocksToFullHTML(
|
|
1402
|
-
blocks: PartialBlock<BSchema, ISchema, SSchema>[]
|
|
1444
|
+
blocks: PartialBlock<BSchema, ISchema, SSchema>[],
|
|
1403
1445
|
): Promise<string> {
|
|
1404
1446
|
const exporter = createInternalHTMLSerializer(this.pmSchema, this);
|
|
1405
1447
|
return exporter.serializeBlocks(blocks, {});
|
|
@@ -1412,7 +1454,7 @@ export class BlockNoteEditor<
|
|
|
1412
1454
|
* @returns The blocks parsed from the HTML string.
|
|
1413
1455
|
*/
|
|
1414
1456
|
public async tryParseHTMLToBlocks(
|
|
1415
|
-
html: string
|
|
1457
|
+
html: string,
|
|
1416
1458
|
): Promise<Block<BSchema, ISchema, SSchema>[]> {
|
|
1417
1459
|
return HTMLToBlocks(html, this.pmSchema);
|
|
1418
1460
|
}
|
|
@@ -1424,7 +1466,7 @@ export class BlockNoteEditor<
|
|
|
1424
1466
|
* @returns The blocks, serialized as a Markdown string.
|
|
1425
1467
|
*/
|
|
1426
1468
|
public async blocksToMarkdownLossy(
|
|
1427
|
-
blocks: PartialBlock<BSchema, ISchema, SSchema>[] = this.document
|
|
1469
|
+
blocks: PartialBlock<BSchema, ISchema, SSchema>[] = this.document,
|
|
1428
1470
|
): Promise<string> {
|
|
1429
1471
|
return blocksToMarkdown(blocks, this.pmSchema, this, {});
|
|
1430
1472
|
}
|
|
@@ -1437,7 +1479,7 @@ export class BlockNoteEditor<
|
|
|
1437
1479
|
* @returns The blocks parsed from the Markdown string.
|
|
1438
1480
|
*/
|
|
1439
1481
|
public async tryParseMarkdownToBlocks(
|
|
1440
|
-
markdown: string
|
|
1482
|
+
markdown: string,
|
|
1441
1483
|
): Promise<Block<BSchema, ISchema, SSchema>[]> {
|
|
1442
1484
|
return markdownToBlocks(markdown, this.pmSchema);
|
|
1443
1485
|
}
|
|
@@ -1448,10 +1490,11 @@ export class BlockNoteEditor<
|
|
|
1448
1490
|
public updateCollaborationUserInfo(user: { name: string; color: string }) {
|
|
1449
1491
|
if (!this.options.collaboration) {
|
|
1450
1492
|
throw new Error(
|
|
1451
|
-
"Cannot update collaboration user info when collaboration is disabled."
|
|
1493
|
+
"Cannot update collaboration user info when collaboration is disabled.",
|
|
1452
1494
|
);
|
|
1453
1495
|
}
|
|
1454
|
-
|
|
1496
|
+
|
|
1497
|
+
this.cursorPlugin.updateUser(user);
|
|
1455
1498
|
}
|
|
1456
1499
|
|
|
1457
1500
|
/**
|
|
@@ -1468,8 +1511,8 @@ export class BlockNoteEditor<
|
|
|
1468
1511
|
* Returns the blocks that were inserted, updated, or deleted by the change that occurred.
|
|
1469
1512
|
*/
|
|
1470
1513
|
getChanges(): BlocksChanged<BSchema, ISchema, SSchema>;
|
|
1471
|
-
}
|
|
1472
|
-
) => void
|
|
1514
|
+
},
|
|
1515
|
+
) => void,
|
|
1473
1516
|
) {
|
|
1474
1517
|
if (this.headless) {
|
|
1475
1518
|
// Note: would be nice if this is possible in headless mode as well
|
|
@@ -1504,7 +1547,7 @@ export class BlockNoteEditor<
|
|
|
1504
1547
|
*/
|
|
1505
1548
|
public onSelectionChange(
|
|
1506
1549
|
callback: (editor: BlockNoteEditor<BSchema, ISchema, SSchema>) => void,
|
|
1507
|
-
includeSelectionChangedByRemote?: boolean
|
|
1550
|
+
includeSelectionChangedByRemote?: boolean,
|
|
1508
1551
|
) {
|
|
1509
1552
|
if (this.headless) {
|
|
1510
1553
|
return;
|
|
@@ -1581,7 +1624,7 @@ export class BlockNoteEditor<
|
|
|
1581
1624
|
pluginState?: {
|
|
1582
1625
|
deleteTriggerCharacter?: boolean;
|
|
1583
1626
|
ignoreQueryLength?: boolean;
|
|
1584
|
-
}
|
|
1627
|
+
},
|
|
1585
1628
|
) {
|
|
1586
1629
|
if (!this.prosemirrorView) {
|
|
1587
1630
|
return;
|
|
@@ -10,7 +10,9 @@ import { createDropFileExtension } from "../api/clipboard/fromClipboard/fileDrop
|
|
|
10
10
|
import { createPasteFromClipboardExtension } from "../api/clipboard/fromClipboard/pasteExtension.js";
|
|
11
11
|
import { createCopyToClipboardExtension } from "../api/clipboard/toClipboard/copyExtension.js";
|
|
12
12
|
import { BackgroundColorExtension } from "../extensions/BackgroundColor/BackgroundColorExtension.js";
|
|
13
|
-
import {
|
|
13
|
+
import { CursorPlugin } from "../extensions/Collaboration/CursorPlugin.js";
|
|
14
|
+
import { UndoPlugin } from "../extensions/Collaboration/UndoPlugin.js";
|
|
15
|
+
import { SyncPlugin } from "../extensions/Collaboration/SyncPlugin.js";
|
|
14
16
|
import { CommentMark } from "../extensions/Comments/CommentMark.js";
|
|
15
17
|
import { CommentsPlugin } from "../extensions/Comments/CommentsPlugin.js";
|
|
16
18
|
import type { ThreadStore } from "../comments/index.js";
|
|
@@ -106,6 +108,15 @@ export const getBlockNoteExtensions = <
|
|
|
106
108
|
ret[ext.name] = ext;
|
|
107
109
|
}
|
|
108
110
|
|
|
111
|
+
if (opts.collaboration) {
|
|
112
|
+
ret["ySyncPlugin"] = new SyncPlugin(opts.collaboration.fragment);
|
|
113
|
+
ret["yUndoPlugin"] = new UndoPlugin();
|
|
114
|
+
|
|
115
|
+
if (opts.collaboration.provider?.awareness) {
|
|
116
|
+
ret["yCursorPlugin"] = new CursorPlugin(opts.collaboration);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
109
120
|
// Note: this is pretty hardcoded and will break when user provides plugins with same keys.
|
|
110
121
|
// Define name on plugins instead and not make this a map?
|
|
111
122
|
ret["formattingToolbar"] = new FormattingToolbarProsemirrorPlugin(
|
|
@@ -285,10 +296,8 @@ const getTipTapExtensions = <
|
|
|
285
296
|
|
|
286
297
|
LINKIFY_INITIALIZED = true;
|
|
287
298
|
|
|
288
|
-
if (opts.collaboration) {
|
|
289
|
-
|
|
290
|
-
} else {
|
|
291
|
-
// disable history extension when collaboration is enabled as Yjs takes care of undo / redo
|
|
299
|
+
if (!opts.collaboration) {
|
|
300
|
+
// disable history extension when collaboration is enabled as y-prosemirror takes care of undo / redo
|
|
292
301
|
tiptapExtensions.push(History);
|
|
293
302
|
}
|
|
294
303
|
|