Copy pasting html that doesn't contain a block node strips marks away


#1

Another bug report here. I noticed that pm doesn’t add marks properly to text that was copy pasted from outside of pm, if the html didn’t have a wrapper block node.

So if pasted html was something like <strong>foo<strong>, strong is not applied to foo when pasted. This doesn’t happen if html had wrapping block nodes (<p><strong>foo</strong></p>) which doesn’t happen frequently unless you had copied multiple blocks.

The bug is easily reproducible as this happens consistently. Gif added to showcase the bug. The console is showing clipboard data on paste.

Not sure if this is really the offending code, but just fyi - I see that the call this.top.addMark doesn’t add the new marks because the node context doesn’t have type:

  addMark(mark) {
    let old = this.activeMarks
    if (this.type && this.type.allowsMarkType(mark.type))
      this.activeMarks = mark.addToSet(old)
    return old
  }

#2

This was a regression since prosemirror-model 1.4.1. I’ve released 1.4.3 with a fix.


#3

I was just trying to upgrade from 1.4.0 to 1.4.3, but I’m still seeing a regression in my tests. The code looks something like this:

const wrapper = new JSDOM().window.document.createElement('div')
wrapper.innerHTML = '<a href="https://www.example.com">Example</a>'
const parser = DOMParser.fromSchema(schema)
const node = parser.parse(wrapper)

With 1.4.0 I get the expected result with a link mark:

{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","marks":[{"type":"link","attrs":{"href":"https://www.example.com","title":null}}],"text":"Example"}]}]}

With 1.4.3 the link mark is missing:

{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"Example"}]}]}

#4

That’s a different problem, but yeah, I’ve released 1.4.4 with a fix.


#5

awesome, thank you for the fast fix!


#6

That was fast, thanks so much!


#7

Hi, I think I have another repro for this behaviour. If HTML with two paragraphs is pasted into PM, any marks that are on the second paragraph itself are lost. This does not happen if the marks end up on the text nodes instead, so PM to PM copy-paste does not trigger this issue.

Debugging I got as far as when constructing the replaceStep, Frontier.prototype.placeContent closes the current paragraph and call open.parent.type.allowedMarks. Now open.parent is the doc node, and it simply rejects all marks of the child node.

Example of HTML losing the italic mark:

<div>Normal</div>
<div><i>Italics</i></div>

Cheers!


#8

I think this patch takes care of that case.


#9

Excellent, thanks!