@blocknote/core 0.24.2 → 0.25.1
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/blocknote.cjs +12 -0
- package/dist/blocknote.cjs.map +1 -0
- package/dist/blocknote.js +4784 -3545
- package/dist/blocknote.js.map +1 -1
- package/dist/comments.cjs +2 -0
- package/dist/comments.cjs.map +1 -0
- package/dist/comments.js +593 -0
- package/dist/comments.js.map +1 -0
- package/dist/style.css +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/webpack-stats.json +1 -1
- package/package.json +40 -27
- package/src/api/blockManipulation/commands/insertBlocks/__snapshots__/insertBlocks.test.ts.snap +1022 -378
- package/src/api/blockManipulation/commands/mergeBlocks/__snapshots__/mergeBlocks.test.ts.snap +730 -270
- package/src/api/blockManipulation/commands/moveBlocks/__snapshots__/moveBlocks.test.ts.snap +3100 -1260
- package/src/api/blockManipulation/commands/removeBlocks/__snapshots__/removeBlocks.test.ts.snap +438 -162
- package/src/api/blockManipulation/commands/replaceBlocks/__snapshots__/replaceBlocks.test.ts.snap +1168 -432
- package/src/api/blockManipulation/commands/splitBlock/__snapshots__/splitBlock.test.ts.snap +930 -378
- package/src/api/blockManipulation/commands/updateBlock/__snapshots__/updateBlock.test.ts.snap +2485 -1015
- package/src/api/blockManipulation/commands/updateBlock/updateBlock.test.ts +28 -1
- package/src/api/blockManipulation/commands/updateBlock/updateBlock.ts +1 -1
- package/src/api/blockManipulation/selections/__snapshots__/selection.test.ts.snap +292 -108
- package/src/api/blockManipulation/setupTestEnv.ts +14 -1
- package/src/api/blockManipulation/tables/tables.test.ts +1987 -0
- package/src/api/blockManipulation/tables/tables.ts +887 -0
- package/src/api/clipboard/__snapshots__/external/pasteEndOfParagraph.html +66 -24
- package/src/api/clipboard/__snapshots__/external/pasteEndOfParagraphText.html +66 -24
- package/src/api/clipboard/__snapshots__/external/pasteImage.html +66 -24
- package/src/api/clipboard/__snapshots__/external/pasteParagraphInCustomBlock.html +66 -24
- package/src/api/clipboard/__snapshots__/external/pasteTable.html +132 -48
- package/src/api/clipboard/__snapshots__/external/pasteTableInExistingTable.html +136 -44
- package/src/api/clipboard/toClipboard/copyExtension.ts +2 -3
- package/src/api/exporters/html/__snapshots__/table/headerCols/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/table/headerCols/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/table/headerRows/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/table/headerRows/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/table/headersRows/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/table/headersRows/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/table/mixedCellColors/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/table/mixedCellColors/internal.html +1 -0
- package/src/api/exporters/html/__snapshots__/table/mixedRowspansAndColspans/external.html +1 -0
- package/src/api/exporters/html/__snapshots__/table/mixedRowspansAndColspans/internal.html +1 -0
- package/src/api/exporters/markdown/__snapshots__/table/headerCols/markdown.md +4 -0
- package/src/api/exporters/markdown/__snapshots__/table/headerRows/markdown.md +4 -0
- package/src/api/exporters/markdown/__snapshots__/table/mixedCellColors/markdown.md +5 -0
- package/src/api/exporters/markdown/__snapshots__/table/mixedRowspansAndColspans/markdown.md +5 -0
- package/src/api/nodeConversions/__snapshots__/nodeConversions.test.ts.snap +985 -20
- package/src/api/nodeConversions/blockToNode.ts +63 -20
- package/src/api/nodeConversions/nodeToBlock.ts +75 -13
- package/src/api/parsers/html/__snapshots__/parse-notion-html.json +145 -54
- package/src/api/testUtil/cases/defaultSchema.ts +782 -9
- package/src/api/testUtil/partialBlockTestUtil.ts +39 -4
- package/src/blocks/TableBlockContent/TableBlockContent.ts +11 -5
- package/src/blocks/defaultBlockTypeGuards.ts +8 -0
- package/src/comments/index.ts +9 -0
- package/src/comments/models/User.ts +8 -0
- package/src/comments/threadstore/DefaultThreadStoreAuth.ts +106 -0
- package/src/comments/threadstore/ThreadStore.ts +134 -0
- package/src/comments/threadstore/ThreadStoreAuth.ts +13 -0
- package/src/comments/threadstore/TipTapThreadStore.ts +292 -0
- package/src/comments/threadstore/yjs/RESTYjsThreadStore.ts +144 -0
- package/src/comments/threadstore/yjs/YjsThreadStore.test.ts +294 -0
- package/src/comments/threadstore/yjs/YjsThreadStore.ts +340 -0
- package/src/comments/threadstore/yjs/YjsThreadStoreBase.ts +48 -0
- package/src/comments/threadstore/yjs/yjsHelpers.ts +121 -0
- package/src/comments/types.ts +117 -0
- package/src/editor/Block.css +16 -8
- package/src/editor/BlockNoteEditor.ts +269 -92
- package/src/editor/BlockNoteExtensions.ts +24 -1
- package/src/editor/BlockNoteTipTapEditor.ts +5 -1
- package/src/editor/editor.css +23 -4
- package/src/extensions/BackgroundColor/BackgroundColorExtension.ts +1 -1
- package/src/extensions/Collaboration/createCollaborationExtensions.ts +8 -17
- package/src/extensions/Comments/CommentMark.ts +61 -0
- package/src/extensions/Comments/CommentsPlugin.ts +301 -0
- package/src/extensions/Comments/userstore/UserStore.ts +72 -0
- package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +9 -5
- package/src/extensions/LinkToolbar/LinkToolbarPlugin.ts +3 -3
- package/src/extensions/ShowSelection/ShowSelectionPlugin.ts +52 -0
- package/src/extensions/SuggestionMenu/getDefaultEmojiPickerItems.ts +34 -17
- package/src/extensions/TableHandles/TableHandlesPlugin.ts +409 -57
- package/src/extensions/TextAlignment/TextAlignmentExtension.ts +2 -0
- package/src/extensions/TextColor/TextColorExtension.ts +1 -1
- package/src/i18n/locales/ar.ts +23 -0
- package/src/i18n/locales/de.ts +15 -0
- package/src/i18n/locales/en.ts +25 -1
- package/src/i18n/locales/es.ts +16 -1
- package/src/i18n/locales/fr.ts +23 -0
- package/src/i18n/locales/hr.ts +18 -0
- package/src/i18n/locales/is.ts +24 -1
- package/src/i18n/locales/it.ts +15 -0
- package/src/i18n/locales/ja.ts +23 -0
- package/src/i18n/locales/ko.ts +23 -0
- package/src/i18n/locales/nl.ts +23 -0
- package/src/i18n/locales/no.ts +23 -0
- package/src/i18n/locales/pl.ts +23 -0
- package/src/i18n/locales/pt.ts +23 -0
- package/src/i18n/locales/ru.ts +23 -0
- package/src/i18n/locales/uk.ts +23 -0
- package/src/i18n/locales/vi.ts +23 -0
- package/src/i18n/locales/zh.ts +23 -0
- package/src/index.ts +6 -4
- package/src/schema/blocks/types.ts +32 -2
- package/src/util/browser.ts +1 -1
- package/src/util/table.ts +107 -0
- package/types/src/api/blockManipulation/tables/tables.d.ts +343 -0
- package/types/src/api/blockManipulation/tables/tables.test.d.ts +1 -0
- package/types/src/api/clipboard/toClipboard/copyExtension.d.ts +1 -1
- package/types/src/blocks/TableBlockContent/TableBlockContent.d.ts +1 -2
- package/types/src/blocks/defaultBlockTypeGuards.d.ts +3 -0
- package/types/src/comments/index.d.ts +9 -0
- package/types/src/comments/models/User.d.ts +8 -0
- package/types/src/comments/threadstore/DefaultThreadStoreAuth.d.ts +47 -0
- package/types/src/comments/threadstore/ThreadStore.d.ts +121 -0
- package/types/src/comments/threadstore/ThreadStoreAuth.d.ts +12 -0
- package/types/src/comments/threadstore/TipTapThreadStore.d.ts +97 -0
- package/types/src/comments/threadstore/yjs/RESTYjsThreadStore.d.ts +83 -0
- package/types/src/comments/threadstore/yjs/YjsThreadStore.d.ts +79 -0
- package/types/src/comments/threadstore/yjs/YjsThreadStore.test.d.ts +1 -0
- package/types/src/comments/threadstore/yjs/YjsThreadStoreBase.d.ts +15 -0
- package/types/src/comments/threadstore/yjs/yjsHelpers.d.ts +13 -0
- package/types/src/comments/types.d.ts +109 -0
- package/types/src/editor/BlockNoteEditor.d.ts +146 -66
- package/types/src/editor/BlockNoteExtensions.d.ts +4 -0
- package/types/src/extensions/Collaboration/createCollaborationExtensions.d.ts +1 -1
- package/types/src/extensions/Comments/CommentMark.d.ts +2 -0
- package/types/src/extensions/Comments/CommentsPlugin.d.ts +49 -0
- package/types/src/extensions/Comments/userstore/UserStore.d.ts +31 -0
- package/types/src/extensions/ShowSelection/ShowSelectionPlugin.d.ts +15 -0
- package/types/src/extensions/TableHandles/TableHandlesPlugin.d.ts +66 -1
- package/types/src/i18n/locales/de.d.ts +15 -0
- package/types/src/i18n/locales/en.d.ts +20 -0
- package/types/src/i18n/locales/es.d.ts +15 -0
- package/types/src/i18n/locales/hr.d.ts +18 -0
- package/types/src/i18n/locales/it.d.ts +15 -0
- package/types/src/index.d.ts +5 -4
- package/types/src/pm-nodes/BlockContainer.d.ts +2 -2
- package/types/src/pm-nodes/BlockGroup.d.ts +2 -2
- package/types/src/schema/blocks/types.d.ts +23 -2
- package/types/src/util/browser.d.ts +1 -1
- package/types/src/util/table.d.ts +12 -0
- package/dist/blocknote.umd.cjs +0 -11
- package/dist/blocknote.umd.cjs.map +0 -1
|
@@ -3,7 +3,9 @@ import {
|
|
|
3
3
|
EditorOptions,
|
|
4
4
|
Extension,
|
|
5
5
|
getSchema,
|
|
6
|
+
isNodeSelection,
|
|
6
7
|
Mark,
|
|
8
|
+
posToDOMRect,
|
|
7
9
|
Node as TipTapNode,
|
|
8
10
|
} from "@tiptap/core";
|
|
9
11
|
import { Node, Schema } from "prosemirror-model";
|
|
@@ -49,9 +51,11 @@ import {
|
|
|
49
51
|
DefaultStyleSchema,
|
|
50
52
|
PartialBlock,
|
|
51
53
|
} from "../blocks/defaultBlocks.js";
|
|
54
|
+
import type { CommentsPlugin } from "../extensions/Comments/CommentsPlugin.js";
|
|
52
55
|
import { FilePanelProsemirrorPlugin } from "../extensions/FilePanel/FilePanelPlugin.js";
|
|
53
56
|
import { FormattingToolbarProsemirrorPlugin } from "../extensions/FormattingToolbar/FormattingToolbarPlugin.js";
|
|
54
57
|
import { LinkToolbarProsemirrorPlugin } from "../extensions/LinkToolbar/LinkToolbarPlugin.js";
|
|
58
|
+
import { ShowSelectionPlugin } from "../extensions/ShowSelection/ShowSelectionPlugin.js";
|
|
55
59
|
import { SideMenuProsemirrorPlugin } from "../extensions/SideMenu/SideMenuPlugin.js";
|
|
56
60
|
import { SuggestionMenuProseMirrorPlugin } from "../extensions/SuggestionMenu/SuggestionPlugin.js";
|
|
57
61
|
import { TableHandlesProsemirrorPlugin } from "../extensions/TableHandles/TableHandlesPlugin.js";
|
|
@@ -90,10 +94,13 @@ import { en } from "../i18n/locales/index.js";
|
|
|
90
94
|
import { Plugin, Transaction } from "@tiptap/pm/state";
|
|
91
95
|
import { dropCursor } from "prosemirror-dropcursor";
|
|
92
96
|
import { EditorView } from "prosemirror-view";
|
|
97
|
+
import { ySyncPluginKey } from "y-prosemirror";
|
|
93
98
|
import { createInternalHTMLSerializer } from "../api/exporters/html/internalHTMLSerializer.js";
|
|
94
99
|
import { inlineContentToNodes } from "../api/nodeConversions/blockToNode.js";
|
|
95
100
|
import { nodeToBlock } from "../api/nodeConversions/nodeToBlock.js";
|
|
101
|
+
import type { ThreadStore, User } from "../comments/index.js";
|
|
96
102
|
import "../style.css";
|
|
103
|
+
import { EventEmitter } from "../util/EventEmitter.js";
|
|
97
104
|
|
|
98
105
|
export type BlockNoteExtensionFactory = (
|
|
99
106
|
editor: BlockNoteEditor<any, any, any>
|
|
@@ -117,69 +124,6 @@ export type BlockNoteEditorOptions<
|
|
|
117
124
|
*/
|
|
118
125
|
animations?: boolean;
|
|
119
126
|
|
|
120
|
-
/**
|
|
121
|
-
* Disable internal extensions (based on keys / extension name)
|
|
122
|
-
*/
|
|
123
|
-
disableExtensions: string[];
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* A dictionary object containing translations for the editor.
|
|
127
|
-
*/
|
|
128
|
-
dictionary?: Dictionary & Record<string, any>;
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* @deprecated, provide placeholders via dictionary instead
|
|
132
|
-
*/
|
|
133
|
-
placeholders: Record<
|
|
134
|
-
string | "default" | "emptyDocument",
|
|
135
|
-
string | undefined
|
|
136
|
-
>;
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* An object containing attributes that should be added to HTML elements of the editor.
|
|
140
|
-
*
|
|
141
|
-
* @example { editor: { class: "my-editor-class" } }
|
|
142
|
-
*/
|
|
143
|
-
domAttributes: Partial<BlockNoteDOMAttributes>;
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* The content that should be in the editor when it's created, represented as an array of partial block objects.
|
|
147
|
-
*/
|
|
148
|
-
initialContent: PartialBlock<
|
|
149
|
-
NoInfer<BSchema>,
|
|
150
|
-
NoInfer<ISchema>,
|
|
151
|
-
NoInfer<SSchema>
|
|
152
|
-
>[];
|
|
153
|
-
/**
|
|
154
|
-
* Use default BlockNote font and reset the styles of <p> <li> <h1> elements etc., that are used in BlockNote.
|
|
155
|
-
*
|
|
156
|
-
* @default true
|
|
157
|
-
*/
|
|
158
|
-
defaultStyles: boolean;
|
|
159
|
-
|
|
160
|
-
schema: BlockNoteSchema<BSchema, ISchema, SSchema>;
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* The `uploadFile` method is what the editor uses when files need to be uploaded (for example when selecting an image to upload).
|
|
164
|
-
* This method should set when creating the editor as this is application-specific.
|
|
165
|
-
*
|
|
166
|
-
* `undefined` means the application doesn't support file uploads.
|
|
167
|
-
*
|
|
168
|
-
* @param file The file that should be uploaded.
|
|
169
|
-
* @returns The URL of the uploaded file OR an object containing props that should be set on the file block (such as an id)
|
|
170
|
-
*/
|
|
171
|
-
uploadFile: (
|
|
172
|
-
file: File,
|
|
173
|
-
blockId?: string
|
|
174
|
-
) => Promise<string | Record<string, any>>;
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Resolve a URL of a file block to one that can be displayed or downloaded. This can be used for creating authenticated URL or
|
|
178
|
-
* implementing custom protocols / schemes
|
|
179
|
-
* @returns The URL that's
|
|
180
|
-
*/
|
|
181
|
-
resolveFileUrl: (url: string) => Promise<string>;
|
|
182
|
-
|
|
183
127
|
/**
|
|
184
128
|
* When enabled, allows for collaboration between multiple users.
|
|
185
129
|
*/
|
|
@@ -212,26 +156,72 @@ export type BlockNoteEditorOptions<
|
|
|
212
156
|
showCursorLabels?: "always" | "activity";
|
|
213
157
|
};
|
|
214
158
|
|
|
159
|
+
comments: {
|
|
160
|
+
threadStore: ThreadStore;
|
|
161
|
+
};
|
|
162
|
+
|
|
215
163
|
/**
|
|
216
|
-
*
|
|
164
|
+
* Use default BlockNote font and reset the styles of <p> <li> <h1> elements etc., that are used in BlockNote.
|
|
165
|
+
*
|
|
166
|
+
* @default true
|
|
217
167
|
*/
|
|
218
|
-
|
|
168
|
+
defaultStyles: boolean;
|
|
219
169
|
|
|
220
170
|
/**
|
|
221
|
-
*
|
|
171
|
+
* A dictionary object containing translations for the editor.
|
|
222
172
|
*/
|
|
223
|
-
|
|
173
|
+
dictionary?: Dictionary & Record<string, any>;
|
|
224
174
|
|
|
225
|
-
|
|
175
|
+
/**
|
|
176
|
+
* Disable internal extensions (based on keys / extension name)
|
|
177
|
+
*/
|
|
178
|
+
disableExtensions: string[];
|
|
226
179
|
|
|
227
180
|
/**
|
|
228
|
-
*
|
|
229
|
-
* Headless mode means we can use features like importing / exporting blocks,
|
|
230
|
-
* but there's no underlying editor (UI) instantiated.
|
|
181
|
+
* An object containing attributes that should be added to HTML elements of the editor.
|
|
231
182
|
*
|
|
232
|
-
*
|
|
183
|
+
* @example { editor: { class: "my-editor-class" } }
|
|
233
184
|
*/
|
|
234
|
-
|
|
185
|
+
domAttributes: Partial<BlockNoteDOMAttributes>;
|
|
186
|
+
|
|
187
|
+
dropCursor?: (opts: {
|
|
188
|
+
editor: BlockNoteEditor<
|
|
189
|
+
NoInfer<BSchema>,
|
|
190
|
+
NoInfer<ISchema>,
|
|
191
|
+
NoInfer<SSchema>
|
|
192
|
+
>;
|
|
193
|
+
color?: string | false;
|
|
194
|
+
width?: number;
|
|
195
|
+
class?: string;
|
|
196
|
+
}) => Plugin;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* The content that should be in the editor when it's created, represented as an array of partial block objects.
|
|
200
|
+
*/
|
|
201
|
+
initialContent: PartialBlock<
|
|
202
|
+
NoInfer<BSchema>,
|
|
203
|
+
NoInfer<ISchema>,
|
|
204
|
+
NoInfer<SSchema>
|
|
205
|
+
>[];
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* @deprecated, provide placeholders via dictionary instead
|
|
209
|
+
*/
|
|
210
|
+
placeholders: Record<
|
|
211
|
+
string | "default" | "emptyDocument",
|
|
212
|
+
string | undefined
|
|
213
|
+
>;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Resolve a URL of a file block to one that can be displayed or downloaded. This can be used for creating authenticated URL or
|
|
217
|
+
* implementing custom protocols / schemes
|
|
218
|
+
* @returns The URL that's
|
|
219
|
+
*/
|
|
220
|
+
resolveFileUrl: (url: string) => Promise<string>;
|
|
221
|
+
|
|
222
|
+
resolveUsers: (userIds: string[]) => Promise<User[]>;
|
|
223
|
+
|
|
224
|
+
schema: BlockNoteSchema<BSchema, ISchema, SSchema>;
|
|
235
225
|
|
|
236
226
|
/**
|
|
237
227
|
* A flag indicating whether to set an HTML ID for every block
|
|
@@ -243,7 +233,14 @@ export type BlockNoteEditorOptions<
|
|
|
243
233
|
*/
|
|
244
234
|
setIdAttribute?: boolean;
|
|
245
235
|
|
|
246
|
-
|
|
236
|
+
/**
|
|
237
|
+
* The detection mode for showing the side menu - "viewport" always shows the
|
|
238
|
+
* side menu for the block next to the mouse cursor, while "editor" only shows
|
|
239
|
+
* it when hovering the editor or the side menu itself.
|
|
240
|
+
*
|
|
241
|
+
* @default "viewport"
|
|
242
|
+
*/
|
|
243
|
+
sideMenuDetection: "viewport" | "editor";
|
|
247
244
|
|
|
248
245
|
/**
|
|
249
246
|
Select desired behavior when pressing `Tab` (or `Shift-Tab`). Specifically,
|
|
@@ -261,13 +258,69 @@ export type BlockNoteEditorOptions<
|
|
|
261
258
|
tabBehavior: "prefer-navigate-ui" | "prefer-indent";
|
|
262
259
|
|
|
263
260
|
/**
|
|
264
|
-
*
|
|
265
|
-
|
|
266
|
-
|
|
261
|
+
* Allows enabling / disabling features of tables.
|
|
262
|
+
*/
|
|
263
|
+
tables?: {
|
|
264
|
+
/**
|
|
265
|
+
* Whether to allow splitting and merging cells within a table.
|
|
266
|
+
*
|
|
267
|
+
* @default false
|
|
268
|
+
*/
|
|
269
|
+
splitCells?: boolean;
|
|
270
|
+
/**
|
|
271
|
+
* Whether to allow changing the background color of cells.
|
|
272
|
+
*
|
|
273
|
+
* @default false
|
|
274
|
+
*/
|
|
275
|
+
cellBackgroundColor?: boolean;
|
|
276
|
+
/**
|
|
277
|
+
* Whether to allow changing the text color of cells.
|
|
278
|
+
*
|
|
279
|
+
* @default false
|
|
280
|
+
*/
|
|
281
|
+
cellTextColor?: boolean;
|
|
282
|
+
/**
|
|
283
|
+
* Whether to allow changing cells into headers.
|
|
284
|
+
*
|
|
285
|
+
* @default false
|
|
286
|
+
*/
|
|
287
|
+
headers?: boolean;
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
trailingBlock?: boolean;
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* The `uploadFile` method is what the editor uses when files need to be uploaded (for example when selecting an image to upload).
|
|
294
|
+
* This method should set when creating the editor as this is application-specific.
|
|
267
295
|
*
|
|
268
|
-
*
|
|
296
|
+
* `undefined` means the application doesn't support file uploads.
|
|
297
|
+
*
|
|
298
|
+
* @param file The file that should be uploaded.
|
|
299
|
+
* @returns The URL of the uploaded file OR an object containing props that should be set on the file block (such as an id)
|
|
269
300
|
*/
|
|
270
|
-
|
|
301
|
+
uploadFile: (
|
|
302
|
+
file: File,
|
|
303
|
+
blockId?: string
|
|
304
|
+
) => Promise<string | Record<string, any>>;
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* additional tiptap options, undocumented
|
|
308
|
+
*/
|
|
309
|
+
_tiptapOptions: Partial<EditorOptions>;
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* (experimental) add extra prosemirror plugins or tiptap extensions to the editor
|
|
313
|
+
*/
|
|
314
|
+
_extensions: Record<string, BlockNoteExtension | BlockNoteExtensionFactory>;
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Boolean indicating whether the editor is in headless mode.
|
|
318
|
+
* Headless mode means we can use features like importing / exporting blocks,
|
|
319
|
+
* but there's no underlying editor (UI) instantiated.
|
|
320
|
+
*
|
|
321
|
+
* You probably don't need to set this manually, but use the `server-util` package instead that uses this option internally
|
|
322
|
+
*/
|
|
323
|
+
_headless: boolean;
|
|
271
324
|
};
|
|
272
325
|
|
|
273
326
|
const blockNoteTipTapOptions = {
|
|
@@ -280,8 +333,13 @@ export class BlockNoteEditor<
|
|
|
280
333
|
BSchema extends BlockSchema = DefaultBlockSchema,
|
|
281
334
|
ISchema extends InlineContentSchema = DefaultInlineContentSchema,
|
|
282
335
|
SSchema extends StyleSchema = DefaultStyleSchema
|
|
283
|
-
> {
|
|
284
|
-
|
|
336
|
+
> extends EventEmitter<{
|
|
337
|
+
create: void;
|
|
338
|
+
}> {
|
|
339
|
+
/**
|
|
340
|
+
* The underlying prosemirror schema
|
|
341
|
+
*/
|
|
342
|
+
public readonly pmSchema: Schema;
|
|
285
343
|
|
|
286
344
|
/**
|
|
287
345
|
* extensions that are added to the editor, can be tiptap extensions or prosemirror plugins
|
|
@@ -352,6 +410,9 @@ export class BlockNoteEditor<
|
|
|
352
410
|
ISchema,
|
|
353
411
|
SSchema
|
|
354
412
|
>;
|
|
413
|
+
public readonly comments?: CommentsPlugin;
|
|
414
|
+
|
|
415
|
+
private readonly showSelectionPlugin: ShowSelectionPlugin;
|
|
355
416
|
|
|
356
417
|
/**
|
|
357
418
|
* The `uploadFile` method is what the editor uses when files need to be uploaded (for example when selecting an image to upload).
|
|
@@ -370,10 +431,18 @@ export class BlockNoteEditor<
|
|
|
370
431
|
private onUploadEndCallbacks: ((blockId?: string) => void)[] = [];
|
|
371
432
|
|
|
372
433
|
public readonly resolveFileUrl?: (url: string) => Promise<string>;
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
434
|
+
public readonly resolveUsers?: (userIds: string[]) => Promise<User[]>;
|
|
435
|
+
/**
|
|
436
|
+
* Editor settings
|
|
437
|
+
*/
|
|
438
|
+
public readonly settings: {
|
|
439
|
+
tables: {
|
|
440
|
+
splitCells: boolean;
|
|
441
|
+
cellBackgroundColor: boolean;
|
|
442
|
+
cellTextColor: boolean;
|
|
443
|
+
headers: boolean;
|
|
444
|
+
};
|
|
445
|
+
};
|
|
377
446
|
|
|
378
447
|
public static create<
|
|
379
448
|
BSchema extends BlockSchema = DefaultBlockSchema,
|
|
@@ -386,6 +455,7 @@ export class BlockNoteEditor<
|
|
|
386
455
|
protected constructor(
|
|
387
456
|
protected readonly options: Partial<BlockNoteEditorOptions<any, any, any>>
|
|
388
457
|
) {
|
|
458
|
+
super();
|
|
389
459
|
const anyOpts = options as any;
|
|
390
460
|
if (anyOpts.onEditorContentChange) {
|
|
391
461
|
throw new Error(
|
|
@@ -412,6 +482,14 @@ export class BlockNoteEditor<
|
|
|
412
482
|
}
|
|
413
483
|
|
|
414
484
|
this.dictionary = options.dictionary || en;
|
|
485
|
+
this.settings = {
|
|
486
|
+
tables: {
|
|
487
|
+
splitCells: options?.tables?.splitCells ?? false,
|
|
488
|
+
cellBackgroundColor: options?.tables?.cellBackgroundColor ?? false,
|
|
489
|
+
cellTextColor: options?.tables?.cellTextColor ?? false,
|
|
490
|
+
headers: options?.tables?.headers ?? false,
|
|
491
|
+
},
|
|
492
|
+
};
|
|
415
493
|
|
|
416
494
|
// apply defaults
|
|
417
495
|
const newOptions = {
|
|
@@ -425,6 +503,12 @@ export class BlockNoteEditor<
|
|
|
425
503
|
},
|
|
426
504
|
};
|
|
427
505
|
|
|
506
|
+
if (newOptions.comments && !newOptions.resolveUsers) {
|
|
507
|
+
throw new Error("resolveUsers is required when using comments");
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
this.resolveUsers = newOptions.resolveUsers;
|
|
511
|
+
|
|
428
512
|
// @ts-ignore
|
|
429
513
|
this.schema = newOptions.schema;
|
|
430
514
|
this.blockImplementations = newOptions.schema.blockSpecs;
|
|
@@ -447,6 +531,7 @@ export class BlockNoteEditor<
|
|
|
447
531
|
placeholders: newOptions.placeholders,
|
|
448
532
|
tabBehavior: newOptions.tabBehavior,
|
|
449
533
|
sideMenuDetection: newOptions.sideMenuDetection || "viewport",
|
|
534
|
+
comments: newOptions.comments,
|
|
450
535
|
});
|
|
451
536
|
|
|
452
537
|
// add extensions from _tiptapOptions
|
|
@@ -469,6 +554,8 @@ export class BlockNoteEditor<
|
|
|
469
554
|
this.suggestionMenus = this.extensions["suggestionMenus"] as any;
|
|
470
555
|
this.filePanel = this.extensions["filePanel"] as any;
|
|
471
556
|
this.tableHandles = this.extensions["tableHandles"] as any;
|
|
557
|
+
this.comments = this.extensions["comments"] as any;
|
|
558
|
+
this.showSelectionPlugin = this.extensions["showSelection"] as any;
|
|
472
559
|
|
|
473
560
|
if (newOptions.uploadFile) {
|
|
474
561
|
const uploadFile = newOptions.uploadFile;
|
|
@@ -500,6 +587,12 @@ export class BlockNoteEditor<
|
|
|
500
587
|
);
|
|
501
588
|
}
|
|
502
589
|
|
|
590
|
+
if (newOptions.comments && !collaborationEnabled) {
|
|
591
|
+
throw new Error(
|
|
592
|
+
"Comments are only supported when collaboration is enabled, please set the collaboration option"
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
|
|
503
596
|
const initialContent =
|
|
504
597
|
newOptions.initialContent ||
|
|
505
598
|
(collaborationEnabled
|
|
@@ -579,17 +672,18 @@ export class BlockNoteEditor<
|
|
|
579
672
|
view: any;
|
|
580
673
|
contentComponent: any;
|
|
581
674
|
};
|
|
582
|
-
this.
|
|
675
|
+
this.pmSchema = this._tiptapEditor.schema;
|
|
583
676
|
} else {
|
|
584
677
|
// In headless mode, we don't instantiate an underlying TipTap editor,
|
|
585
678
|
// but we still need the schema
|
|
586
|
-
this.
|
|
679
|
+
this.pmSchema = getSchema(tiptapOptions.extensions!);
|
|
587
680
|
}
|
|
681
|
+
this.emit("create");
|
|
588
682
|
}
|
|
589
683
|
|
|
590
|
-
dispatch(tr: Transaction) {
|
|
684
|
+
dispatch = (tr: Transaction) => {
|
|
591
685
|
this._tiptapEditor.dispatch(tr);
|
|
592
|
-
}
|
|
686
|
+
};
|
|
593
687
|
|
|
594
688
|
/**
|
|
595
689
|
* Mount the editor to a parent DOM element. Call mount(undefined) to clean up
|
|
@@ -603,10 +697,20 @@ export class BlockNoteEditor<
|
|
|
603
697
|
this._tiptapEditor.mount(parentElement, contentComponent);
|
|
604
698
|
};
|
|
605
699
|
|
|
700
|
+
/**
|
|
701
|
+
* Get the underlying prosemirror view
|
|
702
|
+
*/
|
|
606
703
|
public get prosemirrorView() {
|
|
607
704
|
return this._tiptapEditor.view;
|
|
608
705
|
}
|
|
609
706
|
|
|
707
|
+
/**
|
|
708
|
+
* Get the underlying prosemirror state
|
|
709
|
+
*/
|
|
710
|
+
public get prosemirrorState() {
|
|
711
|
+
return this._tiptapEditor.state;
|
|
712
|
+
}
|
|
713
|
+
|
|
610
714
|
public get domElement() {
|
|
611
715
|
return this.prosemirrorView?.dom as HTMLDivElement | undefined;
|
|
612
716
|
}
|
|
@@ -655,7 +759,7 @@ export class BlockNoteEditor<
|
|
|
655
759
|
public get document(): Block<BSchema, ISchema, SSchema>[] {
|
|
656
760
|
const blocks: Block<BSchema, ISchema, SSchema>[] = [];
|
|
657
761
|
|
|
658
|
-
this.
|
|
762
|
+
this.prosemirrorState.doc.firstChild!.descendants((node) => {
|
|
659
763
|
blocks.push(
|
|
660
764
|
nodeToBlock(
|
|
661
765
|
node,
|
|
@@ -768,6 +872,8 @@ export class BlockNoteEditor<
|
|
|
768
872
|
/**
|
|
769
873
|
* Executes a callback whenever the editor's contents change.
|
|
770
874
|
* @param callback The callback to execute.
|
|
875
|
+
*
|
|
876
|
+
* @deprecated use `onChange` instead
|
|
771
877
|
*/
|
|
772
878
|
public onEditorContentChange(callback: () => void) {
|
|
773
879
|
this._tiptapEditor.on("update", callback);
|
|
@@ -776,6 +882,8 @@ export class BlockNoteEditor<
|
|
|
776
882
|
/**
|
|
777
883
|
* Executes a callback whenever the editor's selection changes.
|
|
778
884
|
* @param callback The callback to execute.
|
|
885
|
+
*
|
|
886
|
+
* @deprecated use `onSelectionChange` instead
|
|
779
887
|
*/
|
|
780
888
|
public onEditorSelectionChange(callback: () => void) {
|
|
781
889
|
this._tiptapEditor.on("selectionUpdate", callback);
|
|
@@ -1217,13 +1325,22 @@ export class BlockNoteEditor<
|
|
|
1217
1325
|
* @returns A function to remove the callback.
|
|
1218
1326
|
*/
|
|
1219
1327
|
public onSelectionChange(
|
|
1220
|
-
callback: (editor: BlockNoteEditor<BSchema, ISchema, SSchema>) => void
|
|
1328
|
+
callback: (editor: BlockNoteEditor<BSchema, ISchema, SSchema>) => void,
|
|
1329
|
+
includeSelectionChangedByRemote?: boolean
|
|
1221
1330
|
) {
|
|
1222
1331
|
if (this.headless) {
|
|
1223
1332
|
return;
|
|
1224
1333
|
}
|
|
1225
1334
|
|
|
1226
|
-
const cb = () => {
|
|
1335
|
+
const cb = (e: { transaction: Transaction }) => {
|
|
1336
|
+
if (
|
|
1337
|
+
e.transaction.getMeta(ySyncPluginKey) &&
|
|
1338
|
+
!includeSelectionChangedByRemote
|
|
1339
|
+
) {
|
|
1340
|
+
// selection changed because of a yjs sync (i.e.: other user was typing)
|
|
1341
|
+
// we don't want to trigger the callback in this case
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1227
1344
|
callback(this);
|
|
1228
1345
|
};
|
|
1229
1346
|
|
|
@@ -1234,6 +1351,53 @@ export class BlockNoteEditor<
|
|
|
1234
1351
|
};
|
|
1235
1352
|
}
|
|
1236
1353
|
|
|
1354
|
+
/**
|
|
1355
|
+
* A callback function that runs when the editor has been initialized.
|
|
1356
|
+
*
|
|
1357
|
+
* This can be useful for plugins to initialize themselves after the editor has been initialized.
|
|
1358
|
+
*/
|
|
1359
|
+
public onCreate(callback: () => void) {
|
|
1360
|
+
this.on("create", callback);
|
|
1361
|
+
|
|
1362
|
+
return () => {
|
|
1363
|
+
this.off("create", callback);
|
|
1364
|
+
};
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
public getSelectionBoundingBox() {
|
|
1368
|
+
if (!this.prosemirrorView) {
|
|
1369
|
+
return undefined;
|
|
1370
|
+
}
|
|
1371
|
+
const state = this.prosemirrorView?.state;
|
|
1372
|
+
const { selection } = state;
|
|
1373
|
+
|
|
1374
|
+
// support for CellSelections
|
|
1375
|
+
const { ranges } = selection;
|
|
1376
|
+
const from = Math.min(...ranges.map((range) => range.$from.pos));
|
|
1377
|
+
const to = Math.max(...ranges.map((range) => range.$to.pos));
|
|
1378
|
+
|
|
1379
|
+
if (isNodeSelection(selection)) {
|
|
1380
|
+
const node = this.prosemirrorView.nodeDOM(from) as HTMLElement;
|
|
1381
|
+
if (node) {
|
|
1382
|
+
return node.getBoundingClientRect();
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
return posToDOMRect(this.prosemirrorView, from, to);
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
public get isEmpty() {
|
|
1390
|
+
const doc = this.document;
|
|
1391
|
+
// Note: only works for paragraphs as default blocks (but for now this is default in blocknote)
|
|
1392
|
+
// checking prosemirror directly might be faster
|
|
1393
|
+
return (
|
|
1394
|
+
doc.length === 0 ||
|
|
1395
|
+
(doc.length === 1 &&
|
|
1396
|
+
doc[0].type === "paragraph" &&
|
|
1397
|
+
(doc[0].content as any).length === 0)
|
|
1398
|
+
);
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1237
1401
|
public openSuggestionMenu(
|
|
1238
1402
|
triggerCharacter: string,
|
|
1239
1403
|
pluginState?: {
|
|
@@ -1260,4 +1424,17 @@ export class BlockNoteEditor<
|
|
|
1260
1424
|
})
|
|
1261
1425
|
);
|
|
1262
1426
|
}
|
|
1427
|
+
|
|
1428
|
+
// `forceSelectionVisible` determines whether the editor selection is shows
|
|
1429
|
+
// even when the editor is not focused. This is useful for e.g. creating new
|
|
1430
|
+
// links, so the user still sees the affected content when an input field is
|
|
1431
|
+
// focused.
|
|
1432
|
+
// TODO: Reconsider naming?
|
|
1433
|
+
public getForceSelectionVisible() {
|
|
1434
|
+
return this.showSelectionPlugin.getEnabled();
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
public setForceSelectionVisible(forceSelectionVisible: boolean) {
|
|
1438
|
+
this.showSelectionPlugin.setEnabled(forceSelectionVisible);
|
|
1439
|
+
}
|
|
1263
1440
|
}
|
|
@@ -12,6 +12,9 @@ import { createPasteFromClipboardExtension } from "../api/clipboard/fromClipboar
|
|
|
12
12
|
import { createCopyToClipboardExtension } from "../api/clipboard/toClipboard/copyExtension.js";
|
|
13
13
|
import { BackgroundColorExtension } from "../extensions/BackgroundColor/BackgroundColorExtension.js";
|
|
14
14
|
import { createCollaborationExtensions } from "../extensions/Collaboration/createCollaborationExtensions.js";
|
|
15
|
+
import { CommentMark } from "../extensions/Comments/CommentMark.js";
|
|
16
|
+
import { CommentsPlugin } from "../extensions/Comments/CommentsPlugin.js";
|
|
17
|
+
import type { ThreadStore } from "../comments/index.js";
|
|
15
18
|
import { FilePanelProsemirrorPlugin } from "../extensions/FilePanel/FilePanelPlugin.js";
|
|
16
19
|
import { FormattingToolbarProsemirrorPlugin } from "../extensions/FormattingToolbar/FormattingToolbarPlugin.js";
|
|
17
20
|
import { KeyboardShortcutsExtension } from "../extensions/KeyboardShortcuts/KeyboardShortcutsExtension.js";
|
|
@@ -23,6 +26,7 @@ import {
|
|
|
23
26
|
import { NodeSelectionKeyboardPlugin } from "../extensions/NodeSelectionKeyboard/NodeSelectionKeyboardPlugin.js";
|
|
24
27
|
import { PlaceholderPlugin } from "../extensions/Placeholder/PlaceholderPlugin.js";
|
|
25
28
|
import { PreviousBlockTypePlugin } from "../extensions/PreviousBlockType/PreviousBlockTypePlugin.js";
|
|
29
|
+
import { ShowSelectionPlugin } from "../extensions/ShowSelection/ShowSelectionPlugin.js";
|
|
26
30
|
import { SideMenuProsemirrorPlugin } from "../extensions/SideMenu/SideMenuPlugin.js";
|
|
27
31
|
import { SuggestionMenuProseMirrorPlugin } from "../extensions/SuggestionMenu/SuggestionPlugin.js";
|
|
28
32
|
import { TableHandlesProsemirrorPlugin } from "../extensions/TableHandles/TableHandlesPlugin.js";
|
|
@@ -75,6 +79,9 @@ type ExtensionOptions<
|
|
|
75
79
|
>;
|
|
76
80
|
tabBehavior?: "prefer-navigate-ui" | "prefer-indent";
|
|
77
81
|
sideMenuDetection: "viewport" | "editor";
|
|
82
|
+
comments?: {
|
|
83
|
+
threadStore: ThreadStore;
|
|
84
|
+
};
|
|
78
85
|
};
|
|
79
86
|
|
|
80
87
|
/**
|
|
@@ -126,6 +133,16 @@ export const getBlockNoteExtensions = <
|
|
|
126
133
|
|
|
127
134
|
ret["nodeSelectionKeyboard"] = new NodeSelectionKeyboardPlugin();
|
|
128
135
|
|
|
136
|
+
ret["showSelection"] = new ShowSelectionPlugin(opts.editor);
|
|
137
|
+
|
|
138
|
+
if (opts.comments) {
|
|
139
|
+
ret["comments"] = new CommentsPlugin(
|
|
140
|
+
opts.editor,
|
|
141
|
+
opts.comments.threadStore,
|
|
142
|
+
CommentMark.name
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
129
146
|
const disableExtensions: string[] = opts.disableExtensions || [];
|
|
130
147
|
for (const ext of disableExtensions) {
|
|
131
148
|
delete ret[ext];
|
|
@@ -134,6 +151,8 @@ export const getBlockNoteExtensions = <
|
|
|
134
151
|
return ret;
|
|
135
152
|
};
|
|
136
153
|
|
|
154
|
+
let LINKIFY_INITIALIZED = false;
|
|
155
|
+
|
|
137
156
|
/**
|
|
138
157
|
* Get all the Tiptap extensions BlockNote is configured with by default
|
|
139
158
|
*/
|
|
@@ -171,7 +190,8 @@ const getTipTapExtensions = <
|
|
|
171
190
|
inclusive: false,
|
|
172
191
|
}).configure({
|
|
173
192
|
defaultProtocol: DEFAULT_LINK_PROTOCOL,
|
|
174
|
-
|
|
193
|
+
// only call this once if we have multiple editors installed. Or fix https://github.com/ueberdosis/tiptap/issues/5450
|
|
194
|
+
protocols: LINKIFY_INITIALIZED ? [] : VALID_LINK_PROTOCOLS,
|
|
175
195
|
}),
|
|
176
196
|
...Object.values(opts.styleSpecs).map((styleSpec) => {
|
|
177
197
|
return styleSpec.implementation.mark.configure({
|
|
@@ -246,8 +266,11 @@ const getTipTapExtensions = <
|
|
|
246
266
|
...(opts.trailingBlock === undefined || opts.trailingBlock
|
|
247
267
|
? [TrailingNode]
|
|
248
268
|
: []),
|
|
269
|
+
...(opts.comments ? [CommentMark] : []),
|
|
249
270
|
];
|
|
250
271
|
|
|
272
|
+
LINKIFY_INITIALIZED = true;
|
|
273
|
+
|
|
251
274
|
if (opts.collaboration) {
|
|
252
275
|
tiptapExtensions.push(...createCollaborationExtensions(opts.collaboration));
|
|
253
276
|
} else {
|
|
@@ -184,7 +184,11 @@ export class BlockNoteTipTapEditor extends TiptapEditor {
|
|
|
184
184
|
|
|
185
185
|
// emit the created event, call here manually because we blocked the default call in the constructor
|
|
186
186
|
// (https://github.com/ueberdosis/tiptap/blob/45bac803283446795ad1b03f43d3746fa54a68ff/packages/core/src/Editor.ts#L117)
|
|
187
|
-
this.commands.focus(
|
|
187
|
+
this.commands.focus(
|
|
188
|
+
this.options.autofocus ||
|
|
189
|
+
this.options.element.getAttribute("data-bn-autofocus") === "true",
|
|
190
|
+
{ scrollIntoView: false }
|
|
191
|
+
);
|
|
188
192
|
this.emit("create", { editor: this });
|
|
189
193
|
this.isInitialized = true;
|
|
190
194
|
}
|