@blocknote/core 0.23.1 → 0.23.2-hotfix.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.
Files changed (28) hide show
  1. package/dist/blocknote.js +2814 -2500
  2. package/dist/blocknote.js.map +1 -1
  3. package/dist/blocknote.umd.cjs +6 -6
  4. package/dist/blocknote.umd.cjs.map +1 -1
  5. package/dist/tsconfig.tsbuildinfo +1 -1
  6. package/dist/webpack-stats.json +1 -1
  7. package/package.json +3 -3
  8. package/src/api/blockManipulation/commands/updateBlock/updateBlock.ts +4 -2
  9. package/src/api/exporters/html/__snapshots__/codeBlock/contains-newlines/external.html +1 -0
  10. package/src/api/exporters/html/__snapshots__/codeBlock/contains-newlines/internal.html +3 -0
  11. package/src/api/exporters/html/util/serializeBlocksInternalHTML.ts +6 -2
  12. package/src/api/exporters/markdown/__snapshots__/codeBlock/contains-newlines/markdown.md +4 -0
  13. package/src/api/nodeConversions/__snapshots__/nodeConversions.test.ts.snap +27 -0
  14. package/src/api/nodeConversions/blockToNode.ts +35 -9
  15. package/src/api/testUtil/cases/defaultSchema.ts +9 -0
  16. package/src/editor/BlockNoteExtensions.ts +4 -128
  17. package/src/extensions/Collaboration/createCollaborationExtensions.ts +144 -0
  18. package/src/extensions/SideMenu/SideMenuPlugin.ts +76 -28
  19. package/src/i18n/locales/fr.ts +2 -2
  20. package/src/i18n/locales/index.ts +2 -1
  21. package/src/i18n/locales/uk.ts +289 -0
  22. package/types/src/api/exporters/html/util/serializeBlocksInternalHTML.d.ts +1 -1
  23. package/types/src/api/nodeConversions/blockToNode.d.ts +1 -1
  24. package/types/src/editor/BlockNoteExtensions.d.ts +1 -1
  25. package/types/src/extensions/Collaboration/createCollaborationExtensions.d.ts +17 -0
  26. package/types/src/extensions/SideMenu/SideMenuPlugin.d.ts +0 -5
  27. package/types/src/i18n/locales/index.d.ts +2 -1
  28. package/types/src/i18n/locales/uk.d.ts +2 -0
@@ -1,5 +1,11 @@
1
1
  import { DOMParser, Slice } from "@tiptap/pm/model";
2
- import { EditorState, Plugin, PluginKey, PluginView } from "@tiptap/pm/state";
2
+ import {
3
+ EditorState,
4
+ Plugin,
5
+ PluginKey,
6
+ TextSelection,
7
+ PluginView,
8
+ } from "@tiptap/pm/state";
3
9
  import { EditorView } from "@tiptap/pm/view";
4
10
 
5
11
  import { Block } from "../../blocks/defaultBlocks.js";
@@ -268,21 +274,56 @@ export class SideMenuView<
268
274
  }
269
275
  };
270
276
 
