Paste and Decorations

I have set up image uploads in my prosemirror instance (based off the great docs example), which has been expanded to works when files are pasted/dropped into the editor, as well as selected.

I am now looking to expand the functionality to check all clipboard HTML; so that any <img> with src that is data:image/png or a hotlinked url, will be uploaded to the server too.

What I would like to do is insert the clipboard HTML into the editor, replacing invalid <img> with placeholder decorations. When the images have finished uploading, replace the placeholders with the new image nodes. Unfortunately, I’m not sure how to add these decorations, as I’m not sure how to get the img positions in the HTML when I don’t want to add invalid image nodes to the editor state.

Additionally, I am updating my placeholder decorations with upload progress. My current approach is to remove the previous decoration and add a new decoration at the same position with updated %progress. This doesn’t seem to cause any performance issues so far, but repeatedly destroying/creating DOM elements seems a little inelegant. Is there a better way of doing this?

Overriding paste behavior is still a little tricky, since there’s so much going on, but you could write a handlePaste prop that, after inserting the pasted slice, scans for invalid nodes and immediately updates them. Or alternatively, fire a separate transaction directly after the paste event to handle this.

That’s the recommended approach—ProseMirror decorations can’t be updated, only recreated (though if you really care a lot, and make sure you only use each DOM node at one position at a time, you could use the same DOM nodes for the updated widgets).

That’s the recommended approach—ProseMirror decorations can’t be updated, only recreated (though if you really care a lot, and make sure you only use each DOM node at one position at a time, you could use the same DOM nodes for the updated widgets).

For my edification, when you say you can reuse the same DOM nodes for updated widgets, are you referring to returning the same DOM node from the toDOM render function for Decoration.widget()?

static widget(pos: number, toDOM: fn(view: EditorView, getPos: fn() → number) → dom.Node | dom.Node, spec: ?⁠Object) → Decoration

No, I mean passing the node directly, rather than using a render function.

ah, ok. I incorrectly read the docs as passing the node type (E.G. “div”), rather than passing the node itself. Thanks.

Would you mind sharing with me which approach you ended up using? A sample of your code would be incredibly helpful, as I’m currently trying to tackle the same problem in my code.

I’m still confused about the way to do it

I mean, what’s the proper way to do scanning after pasting?