I’m using ProseMirror to build an editor for our CMS. When pasting multimedia, it should check whether it’s already hosted by the CMS, and if that’s not true, it should fetch the media and re-upload it to the CMS to keep it self-contained.
So far, I got this:
// Sube los multimedia que no están todavía en ActiveStorage.
export const autoUploadPlugin = new Plugin({
appendTransaction(_, __, newState) {
let tr = newState.tr;
let multimediaToCheck: { node: ProsemirrorNode; pos: number }[] = [];
newState.doc.descendants((node, pos) => {
if (node.type.name === "multimedia")
multimediaToCheck.push({ node, pos });
});
for (const { node, pos } of multimediaToCheck) {
if (!node.attrs.src.startsWith(activeStorageEndpoint)) {
const point = insertPoint(
newState.doc,
pos,
newState.schema.nodes.multimedia
);
const id = {};
tr.setMeta(placeholderPlugin, { add: { id, pos: point } }).delete(
pos,
pos + 1
);
fetch(node.attrs.src)
// TODO: handlear
.then((res) => res.blob())
.then(async (blob) => {
const url = await uploadFile(blob);
const placeholderPos = findPlaceholder(newState, id);
// si se borró el placeholder, no subir imágen
if (placeholderPos == null) return;
const node = newState.schema.nodes.multimedia.createChecked({
src: url,
kind: mimeToKind(blob.type),
});
// ###### this clearly doesn't work because we don't have `view` here.
view.dispatch(
view.state.tr
.replaceWith(placeholderPos, placeholderPos, node)
.setMeta(placeholderPlugin, { remove: { id } })
);
})
.catch((err) => console.error("No pude fetchear el src", err));
}
}
return tr;
},
});
Instead, I am considering handling this in a handlePaste
. However, this won’t work when other methods (like dropping) are used. I think this might be fine though, but I’m not sure. Is there a way to do this with appendTransaction
or something similar? Is using handlePaste
reasonable?