Paste paragraph containing br

Hello, Prosemirror community.

I’m working on Copy / Paste feature, and here’s the problem now I ran into. If I try to paste html like this,

<p>
  text
  <br>
  text
</p>

It’s rendered like this in Prosemirror,

<p>
  textext
</p>

and this is what I want it to be

<p>
  text
</p>
<p>
  text
</p>

In other words, I want to split paragraph from where break(br) tag be when copy paste html.

I used preserveWhitespace option, hard_break schema, but non of them work. Any Idea to solve this problem? Thanks.

Making a <br> node start a new paragraph isn’t something that the DOMParser can currently do—you can of course make it insert any node in its place, for example a hard_break node, as I guess you found out, but there’s no way for a parse rule to force the current parent node to be closed.

That might be a good thing to add to the library, but I’m not sure when I’ll have time to work on that.

2 Likes

Thanks for your quick reply. So there’s no option for parseRule to split or close parent Node…

At the end I added simple logic in transformPastedHTML (DirectEditorProps).

transformPastedHTML: (html: string) => {
  return html.replace(/<br[^>]*>/g, '</p><p>')
}

This is not a complete solution but can bypass the problem in some case. It would be great parseRule can accept option.

/* Suggestion */

{
  tag: 'p',
  breakPoint: [
    { tag: 'br' },
  ],
  ... // other options
}

Could you see if this patch works for you?

Sorry for late check. I really appreciate for your work.

But I don’t figure out how to use that option. I set schema like below and try to paste html content, but paragraph is not closed.

const schema = {
  paragraph: {
    content: 'inline*',
    group: 'block',
    parseDOM: [
      { tag: 'p' },
      { tag: 'br', closeParent: true },
    ],
  },
... // toDOM, etc
}
<p>content<br>content<p> -> <p>contentcontent</p>

Is it a wrong place to set closeParent option?

+) I used prosemirror-model@1.10.0

See the test in the patch I linked. You can’t add such a rule to a schema node spec, since it’s not creating any nodes. You have to manually create your DOMParser to include the rule.

1 Like

@marijn Hi, I am handling a similiar problem and find this closeParent rule only be applied for once. Only the first br will close its parent and the rest brs will just disappear. eg <p>a<br>b<br>c</p> will be transformed to <p>a</p><p>bc</p>. Is this expectable?

No, that’s not expected, and that’s not what I see when I test it. I’m getting three paragraph when I parse this with a closeParent rule for <br> nodes.

While testing it, in this patch, you have called closeParser.parse() function, but while pasting content inside the editor, closeParser.parse() function is not called, closeParser.parseSlice() function is called, to be precise exactly this line is getting called.

The problem is parser.parse() function converts <p>one<br>two<br>three<br>four</p> this html to <p>one</p><p>two</p><p>three</p><p>four</p> as expected, but parser.parseSlice function converts the same html to <p>one</p><p>twothreefour</p> which is not what we want. This is the problem that @zunanlee was trying to say, that only the first br will close its parent.

I’m also facing the same issue, while debugging further, I found out that after encountering first br, since closeParent is true, the first paragraph node gets closed, while encountering second br, the text “two” is wrapped inside a text node and the node gets closed, similarly for the successive brs, the text “three” and “four” are wrapped inside text nodes and not paragraph nodes, as a result of which the text “one” is alone in first paragraph and the rest of the text which are all wrapped inside textnodes all go into the same paragraph since they are all only inline nodes.

Could you check this issue @marijn

It actually produces <p>one</p>twothreefour, with the end text not even wrapped in a paragraph, and the clipboard normalizer (I assume) re-wrapped the paragraph to make it insertable in a document.

Because you’re parsing a slice, so there’s no concept of a top node to fit content into, and the parse rule is telling the parser to exit the node it is currently in, leaving you with orphaned top-level text nodes. This isn’t great, but I’m not sure how to change it without doing rather weird things in the parser.