@verdant-web/tiptap 2.0.0 → 2.1.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/esm/__browserTests__/react.test.js +65 -3
- package/dist/esm/__browserTests__/react.test.js.map +1 -1
- package/dist/esm/extensions/NodeId.d.ts +2 -0
- package/dist/esm/extensions/NodeId.js +66 -0
- package/dist/esm/extensions/NodeId.js.map +1 -0
- package/dist/esm/{plugins.d.ts → extensions/Verdant.d.ts} +0 -1
- package/dist/esm/{plugins.js → extensions/Verdant.js} +2 -75
- package/dist/esm/extensions/Verdant.js.map +1 -0
- package/dist/esm/extensions/VerdantMedia.d.ts +30 -0
- package/dist/esm/extensions/VerdantMedia.js +261 -0
- package/dist/esm/extensions/VerdantMedia.js.map +1 -0
- package/dist/esm/fields.d.ts +1 -0
- package/dist/esm/fields.js +5 -0
- package/dist/esm/fields.js.map +1 -1
- package/dist/esm/index.d.ts +3 -1
- package/dist/esm/index.js +3 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/react.d.ts +4 -2
- package/dist/esm/react.js +12 -4
- package/dist/esm/react.js.map +1 -1
- package/package.json +5 -4
- package/src/__browserTests__/fixtures/cat.jpg +0 -0
- package/src/__browserTests__/fixtures/cat.m4a +0 -0
- package/src/__browserTests__/fixtures/cat.mp4 +0 -0
- package/src/__browserTests__/react.test.tsx +105 -4
- package/src/extensions/NodeId.ts +67 -0
- package/src/{plugins.ts → extensions/Verdant.ts} +1 -80
- package/src/extensions/VerdantMedia.ts +299 -0
- package/src/fields.ts +6 -0
- package/src/index.ts +3 -1
- package/src/react.ts +22 -9
- package/dist/esm/plugins.js.map +0 -1
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { mergeAttributes, Node } from '@tiptap/core';
|
|
2
|
+
import {
|
|
3
|
+
EntityFile,
|
|
4
|
+
EntityFileSnapshot,
|
|
5
|
+
id,
|
|
6
|
+
ObjectEntity,
|
|
7
|
+
} from '@verdant-web/store';
|
|
8
|
+
|
|
9
|
+
export type VerdantMediaFileMap = ObjectEntity<
|
|
10
|
+
Record<string, File>,
|
|
11
|
+
Record<string, EntityFile | null>,
|
|
12
|
+
Record<string, EntityFileSnapshot>
|
|
13
|
+
>;
|
|
14
|
+
export interface VerdantMediaExtensionOptions {
|
|
15
|
+
fileMap: VerdantMediaFileMap;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
declare module '@tiptap/core' {
|
|
19
|
+
interface Commands<ReturnType> {
|
|
20
|
+
verdantMedia: {
|
|
21
|
+
/**
|
|
22
|
+
* Add a file to the editor content.
|
|
23
|
+
* @param file The file to add.
|
|
24
|
+
* @example
|
|
25
|
+
* editor
|
|
26
|
+
* .commands
|
|
27
|
+
* .insertMedia({ src: 'https://tiptap.dev/logo.png', alt: 'tiptap', title: 'tiptap logo' })
|
|
28
|
+
*/
|
|
29
|
+
insertMedia: (file: File) => ReturnType;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const fileIdAttribute = 'data-verdant-file';
|
|
35
|
+
export const VerdantMediaExtension = Node.create<VerdantMediaExtensionOptions>({
|
|
36
|
+
name: 'verdant-media',
|
|
37
|
+
group: 'block',
|
|
38
|
+
draggable: true,
|
|
39
|
+
addOptions() {
|
|
40
|
+
return {
|
|
41
|
+
fileMap: null as any,
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
addAttributes() {
|
|
45
|
+
return {
|
|
46
|
+
[fileIdAttribute]: {
|
|
47
|
+
default: null,
|
|
48
|
+
},
|
|
49
|
+
alt: {
|
|
50
|
+
default: null,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
parseHTML() {
|
|
55
|
+
return [
|
|
56
|
+
{
|
|
57
|
+
tag: `[${fileIdAttribute}]`,
|
|
58
|
+
getAttrs: (element) => {
|
|
59
|
+
const fileId = element.getAttribute(fileIdAttribute);
|
|
60
|
+
return {
|
|
61
|
+
[fileIdAttribute]: fileId,
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
},
|
|
67
|
+
renderHTML(props) {
|
|
68
|
+
const fileId = props.node.attrs[fileIdAttribute];
|
|
69
|
+
if (!fileId) {
|
|
70
|
+
return ['div', props.HTMLAttributes, 'Missing file'];
|
|
71
|
+
}
|
|
72
|
+
const file = this.options.fileMap.get(fileId);
|
|
73
|
+
if (!file) {
|
|
74
|
+
return ['div', props.HTMLAttributes, 'Missing file'];
|
|
75
|
+
}
|
|
76
|
+
if (file.loading) {
|
|
77
|
+
// this means the user didn't preload files before rendering...
|
|
78
|
+
return [
|
|
79
|
+
'div',
|
|
80
|
+
props.HTMLAttributes,
|
|
81
|
+
'Loading file. This file was not preloaded before rendering the document.',
|
|
82
|
+
];
|
|
83
|
+
}
|
|
84
|
+
const type = file.type;
|
|
85
|
+
if (type?.startsWith('image/')) {
|
|
86
|
+
return ['img', mergeAttributes({ src: file.url }, props.HTMLAttributes)];
|
|
87
|
+
} else if (type?.startsWith('video/')) {
|
|
88
|
+
return [
|
|
89
|
+
'video',
|
|
90
|
+
mergeAttributes({ src: file.url }, props.HTMLAttributes),
|
|
91
|
+
];
|
|
92
|
+
} else if (type?.startsWith('audio/')) {
|
|
93
|
+
return [
|
|
94
|
+
'audio',
|
|
95
|
+
mergeAttributes({ src: file.url }, props.HTMLAttributes),
|
|
96
|
+
];
|
|
97
|
+
} else {
|
|
98
|
+
// TODO: render file download
|
|
99
|
+
return ['div', props.HTMLAttributes, 'Unsupported file type'];
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
onBeforeCreate() {
|
|
103
|
+
this.editor.on('paste', (event) => {
|
|
104
|
+
const files = Array.from(event.event.clipboardData?.files ?? []);
|
|
105
|
+
if (files.length === 0) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
for (const file of files) {
|
|
109
|
+
this.editor.chain().insertMedia(file).run();
|
|
110
|
+
}
|
|
111
|
+
event.event.preventDefault();
|
|
112
|
+
});
|
|
113
|
+
this.editor.on('drop', (event) => {
|
|
114
|
+
const files = Array.from(event.event.dataTransfer?.files ?? []);
|
|
115
|
+
if (files.length === 0) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
for (const file of files) {
|
|
119
|
+
this.editor.chain().insertMedia(file).run();
|
|
120
|
+
}
|
|
121
|
+
event.event.preventDefault();
|
|
122
|
+
});
|
|
123
|
+
this.editor.on('update', ({ transaction }) => {
|
|
124
|
+
const fileIds = new Set<string>();
|
|
125
|
+
transaction.doc.forEach((node) => {
|
|
126
|
+
if (node.attrs[fileIdAttribute]) {
|
|
127
|
+
fileIds.add(node.attrs[fileIdAttribute]);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
transaction.before.forEach((node) => {
|
|
131
|
+
const fileId = node.attrs[fileIdAttribute];
|
|
132
|
+
if (fileId && !fileIds.has(fileId)) {
|
|
133
|
+
// the file was removed from the document
|
|
134
|
+
this.options.fileMap.delete(fileId);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
},
|
|
139
|
+
addCommands() {
|
|
140
|
+
return {
|
|
141
|
+
insertMedia:
|
|
142
|
+
(file: File) =>
|
|
143
|
+
({ commands }) => {
|
|
144
|
+
const fileId = id();
|
|
145
|
+
this.options.fileMap.set(fileId, file);
|
|
146
|
+
return commands.insertContent(
|
|
147
|
+
{
|
|
148
|
+
type: this.name,
|
|
149
|
+
attrs: {
|
|
150
|
+
[fileIdAttribute]: fileId,
|
|
151
|
+
},
|
|
152
|
+
} as any,
|
|
153
|
+
{
|
|
154
|
+
updateSelection: false,
|
|
155
|
+
},
|
|
156
|
+
);
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
},
|
|
160
|
+
addNodeView() {
|
|
161
|
+
return ({ node, HTMLAttributes, extension }) => {
|
|
162
|
+
// create a root div to house all content
|
|
163
|
+
const root = document.createElement('div');
|
|
164
|
+
// we don't want users editing this content
|
|
165
|
+
root.setAttribute('contenteditable', 'false');
|
|
166
|
+
// attach any existing attributes if they are not null
|
|
167
|
+
Object.entries(HTMLAttributes).forEach(([key, value]) => {
|
|
168
|
+
if (value !== null) {
|
|
169
|
+
root.setAttribute(key, value as string);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// get the file ID from attrs
|
|
174
|
+
const fileId = node.attrs[fileIdAttribute];
|
|
175
|
+
if (!fileId) {
|
|
176
|
+
root.textContent = 'Missing file';
|
|
177
|
+
return {
|
|
178
|
+
dom: root,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// look up the file in the file map
|
|
183
|
+
// NOTE: for convenience/typing, "this" is used
|
|
184
|
+
// here, but in a userland node view you'd use `extension`.
|
|
185
|
+
const file = this.options.fileMap.get(fileId);
|
|
186
|
+
|
|
187
|
+
// this is a helper function to reconstruct the DOM
|
|
188
|
+
// whenever the file changes
|
|
189
|
+
function updateRootContent() {
|
|
190
|
+
// clear the DOM
|
|
191
|
+
root.innerHTML = '';
|
|
192
|
+
if (file) {
|
|
193
|
+
// minimal loading state
|
|
194
|
+
if (file.loading) {
|
|
195
|
+
root.textContent = 'Loading...';
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// minimal error state
|
|
200
|
+
if (file.failed) {
|
|
201
|
+
root.textContent = 'Failed to load file';
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// it's unlikely we get here without a url
|
|
206
|
+
// but just in case
|
|
207
|
+
const url = file.url;
|
|
208
|
+
if (!url) {
|
|
209
|
+
root.textContent = 'Failed to load file';
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// based on the file type, we try to render
|
|
214
|
+
// a useful DOM representation
|
|
215
|
+
const type = file.type;
|
|
216
|
+
if (type?.startsWith('image/')) {
|
|
217
|
+
const img = document.createElement('img');
|
|
218
|
+
img.src = file.url;
|
|
219
|
+
root.appendChild(img);
|
|
220
|
+
} else if (type?.startsWith('video/')) {
|
|
221
|
+
const video = document.createElement('video');
|
|
222
|
+
video.src = file.url;
|
|
223
|
+
video.controls = true;
|
|
224
|
+
root.appendChild(video);
|
|
225
|
+
} else if (type?.startsWith('audio/')) {
|
|
226
|
+
const audio = document.createElement('audio');
|
|
227
|
+
audio.src = file.url;
|
|
228
|
+
audio.controls = true;
|
|
229
|
+
root.appendChild(audio);
|
|
230
|
+
} else {
|
|
231
|
+
const a = document.createElement('a');
|
|
232
|
+
a.href = file.url;
|
|
233
|
+
a.textContent = 'Download';
|
|
234
|
+
root.appendChild(a);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// if the file is not in the file map, we subscribe to changes
|
|
240
|
+
// to its key in the map, and update the DOM when it changes.
|
|
241
|
+
if (!file) {
|
|
242
|
+
const unsub = this.options.fileMap.subscribeToField(
|
|
243
|
+
fileId,
|
|
244
|
+
'change',
|
|
245
|
+
(file) => {
|
|
246
|
+
if (!file) return;
|
|
247
|
+
// we can unsub after the first change, all further
|
|
248
|
+
// changes can be monitored on the file itself.
|
|
249
|
+
unsub();
|
|
250
|
+
file.subscribe('change', updateRootContent);
|
|
251
|
+
updateRootContent();
|
|
252
|
+
},
|
|
253
|
+
);
|
|
254
|
+
root.textContent = 'Missing file';
|
|
255
|
+
return {
|
|
256
|
+
dom: root,
|
|
257
|
+
};
|
|
258
|
+
} else {
|
|
259
|
+
// otherwise, we go ahead and render whatever we have, and
|
|
260
|
+
// subscribe to future changes on the file for further
|
|
261
|
+
// updates.
|
|
262
|
+
updateRootContent();
|
|
263
|
+
file.subscribe('change', updateRootContent);
|
|
264
|
+
return {
|
|
265
|
+
dom: root,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
export function createVerdantMediaExtension(fileMap: VerdantMediaFileMap) {
|
|
273
|
+
return VerdantMediaExtension.configure({ fileMap });
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Preloads all files provided in the file map field. Use of this
|
|
278
|
+
* is highly recommended, if not required, when rendering a document
|
|
279
|
+
* to HTML. TipTap will not wait for files to load, so if they are
|
|
280
|
+
* not preloaded they will be blank in the rendered version.
|
|
281
|
+
*/
|
|
282
|
+
export async function preloadMedia(files: VerdantMediaFileMap) {
|
|
283
|
+
await Promise.all(
|
|
284
|
+
Array.from(files.values()).map((file) => {
|
|
285
|
+
if (!file) return Promise.resolve();
|
|
286
|
+
// since files immediately begin loading on access,
|
|
287
|
+
// we just wait for the file to finish loading
|
|
288
|
+
if (!file.loading) return Promise.resolve();
|
|
289
|
+
return new Promise<void>((resolve) => {
|
|
290
|
+
const unsub = file.subscribe('change', () => {
|
|
291
|
+
if (!file.loading) {
|
|
292
|
+
unsub();
|
|
293
|
+
resolve();
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
}),
|
|
298
|
+
);
|
|
299
|
+
}
|
package/src/fields.ts
CHANGED
package/src/index.ts
CHANGED
package/src/react.ts
CHANGED
|
@@ -6,7 +6,11 @@ import {
|
|
|
6
6
|
VerdantExtensionOptions,
|
|
7
7
|
type EntitySnapshot,
|
|
8
8
|
type ValidEntityKey,
|
|
9
|
-
} from './
|
|
9
|
+
} from './extensions/Verdant.js';
|
|
10
|
+
import {
|
|
11
|
+
VerdantMediaExtension,
|
|
12
|
+
VerdantMediaFileMap,
|
|
13
|
+
} from './extensions/VerdantMedia.js';
|
|
10
14
|
|
|
11
15
|
export function useSyncedEditor<
|
|
12
16
|
Ent extends AnyEntity<any, any, any>,
|
|
@@ -19,11 +23,13 @@ export function useSyncedEditor<
|
|
|
19
23
|
editorDependencies,
|
|
20
24
|
nullDocumentDefault,
|
|
21
25
|
extensionOptions,
|
|
26
|
+
files,
|
|
22
27
|
}: {
|
|
23
28
|
editorOptions?: UseEditorOptions;
|
|
24
29
|
editorDependencies?: any[];
|
|
25
30
|
nullDocumentDefault?: EntitySnapshot<Ent, Key>;
|
|
26
31
|
extensionOptions?: Partial<VerdantExtensionOptions>;
|
|
32
|
+
files?: VerdantMediaFileMap;
|
|
27
33
|
} = {},
|
|
28
34
|
) {
|
|
29
35
|
const cachedOptions = useRef({
|
|
@@ -36,13 +42,20 @@ export function useSyncedEditor<
|
|
|
36
42
|
};
|
|
37
43
|
// create a configured version of the Verdant extension, which handles
|
|
38
44
|
// the actual syncing of the editor content to the field
|
|
39
|
-
const [
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
const [extensions] = useState(() =>
|
|
46
|
+
[
|
|
47
|
+
VerdantExtension.configure({
|
|
48
|
+
parent,
|
|
49
|
+
fieldName: fieldName as string | number,
|
|
50
|
+
nullDocumentDefault,
|
|
51
|
+
...extensionOptions,
|
|
52
|
+
}),
|
|
53
|
+
files
|
|
54
|
+
? VerdantMediaExtension.configure({
|
|
55
|
+
fileMap: files,
|
|
56
|
+
})
|
|
57
|
+
: undefined,
|
|
58
|
+
].filter((v) => !!v),
|
|
46
59
|
);
|
|
47
60
|
const editor = useEditor(
|
|
48
61
|
{
|
|
@@ -50,7 +63,7 @@ export function useSyncedEditor<
|
|
|
50
63
|
onContentError(props) {
|
|
51
64
|
console.error('Content error:', props.error);
|
|
52
65
|
},
|
|
53
|
-
extensions: [
|
|
66
|
+
extensions: [...extensions, ...(extraOptions?.extensions ?? [])],
|
|
54
67
|
},
|
|
55
68
|
editorDependencies,
|
|
56
69
|
);
|
package/dist/esm/plugins.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"plugins.js","sourceRoot":"","sources":["../../src/plugins.ts"],"names":[],"mappings":"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"}
|