@blocknote/core 0.37.0 → 0.38.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/blocknote.cjs +9 -9
- package/dist/blocknote.cjs.map +1 -1
- package/dist/blocknote.js +1298 -1326
- package/dist/blocknote.js.map +1 -1
- package/dist/{en-CvDoFvhc.js → en-Bq3Es3Np.js} +6 -12
- package/dist/en-Bq3Es3Np.js.map +1 -0
- package/dist/en-D3B48eJ7.cjs +2 -0
- package/dist/en-D3B48eJ7.cjs.map +1 -0
- package/dist/locales.cjs +1 -1
- package/dist/locales.cjs.map +1 -1
- package/dist/locales.js +109 -229
- package/dist/locales.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/webpack-stats.json +1 -1
- package/package.json +7 -7
- package/src/api/clipboard/toClipboard/copyExtension.ts +0 -2
- package/src/api/exporters/html/externalHTMLExporter.ts +0 -1
- package/src/api/exporters/markdown/markdownExporter.ts +13 -22
- package/src/api/exporters/markdown/util/addSpacesToCheckboxesRehypePlugin.ts +2 -12
- package/src/api/parsers/html/parseHTML.ts +3 -2
- package/src/api/parsers/html/util/nestedLists.test.ts +8 -8
- package/src/api/parsers/markdown/parseMarkdown.ts +17 -14
- package/src/api/positionMapping.test.ts +155 -34
- package/src/api/positionMapping.ts +2 -2
- package/src/blocks/AudioBlockContent/AudioBlockContent.ts +0 -1
- package/src/blocks/FileBlockContent/helpers/render/createAddFileButton.ts +3 -2
- package/src/blocks/FileBlockContent/helpers/render/createFileBlockWrapper.ts +1 -7
- package/src/blocks/FileBlockContent/helpers/render/createResizableFileBlockWrapper.ts +42 -17
- package/src/blocks/ImageBlockContent/ImageBlockContent.ts +0 -1
- package/src/blocks/VideoBlockContent/VideoBlockContent.ts +0 -1
- package/src/editor/BlockNoteEditor.ts +17 -23
- package/src/editor/BlockNoteExtensions.ts +3 -0
- package/src/extensions/Comments/CommentsPlugin.ts +2 -0
- package/src/extensions/SideMenu/SideMenuPlugin.ts +0 -2
- package/src/i18n/locales/ar.ts +6 -12
- package/src/i18n/locales/de.ts +6 -12
- package/src/i18n/locales/en.ts +6 -12
- package/src/i18n/locales/es.ts +6 -12
- package/src/i18n/locales/fr.ts +6 -12
- package/src/i18n/locales/he.ts +6 -12
- package/src/i18n/locales/hr.ts +6 -12
- package/src/i18n/locales/is.ts +6 -12
- package/src/i18n/locales/it.ts +6 -12
- package/src/i18n/locales/ja.ts +6 -12
- package/src/i18n/locales/ko.ts +6 -12
- package/src/i18n/locales/nl.ts +6 -12
- package/src/i18n/locales/no.ts +6 -12
- package/src/i18n/locales/pl.ts +6 -12
- package/src/i18n/locales/pt.ts +6 -12
- package/src/i18n/locales/ru.ts +6 -12
- package/src/i18n/locales/sk.ts +6 -12
- package/src/i18n/locales/uk.ts +6 -12
- package/src/i18n/locales/vi.ts +6 -12
- package/src/i18n/locales/zh-tw.ts +6 -12
- package/src/i18n/locales/zh.ts +6 -12
- package/src/index.ts +0 -1
- package/types/src/api/exporters/markdown/markdownExporter.d.ts +1 -1
- package/types/src/api/parsers/html/parseHTML.d.ts +1 -1
- package/types/src/api/parsers/markdown/parseMarkdown.d.ts +2 -2
- package/types/src/blocks/FileBlockContent/helpers/render/createAddFileButton.d.ts +1 -1
- package/types/src/blocks/FileBlockContent/helpers/render/createFileBlockWrapper.d.ts +1 -1
- package/types/src/blocks/FileBlockContent/helpers/render/createResizableFileBlockWrapper.d.ts +1 -1
- package/types/src/editor/BlockNoteEditor.d.ts +6 -9
- package/types/src/editor/BlockNoteExtensions.d.ts +2 -0
- package/types/src/extensions/Comments/CommentsPlugin.d.ts +3 -1
- package/types/src/i18n/locales/en.d.ts +1 -12
- package/types/src/i18n/locales/sk.d.ts +1 -12
- package/types/src/index.d.ts +0 -1
- package/dist/en-CvDoFvhc.js.map +0 -1
- package/dist/en-ub2yVBX0.cjs +0 -2
- package/dist/en-ub2yVBX0.cjs.map +0 -1
- package/src/util/esmDependencies.ts +0 -51
- package/types/src/util/esmDependencies.d.ts +0 -24
|
@@ -1,23 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
2
|
import * as Y from "yjs";
|
|
3
3
|
import { BlockNoteEditor } from "../editor/BlockNoteEditor.js";
|
|
4
4
|
import { trackPosition } from "./positionMapping.js";
|
|
5
5
|
|
|
6
6
|
describe("PositionStorage with local editor", () => {
|
|
7
|
-
let editor: BlockNoteEditor;
|
|
8
|
-
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
editor = BlockNoteEditor.create();
|
|
11
|
-
editor.mount(document.createElement("div"));
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
afterEach(() => {
|
|
15
|
-
editor.mount(undefined);
|
|
16
|
-
editor._tiptapEditor.destroy();
|
|
17
|
-
});
|
|
18
|
-
|
|
19
7
|
describe("mount and unmount", () => {
|
|
20
8
|
it("should register transaction handler on creation", () => {
|
|
9
|
+
const editor = BlockNoteEditor.create();
|
|
10
|
+
editor.mount(document.createElement("div"));
|
|
11
|
+
|
|
21
12
|
editor._tiptapEditor.on = vi.fn();
|
|
22
13
|
trackPosition(editor, 0);
|
|
23
14
|
|
|
@@ -25,24 +16,42 @@ describe("PositionStorage with local editor", () => {
|
|
|
25
16
|
"transaction",
|
|
26
17
|
expect.any(Function),
|
|
27
18
|
);
|
|
19
|
+
|
|
20
|
+
editor.mount(undefined);
|
|
21
|
+
editor._tiptapEditor.destroy();
|
|
28
22
|
});
|
|
29
23
|
});
|
|
30
24
|
|
|
31
25
|
describe("set and get positions", () => {
|
|
32
26
|
it("should store and retrieve positions without Y.js", () => {
|
|
27
|
+
const editor = BlockNoteEditor.create();
|
|
28
|
+
editor.mount(document.createElement("div"));
|
|
29
|
+
|
|
33
30
|
const getPos = trackPosition(editor, 10);
|
|
34
31
|
|
|
35
32
|
expect(getPos()).toBe(10);
|
|
33
|
+
|
|
34
|
+
editor.mount(undefined);
|
|
35
|
+
editor._tiptapEditor.destroy();
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
it("should handle right side positions", () => {
|
|
39
|
+
const editor = BlockNoteEditor.create();
|
|
40
|
+
editor.mount(document.createElement("div"));
|
|
41
|
+
|
|
39
42
|
const getPos = trackPosition(editor, 10, "right");
|
|
40
43
|
|
|
41
44
|
expect(getPos()).toBe(10);
|
|
45
|
+
|
|
46
|
+
editor.mount(undefined);
|
|
47
|
+
editor._tiptapEditor.destroy();
|
|
42
48
|
});
|
|
43
49
|
});
|
|
44
50
|
|
|
45
51
|
it("should update mapping for local transactions before the position", () => {
|
|
52
|
+
const editor = BlockNoteEditor.create();
|
|
53
|
+
editor.mount(document.createElement("div"));
|
|
54
|
+
|
|
46
55
|
// Set initial content
|
|
47
56
|
editor.insertBlocks(
|
|
48
57
|
[
|
|
@@ -79,9 +88,15 @@ describe("PositionStorage with local editor", () => {
|
|
|
79
88
|
|
|
80
89
|
// Position should be updated according to mapping
|
|
81
90
|
expect(getPos()).toBe(14);
|
|
91
|
+
|
|
92
|
+
editor.mount(undefined);
|
|
93
|
+
editor._tiptapEditor.destroy();
|
|
82
94
|
});
|
|
83
95
|
|
|
84
96
|
it("should not update mapping for local transactions after the position", () => {
|
|
97
|
+
const editor = BlockNoteEditor.create();
|
|
98
|
+
editor.mount(document.createElement("div"));
|
|
99
|
+
|
|
85
100
|
// Set initial content
|
|
86
101
|
editor.insertBlocks(
|
|
87
102
|
[
|
|
@@ -117,9 +132,15 @@ describe("PositionStorage with local editor", () => {
|
|
|
117
132
|
|
|
118
133
|
// Position should not be updated
|
|
119
134
|
expect(getPos()).toBe(10);
|
|
135
|
+
|
|
136
|
+
editor.mount(undefined);
|
|
137
|
+
editor._tiptapEditor.destroy();
|
|
120
138
|
});
|
|
121
139
|
|
|
122
140
|
it("should track positions on each side", () => {
|
|
141
|
+
const editor = BlockNoteEditor.create();
|
|
142
|
+
editor.mount(document.createElement("div"));
|
|
143
|
+
|
|
123
144
|
editor.replaceBlocks(editor.document, [
|
|
124
145
|
{
|
|
125
146
|
type: "paragraph",
|
|
@@ -142,9 +163,15 @@ describe("PositionStorage with local editor", () => {
|
|
|
142
163
|
expect(getStartRightPos()).toBe(8); // 3 + 5 ("Test " length)
|
|
143
164
|
expect(getPosAfterPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
144
165
|
expect(getPosAfterRightPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
166
|
+
|
|
167
|
+
editor.mount(undefined);
|
|
168
|
+
editor._tiptapEditor.destroy();
|
|
145
169
|
});
|
|
146
170
|
|
|
147
171
|
it("should handle multiple transactions", () => {
|
|
172
|
+
const editor = BlockNoteEditor.create();
|
|
173
|
+
editor.mount(document.createElement("div"));
|
|
174
|
+
|
|
148
175
|
editor.replaceBlocks(editor.document, [
|
|
149
176
|
{
|
|
150
177
|
type: "paragraph",
|
|
@@ -172,6 +199,9 @@ describe("PositionStorage with local editor", () => {
|
|
|
172
199
|
expect(getStartRightPos()).toBe(8); // 3 + 5 ("Test " length)
|
|
173
200
|
expect(getPosAfterPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
174
201
|
expect(getPosAfterRightPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
202
|
+
|
|
203
|
+
editor.mount(undefined);
|
|
204
|
+
editor._tiptapEditor.destroy();
|
|
175
205
|
});
|
|
176
206
|
});
|
|
177
207
|
|
|
@@ -202,16 +232,12 @@ describe("PositionStorage with remote editor", () => {
|
|
|
202
232
|
}
|
|
203
233
|
|
|
204
234
|
describe("remote editor", () => {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
beforeEach(() => {
|
|
211
|
-
ydoc = new Y.Doc();
|
|
212
|
-
remoteYdoc = new Y.Doc();
|
|
235
|
+
it("should update the local position when collaborating", () => {
|
|
236
|
+
const ydoc = new Y.Doc();
|
|
237
|
+
const remoteYdoc = new Y.Doc();
|
|
238
|
+
|
|
213
239
|
// Create a mock editor
|
|
214
|
-
localEditor = BlockNoteEditor.create({
|
|
240
|
+
const localEditor = BlockNoteEditor.create({
|
|
215
241
|
collaboration: {
|
|
216
242
|
fragment: ydoc.getXmlFragment("doc"),
|
|
217
243
|
user: { color: "#ff0000", name: "Local User" },
|
|
@@ -221,7 +247,7 @@ describe("PositionStorage with remote editor", () => {
|
|
|
221
247
|
const div = document.createElement("div");
|
|
222
248
|
localEditor.mount(div);
|
|
223
249
|
|
|
224
|
-
remoteEditor = BlockNoteEditor.create({
|
|
250
|
+
const remoteEditor = BlockNoteEditor.create({
|
|
225
251
|
collaboration: {
|
|
226
252
|
fragment: remoteYdoc.getXmlFragment("doc"),
|
|
227
253
|
user: { color: "#ff0000", name: "Remote User" },
|
|
@@ -232,18 +258,7 @@ describe("PositionStorage with remote editor", () => {
|
|
|
232
258
|
const remoteDiv = document.createElement("div");
|
|
233
259
|
remoteEditor.mount(remoteDiv);
|
|
234
260
|
setupTwoWaySync(ydoc, remoteYdoc);
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
afterEach(() => {
|
|
238
|
-
ydoc.destroy();
|
|
239
|
-
remoteYdoc.destroy();
|
|
240
|
-
localEditor.mount(undefined);
|
|
241
|
-
localEditor._tiptapEditor.destroy();
|
|
242
|
-
remoteEditor.mount(undefined);
|
|
243
|
-
remoteEditor._tiptapEditor.destroy();
|
|
244
|
-
});
|
|
245
261
|
|
|
246
|
-
it("should update the local position when collaborating", () => {
|
|
247
262
|
localEditor.replaceBlocks(localEditor.document, [
|
|
248
263
|
{
|
|
249
264
|
type: "paragraph",
|
|
@@ -271,9 +286,42 @@ describe("PositionStorage with remote editor", () => {
|
|
|
271
286
|
expect(getStartRightPos()).toBe(8); // 3 + 5 ("Test " length)
|
|
272
287
|
expect(getPosAfterPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
273
288
|
expect(getPosAfterRightPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
289
|
+
|
|
290
|
+
ydoc.destroy();
|
|
291
|
+
remoteYdoc.destroy();
|
|
292
|
+
localEditor.mount(undefined);
|
|
293
|
+
localEditor._tiptapEditor.destroy();
|
|
294
|
+
remoteEditor.mount(undefined);
|
|
295
|
+
remoteEditor._tiptapEditor.destroy();
|
|
274
296
|
});
|
|
275
297
|
|
|
276
298
|
it("should handle multiple transactions when collaborating", () => {
|
|
299
|
+
const ydoc = new Y.Doc();
|
|
300
|
+
const remoteYdoc = new Y.Doc();
|
|
301
|
+
|
|
302
|
+
// Create a mock editor
|
|
303
|
+
const localEditor = BlockNoteEditor.create({
|
|
304
|
+
collaboration: {
|
|
305
|
+
fragment: ydoc.getXmlFragment("doc"),
|
|
306
|
+
user: { color: "#ff0000", name: "Local User" },
|
|
307
|
+
provider: undefined,
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
const div = document.createElement("div");
|
|
311
|
+
localEditor.mount(div);
|
|
312
|
+
|
|
313
|
+
const remoteEditor = BlockNoteEditor.create({
|
|
314
|
+
collaboration: {
|
|
315
|
+
fragment: remoteYdoc.getXmlFragment("doc"),
|
|
316
|
+
user: { color: "#ff0000", name: "Remote User" },
|
|
317
|
+
provider: undefined,
|
|
318
|
+
},
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
const remoteDiv = document.createElement("div");
|
|
322
|
+
remoteEditor.mount(remoteDiv);
|
|
323
|
+
setupTwoWaySync(ydoc, remoteYdoc);
|
|
324
|
+
|
|
277
325
|
localEditor.replaceBlocks(localEditor.document, [
|
|
278
326
|
{
|
|
279
327
|
type: "paragraph",
|
|
@@ -305,9 +353,42 @@ describe("PositionStorage with remote editor", () => {
|
|
|
305
353
|
expect(getStartRightPos()).toBe(8); // 3 + 5 ("Test " length)
|
|
306
354
|
expect(getPosAfterPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
307
355
|
expect(getPosAfterRightPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
356
|
+
|
|
357
|
+
ydoc.destroy();
|
|
358
|
+
remoteYdoc.destroy();
|
|
359
|
+
localEditor.mount(undefined);
|
|
360
|
+
localEditor._tiptapEditor.destroy();
|
|
361
|
+
remoteEditor.mount(undefined);
|
|
362
|
+
remoteEditor._tiptapEditor.destroy();
|
|
308
363
|
});
|
|
309
364
|
|
|
310
365
|
it("should update the local position from a remote transaction", () => {
|
|
366
|
+
const ydoc = new Y.Doc();
|
|
367
|
+
const remoteYdoc = new Y.Doc();
|
|
368
|
+
|
|
369
|
+
// Create a mock editor
|
|
370
|
+
const localEditor = BlockNoteEditor.create({
|
|
371
|
+
collaboration: {
|
|
372
|
+
fragment: ydoc.getXmlFragment("doc"),
|
|
373
|
+
user: { color: "#ff0000", name: "Local User" },
|
|
374
|
+
provider: undefined,
|
|
375
|
+
},
|
|
376
|
+
});
|
|
377
|
+
const div = document.createElement("div");
|
|
378
|
+
localEditor.mount(div);
|
|
379
|
+
|
|
380
|
+
const remoteEditor = BlockNoteEditor.create({
|
|
381
|
+
collaboration: {
|
|
382
|
+
fragment: remoteYdoc.getXmlFragment("doc"),
|
|
383
|
+
user: { color: "#ff0000", name: "Remote User" },
|
|
384
|
+
provider: undefined,
|
|
385
|
+
},
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
const remoteDiv = document.createElement("div");
|
|
389
|
+
remoteEditor.mount(remoteDiv);
|
|
390
|
+
setupTwoWaySync(ydoc, remoteYdoc);
|
|
391
|
+
|
|
311
392
|
remoteEditor.replaceBlocks(remoteEditor.document, [
|
|
312
393
|
{
|
|
313
394
|
type: "paragraph",
|
|
@@ -335,9 +416,42 @@ describe("PositionStorage with remote editor", () => {
|
|
|
335
416
|
expect(getStartRightPos()).toBe(8); // 3 + 5 ("Test " length)
|
|
336
417
|
expect(getPosAfterPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
337
418
|
expect(getPosAfterRightPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
419
|
+
|
|
420
|
+
ydoc.destroy();
|
|
421
|
+
remoteYdoc.destroy();
|
|
422
|
+
localEditor.mount(undefined);
|
|
423
|
+
localEditor._tiptapEditor.destroy();
|
|
424
|
+
remoteEditor.mount(undefined);
|
|
425
|
+
remoteEditor._tiptapEditor.destroy();
|
|
338
426
|
});
|
|
339
427
|
|
|
340
428
|
it("should update the remote position from a remote transaction", () => {
|
|
429
|
+
const ydoc = new Y.Doc();
|
|
430
|
+
const remoteYdoc = new Y.Doc();
|
|
431
|
+
|
|
432
|
+
// Create a mock editor
|
|
433
|
+
const localEditor = BlockNoteEditor.create({
|
|
434
|
+
collaboration: {
|
|
435
|
+
fragment: ydoc.getXmlFragment("doc"),
|
|
436
|
+
user: { color: "#ff0000", name: "Local User" },
|
|
437
|
+
provider: undefined,
|
|
438
|
+
},
|
|
439
|
+
});
|
|
440
|
+
const div = document.createElement("div");
|
|
441
|
+
localEditor.mount(div);
|
|
442
|
+
|
|
443
|
+
const remoteEditor = BlockNoteEditor.create({
|
|
444
|
+
collaboration: {
|
|
445
|
+
fragment: remoteYdoc.getXmlFragment("doc"),
|
|
446
|
+
user: { color: "#ff0000", name: "Remote User" },
|
|
447
|
+
provider: undefined,
|
|
448
|
+
},
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
const remoteDiv = document.createElement("div");
|
|
452
|
+
remoteEditor.mount(remoteDiv);
|
|
453
|
+
setupTwoWaySync(ydoc, remoteYdoc);
|
|
454
|
+
|
|
341
455
|
remoteEditor.replaceBlocks(remoteEditor.document, [
|
|
342
456
|
{
|
|
343
457
|
type: "paragraph",
|
|
@@ -365,6 +479,13 @@ describe("PositionStorage with remote editor", () => {
|
|
|
365
479
|
expect(getStartRightPos()).toBe(8); // 3 + 5 ("Test " length)
|
|
366
480
|
expect(getPosAfterPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
367
481
|
expect(getPosAfterRightPos()).toBe(9); // 4 + 5 ("Test " length)
|
|
482
|
+
|
|
483
|
+
ydoc.destroy();
|
|
484
|
+
remoteYdoc.destroy();
|
|
485
|
+
localEditor.mount(undefined);
|
|
486
|
+
localEditor._tiptapEditor.destroy();
|
|
487
|
+
remoteEditor.mount(undefined);
|
|
488
|
+
remoteEditor._tiptapEditor.destroy();
|
|
368
489
|
});
|
|
369
490
|
});
|
|
370
491
|
});
|
|
@@ -88,7 +88,7 @@ export function trackPosition(
|
|
|
88
88
|
|
|
89
89
|
const relativePosition = absolutePositionToRelativePosition(
|
|
90
90
|
// Track the position after the position if we are on the right side
|
|
91
|
-
position + (side === "right" ? 1 :
|
|
91
|
+
position + (side === "right" ? 1 : -1),
|
|
92
92
|
ySyncPluginState.binding.type,
|
|
93
93
|
ySyncPluginState.binding.mapping,
|
|
94
94
|
);
|
|
@@ -109,6 +109,6 @@ export function trackPosition(
|
|
|
109
109
|
throw new Error("Position not found, cannot track positions");
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
return pos + (side === "right" ? -1 :
|
|
112
|
+
return pos + (side === "right" ? -1 : 1);
|
|
113
113
|
};
|
|
114
114
|
}
|
|
@@ -4,7 +4,6 @@ import { BlockFromConfig, FileBlockConfig } from "../../../../schema/index.js";
|
|
|
4
4
|
export const createAddFileButton = (
|
|
5
5
|
block: BlockFromConfig<FileBlockConfig, any, any>,
|
|
6
6
|
editor: BlockNoteEditor<any, any, any>,
|
|
7
|
-
buttonText?: string,
|
|
8
7
|
buttonIcon?: HTMLElement,
|
|
9
8
|
) => {
|
|
10
9
|
const addFileButton = document.createElement("div");
|
|
@@ -23,7 +22,9 @@ export const createAddFileButton = (
|
|
|
23
22
|
const addFileButtonText = document.createElement("p");
|
|
24
23
|
addFileButtonText.className = "bn-add-file-button-text";
|
|
25
24
|
addFileButtonText.innerHTML =
|
|
26
|
-
|
|
25
|
+
block.type in editor.dictionary.file_blocks.add_button_text
|
|
26
|
+
? editor.dictionary.file_blocks.add_button_text[block.type]
|
|
27
|
+
: editor.dictionary.file_blocks.add_button_text["file"];
|
|
27
28
|
addFileButton.appendChild(addFileButtonText);
|
|
28
29
|
|
|
29
30
|
// Prevents focus from moving to the button.
|
|
@@ -15,7 +15,6 @@ export const createFileBlockWrapper = (
|
|
|
15
15
|
any
|
|
16
16
|
>,
|
|
17
17
|
element?: { dom: HTMLElement; destroy?: () => void },
|
|
18
|
-
buttonText?: string,
|
|
19
18
|
buttonIcon?: HTMLElement,
|
|
20
19
|
) => {
|
|
21
20
|
const wrapper = document.createElement("div");
|
|
@@ -24,12 +23,7 @@ export const createFileBlockWrapper = (
|
|
|
24
23
|
// Show the add file button if the file has not been uploaded yet. Change to
|
|
25
24
|
// show a loader if a file upload for the block begins.
|
|
26
25
|
if (block.props.url === "") {
|
|
27
|
-
const addFileButton = createAddFileButton(
|
|
28
|
-
block,
|
|
29
|
-
editor,
|
|
30
|
-
buttonText,
|
|
31
|
-
buttonIcon,
|
|
32
|
-
);
|
|
26
|
+
const addFileButton = createAddFileButton(block, editor, buttonIcon);
|
|
33
27
|
wrapper.appendChild(addFileButton.dom);
|
|
34
28
|
|
|
35
29
|
const destroyUploadStartHandler = editor.onUploadStart((blockId) => {
|
|
@@ -7,14 +7,12 @@ export const createResizableFileBlockWrapper = (
|
|
|
7
7
|
editor: BlockNoteEditor<any, any, any>,
|
|
8
8
|
element: { dom: HTMLElement; destroy?: () => void },
|
|
9
9
|
resizeHandlesContainerElement: HTMLElement,
|
|
10
|
-
|
|
11
|
-
buttonIcon: HTMLElement,
|
|
10
|
+
buttonIcon?: HTMLElement,
|
|
12
11
|
): { dom: HTMLElement; destroy: () => void } => {
|
|
13
12
|
const { dom, destroy } = createFileBlockWrapper(
|
|
14
13
|
block,
|
|
15
14
|
editor,
|
|
16
15
|
element,
|
|
17
|
-
buttonText,
|
|
18
16
|
buttonIcon,
|
|
19
17
|
);
|
|
20
18
|
const wrapper = dom;
|
|
@@ -56,7 +54,7 @@ export const createResizableFileBlockWrapper = (
|
|
|
56
54
|
|
|
57
55
|
// Updates the element width with an updated width depending on the cursor X
|
|
58
56
|
// offset from when the resize began, and which resize handle is being used.
|
|
59
|
-
const windowMouseMoveHandler = (event: MouseEvent) => {
|
|
57
|
+
const windowMouseMoveHandler = (event: MouseEvent | TouchEvent) => {
|
|
60
58
|
if (!resizeParams) {
|
|
61
59
|
if (
|
|
62
60
|
!editor.isEditable &&
|
|
@@ -72,27 +70,26 @@ export const createResizableFileBlockWrapper = (
|
|
|
72
70
|
|
|
73
71
|
let newWidth: number;
|
|
74
72
|
|
|
73
|
+
const clientX =
|
|
74
|
+
"touches" in event ? event.touches[0].clientX : event.clientX;
|
|
75
|
+
|
|
75
76
|
if (block.props.textAlignment === "center") {
|
|
76
77
|
if (resizeParams.handleUsed === "left") {
|
|
77
78
|
newWidth =
|
|
78
79
|
resizeParams.initialWidth +
|
|
79
|
-
(resizeParams.initialClientX -
|
|
80
|
+
(resizeParams.initialClientX - clientX) * 2;
|
|
80
81
|
} else {
|
|
81
82
|
newWidth =
|
|
82
83
|
resizeParams.initialWidth +
|
|
83
|
-
(
|
|
84
|
+
(clientX - resizeParams.initialClientX) * 2;
|
|
84
85
|
}
|
|
85
86
|
} else {
|
|
86
87
|
if (resizeParams.handleUsed === "left") {
|
|
87
88
|
newWidth =
|
|
88
|
-
resizeParams.initialWidth +
|
|
89
|
-
resizeParams.initialClientX -
|
|
90
|
-
event.clientX;
|
|
89
|
+
resizeParams.initialWidth + resizeParams.initialClientX - clientX;
|
|
91
90
|
} else {
|
|
92
91
|
newWidth =
|
|
93
|
-
resizeParams.initialWidth +
|
|
94
|
-
event.clientX -
|
|
95
|
-
resizeParams.initialClientX;
|
|
92
|
+
resizeParams.initialWidth + clientX - resizeParams.initialClientX;
|
|
96
93
|
}
|
|
97
94
|
}
|
|
98
95
|
|
|
@@ -109,7 +106,7 @@ export const createResizableFileBlockWrapper = (
|
|
|
109
106
|
};
|
|
110
107
|
// Stops mouse movements from resizing the element and updates the block's
|
|
111
108
|
// `width` prop to the new value.
|
|
112
|
-
const windowMouseUpHandler = (event: MouseEvent) => {
|
|
109
|
+
const windowMouseUpHandler = (event: MouseEvent | TouchEvent) => {
|
|
113
110
|
// Hides the drag handles if the cursor is no longer over the element.
|
|
114
111
|
if (
|
|
115
112
|
(!event.target ||
|
|
@@ -172,62 +169,90 @@ export const createResizableFileBlockWrapper = (
|
|
|
172
169
|
|
|
173
170
|
// Sets the resize params, allowing the user to begin resizing the element by
|
|
174
171
|
// moving the cursor left or right.
|
|
175
|
-
const leftResizeHandleMouseDownHandler = (event: MouseEvent) => {
|
|
172
|
+
const leftResizeHandleMouseDownHandler = (event: MouseEvent | TouchEvent) => {
|
|
176
173
|
event.preventDefault();
|
|
177
174
|
|
|
178
175
|
if (!wrapper.contains(eventCaptureElement)) {
|
|
179
176
|
wrapper.appendChild(eventCaptureElement);
|
|
180
177
|
}
|
|
181
178
|
|
|
179
|
+
const clientX =
|
|
180
|
+
"touches" in event ? event.touches[0].clientX : event.clientX;
|
|
181
|
+
|
|
182
182
|
resizeParams = {
|
|
183
183
|
handleUsed: "left",
|
|
184
184
|
initialWidth: wrapper.clientWidth,
|
|
185
|
-
initialClientX:
|
|
185
|
+
initialClientX: clientX,
|
|
186
186
|
};
|
|
187
187
|
};
|
|
188
|
-
const rightResizeHandleMouseDownHandler = (
|
|
188
|
+
const rightResizeHandleMouseDownHandler = (
|
|
189
|
+
event: MouseEvent | TouchEvent,
|
|
190
|
+
) => {
|
|
189
191
|
event.preventDefault();
|
|
190
192
|
|
|
191
193
|
if (!wrapper.contains(eventCaptureElement)) {
|
|
192
194
|
wrapper.appendChild(eventCaptureElement);
|
|
193
195
|
}
|
|
194
196
|
|
|
197
|
+
const clientX =
|
|
198
|
+
"touches" in event ? event.touches[0].clientX : event.clientX;
|
|
199
|
+
|
|
195
200
|
resizeParams = {
|
|
196
201
|
handleUsed: "right",
|
|
197
202
|
initialWidth: wrapper.clientWidth,
|
|
198
|
-
initialClientX:
|
|
203
|
+
initialClientX: clientX,
|
|
199
204
|
};
|
|
200
205
|
};
|
|
201
206
|
|
|
202
207
|
window.addEventListener("mousemove", windowMouseMoveHandler);
|
|
208
|
+
window.addEventListener("touchmove", windowMouseMoveHandler);
|
|
203
209
|
window.addEventListener("mouseup", windowMouseUpHandler);
|
|
210
|
+
window.addEventListener("touchend", windowMouseUpHandler);
|
|
204
211
|
wrapper.addEventListener("mouseenter", wrapperMouseEnterHandler);
|
|
205
212
|
wrapper.addEventListener("mouseleave", wrapperMouseLeaveHandler);
|
|
206
213
|
leftResizeHandle.addEventListener(
|
|
207
214
|
"mousedown",
|
|
208
215
|
leftResizeHandleMouseDownHandler,
|
|
209
216
|
);
|
|
217
|
+
leftResizeHandle.addEventListener(
|
|
218
|
+
"touchstart",
|
|
219
|
+
leftResizeHandleMouseDownHandler,
|
|
220
|
+
);
|
|
210
221
|
rightResizeHandle.addEventListener(
|
|
211
222
|
"mousedown",
|
|
212
223
|
rightResizeHandleMouseDownHandler,
|
|
213
224
|
);
|
|
225
|
+
rightResizeHandle.addEventListener(
|
|
226
|
+
"touchstart",
|
|
227
|
+
rightResizeHandleMouseDownHandler,
|
|
228
|
+
);
|
|
214
229
|
|
|
215
230
|
return {
|
|
216
231
|
dom: wrapper,
|
|
217
232
|
destroy: () => {
|
|
218
233
|
destroy?.();
|
|
219
234
|
window.removeEventListener("mousemove", windowMouseMoveHandler);
|
|
235
|
+
window.removeEventListener("touchmove", windowMouseMoveHandler);
|
|
220
236
|
window.removeEventListener("mouseup", windowMouseUpHandler);
|
|
237
|
+
window.removeEventListener("touchend", windowMouseUpHandler);
|
|
221
238
|
wrapper.removeEventListener("mouseenter", wrapperMouseEnterHandler);
|
|
222
239
|
wrapper.removeEventListener("mouseleave", wrapperMouseLeaveHandler);
|
|
223
240
|
leftResizeHandle.removeEventListener(
|
|
224
241
|
"mousedown",
|
|
225
242
|
leftResizeHandleMouseDownHandler,
|
|
226
243
|
);
|
|
244
|
+
leftResizeHandle.removeEventListener(
|
|
245
|
+
"touchstart",
|
|
246
|
+
leftResizeHandleMouseDownHandler,
|
|
247
|
+
);
|
|
227
248
|
rightResizeHandle.removeEventListener(
|
|
228
249
|
"mousedown",
|
|
229
250
|
rightResizeHandleMouseDownHandler,
|
|
230
251
|
);
|
|
252
|
+
rightResizeHandle.removeEventListener(
|
|
253
|
+
"touchstart",
|
|
254
|
+
rightResizeHandleMouseDownHandler,
|
|
255
|
+
);
|
|
231
256
|
},
|
|
232
257
|
};
|
|
233
258
|
};
|
|
@@ -105,22 +105,21 @@ import { dropCursor } from "prosemirror-dropcursor";
|
|
|
105
105
|
import { EditorView } from "prosemirror-view";
|
|
106
106
|
import { redoCommand, undoCommand, ySyncPluginKey } from "y-prosemirror";
|
|
107
107
|
import { createInternalHTMLSerializer } from "../api/exporters/html/internalHTMLSerializer.js";
|
|
108
|
-
import { inlineContentToNodes } from "../api/nodeConversions/blockToNode.js";
|
|
109
|
-
import { docToBlocks } from "../api/nodeConversions/nodeToBlock.js";
|
|
110
108
|
import {
|
|
111
109
|
BlocksChanged,
|
|
112
110
|
getBlocksChangedByTransaction,
|
|
113
111
|
} from "../api/getBlocksChangedByTransaction.js";
|
|
114
|
-
import {
|
|
112
|
+
import { inlineContentToNodes } from "../api/nodeConversions/blockToNode.js";
|
|
113
|
+
import { docToBlocks } from "../api/nodeConversions/nodeToBlock.js";
|
|
115
114
|
import { CodeBlockOptions } from "../blocks/CodeBlockContent/CodeBlockContent.js";
|
|
116
115
|
import type { ThreadStore, User } from "../comments/index.js";
|
|
116
|
+
import { BlockChangePlugin } from "../extensions/BlockChange/BlockChangePlugin.js";
|
|
117
117
|
import type { CursorPlugin } from "../extensions/Collaboration/CursorPlugin.js";
|
|
118
118
|
import type { ForkYDocPlugin } from "../extensions/Collaboration/ForkYDocPlugin.js";
|
|
119
119
|
import { EventEmitter } from "../util/EventEmitter.js";
|
|
120
120
|
import { BlockNoteExtension } from "./BlockNoteExtension.js";
|
|
121
121
|
|
|
122
122
|
import "../style.css";
|
|
123
|
-
import { BlockChangePlugin } from "../extensions/BlockChange/BlockChangePlugin.js";
|
|
124
123
|
|
|
125
124
|
/**
|
|
126
125
|
* A factory function that returns a BlockNoteExtension
|
|
@@ -201,6 +200,7 @@ export type BlockNoteEditorOptions<
|
|
|
201
200
|
* @remarks `CommentsOptions`
|
|
202
201
|
*/
|
|
203
202
|
comments?: {
|
|
203
|
+
schema?: BlockNoteSchema<any, any, any>;
|
|
204
204
|
threadStore: ThreadStore;
|
|
205
205
|
};
|
|
206
206
|
|
|
@@ -1574,9 +1574,9 @@ export class BlockNoteEditor<
|
|
|
1574
1574
|
* @param blocks An array of blocks that should be serialized into HTML.
|
|
1575
1575
|
* @returns The blocks, serialized as an HTML string.
|
|
1576
1576
|
*/
|
|
1577
|
-
public
|
|
1577
|
+
public blocksToHTMLLossy(
|
|
1578
1578
|
blocks: PartialBlock<BSchema, ISchema, SSchema>[] = this.document,
|
|
1579
|
-
):
|
|
1579
|
+
): string {
|
|
1580
1580
|
const exporter = createExternalHTMLExporter(this.pmSchema, this);
|
|
1581
1581
|
return exporter.exportBlocks(blocks, {});
|
|
1582
1582
|
}
|
|
@@ -1590,9 +1590,9 @@ export class BlockNoteEditor<
|
|
|
1590
1590
|
* @param blocks An array of blocks that should be serialized into HTML.
|
|
1591
1591
|
* @returns The blocks, serialized as an HTML string.
|
|
1592
1592
|
*/
|
|
1593
|
-
public
|
|
1593
|
+
public blocksToFullHTML(
|
|
1594
1594
|
blocks: PartialBlock<BSchema, ISchema, SSchema>[],
|
|
1595
|
-
):
|
|
1595
|
+
): string {
|
|
1596
1596
|
const exporter = createInternalHTMLSerializer(this.pmSchema, this);
|
|
1597
1597
|
return exporter.serializeBlocks(blocks, {});
|
|
1598
1598
|
}
|
|
@@ -1603,9 +1603,9 @@ export class BlockNoteEditor<
|
|
|
1603
1603
|
* @param html The HTML string to parse blocks from.
|
|
1604
1604
|
* @returns The blocks parsed from the HTML string.
|
|
1605
1605
|
*/
|
|
1606
|
-
public
|
|
1606
|
+
public tryParseHTMLToBlocks(
|
|
1607
1607
|
html: string,
|
|
1608
|
-
):
|
|
1608
|
+
): Block<BSchema, ISchema, SSchema>[] {
|
|
1609
1609
|
return HTMLToBlocks(html, this.pmSchema);
|
|
1610
1610
|
}
|
|
1611
1611
|
|
|
@@ -1615,9 +1615,9 @@ export class BlockNoteEditor<
|
|
|
1615
1615
|
* @param blocks An array of blocks that should be serialized into Markdown.
|
|
1616
1616
|
* @returns The blocks, serialized as a Markdown string.
|
|
1617
1617
|
*/
|
|
1618
|
-
public
|
|
1618
|
+
public blocksToMarkdownLossy(
|
|
1619
1619
|
blocks: PartialBlock<BSchema, ISchema, SSchema>[] = this.document,
|
|
1620
|
-
):
|
|
1620
|
+
): string {
|
|
1621
1621
|
return blocksToMarkdown(blocks, this.pmSchema, this, {});
|
|
1622
1622
|
}
|
|
1623
1623
|
|
|
@@ -1832,14 +1832,6 @@ export class BlockNoteEditor<
|
|
|
1832
1832
|
this.showSelectionPlugin.setEnabled(forceSelectionVisible);
|
|
1833
1833
|
}
|
|
1834
1834
|
|
|
1835
|
-
/**
|
|
1836
|
-
* This will convert HTML into a format that is compatible with BlockNote.
|
|
1837
|
-
*/
|
|
1838
|
-
private convertHtmlToBlockNoteHtml(html: string) {
|
|
1839
|
-
const htmlNode = nestedListsToBlockNoteStructure(html.trim());
|
|
1840
|
-
return htmlNode.innerHTML;
|
|
1841
|
-
}
|
|
1842
|
-
|
|
1843
1835
|
/**
|
|
1844
1836
|
* Paste HTML into the editor. Defaults to converting HTML to BlockNote HTML.
|
|
1845
1837
|
* @param html The HTML to paste.
|
|
@@ -1848,7 +1840,8 @@ export class BlockNoteEditor<
|
|
|
1848
1840
|
public pasteHTML(html: string, raw = false) {
|
|
1849
1841
|
let htmlToPaste = html;
|
|
1850
1842
|
if (!raw) {
|
|
1851
|
-
|
|
1843
|
+
const blocks = this.tryParseHTMLToBlocks(html);
|
|
1844
|
+
htmlToPaste = this.blocksToFullHTML(blocks);
|
|
1852
1845
|
}
|
|
1853
1846
|
if (!htmlToPaste) {
|
|
1854
1847
|
return;
|
|
@@ -1868,7 +1861,8 @@ export class BlockNoteEditor<
|
|
|
1868
1861
|
* Paste markdown into the editor.
|
|
1869
1862
|
* @param markdown The markdown to paste.
|
|
1870
1863
|
*/
|
|
1871
|
-
public
|
|
1872
|
-
|
|
1864
|
+
public pasteMarkdown(markdown: string) {
|
|
1865
|
+
const html = markdownToHTML(markdown);
|
|
1866
|
+
return this.pasteHTML(html);
|
|
1873
1867
|
}
|
|
1874
1868
|
}
|