Modifying an img's src before it's rendered?

First, thanks for building ProseMirror. We’re considering using it for V2.

One thing I’m trying to wrap my head around, which maybe someone could point me in the right direction, is how to modify the src attribute of a rendered img node after it’s inserted using the image:insert command.

Here’s my use case: Our CMS UI we’re building supports image uploads, which upload the images directly to a temporary CDN location. When you insert the image into your post though, we insert the image’s relative URL since it will eventually publish directly to your site. What I’m hoping to do is identify any image node with a relative URL and modify the rendered img's src attribute so I can use the CDN url for the preview.

Any tips?

1 Like

You’d use a regular transform, using either setNodeType or replace to put in the image node you want.

I have a somewhat similar question. I’m implementing dropping images in the document, first with data-uris but eventually I might want to do something similar to @sawyer, uploading them and then switching out the URL.

I started to change the drop handler a little, in order to trigger a different event when the dataTransfer object has files, but it’s a bit tricky since the interface is synchronous and the loading of image data is not. Do you have any thoughts on this matter and do you have any plans to implement pasting/dropping of images?

What happens when you register a drop handler, prevent the default behavior, and then, after loading the file finishes, insert the relevant node?

Yeah that’s my second approach, and I’ll try that out now. I hoped to be able to use the drop handler’s insert logic, perhaps by returning a document with the image inserted, and then replacing the src when the file had finished loading.

Sorry for buggering you about this, but do you have any suggestions how to register a drop handler for the content area? Because as it stands, the default drop handler will trigger first and causing all sorts of problems. I may well be missing something here in the editor API.

That’s a good point. This patch adds a drop event that you can use to override the default drop behavior.

Thanks for that, – this works! However, I only seem to be able to insert the image using pm.execCommand(“image:insert”…), and so I have to move the cursor first. How should I go about this, is that a good approach or can I use tr somehow? Any approach I’ve tried (creating node with fromDOM, using new Image().create, …) and then passing that to insertInline and friends, result in no transformation at all (returns false from apply()).

Why is that?, pm.schema.node("image", {ATTRS})).apply() should also work.

What do you know, that works fine! I had missed that method. I tried all kinds of ways to instantiate an image node. Thanks, this is starting to shape up.

@marijn Thanks for the tip. Using that and this I was able to get it somewhat working. The one thing that doesn’t work for me is what @linus seemed to run into, which is the transformation doesn’t apply. The node is definitely getting replaced — when I getContent(), the Node has the updated attributes, however in the rendered DOM, it still has the old attributes. I’ve created a gist for the relevant bit of code:

Any ideas what might be going on?

attrs.src = '';

You’re mutating a value that’s shared with the current document tree. That isn’t allowed, and will confuse the library. Copy the object before changing it.

Ah, that was it, thanks! Will follow up and share the code when it’s all ready.