@seorii/tiptap 0.4.4 → 0.4.5
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.
|
@@ -71,14 +71,13 @@ export const dropImagePlugin = () => {
|
|
|
71
71
|
const upload = imageUploader || fallbackUpload;
|
|
72
72
|
const items = Array.from(event.clipboardData?.items || []);
|
|
73
73
|
const { schema } = view.state;
|
|
74
|
+
let handledImagePaste = false;
|
|
74
75
|
items.forEach((item) => {
|
|
75
76
|
const image = item.getAsFile();
|
|
76
77
|
if (item.type.indexOf('image') === 0) {
|
|
78
|
+
handledImagePaste = true;
|
|
77
79
|
event.preventDefault();
|
|
78
|
-
const skeleton = insertUploadSkeleton({
|
|
79
|
-
state: view.state,
|
|
80
|
-
view
|
|
81
|
-
}, {
|
|
80
|
+
const skeleton = insertUploadSkeleton({ view }, {
|
|
82
81
|
kind: 'image',
|
|
83
82
|
height: 220
|
|
84
83
|
});
|
|
@@ -119,7 +118,7 @@ export const dropImagePlugin = () => {
|
|
|
119
118
|
reader.readAsDataURL(image);
|
|
120
119
|
}
|
|
121
120
|
});
|
|
122
|
-
return
|
|
121
|
+
return handledImagePaste;
|
|
123
122
|
},
|
|
124
123
|
drop: (view, event) => {
|
|
125
124
|
const imageUploader = window.__image_uploader;
|
|
@@ -142,10 +141,7 @@ export const dropImagePlugin = () => {
|
|
|
142
141
|
return false;
|
|
143
142
|
images.forEach(async (image) => {
|
|
144
143
|
const reader = new FileReader();
|
|
145
|
-
const skeleton = insertUploadSkeleton({
|
|
146
|
-
state: view.state,
|
|
147
|
-
view
|
|
148
|
-
}, {
|
|
144
|
+
const skeleton = insertUploadSkeleton({ view }, {
|
|
149
145
|
kind: 'image',
|
|
150
146
|
height: 220,
|
|
151
147
|
at: coordinates.pos
|
|
@@ -18,7 +18,7 @@ type InsertUploadSkeletonOptions = {
|
|
|
18
18
|
type ReplaceOptions = {
|
|
19
19
|
select?: boolean;
|
|
20
20
|
};
|
|
21
|
-
type EditorLike = Pick<Editor, '
|
|
21
|
+
type EditorLike = Pick<Editor, 'view'>;
|
|
22
22
|
export type UploadSkeletonHandle = {
|
|
23
23
|
id: string;
|
|
24
24
|
exists: () => boolean;
|
|
@@ -11,20 +11,16 @@ const defaultHeight = {
|
|
|
11
11
|
block: 180
|
|
12
12
|
};
|
|
13
13
|
function findUploadSkeleton(doc, id) {
|
|
14
|
-
let
|
|
15
|
-
let foundNode = null;
|
|
14
|
+
let target = null;
|
|
16
15
|
doc.descendants((node, pos) => {
|
|
17
16
|
if (node.type.name !== UPLOAD_SKELETON_NODE)
|
|
18
17
|
return;
|
|
19
18
|
if (node.attrs.uploadId !== id)
|
|
20
19
|
return;
|
|
21
|
-
|
|
22
|
-
foundNode = node;
|
|
20
|
+
target = { pos, node };
|
|
23
21
|
return false;
|
|
24
22
|
});
|
|
25
|
-
|
|
26
|
-
return null;
|
|
27
|
-
return { pos: foundPos, node: foundNode };
|
|
23
|
+
return target;
|
|
28
24
|
}
|
|
29
25
|
function tryCreateNodeSelection(doc, pos) {
|
|
30
26
|
if (pos < 0 || pos > doc.content.size)
|
|
@@ -40,15 +36,16 @@ function tryCreateNodeSelection(doc, pos) {
|
|
|
40
36
|
}
|
|
41
37
|
}
|
|
42
38
|
export function insertUploadSkeleton(editor, { kind = 'block', height = defaultHeight[kind], at, select = true, insertParagraph = true } = {}) {
|
|
43
|
-
const
|
|
39
|
+
const getState = () => editor.view.state;
|
|
40
|
+
const skeletonType = getState().schema.nodes[UPLOAD_SKELETON_NODE];
|
|
44
41
|
if (!skeletonType)
|
|
45
42
|
return null;
|
|
46
43
|
const clampedHeight = Math.max(44, Math.min(1200, Math.round(height)));
|
|
47
44
|
const uploadId = `upload-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
48
45
|
const node = skeletonType.create({ uploadId, kind, height: clampedHeight });
|
|
49
|
-
const paragraph =
|
|
50
|
-
const safePos = Math.max(0, Math.min(at ??
|
|
51
|
-
const tr =
|
|
46
|
+
const paragraph = getState().schema.nodes.paragraph?.create();
|
|
47
|
+
const safePos = Math.max(0, Math.min(at ?? getState().selection.from, getState().doc.content.size));
|
|
48
|
+
const tr = getState().tr.insert(safePos, node);
|
|
52
49
|
if (insertParagraph && paragraph) {
|
|
53
50
|
tr.insert(safePos + node.nodeSize, paragraph);
|
|
54
51
|
}
|
|
@@ -60,21 +57,22 @@ export function insertUploadSkeleton(editor, { kind = 'block', height = defaultH
|
|
|
60
57
|
editor.view.dispatch(tr);
|
|
61
58
|
return {
|
|
62
59
|
id: uploadId,
|
|
63
|
-
exists: () => Boolean(findUploadSkeleton(
|
|
60
|
+
exists: () => Boolean(findUploadSkeleton(getState().doc, uploadId)),
|
|
64
61
|
replaceWith: (content, options = {}) => {
|
|
65
|
-
const
|
|
62
|
+
const state = getState();
|
|
63
|
+
const target = findUploadSkeleton(state.doc, uploadId);
|
|
66
64
|
if (!target)
|
|
67
65
|
return false;
|
|
68
66
|
if (!content?.type)
|
|
69
67
|
return false;
|
|
70
68
|
let nextNode;
|
|
71
69
|
try {
|
|
72
|
-
nextNode =
|
|
70
|
+
nextNode = state.schema.nodeFromJSON(content);
|
|
73
71
|
}
|
|
74
72
|
catch {
|
|
75
73
|
return false;
|
|
76
74
|
}
|
|
77
|
-
const tr =
|
|
75
|
+
const tr = state.tr.replaceWith(target.pos, target.pos + target.node.nodeSize, nextNode);
|
|
78
76
|
if (options.select ?? true) {
|
|
79
77
|
const nodeSelection = tryCreateNodeSelection(tr.doc, target.pos);
|
|
80
78
|
if (nodeSelection)
|
|
@@ -84,16 +82,17 @@ export function insertUploadSkeleton(editor, { kind = 'block', height = defaultH
|
|
|
84
82
|
return true;
|
|
85
83
|
},
|
|
86
84
|
remove: () => {
|
|
87
|
-
const
|
|
85
|
+
const state = getState();
|
|
86
|
+
const target = findUploadSkeleton(state.doc, uploadId);
|
|
88
87
|
if (!target)
|
|
89
88
|
return false;
|
|
90
89
|
const removeFrom = target.pos;
|
|
91
90
|
let removeTo = target.pos + target.node.nodeSize;
|
|
92
|
-
const nextNode =
|
|
91
|
+
const nextNode = state.doc.nodeAt(removeTo);
|
|
93
92
|
if (nextNode?.type.name === 'paragraph' && nextNode.content.size === 0) {
|
|
94
93
|
removeTo += nextNode.nodeSize;
|
|
95
94
|
}
|
|
96
|
-
editor.view.dispatch(
|
|
95
|
+
editor.view.dispatch(state.tr.deleteRange(removeFrom, removeTo));
|
|
97
96
|
return true;
|
|
98
97
|
}
|
|
99
98
|
};
|