@blocknote/core 0.42.3 → 0.44.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/dist/BlockNoteExtension-BWw0r8Gy.cjs +2 -0
- package/dist/BlockNoteExtension-BWw0r8Gy.cjs.map +1 -0
- package/dist/BlockNoteExtension-C2X7LW-V.js +25 -0
- package/dist/BlockNoteExtension-C2X7LW-V.js.map +1 -0
- package/dist/BlockNoteSchema-B4gm-Qco.cjs +2 -0
- package/dist/BlockNoteSchema-B4gm-Qco.cjs.map +1 -0
- package/dist/BlockNoteSchema-C-l154WP.js +270 -0
- package/dist/BlockNoteSchema-C-l154WP.js.map +1 -0
- package/dist/EventEmitter-CLwfmbqG.cjs +2 -0
- package/dist/EventEmitter-CLwfmbqG.cjs.map +1 -0
- package/dist/EventEmitter-CjSwpTbz.js +27 -0
- package/dist/EventEmitter-CjSwpTbz.js.map +1 -0
- package/dist/ShowSelection-BW37oJ6h.cjs +2 -0
- package/dist/ShowSelection-BW37oJ6h.cjs.map +1 -0
- package/dist/ShowSelection-Dz-NEase.js +43 -0
- package/dist/ShowSelection-Dz-NEase.js.map +1 -0
- package/dist/TrailingNode-B_zPMWxw.js +2098 -0
- package/dist/TrailingNode-B_zPMWxw.js.map +1 -0
- package/dist/TrailingNode-CRHrgOnK.cjs +2 -0
- package/dist/TrailingNode-CRHrgOnK.cjs.map +1 -0
- package/dist/{blockToNode-DIfPWLH8.js → blockToNode-DBNbhwwC.js} +33 -33
- package/dist/blockToNode-DBNbhwwC.js.map +1 -0
- package/dist/blockToNode-w7H99R6p.cjs.map +1 -1
- package/dist/blocknote.cjs +4 -4
- package/dist/blocknote.cjs.map +1 -1
- package/dist/blocknote.js +2496 -5686
- package/dist/blocknote.js.map +1 -1
- package/dist/blocks.cjs +1 -1
- package/dist/blocks.js +71 -70
- package/dist/blocks.js.map +1 -1
- package/dist/comments.cjs +1 -1
- package/dist/comments.cjs.map +1 -1
- package/dist/comments.js +451 -137
- package/dist/comments.js.map +1 -1
- package/dist/defaultBlocks-DLJ4Q1_J.cjs +6 -0
- package/dist/defaultBlocks-DLJ4Q1_J.cjs.map +1 -0
- package/dist/{BlockNoteSchema-Bi-eeHal.js → defaultBlocks-DgA_mtQV.js} +974 -1027
- package/dist/defaultBlocks-DgA_mtQV.js.map +1 -0
- package/dist/extensions.cjs +2 -0
- package/dist/extensions.cjs.map +1 -0
- package/dist/extensions.js +57 -0
- package/dist/extensions.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/webpack-stats.json +1 -1
- package/dist/yjs.js +1 -1
- package/package.json +9 -3
- package/src/api/nodeConversions/blockToNode.ts +1 -1
- package/src/api/nodeConversions/nodeToBlock.ts +1 -1
- package/src/blocks/Code/block.ts +4 -4
- package/src/blocks/Divider/block.ts +2 -2
- package/src/blocks/File/helpers/render/createAddFileButton.ts +7 -5
- package/src/blocks/Heading/block.ts +23 -20
- package/src/blocks/ListItem/BulletListItem/block.ts +2 -2
- package/src/blocks/ListItem/CheckListItem/block.ts +2 -2
- package/src/blocks/ListItem/NumberedListItem/block.ts +3 -3
- package/src/blocks/ListItem/ToggleListItem/block.ts +2 -2
- package/src/blocks/PageBreak/getPageBreakSlashMenuItems.ts +2 -2
- package/src/blocks/Paragraph/block.ts +2 -2
- package/src/blocks/Quote/block.ts +2 -2
- package/src/blocks/Table/block.ts +4 -3
- package/src/blocks/ToggleWrapper/createToggleWrapper.ts +2 -1
- package/src/comments/extension.ts +353 -0
- package/src/comments/index.ts +2 -1
- package/src/comments/types.ts +8 -0
- package/src/{extensions/Comments → comments}/userstore/UserStore.ts +2 -2
- package/src/editor/BlockNoteEditor.test.ts +2 -23
- package/src/editor/BlockNoteEditor.ts +60 -453
- package/src/editor/BlockNoteExtension.test.ts +103 -0
- package/src/editor/BlockNoteExtension.ts +174 -56
- package/src/editor/managers/EventManager.ts +64 -35
- package/src/editor/managers/ExtensionManager/extensions.ts +214 -0
- package/src/editor/managers/ExtensionManager/index.ts +514 -0
- package/src/editor/managers/ExtensionManager/symbol.ts +6 -0
- package/src/editor/managers/SelectionManager.ts +5 -1
- package/src/editor/managers/StateManager.ts +29 -17
- package/src/editor/managers/index.ts +1 -5
- package/src/extensions/BlockChange/{BlockChangePlugin.ts → BlockChange.ts} +27 -29
- package/src/extensions/Collaboration/{ForkYDocPlugin.test.ts → ForkYDoc.test.ts} +6 -5
- package/src/extensions/Collaboration/ForkYDoc.ts +158 -0
- package/src/extensions/Collaboration/YCursorPlugin.ts +183 -0
- package/src/extensions/Collaboration/YSync.ts +16 -0
- package/src/extensions/Collaboration/YUndo.ts +12 -0
- package/src/extensions/Collaboration/schemaMigration/SchemaMigration.ts +59 -0
- package/src/extensions/DropCursor/DropCursor.ts +26 -0
- package/src/extensions/FilePanel/FilePanel.ts +41 -0
- package/src/extensions/FormattingToolbar/FormattingToolbar.ts +119 -0
- package/src/extensions/History/History.ts +11 -0
- package/src/extensions/LinkToolbar/LinkToolbar.ts +121 -0
- package/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboard.ts +74 -0
- package/src/extensions/Placeholder/Placeholder.ts +148 -0
- package/src/extensions/PreviousBlockType/{PreviousBlockTypePlugin.ts → PreviousBlockType.ts} +9 -13
- package/src/extensions/ShowSelection/{ShowSelectionPlugin.ts → ShowSelection.ts} +27 -33
- package/src/extensions/SideMenu/{SideMenuPlugin.ts → SideMenu.ts} +63 -83
- package/src/extensions/SuggestionMenu/{SuggestionPlugin.ts → SuggestionMenu.ts} +71 -77
- package/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.ts +29 -44
- package/src/extensions/TableHandles/{TableHandlesPlugin.ts → TableHandles.ts} +416 -437
- package/src/extensions/TrailingNode/{TrailingNodeExtension.ts → TrailingNode.ts} +8 -17
- package/src/extensions/index.ts +24 -0
- package/src/extensions/{BackgroundColor → tiptap-extensions/BackgroundColor}/BackgroundColorExtension.ts +1 -1
- package/src/extensions/{KeyboardShortcuts → tiptap-extensions/KeyboardShortcuts}/KeyboardShortcutsExtension.ts +21 -16
- package/src/extensions/{TextColor → tiptap-extensions/TextColor}/TextColorExtension.ts +1 -1
- package/src/extensions/tiptap-extensions/index.ts +31 -0
- package/src/index.ts +1 -13
- package/src/schema/blocks/createSpec.ts +14 -11
- package/src/schema/blocks/internal.ts +2 -2
- package/src/schema/blocks/types.ts +8 -5
- package/src/schema/schema.ts +11 -36
- package/src/util/topo-sort.ts +46 -0
- package/types/src/comments/extension.d.ts +70 -0
- package/types/src/comments/index.d.ts +2 -1
- package/types/src/comments/types.d.ts +8 -0
- package/types/src/{extensions/Comments → comments}/userstore/UserStore.d.ts +2 -2
- package/types/src/editor/BlockNoteEditor.d.ts +34 -105
- package/types/src/editor/BlockNoteExtension.d.ts +87 -22
- package/types/src/editor/managers/EventManager.d.ts +25 -16
- package/types/src/editor/managers/ExtensionManager/extensions.d.ts +8 -0
- package/types/src/editor/managers/ExtensionManager/index.d.ts +83 -0
- package/types/src/editor/managers/ExtensionManager/symbol.d.ts +5 -0
- package/types/src/editor/managers/StateManager.d.ts +1 -12
- package/types/src/editor/managers/index.d.ts +1 -2
- package/types/src/extensions/BlockChange/BlockChange.d.ts +16 -0
- package/types/src/extensions/Collaboration/ForkYDoc.d.ts +34 -0
- package/types/src/extensions/Collaboration/ForkYDoc.test.d.ts +1 -0
- package/types/src/extensions/Collaboration/YCursorPlugin.d.ts +24 -0
- package/types/src/extensions/Collaboration/YSync.d.ts +8 -0
- package/types/src/extensions/Collaboration/YUndo.d.ts +12 -0
- package/types/src/extensions/Collaboration/schemaMigration/SchemaMigration.d.ts +8 -0
- package/types/src/extensions/DropCursor/DropCursor.d.ts +5 -0
- package/types/src/extensions/FilePanel/FilePanel.d.ts +11 -0
- package/types/src/extensions/FormattingToolbar/FormattingToolbar.d.ts +9 -0
- package/types/src/extensions/History/History.d.ts +6 -0
- package/types/src/extensions/LinkToolbar/LinkToolbar.d.ts +24 -0
- package/types/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboard.d.ts +5 -0
- package/types/src/extensions/Placeholder/Placeholder.d.ts +6 -0
- package/types/src/extensions/PreviousBlockType/{PreviousBlockTypePlugin.d.ts → PreviousBlockType.d.ts} +9 -5
- package/types/src/extensions/ShowSelection/ShowSelection.d.ts +21 -0
- package/types/src/extensions/SideMenu/{SideMenuPlugin.d.ts → SideMenu.d.ts} +11 -15
- package/types/src/extensions/SuggestionMenu/SuggestionMenu.d.ts +54 -0
- package/types/src/extensions/SuggestionMenu/getDefaultSlashMenuItems.d.ts +1 -1
- package/types/src/extensions/TableHandles/{TableHandlesPlugin.d.ts → TableHandles.d.ts} +28 -31
- package/types/src/extensions/TrailingNode/TrailingNode.d.ts +8 -0
- package/types/src/extensions/index.d.ts +24 -0
- package/types/src/extensions/{KeyboardShortcuts → tiptap-extensions/KeyboardShortcuts}/KeyboardShortcutsExtension.d.ts +1 -1
- package/types/src/extensions/tiptap-extensions/index.d.ts +11 -0
- package/types/src/index.d.ts +1 -13
- package/types/src/schema/blocks/createSpec.d.ts +4 -4
- package/types/src/schema/blocks/internal.d.ts +2 -2
- package/types/src/schema/blocks/types.d.ts +5 -5
- package/types/src/util/topo-sort.d.ts +8 -0
- package/dist/BlockNoteSchema-Bi-eeHal.js.map +0 -1
- package/dist/BlockNoteSchema-DjDaA2C3.cjs +0 -6
- package/dist/BlockNoteSchema-DjDaA2C3.cjs.map +0 -1
- package/dist/blockToNode-DIfPWLH8.js.map +0 -1
- package/src/comments/models/User.ts +0 -8
- package/src/editor/BlockNoteExtensions.ts +0 -325
- package/src/editor/managers/CollaborationManager.ts +0 -212
- package/src/editor/managers/ExtensionManager.ts +0 -130
- package/src/extensions/Collaboration/CursorPlugin.ts +0 -189
- package/src/extensions/Collaboration/ForkYDocPlugin.ts +0 -192
- package/src/extensions/Collaboration/SyncPlugin.ts +0 -18
- package/src/extensions/Collaboration/UndoPlugin.ts +0 -18
- package/src/extensions/Collaboration/schemaMigration/SchemaMigrationPlugin.ts +0 -59
- package/src/extensions/Comments/CommentsPlugin.ts +0 -392
- package/src/extensions/FilePanel/FilePanelPlugin.ts +0 -206
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +0 -363
- package/src/extensions/LinkToolbar/LinkToolbarPlugin.ts +0 -380
- package/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.ts +0 -75
- package/src/extensions/Placeholder/PlaceholderPlugin.ts +0 -147
- package/types/src/comments/models/User.d.ts +0 -8
- package/types/src/editor/BlockNoteExtensions.d.ts +0 -43
- package/types/src/editor/managers/CollaborationManager.d.ts +0 -115
- package/types/src/editor/managers/ExtensionManager.d.ts +0 -68
- package/types/src/extensions/BlockChange/BlockChangePlugin.d.ts +0 -15
- package/types/src/extensions/Collaboration/CursorPlugin.d.ts +0 -37
- package/types/src/extensions/Collaboration/ForkYDocPlugin.d.ts +0 -41
- package/types/src/extensions/Collaboration/SyncPlugin.d.ts +0 -7
- package/types/src/extensions/Collaboration/UndoPlugin.d.ts +0 -9
- package/types/src/extensions/Collaboration/schemaMigration/SchemaMigrationPlugin.d.ts +0 -7
- package/types/src/extensions/Comments/CommentsPlugin.d.ts +0 -66
- package/types/src/extensions/FilePanel/FilePanelPlugin.d.ts +0 -31
- package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +0 -41
- package/types/src/extensions/LinkToolbar/LinkToolbarPlugin.d.ts +0 -42
- package/types/src/extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.d.ts +0 -5
- package/types/src/extensions/Placeholder/PlaceholderPlugin.d.ts +0 -6
- package/types/src/extensions/ShowSelection/ShowSelectionPlugin.d.ts +0 -15
- package/types/src/extensions/SuggestionMenu/SuggestionPlugin.d.ts +0 -31
- package/types/src/extensions/TrailingNode/TrailingNodeExtension.d.ts +0 -13
- /package/src/{extensions/Comments/CommentMark.ts → comments/mark.ts} +0 -0
- /package/src/extensions/{HardBreak → tiptap-extensions/HardBreak}/HardBreak.ts +0 -0
- /package/src/extensions/{Suggestions → tiptap-extensions/Suggestions}/SuggestionMarks.ts +0 -0
- /package/src/extensions/{TextAlignment → tiptap-extensions/TextAlignment}/TextAlignmentExtension.ts +0 -0
- /package/src/extensions/{UniqueID → tiptap-extensions/UniqueID}/UniqueID.ts +0 -0
- /package/types/src/{extensions/Comments/CommentMark.d.ts → comments/mark.d.ts} +0 -0
- /package/types/src/{extensions/Collaboration/ForkYDocPlugin.test.d.ts → editor/BlockNoteExtension.test.d.ts} +0 -0
- /package/types/src/extensions/{BackgroundColor → tiptap-extensions/BackgroundColor}/BackgroundColorExtension.d.ts +0 -0
- /package/types/src/extensions/{HardBreak → tiptap-extensions/HardBreak}/HardBreak.d.ts +0 -0
- /package/types/src/extensions/{Suggestions → tiptap-extensions/Suggestions}/SuggestionMarks.d.ts +0 -0
- /package/types/src/extensions/{TextAlignment → tiptap-extensions/TextAlignment}/TextAlignmentExtension.d.ts +0 -0
- /package/types/src/extensions/{TextColor → tiptap-extensions/TextColor}/TextColorExtension.d.ts +0 -0
- /package/types/src/extensions/{UniqueID → tiptap-extensions/UniqueID}/UniqueID.d.ts +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { expect, it } from "vitest";
|
|
2
|
+
import { createExtension, ExtensionOptions } from "./BlockNoteExtension.js";
|
|
3
|
+
import { BlockNoteEditor } from "./BlockNoteEditor.js";
|
|
4
|
+
|
|
5
|
+
const editor = BlockNoteEditor.create();
|
|
6
|
+
/**
|
|
7
|
+
* @vitest-environment jsdom
|
|
8
|
+
*/
|
|
9
|
+
it("creates an extension factory", () => {
|
|
10
|
+
const extension = createExtension(() => {
|
|
11
|
+
return {
|
|
12
|
+
key: "test",
|
|
13
|
+
prosemirrorPlugins: [],
|
|
14
|
+
} as const;
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const extInstance = extension()({ editor });
|
|
18
|
+
expect(extInstance.key).toBe("test");
|
|
19
|
+
expect(extInstance.prosemirrorPlugins).toEqual([]);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("creates an extension factory with options", () => {
|
|
23
|
+
const extension = createExtension((opts: ExtensionOptions<{ x: number }>) => {
|
|
24
|
+
expect(opts.options.x).toBe(1);
|
|
25
|
+
return {
|
|
26
|
+
key: "test",
|
|
27
|
+
prosemirrorPlugins: [],
|
|
28
|
+
} as const;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const extInstance = extension({ x: 1 })({ editor });
|
|
32
|
+
expect(extInstance.key).toBe("test");
|
|
33
|
+
expect(extInstance.prosemirrorPlugins).toEqual([]);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("creates an extension factory with undefined options", () => {
|
|
37
|
+
const extension = createExtension(
|
|
38
|
+
(opts: ExtensionOptions<{ x: number } | undefined>) => {
|
|
39
|
+
expect(opts.options).toBe(undefined);
|
|
40
|
+
return {
|
|
41
|
+
key: "test",
|
|
42
|
+
prosemirrorPlugins: [],
|
|
43
|
+
} as const;
|
|
44
|
+
},
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const extInstance = extension()({ editor });
|
|
48
|
+
expect(extInstance.key).toBe("test");
|
|
49
|
+
expect(extInstance.prosemirrorPlugins).toEqual([]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("creates an extension factory from an object", () => {
|
|
53
|
+
const extension = createExtension({
|
|
54
|
+
key: "test",
|
|
55
|
+
prosemirrorPlugins: [],
|
|
56
|
+
} as const);
|
|
57
|
+
|
|
58
|
+
const extInstance = extension({ editor });
|
|
59
|
+
expect(extInstance.key).toBe("test");
|
|
60
|
+
expect(extInstance.prosemirrorPlugins).toEqual([]);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("allows arbitrary properties on a no-options extension", () => {
|
|
64
|
+
const extension = createExtension(() => {
|
|
65
|
+
return {
|
|
66
|
+
key: "test",
|
|
67
|
+
prosemirrorPlugins: [],
|
|
68
|
+
arbitraryProperty: "arbitraryValue",
|
|
69
|
+
arbitraryMethod: () => {
|
|
70
|
+
return "arbitraryValue";
|
|
71
|
+
},
|
|
72
|
+
} as const;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const extInstance = extension()({ editor });
|
|
76
|
+
expect(extInstance.arbitraryProperty).toBe("arbitraryValue");
|
|
77
|
+
expect(extInstance.arbitraryMethod()).toBe("arbitraryValue");
|
|
78
|
+
// @ts-expect-error - this method takes no arguments
|
|
79
|
+
extInstance.arbitraryMethod(90);
|
|
80
|
+
// @ts-expect-error - this property is not defined
|
|
81
|
+
extInstance.nonExistentProperty = "newArbitraryValue";
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("allows arbitrary properties on an extension with options", () => {
|
|
85
|
+
const extension = createExtension((opts: ExtensionOptions<{ x: number }>) => {
|
|
86
|
+
expect(opts.options.x).toBe(1);
|
|
87
|
+
return {
|
|
88
|
+
key: "test",
|
|
89
|
+
prosemirrorPlugins: [],
|
|
90
|
+
arbitraryProperty: "arbitraryValue",
|
|
91
|
+
arbitraryMethod: () => {
|
|
92
|
+
return "arbitraryValue";
|
|
93
|
+
},
|
|
94
|
+
} as const;
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const extInstance = extension({ x: 1 })({ editor });
|
|
98
|
+
expect(extInstance.arbitraryProperty).toBe("arbitraryValue");
|
|
99
|
+
// @ts-expect-error - this method takes no arguments
|
|
100
|
+
extInstance.arbitraryMethod(90);
|
|
101
|
+
// @ts-expect-error - this property is not defined
|
|
102
|
+
extInstance.nonExistentProperty = "newArbitraryValue";
|
|
103
|
+
});
|
|
@@ -1,42 +1,57 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
InlineContentSchema,
|
|
8
|
-
PartialBlockNoDefaults,
|
|
9
|
-
StyleSchema,
|
|
10
|
-
} from "../schema/index.js";
|
|
11
|
-
import { BlockNoteEditor } from "./BlockNoteEditor.js";
|
|
12
|
-
|
|
13
|
-
export abstract class BlockNoteExtension<
|
|
14
|
-
TEvent extends Record<string, any> = any,
|
|
15
|
-
> extends EventEmitter<TEvent> {
|
|
16
|
-
public static key(): string {
|
|
17
|
-
throw new Error("You must implement the key method in your extension");
|
|
18
|
-
}
|
|
1
|
+
import { Store, StoreOptions } from "@tanstack/store";
|
|
2
|
+
import { type AnyExtension } from "@tiptap/core";
|
|
3
|
+
import type { Plugin as ProsemirrorPlugin } from "prosemirror-state";
|
|
4
|
+
import type { PartialBlockNoDefaults } from "../schema/index.js";
|
|
5
|
+
import type { BlockNoteEditor } from "./BlockNoteEditor.js";
|
|
6
|
+
import { originalFactorySymbol } from "./managers/ExtensionManager/symbol.js";
|
|
19
7
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
8
|
+
/**
|
|
9
|
+
* This function is called when the extension is destroyed.
|
|
10
|
+
*/
|
|
11
|
+
type OnDestroy = () => void;
|
|
23
12
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Describes a BlockNote extension.
|
|
15
|
+
*/
|
|
16
|
+
export interface Extension<State = any, Key extends string = string> {
|
|
17
|
+
/**
|
|
18
|
+
* The unique identifier for the extension.
|
|
19
|
+
*/
|
|
20
|
+
readonly key: Key;
|
|
28
21
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Triggered when the extension is mounted to the editor.
|
|
24
|
+
*/
|
|
25
|
+
readonly mount?: (ctx: {
|
|
26
|
+
/**
|
|
27
|
+
* The DOM element that the editor is mounted to.
|
|
28
|
+
*/
|
|
29
|
+
dom: HTMLElement;
|
|
30
|
+
/**
|
|
31
|
+
* The root document of the {@link document} that the editor is mounted to.
|
|
32
|
+
*/
|
|
33
|
+
root: Document | ShadowRoot;
|
|
34
|
+
/**
|
|
35
|
+
* An {@link AbortSignal} that will be aborted when the extension is destroyed.
|
|
36
|
+
*/
|
|
37
|
+
signal: AbortSignal;
|
|
38
|
+
}) => void | OnDestroy;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The store for the extension.
|
|
42
|
+
*/
|
|
43
|
+
readonly store?: Store<State>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Declares what {@link Extension}s that this extension depends on.
|
|
47
|
+
*/
|
|
48
|
+
readonly runsBefore?: ReadonlyArray<string>;
|
|
35
49
|
|
|
36
50
|
/**
|
|
37
|
-
* Input rules for
|
|
51
|
+
* Input rules for a block: An input rule is what is used to replace text in a block when a regular expression match is found.
|
|
52
|
+
* As an example, typing `#` in a paragraph block will trigger an input rule to replace the text with a heading block.
|
|
38
53
|
*/
|
|
39
|
-
|
|
54
|
+
readonly inputRules?: ReadonlyArray<InputRule>;
|
|
40
55
|
|
|
41
56
|
/**
|
|
42
57
|
* A mapping of a keyboard shortcut to a function that will be called when the shortcut is pressed
|
|
@@ -60,17 +75,27 @@ export abstract class BlockNoteExtension<
|
|
|
60
75
|
* }
|
|
61
76
|
* ```
|
|
62
77
|
*/
|
|
63
|
-
|
|
78
|
+
readonly keyboardShortcuts?: Record<
|
|
64
79
|
string,
|
|
65
|
-
(ctx: {
|
|
66
|
-
editor: BlockNoteEditor<BlockSchema, InlineContentSchema, StyleSchema>;
|
|
67
|
-
}) => boolean
|
|
80
|
+
(ctx: { editor: BlockNoteEditor<any, any, any> }) => boolean
|
|
68
81
|
>;
|
|
69
82
|
|
|
70
|
-
|
|
83
|
+
/**
|
|
84
|
+
* Add additional prosemirror plugins to the editor.
|
|
85
|
+
*/
|
|
86
|
+
readonly prosemirrorPlugins?: ReadonlyArray<ProsemirrorPlugin>;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Add additional tiptap extensions to the editor.
|
|
90
|
+
*/
|
|
91
|
+
readonly tiptapExtensions?: ReadonlyArray<AnyExtension>;
|
|
71
92
|
}
|
|
72
93
|
|
|
73
|
-
|
|
94
|
+
/**
|
|
95
|
+
* An input rule is what is used to replace text in a block when a regular expression match is found.
|
|
96
|
+
* As an example, typing `#` in a paragraph block will trigger an input rule to replace the text with a heading block.
|
|
97
|
+
*/
|
|
98
|
+
type InputRule = {
|
|
74
99
|
/**
|
|
75
100
|
* The regex to match when to trigger the input rule
|
|
76
101
|
*/
|
|
@@ -97,22 +122,115 @@ export type InputRule = {
|
|
|
97
122
|
};
|
|
98
123
|
|
|
99
124
|
/**
|
|
100
|
-
*
|
|
101
|
-
|
|
125
|
+
* These are the arguments that are passed to an {@link ExtensionFactoryInstance}.
|
|
126
|
+
*/
|
|
127
|
+
export interface ExtensionOptions<
|
|
128
|
+
Options extends Record<string, any> | undefined =
|
|
129
|
+
| Record<string, any>
|
|
130
|
+
| undefined,
|
|
131
|
+
> {
|
|
132
|
+
options: Options;
|
|
133
|
+
editor: BlockNoteEditor<any, any, any>;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// a type that maps the extension key to the return type of the extension factory
|
|
137
|
+
export type ExtensionMap<T extends ReadonlyArray<ExtensionFactoryInstance>> = {
|
|
138
|
+
[K in T[number] extends ExtensionFactoryInstance<infer Ext>
|
|
139
|
+
? Ext["key"]
|
|
140
|
+
: never]: T[number] extends ExtensionFactoryInstance<infer Ext>
|
|
141
|
+
? Ext
|
|
142
|
+
: never;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* This is a type that represents the function which will actually create the extension.
|
|
147
|
+
* It requires the editor instance to be passed in, but will already have the options applied automatically.
|
|
148
|
+
*
|
|
149
|
+
* @note Only the BlockNoteEditor should instantiate this function, not the user. Look at {@link createExtension} for user-facing functions.
|
|
102
150
|
*/
|
|
103
|
-
export
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
151
|
+
export type ExtensionFactoryInstance<
|
|
152
|
+
Ext extends Extension<any, any> = Extension<any, any>,
|
|
153
|
+
> = (ctx: Omit<ExtensionOptions<any>, "options">) => Ext;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* This is the return type of the {@link createExtension} function.
|
|
157
|
+
* It is a function that can be invoked with the extension's options to create a new extension factory.
|
|
158
|
+
*/
|
|
159
|
+
export type ExtensionFactory<
|
|
160
|
+
State = any,
|
|
161
|
+
Key extends string = string,
|
|
162
|
+
Factory extends (ctx: any) => Extension<State, Key> = (
|
|
163
|
+
ctx: ExtensionOptions<any>,
|
|
164
|
+
) => Extension<State, Key>,
|
|
165
|
+
> =
|
|
166
|
+
Parameters<Factory>[0] extends ExtensionOptions<infer Options>
|
|
167
|
+
? undefined extends Options
|
|
168
|
+
? (
|
|
169
|
+
options?: Exclude<Options, undefined>,
|
|
170
|
+
) => ExtensionFactoryInstance<ReturnType<Factory>>
|
|
171
|
+
: (options: Options) => ExtensionFactoryInstance<ReturnType<Factory>>
|
|
172
|
+
: () => ExtensionFactoryInstance<ReturnType<Factory>>;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Constructs a BlockNote {@link ExtensionFactory} from a factory function or object
|
|
176
|
+
*/
|
|
177
|
+
// This overload is for `createExtension({ key: "test", ... })`
|
|
178
|
+
export function createExtension<
|
|
179
|
+
const State = any,
|
|
180
|
+
const Key extends string = string,
|
|
181
|
+
const Ext extends Extension<State, Key> = Extension<State, Key>,
|
|
182
|
+
>(factory: Ext): ExtensionFactoryInstance<Ext>;
|
|
183
|
+
// This overload is for `createExtension(({editor, options}) => ({ key: "test", ... }))`
|
|
184
|
+
export function createExtension<
|
|
185
|
+
const State = any,
|
|
186
|
+
const Options extends Record<string, any> | undefined = any,
|
|
187
|
+
const Key extends string = string,
|
|
188
|
+
const Factory extends (ctx: any) => Extension<State, Key> = (
|
|
189
|
+
ctx: ExtensionOptions<Options>,
|
|
190
|
+
) => Extension<State, Key>,
|
|
191
|
+
>(factory: Factory): ExtensionFactory<State, Key, Factory>;
|
|
192
|
+
// This overload is for both of the above overloads as it is the implementation of the function
|
|
193
|
+
export function createExtension<
|
|
194
|
+
const State = any,
|
|
195
|
+
const Options extends Record<string, any> | undefined = any,
|
|
196
|
+
const Key extends string = string,
|
|
197
|
+
const Factory extends
|
|
198
|
+
| Extension<State, Key>
|
|
199
|
+
| ((ctx: any) => Extension<State, Key>) = (
|
|
200
|
+
ctx: ExtensionOptions<Options>,
|
|
201
|
+
) => Extension<State, Key>,
|
|
202
|
+
>(
|
|
203
|
+
factory: Factory,
|
|
204
|
+
): Factory extends Extension<State, Key>
|
|
205
|
+
? ExtensionFactoryInstance<Factory>
|
|
206
|
+
: Factory extends (ctx: any) => Extension<State, Key>
|
|
207
|
+
? ExtensionFactory<State, Key, Factory>
|
|
208
|
+
: never {
|
|
209
|
+
if (typeof factory === "object" && "key" in factory) {
|
|
210
|
+
return function factoryFn() {
|
|
211
|
+
(factory as any)[originalFactorySymbol] = factoryFn;
|
|
212
|
+
return factory;
|
|
213
|
+
} as any;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (typeof factory !== "function") {
|
|
217
|
+
throw new Error("factory must be a function");
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return function factoryFn(options: Options) {
|
|
221
|
+
return (ctx: { editor: BlockNoteEditor<any, any, any> }) => {
|
|
222
|
+
const extension = factory({ editor: ctx.editor, options });
|
|
223
|
+
// We stick a symbol onto the extension to allow us to retrieve the original factory for comparison later.
|
|
224
|
+
// This enables us to do things like: `editor.getExtension(YSync).prosemirrorPlugins`
|
|
225
|
+
(extension as any)[originalFactorySymbol] = factoryFn;
|
|
226
|
+
return extension;
|
|
227
|
+
};
|
|
228
|
+
} as any;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export function createStore<T = any>(
|
|
232
|
+
initialState: T,
|
|
233
|
+
options?: StoreOptions<T>,
|
|
234
|
+
): Store<T> {
|
|
235
|
+
return new Store(initialState, options);
|
|
118
236
|
}
|
|
@@ -5,6 +5,11 @@ import {
|
|
|
5
5
|
} from "../../api/getBlocksChangedByTransaction.js";
|
|
6
6
|
import { Transaction } from "prosemirror-state";
|
|
7
7
|
import { EventEmitter } from "../../util/EventEmitter.js";
|
|
8
|
+
import {
|
|
9
|
+
BlockSchema,
|
|
10
|
+
InlineContentSchema,
|
|
11
|
+
StyleSchema,
|
|
12
|
+
} from "../../schema/index.js";
|
|
8
13
|
|
|
9
14
|
/**
|
|
10
15
|
* A function that can be used to unsubscribe from an event.
|
|
@@ -14,37 +19,33 @@ export type Unsubscribe = () => void;
|
|
|
14
19
|
/**
|
|
15
20
|
* EventManager is a class which manages the events of the editor
|
|
16
21
|
*/
|
|
17
|
-
export class EventManager<
|
|
22
|
+
export class EventManager<
|
|
23
|
+
BSchema extends BlockSchema,
|
|
24
|
+
I extends InlineContentSchema,
|
|
25
|
+
S extends StyleSchema,
|
|
26
|
+
> extends EventEmitter<{
|
|
18
27
|
onChange: [
|
|
19
|
-
editor: Editor,
|
|
20
28
|
ctx: {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
Editor["schema"]["styleSchema"]
|
|
25
|
-
>;
|
|
29
|
+
editor: BlockNoteEditor<BSchema, I, S>;
|
|
30
|
+
transaction: Transaction;
|
|
31
|
+
appendedTransactions: Transaction[];
|
|
26
32
|
},
|
|
27
33
|
];
|
|
28
|
-
onSelectionChange: [
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
onSelectionChange: [
|
|
35
|
+
ctx: { editor: BlockNoteEditor<BSchema, I, S>; transaction: Transaction },
|
|
36
|
+
];
|
|
37
|
+
onMount: [ctx: { editor: BlockNoteEditor<BSchema, I, S> }];
|
|
38
|
+
onUnmount: [ctx: { editor: BlockNoteEditor<BSchema, I, S> }];
|
|
31
39
|
}> {
|
|
32
|
-
constructor(private editor:
|
|
40
|
+
constructor(private editor: BlockNoteEditor<BSchema, I, S>) {
|
|
33
41
|
super();
|
|
34
42
|
// We register tiptap events only once the editor is finished initializing
|
|
35
43
|
// otherwise we would be trying to register events on a tiptap editor which does not exist yet
|
|
36
|
-
editor.
|
|
44
|
+
editor.on("create", () => {
|
|
37
45
|
editor._tiptapEditor.on(
|
|
38
46
|
"update",
|
|
39
47
|
({ transaction, appendedTransactions }) => {
|
|
40
|
-
this.emit("onChange", editor,
|
|
41
|
-
getChanges() {
|
|
42
|
-
return getBlocksChangedByTransaction(
|
|
43
|
-
transaction,
|
|
44
|
-
appendedTransactions,
|
|
45
|
-
);
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
+
this.emit("onChange", { editor, transaction, appendedTransactions });
|
|
48
49
|
},
|
|
49
50
|
);
|
|
50
51
|
editor._tiptapEditor.on("selectionUpdate", ({ transaction }) => {
|
|
@@ -64,20 +65,41 @@ export class EventManager<Editor extends BlockNoteEditor> extends EventEmitter<{
|
|
|
64
65
|
*/
|
|
65
66
|
public onChange(
|
|
66
67
|
callback: (
|
|
67
|
-
editor:
|
|
68
|
+
editor: BlockNoteEditor<BSchema, I, S>,
|
|
68
69
|
ctx: {
|
|
69
|
-
getChanges(): BlocksChanged<
|
|
70
|
-
Editor["schema"]["blockSchema"],
|
|
71
|
-
Editor["schema"]["inlineContentSchema"],
|
|
72
|
-
Editor["schema"]["styleSchema"]
|
|
73
|
-
>;
|
|
70
|
+
getChanges(): BlocksChanged<BSchema, I, S>;
|
|
74
71
|
},
|
|
75
72
|
) => void,
|
|
73
|
+
/**
|
|
74
|
+
* If true, the callback will be triggered when the changes are caused by a remote user
|
|
75
|
+
* @default true
|
|
76
|
+
*/
|
|
77
|
+
includeUpdatesFromRemote = true,
|
|
76
78
|
): Unsubscribe {
|
|
77
|
-
|
|
79
|
+
const cb = ({
|
|
80
|
+
transaction,
|
|
81
|
+
appendedTransactions,
|
|
82
|
+
}: {
|
|
83
|
+
transaction: Transaction;
|
|
84
|
+
appendedTransactions: Transaction[];
|
|
85
|
+
}) => {
|
|
86
|
+
if (!includeUpdatesFromRemote && isRemoteTransaction(transaction)) {
|
|
87
|
+
// don't trigger the callback if the changes are caused by a remote user
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
callback(this.editor, {
|
|
91
|
+
getChanges() {
|
|
92
|
+
return getBlocksChangedByTransaction(
|
|
93
|
+
transaction,
|
|
94
|
+
appendedTransactions,
|
|
95
|
+
);
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
this.on("onChange", cb);
|
|
78
100
|
|
|
79
101
|
return () => {
|
|
80
|
-
this.off("onChange",
|
|
102
|
+
this.off("onChange", cb);
|
|
81
103
|
};
|
|
82
104
|
}
|
|
83
105
|
|
|
@@ -85,7 +107,7 @@ export class EventManager<Editor extends BlockNoteEditor> extends EventEmitter<{
|
|
|
85
107
|
* Register a callback that will be called when the selection changes.
|
|
86
108
|
*/
|
|
87
109
|
public onSelectionChange(
|
|
88
|
-
callback: (editor:
|
|
110
|
+
callback: (editor: BlockNoteEditor<BSchema, I, S>) => void,
|
|
89
111
|
/**
|
|
90
112
|
* If true, the callback will be triggered when the selection changes due to a yjs sync (i.e.: other user was typing)
|
|
91
113
|
*/
|
|
@@ -93,11 +115,10 @@ export class EventManager<Editor extends BlockNoteEditor> extends EventEmitter<{
|
|
|
93
115
|
): Unsubscribe {
|
|
94
116
|
const cb = (e: { transaction: Transaction }) => {
|
|
95
117
|
if (
|
|
96
|
-
|
|
97
|
-
|
|
118
|
+
!includeSelectionChangedByRemote &&
|
|
119
|
+
isRemoteTransaction(e.transaction)
|
|
98
120
|
) {
|
|
99
|
-
// selection changed because of a
|
|
100
|
-
// we don't want to trigger the callback in this case
|
|
121
|
+
// don't trigger the callback if the selection changed because of a remote user
|
|
101
122
|
return;
|
|
102
123
|
}
|
|
103
124
|
callback(this.editor);
|
|
@@ -113,7 +134,9 @@ export class EventManager<Editor extends BlockNoteEditor> extends EventEmitter<{
|
|
|
113
134
|
/**
|
|
114
135
|
* Register a callback that will be called when the editor is mounted.
|
|
115
136
|
*/
|
|
116
|
-
public onMount(
|
|
137
|
+
public onMount(
|
|
138
|
+
callback: (ctx: { editor: BlockNoteEditor<BSchema, I, S> }) => void,
|
|
139
|
+
): Unsubscribe {
|
|
117
140
|
this.on("onMount", callback);
|
|
118
141
|
|
|
119
142
|
return () => {
|
|
@@ -124,7 +147,9 @@ export class EventManager<Editor extends BlockNoteEditor> extends EventEmitter<{
|
|
|
124
147
|
/**
|
|
125
148
|
* Register a callback that will be called when the editor is unmounted.
|
|
126
149
|
*/
|
|
127
|
-
public onUnmount(
|
|
150
|
+
public onUnmount(
|
|
151
|
+
callback: (ctx: { editor: BlockNoteEditor<BSchema, I, S> }) => void,
|
|
152
|
+
): Unsubscribe {
|
|
128
153
|
this.on("onUnmount", callback);
|
|
129
154
|
|
|
130
155
|
return () => {
|
|
@@ -132,3 +157,7 @@ export class EventManager<Editor extends BlockNoteEditor> extends EventEmitter<{
|
|
|
132
157
|
};
|
|
133
158
|
}
|
|
134
159
|
}
|
|
160
|
+
|
|
161
|
+
function isRemoteTransaction(transaction: Transaction): boolean {
|
|
162
|
+
return !!transaction.getMeta("y-sync$");
|
|
163
|
+
}
|