How to insert a paragraph containing an image with prosemirror

Hello Prosemirror! I’d like to insert a paragraph with an image inside, so the ultimate markup will be:

<p>
  <img />
</p>

Is there an example of creating a nested insertion anywhere? Any pointers would be very helpful!

Here’s what I’m using right now, which just inserts an image (as opposed to an image wrapped in a paragraph, which is what I want):

const { tr } = state;
const url = 'https://via.placeholder.com/45x30';
const node = schema.nodes.image.create({src: url});
if (node) {
  const _tr = tr.replaceSelectionWith(node);
  dispatch(_tr.scrollIntoView());
}

How can I modify this to wrap my image in a paragraph?

Okay, this wraps the image in a paragraph, but also inserts a blank paragraph before the new image + paragraph:

const { tr, selection } = state;
const from = selection.from;
const node = schema.nodes.image.create({src: input?.value});
if (node) {
  const _tr = tr.replaceSelectionWith(node).insert(from, schema.node('paragraph'));
  dispatch(_tr.scrollIntoView());
}

How to remove that blank paragraph…

Depending on your image schema definition (whether its inline or not), wouldnt the paragraph be created automatically (if inline), in order to preserve the schema? @marijn

Do you know how I can specify that I want images to always be block?

https://prosemirror.net/docs/ref/#model.SchemaSpec

Check out inline attribute

Here is the default image node schema

The default schema has inline: true (also read the spec on groups as you’ll likely need to override that attribute list as well.

If you only go with that, I don’t think you’ll be able to insert images next to text. Curious how it goes though. (If you decide to keep the inline image type in parallel, you’ll have to worry about converting back and forth.)

Friendly suggestion to think more about what you really what the user to be able to do before overriding the attribute. It’s quite likely you should just work on implementing the programmatic insertion / wrapped with paragraph (if required, desired by user)

1 Like

I meet this problem too when I would like to insert a block with paragraph inside. Instead of using some given functions , for example “wrap”, I create a node Json to describe the node to insert.

export const createNotice = (schema: Schema, attrs): ProsemirrorNode => {
  const noticeJson = { "type": "container_notice", "attrs": attrs, "content": [{ "type": "paragraph" }] }
  return ProsemirrorNode.fromJSON(schema, noticeJson);
}

It may be a little difficult to create a complicated node in ProseMirror by given APIs, while we are not familiar with them. But we can do this easily with json object, which can be changed to whatever we want.

For this question, A easy way to do this is as follow.

export const createParagraphWithImage = (schema: Schema, url): ProsemirrorNode => {
  const paragraphJson = { "type": "paragraph", "content": [{ "type": "image", "attrs": {"url": url}}] }
  return ProsemirrorNode.fromJSON(schema, paragraphJson);
}