tr.setNodeMarkup() fails to update node attribute on a first call

I have a certain node type : editorTitle with an attribute ‘data-before-content’ which sets its value as a kind of “placeholder” in the node’s related dom element. (Actually the trick is done with the following css content rule)

    div.editorTitleCls::before {
      content: attr(data-before-content);

When initially the editor content is empty (in my code i set the initial content in this variable):

let textPageContent = ‘’

the ‘Untitled item’ placeholder will be displayed and once i started change the node inner text using the keyboard , the placeholder will vanish (in this case the update with tr.setNodeMarkup() works fine).

But if the initial content is not empty :

let textPageContent = <div class="editorTitleCls" data-before-content=""><p>I'm a title</p></div>;

Then intially no placeholder is displayed and and once i erase all the content (with SUPPR or backspace keys…) then the placeholder won’t be displayed (this is the bug)

It’s strange because i noticed that even the node’s toDom function will run but the placeholder won’t show

When later i repeate writting and erasing the content , the node will be updated correctly and the placeholder will be displayed when it should

This is a visual demo for the bug

In this codesandbox i could reproduce the bug which happens on a first call to tr.setNodeMarkup() after changing the content

toDOM isn’t dynamic, and won’t be re-run when the node’s content changes. A node view can do this though (that will have its update method called every time the node’s content changes).

Drawbacks of using a node view is having its dom isolated and out of prosemirror control.

One of my needs is to insert emoji in cursor position and i couldn’t achieve it inside a node view. The emoji will always be inserted on pos 0 of the node view…

Another alternative i have tried was to use another prosemirror editor nested but as i factorized the code that generates both the inner and outer editors i got much confusions as they will trigger same event and transactions handlers and it was hard to know which editor have triggered each handler. Besides the fact that any transaction that occurs in the inner editor will be handled by both of them as it’s nested. So i stopped trying with that solution.

And anyway , even if i use a nested editor , i ll have the same schema structure on it as the one in the codesandbox and i guess i ll finally get the same bug.

I wonder why such as clean and simple solution of using just a custom node isn’t supposed to work well all the time.It does work well as the node gets updated all the time but just not in the bug scenario!

And I wonder why using a custom node with few custom attributes and a prosemirror usual method for updating it seems against prosemirror philosophy!

That doesn’t sound right. If the node view has a contentDOM property its content will be managed by ProseMirror.