271
- /**
272
- * If the event is outside the editor contents,
273
- * we dispatch a fake event, so that we can still drop the content
274
- * when dragging / dropping to the side of the editor
275
- */
276
277
  onDrop = (event: DragEvent) => {
278
+ // Content from outside a BlockNote editor is being dropped - just let
279
+ // ProseMirror's default behaviour handle it.
280
+ if (this.pmView.dragging === null) {
281
+ return;
282
+ }
283
+
277
284
  this.editor._tiptapEditor.commands.blur();
278
285
 
279
- // ProseMirror doesn't remove the dragged content if it's dropped outside
280
- // the editor (e.g. to other editors), so we need to do it manually. Since
281
- // the dragged content is the same as the selected content, we can just
282
- // delete the selection.
283
- if (this.isDragOrigin && !this.pmView.dom.contains(event.target as Node)) {
284
- this.pmView.dispatch(this.pmView.state.tr.deleteSelection());
286
+ // When ProseMirror handles a drop event on the editor while
287
+ // `view.dragging` is set, it deletes the selected content. However, if
288
+ // a block from a different editor is being dropped, this causes some
289
+ // issues that the code below fixes:
290
+ if (!this.isDragOrigin && this.pmView.dom.contains(event.target as Node)) {
291
+ // 1. Because the editor selection is unrelated to the dragged content,
292
+ // we don't want PM to delete its content. Therefore, we collapse the
293
+ // selection.
294
+ this.pmView.dispatch(
295
+ this.pmView.state.tr.setSelection(
296
+ TextSelection.create(
297
+ this.pmView.state.tr.doc,
298
+ this.pmView.state.tr.selection.to
299
+ )
300
+ )
301
+ );
302
+ } else if (
303
+ this.isDragOrigin &&
304
+ !this.pmView.dom.contains(event.target as Node)
305
+ ) {
306
+ // 2. Because the editor from which the block originates doesn't get a
307
+ // drop event on it, PM doesn't delete its selected content. Therefore, we
308
+ // need to do so manually.
309
+ //
310
+ // Note: Deleting the selected content from the editor from which the
311
+ // block originates, may change its height. This can cause the position of
312
+ // the editor in which the block is being dropping to shift, before it
313
+ // can handle the drop event. That in turn can cause the drop to happen
314
+ // somewhere other than the user intended. To get around this, we delay
315
+ // deleting the selected content until all editors have had the chance to
316
+ // handle the event.
317
+ setTimeout(
318
+ () => this.pmView.dispatch(this.pmView.state.tr.deleteSelection()),
319
+ 0
320
+ );
285
321
  }
322
+ // 3. PM only clears `view.dragging` on the editor that the block was
323
+ // dropped, so we manually have to clear it on all the others. However,
324
+ // PM also needs to read `view.dragging` while handling the event, so we
325
+ // use a `setTimeout` to ensure it's only cleared after that.
326
+ setTimeout(() => (this.pmView.dragging = null), 0);
286
327
 
287
328
  if (
288
329
  this.sideMenuDetection === "editor" ||
@@ -298,6 +339,11 @@ export class SideMenuView<
298
339
  });
299
340
 
300
341
  if (!pos || pos.inside === -1) {
342
+ /**
343
+ * When `this.sideMenuSelection === "viewport"`, if the event is outside the
344
+ * editor contents, we dispatch a fake event, so that we can still drop the
345
+ * content when dragging / dropping to the side of the editor
346
+ */
301
347
  const evt = this.createSyntheticEvent(event);
302
348
  // console.log("dispatch fake drop");
303
349
  this.pmView.dom.dispatchEvent(evt);
@@ -323,25 +369,27 @@ export class SideMenuView<
323
369
  * access `dataTransfer` contents on `dragstart` and `drop` events.
324
370
  */
325
371
  onDragStart = (event: DragEvent) => {
326
- if (!this.pmView.dragging) {
327
- const html = event.dataTransfer?.getData("blocknote/html");
328
- if (!html) {
329
- return;
330
- }
372
+ const html = event.dataTransfer?.getData("blocknote/html");
373
+ if (!html) {
374
+ return;
375
+ }
376
+
377
+ if (this.pmView.dragging) {
378
+ throw new Error("New drag was started while an existing drag is ongoing");
379
+ }
331
380
 
332
- const element = document.createElement("div");
333
- element.innerHTML = html;
381
+ const element = document.createElement("div");
382
+ element.innerHTML = html;
334
383
 
335
- const parser = DOMParser.fromSchema(this.pmView.state.schema);
336
- const node = parser.parse(element, {
337
- topNode: this.pmView.state.schema.nodes["blockGroup"].create(),
338
- });
384
+ const parser = DOMParser.fromSchema(this.pmView.state.schema);
385
+ const node = parser.parse(element, {
386
+ topNode: this.pmView.state.schema.nodes["blockGroup"].create(),
387
+ });
339
388
 
340
- this.pmView.dragging = {
341
- slice: new Slice(node.content, 0, 0),
342
- move: true,
343
- };
344
- }
389
+ this.pmView.dragging = {
390
+ slice: new Slice(node.content, 0, 0),
391
+ move: true,
392
+ };
345
393
  };
346
394
 
347
395
  /**
@@ -281,11 +281,11 @@ export const fr: Dictionary = {
281
281
  tooltip: "Basculer l'aperçu",
282
282
  },
283
283
  nest: {
284
- tooltip: "Emboîter le bloc",
284
+ tooltip: "Augmenter le retrait du bloc",
285
285
  secondary_tooltip: "Tab",
286
286
  },
287
287
  unnest: {
288
- tooltip: "Démboîter le bloc",
288
+ tooltip: "Diminuer le retait du bloc",
289
289
  secondary_tooltip: "Shift+Tab",
290
290
  },
291
291
  align_left: {
@@ -5,12 +5,13 @@ export * from "./es.js";
5
5
  export * from "./fr.js";
6
6
  export * from "./hr.js";
7
7
  export * from "./is.js";
8
+ export * from "./it.js";
8
9
  export * from "./ja.js";
9
10
  export * from "./ko.js";
10
11
  export * from "./nl.js";
11
12
  export * from "./pl.js";
12
13
  export * from "./pt.js";
13
14
  export * from "./ru.js";
15
+ export * from "./uk.js";
14
16
  export * from "./vi.js";
15
17
  export * from "./zh.js";
16
- export * from "./it.js"
@@ -0,0 +1,289 @@
1
+ import { Dictionary } from "../dictionary.js";
2
+
3
+ export const uk: Dictionary = {
4
+ slash_menu: {
5
+ heading: {
6
+ title: "Заголовок 1",
7
+ subtext: "Заголовок найвищого рівня",
8
+ aliases: ["h", "heading1", "h1", "заголовок1"],
9
+ group: "Заголовки",
10
+ },
11
+ heading_2: {
12
+ title: "Заголовок 2",
13
+ subtext: "Основний заголовок розділу",
14
+ aliases: ["h2", "heading2", "subheading", "заголовок2"],
15
+ group: "Заголовки",
16
+ },
17
+ heading_3: {
18
+ title: "Заголовок 3",
19
+ subtext: "Підзаголовок і груповий заголовок",
20
+ aliases: ["h3", "heading3", "subheading", "заголовок3"],
21
+ group: "Заголовки",
22
+ },
23
+ numbered_list: {
24
+ title: "Нумерований список",
25
+ subtext: "Список із впорядкованими елементами",
26
+ aliases: ["ol", "li", "list", "numberedlist", "numbered list", "список", "нумерований список"],
27
+ group: "Базові блоки",
28
+ },
29
+ bullet_list: {
30
+ title: "Маркований список",
31
+ subtext: "Список із невпорядкованими елементами",
32
+ aliases: ["ul", "li", "list", "bulletlist", "bullet list", "список", "маркований список"],
33
+ group: "Базові блоки",
34
+ },
35
+ check_list: {
36
+ title: "Чек-лист",
37
+ subtext: "Список із чекбоксами",
38
+ aliases: ["ul", "li", "list", "checklist", "check list", "checked list", "checkbox", "чекбокс", "чек-лист"],
39
+ group: "Базові блоки",
40
+ },
41
+ paragraph: {
42
+ title: "Параграф",
43
+ subtext: "Основний текст документа",
44
+ aliases: ["p", "paragraph", "параграф"],
45
+ group: "Базові блоки",
46
+ },
47
+ code_block: {
48
+ title: "Блок коду",
49
+ subtext: "Блок коду з підсвіткою синтаксису",
50
+ aliases: ["code", "pre", "блок коду"],
51
+ group: "Базові блоки",
52
+ },
53
+ page_break: {
54
+ title: "Розрив сторінки",
55
+ subtext: "Роздільник сторінки",
56
+ aliases: ["page", "break", "separator", "розрив сторінки", "розділювач"],
57
+ group: "Базові блоки",
58
+ },
59
+ table: {
60
+ title: "Таблиця",
61
+ subtext: "Таблиця з редагованими клітинками",
62
+ aliases: ["table", "таблиця"],
63
+ group: "Розширені",
64
+ },
65
+ image: {
66
+ title: "Зображення",
67
+ subtext: "Масштабоване зображення з підписом",
68
+ aliases: ["image", "imageUpload", "upload", "img", "picture", "media", "url", "зображення", "медіа"],
69
+ group: "Медіа",
70
+ },
71
+ video: {
72
+ title: "Відео",
73
+ subtext: "Масштабоване відео з підписом",
74
+ aliases: ["video", "videoUpload", "upload", "mp4", "film", "media", "url", "відео", "медіа"],
75
+ group: "Медіа",
76
+ },
77
+ audio: {
78
+ title: "Аудіо",
79
+ subtext: "Вбудоване аудіо з підписом",
80
+ aliases: ["audio", "audioUpload", "upload", "mp3", "sound", "media", "url", "аудіо", "медіа"],
81
+ group: "Медіа",
82
+ },
83
+ file: {
84
+ title: "Файл",
85
+ subtext: "Вбудований файл",
86
+ aliases: ["file", "upload", "embed", "media", "url", "файл", "медіа"],
87
+ group: "Медіа",
88
+ },
89
+ emoji: {
90
+ title: "Емодзі",
91
+ subtext: "Пошук і вставка емодзі",
92
+ aliases: ["emoji", "emote", "emotion", "face", "смайлик", "емодзі"],
93
+ group: "Інше",
94
+ },
95
+ },
96
+ placeholders: {
97
+ default: "Введіть текст або наберіть '/' для команд",
98
+ heading: "Заголовок",
99
+ bulletListItem: "Список",
100
+ numberedListItem: "Список",
101
+ checkListItem: "Список",
102
+ },
103
+ file_blocks: {
104
+ image: {
105
+ add_button_text: "Додати зображення",
106
+ },
107
+ video: {
108
+ add_button_text: "Додати відео",
109
+ },
110
+ audio: {
111
+ add_button_text: "Додати аудіо",
112
+ },
113
+ file: {
114
+ add_button_text: "Додати файл",
115
+ },
116
+ },
117
+ // from react package:
118
+ side_menu: {
119
+ add_block_label: "Додати блок",
120
+ drag_handle_label: "Відкрити меню блока",
121
+ },
122
+ drag_handle: {
123
+ delete_menuitem: "Видалити",
124
+ colors_menuitem: "Кольори",
125
+ },
126
+ table_handle: {
127
+ delete_column_menuitem: "Видалити стовпець",
128
+ delete_row_menuitem: "Видалити рядок",
129
+ add_left_menuitem: "Додати стовпець зліва",
130
+ add_right_menuitem: "Додати стовпець справа",
131
+ add_above_menuitem: "Додати рядок вище",
132
+ add_below_menuitem: "Додати рядок нижче",
133
+ },
134
+ suggestion_menu: {
135
+ no_items_title: "Нічого не знайдено",
136
+ loading: "Завантаження…",
137
+ },
138
+ color_picker: {
139
+ text_title: "Текст",
140
+ background_title: "Фон",
141
+ colors: {
142
+ default: "За замовчуванням",
143
+ gray: "Сірий",
144
+ brown: "Коричневий",
145
+ red: "Червоний",
146
+ orange: "Помаранчевий",
147
+ yellow: "Жовтий",
148
+ green: "Зелений",
149
+ blue: "Блакитний",
150
+ purple: "Фіолетовий",
151
+ pink: "Рожевий",
152
+ },
153
+ },
154
+ formatting_toolbar: {
155
+ bold: {
156
+ tooltip: "Жирний",
157
+ secondary_tooltip: "Mod+B",
158
+ },
159
+ italic: {
160
+ tooltip: "Курсив",
161
+ secondary_tooltip: "Mod+I",
162
+ },
163
+ underline: {
164
+ tooltip: "Підкреслений",
165
+ secondary_tooltip: "Mod+U",
166
+ },
167
+ strike: {
168
+ tooltip: "Закреслений",
169
+ secondary_tooltip: "Mod+Shift+X",
170
+ },
171
+ code: {
172
+ tooltip: "Код",
173
+ secondary_tooltip: "",
174
+ },
175
+ colors: {
176
+ tooltip: "Кольори",
177
+ },
178
+ link: {
179
+ tooltip: "Створити посилання",
180
+ secondary_tooltip: "Mod+K",
181
+ },
182
+ file_caption: {
183
+ tooltip: "Редагувати підпис",
184
+ input_placeholder: "Редагувати підпис",
185
+ },
186
+ file_replace: {
187
+ tooltip: {
188
+ image: "Замінити зображення",
189
+ video: "Замінити відео",
190
+ audio: "Замінити аудіо",
191
+ file: "Замінити файл",
192
+ },
193
+ },
194
+ file_rename: {
195
+ tooltip: {
196
+ image: "Перейменувати зображення",
197
+ video: "Перейменувати відео",
198
+ audio: "Перейменувати аудіо",
199
+ file: "Перейменувати файл",
200
+ },
201
+ input_placeholder: {
202
+ image: "Перейменувати зображення",
203
+ video: "Перейменувати відео",
204
+ audio: "Перейменувати аудіо",
205
+ file: "Перейменувати файл",
206
+ },
207
+ },
208
+ file_download: {
209
+ tooltip: {
210
+ image: "Завантажити зображення",
211
+ video: "Завантажити відео",
212
+ audio: "Завантажити аудіо",
213
+ file: "Завантажити файл",
214
+ },
215
+ },
216
+ file_delete: {
217
+ tooltip: {
218
+ image: "Видалити зображення",
219
+ video: "Видалити відео",
220
+ audio: "Видалити аудіо",
221
+ file: "Видалити файл",
222
+ },
223
+ },
224
+ file_preview_toggle: {
225
+ tooltip: "Перемкнути попередній перегляд",
226
+ },
227
+ nest: {
228
+ tooltip: "Вкладений блок",
229
+ secondary_tooltip: "Tab",
230
+ },
231
+ unnest: {
232
+ tooltip: "Розгрупувати блок",
233
+ secondary_tooltip: "Shift+Tab",
234
+ },
235
+ align_left: {
236
+ tooltip: "Вирівняти за лівим краєм",
237
+ },
238
+ align_center: {
239
+ tooltip: "Вирівняти по центру",
240
+ },
241
+ align_right: {
242
+ tooltip: "Вирівняти за правим краєм",
243
+ },
244
+ align_justify: {
245
+ tooltip: "Вирівняти за шириною",
246
+ },
247
+ },
248
+ file_panel: {
249
+ upload: {
250
+ title: "Завантажити",
251
+ file_placeholder: {
252
+ image: "Завантажити зображення",
253
+ video: "Завантажити відео",
254
+ audio: "Завантажити аудіо",
255
+ file: "Завантажити файл",
256
+ },
257
+ upload_error: "Помилка: не вдалося завантажити",
258
+ },
259
+ embed: {
260
+ title: "Вставити",
261
+ embed_button: {
262
+ image: "Вставити зображення",
263
+ video: "Вставити відео",
264
+ audio: "Вставити аудіо",
265
+ file: "Вставити файл",
266
+ },
267
+ url_placeholder: "Введіть URL",
268
+ },
269
+ },
270
+ link_toolbar: {
271
+ delete: {
272
+ tooltip: "Видалити посилання",
273
+ },
274
+ edit: {
275
+ text: "Редагувати посилання",
276
+ tooltip: "Редагувати",
277
+ },
278
+ open: {
279
+ tooltip: "Відкрити в новій вкладці",
280
+ },
281
+ form: {
282
+ title_placeholder: "Редагувати заголовок",
283
+ url_placeholder: "Редагувати URL",
284
+ },
285
+ },
286
+ generic: {
287
+ ctrl_shortcut: "Ctrl",
288
+ },
289
+ };
@@ -2,7 +2,7 @@ import { DOMSerializer } from "prosemirror-model";
2
2
  import { PartialBlock } from "../../../../blocks/defaultBlocks.js";
3
3
  import type { BlockNoteEditor } from "../../../../editor/BlockNoteEditor.js";
4
4
  import { BlockSchema, InlineContentSchema, StyleSchema } from "../../../../schema/index.js";
5
- export declare function serializeInlineContentInternalHTML<BSchema extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema>(editor: BlockNoteEditor<any, I, S>, blockContent: PartialBlock<BSchema, I, S>["content"], serializer: DOMSerializer, options?: {
5
+ export declare function serializeInlineContentInternalHTML<BSchema extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema>(editor: BlockNoteEditor<any, I, S>, blockContent: PartialBlock<BSchema, I, S>["content"], serializer: DOMSerializer, blockType?: string, options?: {
6
6
  document?: Document;
7
7
  }): HTMLElement | DocumentFragment;
8
8
  export declare const serializeBlocksInternalHTML: <BSchema extends Record<string, import("../../../../schema/index.js").BlockConfig>, I extends InlineContentSchema, S extends StyleSchema>(editor: BlockNoteEditor<BSchema, I, S>, blocks: PartialBlock<BSchema, I, S>[], serializer: DOMSerializer, options?: {
@@ -4,7 +4,7 @@ import type { PartialBlock } from "../../blocks/defaultBlocks";
4
4
  /**
5
5
  * converts an array of inline content elements to prosemirror nodes
6
6
  */
7
- export declare function inlineContentToNodes<I extends InlineContentSchema, S extends StyleSchema>(blockContent: PartialInlineContent<I, S>, schema: Schema, styleSchema: S): Node[];
7
+ export declare function inlineContentToNodes<I extends InlineContentSchema, S extends StyleSchema>(blockContent: PartialInlineContent<I, S>, schema: Schema, styleSchema: S, blockType?: string): Node[];
8
8
  /**
9
9
  * converts an array of inline content elements to prosemirror nodes
10
10
  */
@@ -1,6 +1,6 @@
1
- import type { BlockNoteEditor, BlockNoteExtension } from "./BlockNoteEditor.js";
2
1
  import { Plugin } from "prosemirror-state";
3
2
  import * as Y from "yjs";
3
+ import type { BlockNoteEditor, BlockNoteExtension } from "./BlockNoteEditor.js";
4
4
  import { BlockNoteDOMAttributes, BlockSchema, BlockSpecs, InlineContentSchema, InlineContentSpecs, StyleSchema, StyleSpecs } from "../schema/index.js";
5
5
  type ExtensionOptions<BSchema extends BlockSchema, I extends InlineContentSchema, S extends StyleSchema> = {
6
6
  editor: BlockNoteEditor<BSchema, I, S>;
@@ -0,0 +1,17 @@
1
+ import * as Y from "yjs";
2
+ export declare const createCollaborationExtensions: (collaboration: {
3
+ fragment: Y.XmlFragment;
4
+ user: {
5
+ name: string;
6
+ color: string;
7
+ [key: string]: string;
8
+ };
9
+ provider: any;
10
+ renderCursor?: (user: any) => HTMLElement;
11
+ showCursorLabels?: "always" | "activity";
12
+ }) => (import("@tiptap/core").Extension<import("@tiptap/extension-collaboration").CollaborationOptions, any> | import("@tiptap/core").Extension<import("@tiptap/extension-collaboration-cursor").CollaborationCursorOptions, {
13
+ users: {
14
+ [key: string]: any;
15
+ clientId: number;
16
+ }[];
17
+ }>)[];
@@ -24,11 +24,6 @@ export declare class SideMenuView<BSchema extends BlockSchema, I extends InlineC
24
24
  constructor(editor: BlockNoteEditor<BSchema, I, S>, sideMenuDetection: "viewport" | "editor", pmView: EditorView, emitUpdate: (state: SideMenuState<BSchema, I, S>) => void);
25
25
  updateState: (state: SideMenuState<BSchema, I, S>) => void;
26
26
  updateStateFromMousePos: () => void;
27
- /**
28
- * If the event is outside the editor contents,
29
- * we dispatch a fake event, so that we can still drop the content
30
- * when dragging / dropping to the side of the editor
31
- */
32
27
  onDrop: (event: DragEvent) => void;
33
28
  /**
34
29
  * If a block is being dragged, ProseMirror usually gets the context of what's
@@ -5,12 +5,13 @@ export * from "./es.js";
5
5
  export * from "./fr.js";
6
6
  export * from "./hr.js";
7
7
  export * from "./is.js";
8
+ export * from "./it.js";
8
9
  export * from "./ja.js";
9
10
  export * from "./ko.js";
10
11
  export * from "./nl.js";
11
12
  export * from "./pl.js";
12
13
  export * from "./pt.js";
13
14
  export * from "./ru.js";
15
+ export * from "./uk.js";
14
16
  export * from "./vi.js";
15
17
  export * from "./zh.js";
16
- export * from "./it.js";
@@ -0,0 +1,2 @@
1
+ import { Dictionary } from "../dictionary.js";
2
+ export declare const uk: Dictionary;