@blocknote/core 0.9.2 → 0.9.4
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.js +1562 -1240
- package/dist/blocknote.js.map +1 -1
- package/dist/blocknote.umd.cjs +5 -5
- package/dist/blocknote.umd.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +2 -2
- package/src/BlockNoteEditor.ts +44 -12
- package/src/api/blockManipulation/__snapshots__/blockManipulation.test.ts.snap +21 -21
- package/src/api/blockManipulation/blockManipulation.test.ts +8 -11
- package/src/api/formatConversions/__snapshots__/formatConversions.test.ts.snap +3 -3
- package/src/api/formatConversions/formatConversions.test.ts +5 -5
- package/src/api/nodeConversions/__snapshots__/nodeConversions.test.ts.snap +3 -3
- package/src/api/nodeConversions/nodeConversions.test.ts +10 -4
- package/src/api/nodeConversions/nodeConversions.ts +9 -7
- package/src/api/nodeConversions/testUtil.ts +3 -3
- package/src/editor.module.css +1 -1
- package/src/extensions/BackgroundColor/BackgroundColorExtension.ts +5 -3
- package/src/extensions/BackgroundColor/BackgroundColorMark.ts +2 -1
- package/src/extensions/Blocks/NonEditableBlockPlugin.ts +17 -0
- package/src/extensions/Blocks/api/block.ts +29 -16
- package/src/extensions/Blocks/api/blockTypes.ts +79 -27
- package/src/extensions/Blocks/api/defaultBlocks.ts +13 -41
- package/src/extensions/Blocks/api/defaultProps.ts +16 -0
- package/src/extensions/Blocks/nodes/Block.module.css +78 -24
- package/src/extensions/Blocks/nodes/BlockContainer.ts +45 -45
- package/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContent.ts +61 -13
- package/src/extensions/Blocks/nodes/BlockContent/ImageBlockContent/ImageBlockContent.ts +305 -0
- package/src/extensions/Blocks/nodes/BlockContent/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.ts +13 -0
- package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +26 -2
- package/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +146 -118
- package/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.ts +12 -2
- package/src/extensions/ImageToolbar/ImageToolbarPlugin.ts +239 -0
- package/src/extensions/SlashMenu/defaultSlashMenuItems.ts +47 -6
- package/src/extensions/TextColor/TextColorExtension.ts +4 -3
- package/src/extensions/TextColor/TextColorMark.ts +2 -1
- package/src/extensions/TrailingNode/TrailingNodeExtension.ts +13 -1
- package/src/index.ts +4 -0
- package/types/src/BlockNoteEditor.d.ts +9 -0
- package/types/src/BlockNoteExtensions.d.ts +1 -1
- package/types/src/extensions/Blocks/NonEditableBlockPlugin.d.ts +2 -0
- package/types/src/extensions/Blocks/api/block.d.ts +7 -8
- package/types/src/extensions/Blocks/api/blockTypes.d.ts +29 -20
- package/types/src/extensions/Blocks/api/defaultBlocks.d.ts +55 -51
- package/types/src/extensions/Blocks/api/defaultProps.d.ts +14 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/HeadingBlockContent/HeadingBlockContent.d.ts +43 -9
- package/types/src/extensions/Blocks/nodes/BlockContent/ImageBlockContent/Image.d.ts +6 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ImageBlockContent/ImageBlockContent.d.ts +37 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ImageBlockContent/uploadToTmpFilesDotOrg_DEV_ONLY.d.ts +1 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ImageBlockContent/uploadToTmpFilesOrg_DEV_ONLY.d.ts +1 -0
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.d.ts +35 -9
- package/types/src/extensions/Blocks/nodes/BlockContent/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.d.ts +35 -9
- package/types/src/extensions/Blocks/nodes/BlockContent/ParagraphBlockContent/ParagraphBlockContent.d.ts +36 -1
- package/types/src/extensions/ImageToolbar/ImageToolbarPlugin.d.ts +36 -0
- package/types/src/extensions/SlashMenu/defaultSlashMenuItems.d.ts +1 -1
- package/types/src/index.d.ts +4 -0
- package/types/src/shared/plugins/suggestion/SuggestionPlugin.d.ts +1 -1
- package/types/src/extensions/Blocks/nodes/TableCell.d.ts +0 -5
- package/types/src/extensions/Blocks/nodes/TableRow.d.ts +0 -5
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"homepage": "https://github.com/TypeCellOS/BlockNote",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
|
-
"version": "0.9.
|
|
6
|
+
"version": "0.9.4",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
9
9
|
"types",
|
|
@@ -109,5 +109,5 @@
|
|
|
109
109
|
"access": "public",
|
|
110
110
|
"registry": "https://registry.npmjs.org/"
|
|
111
111
|
},
|
|
112
|
-
"gitHead": "
|
|
112
|
+
"gitHead": "31e3c53bdcc082e3793bbb5517462cc18abd9e22"
|
|
113
113
|
}
|
package/src/BlockNoteEditor.ts
CHANGED
|
@@ -11,9 +11,9 @@ import {
|
|
|
11
11
|
updateBlock,
|
|
12
12
|
} from "./api/blockManipulation/blockManipulation";
|
|
13
13
|
import {
|
|
14
|
+
HTMLToBlocks,
|
|
14
15
|
blocksToHTML,
|
|
15
16
|
blocksToMarkdown,
|
|
16
|
-
HTMLToBlocks,
|
|
17
17
|
markdownToBlocks,
|
|
18
18
|
} from "./api/formatConversions/formatConversions";
|
|
19
19
|
import {
|
|
@@ -44,6 +44,7 @@ import { getBlockInfoFromPos } from "./extensions/Blocks/helpers/getBlockInfoFro
|
|
|
44
44
|
|
|
45
45
|
import { FormattingToolbarProsemirrorPlugin } from "./extensions/FormattingToolbar/FormattingToolbarPlugin";
|
|
46
46
|
import { HyperlinkToolbarProsemirrorPlugin } from "./extensions/HyperlinkToolbar/HyperlinkToolbarPlugin";
|
|
47
|
+
import { ImageToolbarProsemirrorPlugin } from "./extensions/ImageToolbar/ImageToolbarPlugin";
|
|
47
48
|
import { SideMenuProsemirrorPlugin } from "./extensions/SideMenu/SideMenuPlugin";
|
|
48
49
|
import { BaseSlashMenuItem } from "./extensions/SlashMenu/BaseSlashMenuItem";
|
|
49
50
|
import { SlashMenuProsemirrorPlugin } from "./extensions/SlashMenu/SlashMenuPlugin";
|
|
@@ -106,6 +107,13 @@ export type BlockNoteEditorOptions<BSchema extends BlockSchema> = {
|
|
|
106
107
|
*/
|
|
107
108
|
blockSchema: BSchema;
|
|
108
109
|
|
|
110
|
+
/**
|
|
111
|
+
* A custom function to handle file uploads.
|
|
112
|
+
* @param file The file that should be uploaded.
|
|
113
|
+
* @returns The URL of the uploaded file.
|
|
114
|
+
*/
|
|
115
|
+
uploadFile: (file: File) => Promise<string>;
|
|
116
|
+
|
|
109
117
|
/**
|
|
110
118
|
* When enabled, allows for collaboration between multiple users.
|
|
111
119
|
*/
|
|
@@ -151,6 +159,9 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
|
|
|
151
159
|
public readonly formattingToolbar: FormattingToolbarProsemirrorPlugin<BSchema>;
|
|
152
160
|
public readonly slashMenu: SlashMenuProsemirrorPlugin<BSchema, any>;
|
|
153
161
|
public readonly hyperlinkToolbar: HyperlinkToolbarProsemirrorPlugin<BSchema>;
|
|
162
|
+
public readonly imageToolbar: ImageToolbarProsemirrorPlugin<BSchema>;
|
|
163
|
+
|
|
164
|
+
public readonly uploadFile: ((file: File) => Promise<string>) | undefined;
|
|
154
165
|
|
|
155
166
|
constructor(
|
|
156
167
|
private readonly options: Partial<BlockNoteEditorOptions<BSchema>> = {}
|
|
@@ -178,6 +189,7 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
|
|
|
178
189
|
getDefaultSlashMenuItems(newOptions.blockSchema)
|
|
179
190
|
);
|
|
180
191
|
this.hyperlinkToolbar = new HyperlinkToolbarProsemirrorPlugin(this);
|
|
192
|
+
this.imageToolbar = new ImageToolbarProsemirrorPlugin(this);
|
|
181
193
|
|
|
182
194
|
const extensions = getBlockNoteExtensions<BSchema>({
|
|
183
195
|
editor: this,
|
|
@@ -195,6 +207,7 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
|
|
|
195
207
|
this.formattingToolbar.plugin,
|
|
196
208
|
this.slashMenu.plugin,
|
|
197
209
|
this.hyperlinkToolbar.plugin,
|
|
210
|
+
this.imageToolbar.plugin,
|
|
198
211
|
];
|
|
199
212
|
},
|
|
200
213
|
});
|
|
@@ -202,6 +215,8 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
|
|
|
202
215
|
|
|
203
216
|
this.schema = newOptions.blockSchema;
|
|
204
217
|
|
|
218
|
+
this.uploadFile = newOptions.uploadFile;
|
|
219
|
+
|
|
205
220
|
const initialContent =
|
|
206
221
|
newOptions.initialContent ||
|
|
207
222
|
(options.collaboration
|
|
@@ -216,28 +231,36 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
|
|
|
216
231
|
const tiptapOptions: EditorOptions = {
|
|
217
232
|
...blockNoteTipTapOptions,
|
|
218
233
|
...newOptions._tiptapOptions,
|
|
219
|
-
onCreate: () => {
|
|
220
|
-
newOptions.onEditorReady?.(this);
|
|
221
|
-
this.ready = true;
|
|
222
|
-
},
|
|
223
234
|
onBeforeCreate(editor) {
|
|
224
235
|
if (!initialContent) {
|
|
225
236
|
// when using collaboration
|
|
226
237
|
return;
|
|
227
238
|
}
|
|
228
|
-
// we have to set the initial content here, because now we can use the editor schema
|
|
229
|
-
// which has been created at this point
|
|
230
|
-
const schema = editor.editor.schema;
|
|
231
|
-
const ic = initialContent.map((block) => blockToNode(block, schema));
|
|
232
239
|
|
|
240
|
+
// We always set the initial content to a single paragraph block. This
|
|
241
|
+
// allows us to easily replace it with the actual initial content once
|
|
242
|
+
// the TipTap editor is initialized.
|
|
243
|
+
const schema = editor.editor.schema;
|
|
233
244
|
const root = schema.node(
|
|
234
245
|
"doc",
|
|
235
246
|
undefined,
|
|
236
|
-
schema.node("blockGroup", undefined,
|
|
247
|
+
schema.node("blockGroup", undefined, [
|
|
248
|
+
blockToNode({ id: "initialBlock", type: "paragraph" }, schema),
|
|
249
|
+
])
|
|
237
250
|
);
|
|
238
|
-
// override the initialcontent
|
|
239
251
|
editor.editor.options.content = root.toJSON();
|
|
240
252
|
},
|
|
253
|
+
onCreate: () => {
|
|
254
|
+
// We need to wait for the TipTap editor to init before we can set the
|
|
255
|
+
// initial content, as the schema may contain custom blocks which need
|
|
256
|
+
// it to render.
|
|
257
|
+
if (initialContent !== undefined) {
|
|
258
|
+
this.replaceBlocks(this.topLevelBlocks, initialContent);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
newOptions.onEditorReady?.(this);
|
|
262
|
+
this.ready = true;
|
|
263
|
+
},
|
|
241
264
|
onUpdate: () => {
|
|
242
265
|
// This seems to be necessary due to a bug in TipTap:
|
|
243
266
|
// https://github.com/ueberdosis/tiptap/issues/2583
|
|
@@ -460,6 +483,12 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
|
|
|
460
483
|
posBeforeNode + 2
|
|
461
484
|
)!;
|
|
462
485
|
|
|
486
|
+
// For blocks without inline content
|
|
487
|
+
if (contentNode.type.spec.content === "") {
|
|
488
|
+
this._tiptapEditor.commands.setNodeSelection(startPos);
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
|
|
463
492
|
if (placement === "start") {
|
|
464
493
|
this._tiptapEditor.commands.setTextSelection(startPos + 1);
|
|
465
494
|
} else {
|
|
@@ -473,9 +502,12 @@ export class BlockNoteEditor<BSchema extends BlockSchema = DefaultBlockSchema> {
|
|
|
473
502
|
* Gets a snapshot of the current selection.
|
|
474
503
|
*/
|
|
475
504
|
public getSelection(): Selection<BSchema> | undefined {
|
|
505
|
+
// Either the TipTap selection is empty, or it's a node selection. In either
|
|
506
|
+
// case, it only spans one block, so we return undefined.
|
|
476
507
|
if (
|
|
477
508
|
this._tiptapEditor.state.selection.from ===
|
|
478
|
-
|
|
509
|
+
this._tiptapEditor.state.selection.to ||
|
|
510
|
+
"node" in this._tiptapEditor.state.selection
|
|
479
511
|
) {
|
|
480
512
|
return undefined;
|
|
481
513
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Vitest Snapshot v1
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
3
|
exports[`Insert, Update, & Delete Blocks > Insert, update, & delete multiple blocks 1`] = `
|
|
4
4
|
[
|
|
@@ -16,7 +16,7 @@ exports[`Insert, Update, & Delete Blocks > Insert, update, & delete multiple blo
|
|
|
16
16
|
"id": "2",
|
|
17
17
|
"props": {
|
|
18
18
|
"backgroundColor": "default",
|
|
19
|
-
"level":
|
|
19
|
+
"level": 1,
|
|
20
20
|
"textAlignment": "left",
|
|
21
21
|
"textColor": "default",
|
|
22
22
|
},
|
|
@@ -33,7 +33,7 @@ exports[`Insert, Update, & Delete Blocks > Insert, update, & delete multiple blo
|
|
|
33
33
|
"id": "1",
|
|
34
34
|
"props": {
|
|
35
35
|
"backgroundColor": "default",
|
|
36
|
-
"level":
|
|
36
|
+
"level": 1,
|
|
37
37
|
"textAlignment": "left",
|
|
38
38
|
"textColor": "default",
|
|
39
39
|
},
|
|
@@ -53,7 +53,7 @@ exports[`Insert, Update, & Delete Blocks > Insert, update, & delete multiple blo
|
|
|
53
53
|
"id": "4",
|
|
54
54
|
"props": {
|
|
55
55
|
"backgroundColor": "default",
|
|
56
|
-
"level":
|
|
56
|
+
"level": 2,
|
|
57
57
|
"textAlignment": "left",
|
|
58
58
|
"textColor": "default",
|
|
59
59
|
},
|
|
@@ -70,7 +70,7 @@ exports[`Insert, Update, & Delete Blocks > Insert, update, & delete multiple blo
|
|
|
70
70
|
"id": "3",
|
|
71
71
|
"props": {
|
|
72
72
|
"backgroundColor": "default",
|
|
73
|
-
"level":
|
|
73
|
+
"level": 2,
|
|
74
74
|
"textAlignment": "left",
|
|
75
75
|
"textColor": "default",
|
|
76
76
|
},
|
|
@@ -106,7 +106,7 @@ exports[`Insert, Update, & Delete Blocks > Insert, update, & delete multiple blo
|
|
|
106
106
|
"id": "2",
|
|
107
107
|
"props": {
|
|
108
108
|
"backgroundColor": "default",
|
|
109
|
-
"level":
|
|
109
|
+
"level": 1,
|
|
110
110
|
"textAlignment": "left",
|
|
111
111
|
"textColor": "default",
|
|
112
112
|
},
|
|
@@ -142,7 +142,7 @@ exports[`Insert, Update, & Delete Blocks > Insert, update, & delete multiple blo
|
|
|
142
142
|
"id": "4",
|
|
143
143
|
"props": {
|
|
144
144
|
"backgroundColor": "default",
|
|
145
|
-
"level":
|
|
145
|
+
"level": 2,
|
|
146
146
|
"textAlignment": "left",
|
|
147
147
|
"textColor": "default",
|
|
148
148
|
},
|
|
@@ -159,7 +159,7 @@ exports[`Insert, Update, & Delete Blocks > Insert, update, & delete multiple blo
|
|
|
159
159
|
"id": "3",
|
|
160
160
|
"props": {
|
|
161
161
|
"backgroundColor": "default",
|
|
162
|
-
"level":
|
|
162
|
+
"level": 2,
|
|
163
163
|
"textAlignment": "left",
|
|
164
164
|
"textColor": "default",
|
|
165
165
|
},
|
|
@@ -286,7 +286,7 @@ exports[`Insert, Update, & Delete Blocks > Insert, update, & delete single block
|
|
|
286
286
|
"id": "1",
|
|
287
287
|
"props": {
|
|
288
288
|
"backgroundColor": "default",
|
|
289
|
-
"level":
|
|
289
|
+
"level": 3,
|
|
290
290
|
"textAlignment": "right",
|
|
291
291
|
"textColor": "default",
|
|
292
292
|
},
|
|
@@ -349,7 +349,7 @@ exports[`Inserting Blocks with Different Placements > Insert after existing bloc
|
|
|
349
349
|
"id": "2",
|
|
350
350
|
"props": {
|
|
351
351
|
"backgroundColor": "default",
|
|
352
|
-
"level":
|
|
352
|
+
"level": 1,
|
|
353
353
|
"textAlignment": "left",
|
|
354
354
|
"textColor": "default",
|
|
355
355
|
},
|
|
@@ -366,7 +366,7 @@ exports[`Inserting Blocks with Different Placements > Insert after existing bloc
|
|
|
366
366
|
"id": "1",
|
|
367
367
|
"props": {
|
|
368
368
|
"backgroundColor": "default",
|
|
369
|
-
"level":
|
|
369
|
+
"level": 1,
|
|
370
370
|
"textAlignment": "left",
|
|
371
371
|
"textColor": "default",
|
|
372
372
|
},
|
|
@@ -386,7 +386,7 @@ exports[`Inserting Blocks with Different Placements > Insert after existing bloc
|
|
|
386
386
|
"id": "4",
|
|
387
387
|
"props": {
|
|
388
388
|
"backgroundColor": "default",
|
|
389
|
-
"level":
|
|
389
|
+
"level": 2,
|
|
390
390
|
"textAlignment": "left",
|
|
391
391
|
"textColor": "default",
|
|
392
392
|
},
|
|
@@ -403,7 +403,7 @@ exports[`Inserting Blocks with Different Placements > Insert after existing bloc
|
|
|
403
403
|
"id": "3",
|
|
404
404
|
"props": {
|
|
405
405
|
"backgroundColor": "default",
|
|
406
|
-
"level":
|
|
406
|
+
"level": 2,
|
|
407
407
|
"textAlignment": "left",
|
|
408
408
|
"textColor": "default",
|
|
409
409
|
},
|
|
@@ -439,7 +439,7 @@ exports[`Inserting Blocks with Different Placements > Insert before existing blo
|
|
|
439
439
|
"id": "2",
|
|
440
440
|
"props": {
|
|
441
441
|
"backgroundColor": "default",
|
|
442
|
-
"level":
|
|
442
|
+
"level": 1,
|
|
443
443
|
"textAlignment": "left",
|
|
444
444
|
"textColor": "default",
|
|
445
445
|
},
|
|
@@ -456,7 +456,7 @@ exports[`Inserting Blocks with Different Placements > Insert before existing blo
|
|
|
456
456
|
"id": "1",
|
|
457
457
|
"props": {
|
|
458
458
|
"backgroundColor": "default",
|
|
459
|
-
"level":
|
|
459
|
+
"level": 1,
|
|
460
460
|
"textAlignment": "left",
|
|
461
461
|
"textColor": "default",
|
|
462
462
|
},
|
|
@@ -476,7 +476,7 @@ exports[`Inserting Blocks with Different Placements > Insert before existing blo
|
|
|
476
476
|
"id": "4",
|
|
477
477
|
"props": {
|
|
478
478
|
"backgroundColor": "default",
|
|
479
|
-
"level":
|
|
479
|
+
"level": 2,
|
|
480
480
|
"textAlignment": "left",
|
|
481
481
|
"textColor": "default",
|
|
482
482
|
},
|
|
@@ -493,7 +493,7 @@ exports[`Inserting Blocks with Different Placements > Insert before existing blo
|
|
|
493
493
|
"id": "3",
|
|
494
494
|
"props": {
|
|
495
495
|
"backgroundColor": "default",
|
|
496
|
-
"level":
|
|
496
|
+
"level": 2,
|
|
497
497
|
"textAlignment": "left",
|
|
498
498
|
"textColor": "default",
|
|
499
499
|
},
|
|
@@ -531,7 +531,7 @@ exports[`Inserting Blocks with Different Placements > Insert nested inside exist
|
|
|
531
531
|
"id": "2",
|
|
532
532
|
"props": {
|
|
533
533
|
"backgroundColor": "default",
|
|
534
|
-
"level":
|
|
534
|
+
"level": 1,
|
|
535
535
|
"textAlignment": "left",
|
|
536
536
|
"textColor": "default",
|
|
537
537
|
},
|
|
@@ -548,7 +548,7 @@ exports[`Inserting Blocks with Different Placements > Insert nested inside exist
|
|
|
548
548
|
"id": "1",
|
|
549
549
|
"props": {
|
|
550
550
|
"backgroundColor": "default",
|
|
551
|
-
"level":
|
|
551
|
+
"level": 1,
|
|
552
552
|
"textAlignment": "left",
|
|
553
553
|
"textColor": "default",
|
|
554
554
|
},
|
|
@@ -568,7 +568,7 @@ exports[`Inserting Blocks with Different Placements > Insert nested inside exist
|
|
|
568
568
|
"id": "4",
|
|
569
569
|
"props": {
|
|
570
570
|
"backgroundColor": "default",
|
|
571
|
-
"level":
|
|
571
|
+
"level": 2,
|
|
572
572
|
"textAlignment": "left",
|
|
573
573
|
"textColor": "default",
|
|
574
574
|
},
|
|
@@ -585,7 +585,7 @@ exports[`Inserting Blocks with Different Placements > Insert nested inside exist
|
|
|
585
585
|
"id": "3",
|
|
586
586
|
"props": {
|
|
587
587
|
"backgroundColor": "default",
|
|
588
|
-
"level":
|
|
588
|
+
"level": 2,
|
|
589
589
|
"textAlignment": "left",
|
|
590
590
|
"textColor": "default",
|
|
591
591
|
},
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
2
2
|
import { Block, BlockNoteEditor, PartialBlock } from "../..";
|
|
3
|
-
import { DefaultBlockSchema } from "../../extensions/Blocks/api/defaultBlocks";
|
|
4
3
|
|
|
5
4
|
let editor: BlockNoteEditor;
|
|
6
5
|
|
|
@@ -15,13 +14,11 @@ function waitForEditor() {
|
|
|
15
14
|
});
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
let singleBlock: PartialBlock
|
|
17
|
+
let singleBlock: PartialBlock;
|
|
19
18
|
|
|
20
|
-
let multipleBlocks: PartialBlock
|
|
19
|
+
let multipleBlocks: PartialBlock[];
|
|
21
20
|
|
|
22
|
-
let insert: (
|
|
23
|
-
placement: "before" | "nested" | "after"
|
|
24
|
-
) => Block<DefaultBlockSchema>[];
|
|
21
|
+
let insert: (placement: "before" | "nested" | "after") => Block[];
|
|
25
22
|
|
|
26
23
|
beforeEach(() => {
|
|
27
24
|
(window as Window & { __TEST_OPTIONS?: any }).__TEST_OPTIONS = {};
|
|
@@ -37,14 +34,14 @@ beforeEach(() => {
|
|
|
37
34
|
{
|
|
38
35
|
type: "heading",
|
|
39
36
|
props: {
|
|
40
|
-
level:
|
|
37
|
+
level: 1,
|
|
41
38
|
},
|
|
42
39
|
content: "Heading 1",
|
|
43
40
|
children: [
|
|
44
41
|
{
|
|
45
42
|
type: "heading",
|
|
46
43
|
props: {
|
|
47
|
-
level:
|
|
44
|
+
level: 1,
|
|
48
45
|
},
|
|
49
46
|
content: "Nested Heading 1",
|
|
50
47
|
},
|
|
@@ -53,14 +50,14 @@ beforeEach(() => {
|
|
|
53
50
|
{
|
|
54
51
|
type: "heading",
|
|
55
52
|
props: {
|
|
56
|
-
level:
|
|
53
|
+
level: 2,
|
|
57
54
|
},
|
|
58
55
|
content: "Heading 2",
|
|
59
56
|
children: [
|
|
60
57
|
{
|
|
61
58
|
type: "heading",
|
|
62
59
|
props: {
|
|
63
|
-
level:
|
|
60
|
+
level: 2,
|
|
64
61
|
},
|
|
65
62
|
content: "Nested Heading 2",
|
|
66
63
|
},
|
|
@@ -123,7 +120,7 @@ describe("Insert, Update, & Delete Blocks", () => {
|
|
|
123
120
|
type: "heading",
|
|
124
121
|
props: {
|
|
125
122
|
textAlignment: "right",
|
|
126
|
-
level:
|
|
123
|
+
level: 3,
|
|
127
124
|
},
|
|
128
125
|
content: [
|
|
129
126
|
{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Vitest Snapshot v1
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
3
|
exports[`Complex Block/HTML/Markdown Conversions > Convert complex blocks to HTML 1`] = `"<h1>Heading 1</h1><h2>Heading 2</h2><h3>Heading 3</h3><p><span data-text-color=\\"purple\\"><span data-background-color=\\"green\\">Paragraph</span></span></p><p>P<strong>ara</strong><em>grap</em>h</p><p>P<u>ara</u><s>grap</s>h</p><ul><li><p>Bullet List Item</p></li><li><p>Bullet List Item</p><ul><li><p>Bullet List Item</p><ul><li><p>Bullet List Item</p></li></ul><p>Paragraph</p><ol><li><p>Numbered List Item</p></li><li><p>Numbered List Item</p></li><li><p>Numbered List Item</p><ol><li><p>Numbered List Item</p></li></ol></li></ol><ul><li><p>Bullet List Item</p></li></ul></li><li><p>Bullet List Item</p></li></ul></li><li><p>Bullet List Item</p></li></ul>"`;
|
|
4
4
|
|
|
@@ -68,7 +68,7 @@ exports[`Non-Nested Block/HTML/Markdown Conversions > Convert non-nested HTML to
|
|
|
68
68
|
"id": "1",
|
|
69
69
|
"props": {
|
|
70
70
|
"backgroundColor": "default",
|
|
71
|
-
"level":
|
|
71
|
+
"level": 1,
|
|
72
72
|
"textAlignment": "left",
|
|
73
73
|
"textColor": "default",
|
|
74
74
|
},
|
|
@@ -142,7 +142,7 @@ exports[`Non-Nested Block/HTML/Markdown Conversions > Convert non-nested Markdow
|
|
|
142
142
|
"id": "1",
|
|
143
143
|
"props": {
|
|
144
144
|
"backgroundColor": "default",
|
|
145
|
-
"level":
|
|
145
|
+
"level": 1,
|
|
146
146
|
"textAlignment": "left",
|
|
147
147
|
"textColor": "default",
|
|
148
148
|
},
|
|
@@ -12,7 +12,7 @@ const getNonNestedBlocks = (): Block[] => [
|
|
|
12
12
|
backgroundColor: "default",
|
|
13
13
|
textColor: "default",
|
|
14
14
|
textAlignment: "left",
|
|
15
|
-
level:
|
|
15
|
+
level: 1,
|
|
16
16
|
},
|
|
17
17
|
content: [
|
|
18
18
|
{
|
|
@@ -84,7 +84,7 @@ const getNestedBlocks = (): Block[] => [
|
|
|
84
84
|
backgroundColor: "default",
|
|
85
85
|
textColor: "default",
|
|
86
86
|
textAlignment: "left",
|
|
87
|
-
level:
|
|
87
|
+
level: 1,
|
|
88
88
|
},
|
|
89
89
|
content: [
|
|
90
90
|
{
|
|
@@ -224,7 +224,7 @@ const getComplexBlocks = (): Block[] => [
|
|
|
224
224
|
backgroundColor: "red",
|
|
225
225
|
textColor: "yellow",
|
|
226
226
|
textAlignment: "right",
|
|
227
|
-
level:
|
|
227
|
+
level: 1,
|
|
228
228
|
},
|
|
229
229
|
content: [
|
|
230
230
|
{
|
|
@@ -241,7 +241,7 @@ const getComplexBlocks = (): Block[] => [
|
|
|
241
241
|
backgroundColor: "orange",
|
|
242
242
|
textColor: "orange",
|
|
243
243
|
textAlignment: "center",
|
|
244
|
-
level:
|
|
244
|
+
level: 2,
|
|
245
245
|
},
|
|
246
246
|
content: [
|
|
247
247
|
{
|
|
@@ -258,7 +258,7 @@ const getComplexBlocks = (): Block[] => [
|
|
|
258
258
|
backgroundColor: "yellow",
|
|
259
259
|
textColor: "red",
|
|
260
260
|
textAlignment: "left",
|
|
261
|
-
level:
|
|
261
|
+
level: 3,
|
|
262
262
|
},
|
|
263
263
|
content: [
|
|
264
264
|
{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Vitest Snapshot v1
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
3
|
exports[`Complex ProseMirror Node Conversions > Convert complex block to node 1`] = `
|
|
4
4
|
{
|
|
@@ -10,7 +10,7 @@ exports[`Complex ProseMirror Node Conversions > Convert complex block to node 1`
|
|
|
10
10
|
"content": [
|
|
11
11
|
{
|
|
12
12
|
"attrs": {
|
|
13
|
-
"level":
|
|
13
|
+
"level": 2,
|
|
14
14
|
"textAlignment": "right",
|
|
15
15
|
},
|
|
16
16
|
"content": [
|
|
@@ -142,7 +142,7 @@ exports[`Complex ProseMirror Node Conversions > Convert complex node to block 1`
|
|
|
142
142
|
"id": "1",
|
|
143
143
|
"props": {
|
|
144
144
|
"backgroundColor": "blue",
|
|
145
|
-
"level":
|
|
145
|
+
"level": 2,
|
|
146
146
|
"textAlignment": "right",
|
|
147
147
|
"textColor": "yellow",
|
|
148
148
|
},
|
|
@@ -49,7 +49,10 @@ describe("Simple ProseMirror Node Conversions", () => {
|
|
|
49
49
|
|
|
50
50
|
expect(firstBlockConversion).toMatchSnapshot();
|
|
51
51
|
|
|
52
|
-
const firstNodeConversion = blockToNode(
|
|
52
|
+
const firstNodeConversion = blockToNode<DefaultBlockSchema>(
|
|
53
|
+
firstBlockConversion,
|
|
54
|
+
tt.schema
|
|
55
|
+
);
|
|
53
56
|
|
|
54
57
|
expect(firstNodeConversion).toStrictEqual(node);
|
|
55
58
|
});
|
|
@@ -63,7 +66,7 @@ describe("Complex ProseMirror Node Conversions", () => {
|
|
|
63
66
|
backgroundColor: "blue",
|
|
64
67
|
textColor: "yellow",
|
|
65
68
|
textAlignment: "right",
|
|
66
|
-
level:
|
|
69
|
+
level: 2,
|
|
67
70
|
},
|
|
68
71
|
content: [
|
|
69
72
|
{
|
|
@@ -111,7 +114,7 @@ describe("Complex ProseMirror Node Conversions", () => {
|
|
|
111
114
|
},
|
|
112
115
|
[
|
|
113
116
|
tt.schema.nodes["heading"].create(
|
|
114
|
-
{ textAlignment: "right", level:
|
|
117
|
+
{ textAlignment: "right", level: 2 },
|
|
115
118
|
[
|
|
116
119
|
tt.schema.text("Heading ", [
|
|
117
120
|
tt.schema.mark("bold"),
|
|
@@ -147,7 +150,10 @@ describe("Complex ProseMirror Node Conversions", () => {
|
|
|
147
150
|
|
|
148
151
|
expect(firstBlockConversion).toMatchSnapshot();
|
|
149
152
|
|
|
150
|
-
const firstNodeConversion = blockToNode(
|
|
153
|
+
const firstNodeConversion = blockToNode<DefaultBlockSchema>(
|
|
154
|
+
firstBlockConversion,
|
|
155
|
+
tt.schema
|
|
156
|
+
);
|
|
151
157
|
|
|
152
158
|
expect(firstNodeConversion).toStrictEqual(node);
|
|
153
159
|
});
|
|
@@ -5,8 +5,7 @@ import {
|
|
|
5
5
|
BlockSchema,
|
|
6
6
|
PartialBlock,
|
|
7
7
|
} from "../../extensions/Blocks/api/blockTypes";
|
|
8
|
-
|
|
9
|
-
import { defaultProps } from "../../extensions/Blocks/api/defaultBlocks";
|
|
8
|
+
import { defaultProps } from "../../extensions/Blocks/api/defaultProps";
|
|
10
9
|
import {
|
|
11
10
|
ColorStyle,
|
|
12
11
|
InlineContent,
|
|
@@ -16,9 +15,9 @@ import {
|
|
|
16
15
|
Styles,
|
|
17
16
|
ToggledStyle,
|
|
18
17
|
} from "../../extensions/Blocks/api/inlineContentTypes";
|
|
18
|
+
import { getBlockInfo } from "../../extensions/Blocks/helpers/getBlockInfoFromPos";
|
|
19
19
|
import UniqueID from "../../extensions/UniqueID/UniqueID";
|
|
20
20
|
import { UnreachableCaseError } from "../../shared/utils";
|
|
21
|
-
import { getBlockInfo } from "../../extensions/Blocks/helpers/getBlockInfoFromPos";
|
|
22
21
|
|
|
23
22
|
const toggleStyles = new Set<ToggledStyle>([
|
|
24
23
|
"bold",
|
|
@@ -409,7 +408,7 @@ export function nodeToBlock<BSchema extends BlockSchema>(
|
|
|
409
408
|
}
|
|
410
409
|
}
|
|
411
410
|
|
|
412
|
-
const
|
|
411
|
+
const blockSpec = blockSchema[blockInfo.contentType.name];
|
|
413
412
|
|
|
414
413
|
const children: Block<BSchema>[] = [];
|
|
415
414
|
for (let i = 0; i < blockInfo.numChildBlocks; i++) {
|
|
@@ -420,11 +419,14 @@ export function nodeToBlock<BSchema extends BlockSchema>(
|
|
|
420
419
|
|
|
421
420
|
const block: Block<BSchema> = {
|
|
422
421
|
id,
|
|
423
|
-
type:
|
|
422
|
+
type: blockSpec.node.name,
|
|
424
423
|
props,
|
|
425
|
-
content
|
|
424
|
+
content:
|
|
425
|
+
blockSpec.node.config.content === "inline*"
|
|
426
|
+
? contentNodeToInlineContent(blockInfo.contentNode)
|
|
427
|
+
: undefined,
|
|
426
428
|
children,
|
|
427
|
-
}
|
|
429
|
+
} as Block<BSchema>;
|
|
428
430
|
|
|
429
431
|
blockCache?.set(node, block);
|
|
430
432
|
|
|
@@ -48,14 +48,14 @@ export function partialBlockToBlockForTesting<BSchema extends BlockSchema>(
|
|
|
48
48
|
): Block<BSchema> {
|
|
49
49
|
const withDefaults = {
|
|
50
50
|
id: "",
|
|
51
|
-
type: "paragraph"
|
|
51
|
+
type: "paragraph",
|
|
52
52
|
// because at this point we don't have an easy way to access default props at runtime,
|
|
53
53
|
// partialBlockToBlockForTesting will not set them.
|
|
54
54
|
props: {} as any,
|
|
55
|
-
content: [],
|
|
55
|
+
content: [] as any,
|
|
56
56
|
children: [],
|
|
57
57
|
...partialBlock,
|
|
58
|
-
}
|
|
58
|
+
} satisfies PartialBlock<BSchema>;
|
|
59
59
|
|
|
60
60
|
return {
|
|
61
61
|
...withDefaults,
|
package/src/editor.module.css
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Extension } from "@tiptap/core";
|
|
2
2
|
import { getBlockInfoFromPos } from "../Blocks/helpers/getBlockInfoFromPos";
|
|
3
|
+
import { defaultProps } from "../Blocks/api/defaultProps";
|
|
3
4
|
|
|
4
5
|
declare module "@tiptap/core" {
|
|
5
6
|
interface Commands<ReturnType> {
|
|
@@ -21,13 +22,14 @@ export const BackgroundColorExtension = Extension.create({
|
|
|
21
22
|
types: ["blockContainer"],
|
|
22
23
|
attributes: {
|
|
23
24
|
backgroundColor: {
|
|
24
|
-
default:
|
|
25
|
+
default: defaultProps.backgroundColor.default,
|
|
25
26
|
parseHTML: (element) =>
|
|
26
27
|
element.hasAttribute("data-background-color")
|
|
27
28
|
? element.getAttribute("data-background-color")
|
|
28
|
-
:
|
|
29
|
+
: defaultProps.backgroundColor.default,
|
|
29
30
|
renderHTML: (attributes) =>
|
|
30
|
-
attributes.backgroundColor !==
|
|
31
|
+
attributes.backgroundColor !==
|
|
32
|
+
defaultProps.backgroundColor.default && {
|
|
31
33
|
"data-background-color": attributes.backgroundColor,
|
|
32
34
|
},
|
|
33
35
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Mark } from "@tiptap/core";
|
|
2
|
+
import { defaultProps } from "../Blocks/api/defaultProps";
|
|
2
3
|
|
|
3
4
|
declare module "@tiptap/core" {
|
|
4
5
|
interface Commands<ReturnType> {
|
|
@@ -51,7 +52,7 @@ export const BackgroundColorMark = Mark.create({
|
|
|
51
52
|
setBackgroundColor:
|
|
52
53
|
(color) =>
|
|
53
54
|
({ commands }) => {
|
|
54
|
-
if (color !==
|
|
55
|
+
if (color !== defaultProps.backgroundColor.default) {
|
|
55
56
|
return commands.setMark(this.name, { color: color });
|
|
56
57
|
}
|
|
57
58
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Plugin, PluginKey } from "prosemirror-state";
|
|
2
|
+
|
|
3
|
+
const PLUGIN_KEY = new PluginKey("non-editable-block");
|
|
4
|
+
// Prevent typing for blocks without inline content, as this would otherwise
|
|
5
|
+
// convert them into paragraph blocks.
|
|
6
|
+
export const NonEditableBlockPlugin = () => {
|
|
7
|
+
return new Plugin({
|
|
8
|
+
key: PLUGIN_KEY,
|
|
9
|
+
props: {
|
|
10
|
+
handleKeyDown: (view, event) => {
|
|
11
|
+
if ("node" in view.state.selection) {
|
|
12
|
+
event.preventDefault();
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
};
|