Skip to content

Commit 0eb3bce

Browse files
committed
fix: put json on the clipboard, not html
1 parent 3e94d1a commit 0eb3bce

File tree

5 files changed

+38
-34
lines changed

5 files changed

+38
-34
lines changed

packages/core/src/api/clipboard/fromClipboard/acceptedMIMETypes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export const acceptedMIMETypes = [
22
"vscode-editor-data",
3-
"blocknote/html",
3+
"blocknote/json",
44
"text/markdown",
55
"text/html",
66
"text/plain",

packages/core/src/api/clipboard/fromClipboard/pasteExtension.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import {
1414
import { acceptedMIMETypes } from "./acceptedMIMETypes.js";
1515
import { handleFileInsertion } from "./handleFileInsertion.js";
1616
import { handleVSCodePaste } from "./handleVSCodePaste.js";
17+
import { Slice } from "prosemirror-model";
18+
import { getPmSchema } from "../../pmUtil.js";
1719

1820
function defaultPasteHandler({
1921
event,
@@ -68,9 +70,13 @@ function defaultPasteHandler({
6870

6971
const data = event.clipboardData!.getData(format);
7072

71-
if (format === "blocknote/html") {
72-
// Is blocknote/html, so no need to convert it
73-
editor.pasteHTML(data, true);
73+
if (format === "blocknote/json") {
74+
editor.transact((tr) => {
75+
const schema = getPmSchema(tr);
76+
const slice = Slice.fromJSON(schema, JSON.parse(data));
77+
// Probably need to expand the selection to the block that is being pasted into?
78+
tr.replaceSelection(slice);
79+
});
7480
return true;
7581
}
7682

packages/core/src/api/clipboard/toClipboard/copyExtension.ts

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Extension } from "@tiptap/core";
2-
import { Fragment, Node } from "prosemirror-model";
2+
import { Fragment, Node, Slice } from "prosemirror-model";
33
import { NodeSelection, Plugin } from "prosemirror-state";
44
import { CellSelection } from "prosemirror-tables";
55
import type { EditorView } from "prosemirror-view";
@@ -111,6 +111,7 @@ export function selectedFragmentToHTML<
111111
clipboardHTML: string;
112112
externalHTML: string;
113113
markdown: string;
114+
slice: Slice;
114115
} {
115116
// Checks if a `blockContent` node is being copied and expands
116117
// the selection to the parent `blockContainer` node. This is
@@ -127,22 +128,21 @@ export function selectedFragmentToHTML<
127128
);
128129
}
129130

131+
const slice = view.state.selection.content();
130132
// Uses default ProseMirror clipboard serialization.
131-
const clipboardHTML: string = view.serializeForClipboard(
132-
view.state.selection.content(),
133-
).dom.innerHTML;
134-
135-
const selectedFragment = view.state.selection.content().content;
133+
const clipboardHTML: string = view.serializeForClipboard(slice).dom.innerHTML;
136134

135+
// TODO should probably remove this and just use the slice.toJSON()
136+
// Kept it so that the tests still pass
137137
const externalHTML = fragmentToExternalHTML<BSchema, I, S>(
138138
view,
139-
selectedFragment,
139+
slice.content,
140140
editor,
141141
);
142142

143143
const markdown = cleanHTMLToMarkdown(externalHTML);
144144

145-
return { clipboardHTML, externalHTML, markdown };
145+
return { clipboardHTML, externalHTML, markdown, slice };
146146
}
147147

148148
const checkIfSelectionInNonEditableBlock = () => {
@@ -186,14 +186,17 @@ const copyToClipboard = <
186186
event.preventDefault();
187187
event.clipboardData!.clearData();
188188

189-
const { clipboardHTML, externalHTML, markdown } = selectedFragmentToHTML(
189+
const { externalHTML, markdown, slice } = selectedFragmentToHTML(
190190
view,
191191
editor,
192192
);
193193

194194
// TODO: Writing to other MIME types not working in Safari for
195195
// some reason.
196-
event.clipboardData!.setData("blocknote/html", clipboardHTML);
196+
event.clipboardData!.setData(
197+
"blocknote/json",
198+
JSON.stringify(slice.toJSON()),
199+
);
197200
event.clipboardData!.setData("text/html", externalHTML);
198201
event.clipboardData!.setData("text/plain", markdown);
199202
};
@@ -263,12 +266,15 @@ export const createCopyToClipboardExtension = <
263266
event.preventDefault();
264267
event.dataTransfer!.clearData();
265268

266-
const { clipboardHTML, externalHTML, markdown } =
269+
const { externalHTML, markdown, slice } =
267270
selectedFragmentToHTML(view, editor);
268271

269272
// TODO: Writing to other MIME types not working in Safari for
270273
// some reason.
271-
event.dataTransfer!.setData("blocknote/html", clipboardHTML);
274+
event.dataTransfer!.setData(
275+
"blocknote/json",
276+
JSON.stringify(slice.toJSON()),
277+
);
272278
event.dataTransfer!.setData("text/html", externalHTML);
273279
event.dataTransfer!.setData("text/plain", markdown);
274280

packages/core/src/extensions/SideMenu/SideMenuPlugin.ts

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { DOMParser, Slice } from "@tiptap/pm/model";
1+
import { Slice } from "@tiptap/pm/model";
22
import {
33
EditorState,
44
Plugin,
@@ -338,7 +338,7 @@ export class SideMenuView<
338338
if (
339339
this.sideMenuDetection === "editor" ||
340340
(event as any).synthetic ||
341-
!event.dataTransfer?.types.includes("blocknote/html")
341+
!event.dataTransfer?.types.includes("blocknote/json")
342342
) {
343343
return;
344344
}
@@ -387,25 +387,17 @@ export class SideMenuView<
387387
* access `dataTransfer` contents on `dragstart` and `drop` events.
388388
*/
389389
onDragStart = (event: DragEvent) => {
390-
const html = event.dataTransfer?.getData("blocknote/html");
391-
if (!html) {
390+
const json = event.dataTransfer?.getData("blocknote/json");
391+
if (!json) {
392392
return;
393393
}
394394

395395
if (this.pmView.dragging) {
396396
throw new Error("New drag was started while an existing drag is ongoing");
397397
}
398398

399-
const element = document.createElement("div");
400-
element.innerHTML = html;
401-
402-
const parser = DOMParser.fromSchema(this.pmView.state.schema);
403-
const node = parser.parse(element, {
404-
topNode: this.pmView.state.schema.nodes["blockGroup"].create(),
405-
});
406-
407399
this.pmView.dragging = {
408-
slice: new Slice(node.content, 0, 0),
400+
slice: Slice.fromJSON(this.pmView.state.schema, JSON.parse(json)),
409401
move: true,
410402
};
411403
};
@@ -419,7 +411,7 @@ export class SideMenuView<
419411
if (
420412
this.sideMenuDetection === "editor" ||
421413
(event as any).synthetic ||
422-
!event.dataTransfer?.types.includes("blocknote/html")
414+
!event.dataTransfer?.types.includes("blocknote/json")
423415
) {
424416
return;
425417
}

packages/core/src/extensions/SideMenu/dragging.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,6 @@ export function dragStart<
196196
const selectedSlice = view.state.selection.content();
197197
const schema = editor.pmSchema;
198198

199-
const clipboardHTML =
200-
view.serializeForClipboard(selectedSlice).dom.innerHTML;
201-
202199
const externalHTMLExporter = createExternalHTMLExporter(schema, editor);
203200

204201
const blocks = fragmentToBlocks(selectedSlice.content);
@@ -207,7 +204,10 @@ export function dragStart<
207204
const plainText = cleanHTMLToMarkdown(externalHTML);
208205

209206
e.dataTransfer.clearData();
210-
e.dataTransfer.setData("blocknote/html", clipboardHTML);
207+
e.dataTransfer.setData(
208+
"blocknote/json",
209+
JSON.stringify(selectedSlice.toJSON()),
210+
);
211211
e.dataTransfer.setData("text/html", externalHTML);
212212
e.dataTransfer.setData("text/plain", plainText);
213213
e.dataTransfer.effectAllowed = "move";

0 commit comments

Comments
 (0)