Domobserver / parseRange bug?

Hi,

i’m programmatically inserting DOM in a nodeView’s contentDOM. I can’t do otherwise because that nodeView is actually a custom element that fills its content itself using remote data, and that cannot depend on prosemirror. Also i would like to avoid having two paths to fill its content (one for frontend DOM, one for prosemirror editor). Anyway let’s say that contentDOM is at position 16 in the document: var ref = view.docView.parseRange(16, 16) returns that ref:

from: 0
fromOffset: 0
node: div.mycontent
to: 0
toOffset: 1

and parseBetween then goes on to reparse the whole document. If i manually set during a debug session ref.from = ref.to = 16, parseBetween properly parses only div.mycontent.

So i figured it’s some bug, but i’m not sure it is on my end or in prosemirror-view.

Is it possible that https://github.com/ProseMirror/prosemirror-view/blob/ad82ca8b5cae01fbaebfab158124d504eadba72b/src/viewdesc.js#L270 needs to re-add base to from and to before returning ? Following code from = base + offset and to = base + end suggests so. `

Does this patch help for you?

Yes, a great improvement.

However there is still something missing when it comes to the parse context:

Let’s say i append some DOM node (type C) inside a contentDOM of a nodeView (type B), which itself is in the contentDOM of a parent nodeView (type A), and let’s say type C has a parseRule.context = "A/B/":

  • parseBetween defines topNode to be the one with type B
  • context.matchesContext finds parseRule and checks added C node is in B/
  • then continues to check it is in A/B/ but fails because A is “out of reach”.

and the appended DOM node is ignored.

Note about multi-level context expresssion like described above: i happened to use it only in one place, and even there it wasn’t strictly necessary. Finding this problem was pure (bad) luck !

Update: i see something odd happening when i do several user-triggered insertions of identical DOM nodes.

The first one works all right but not the second one (invalid content). Am trying to see what’s wrong.

Update 1: problem appears only when inserted DOM nodes are contiguous, not when they are separated by some preexisting node. I suspect something’s happening with the nodeView update method.

Update 2: i’m narrowing it down to what might be a mistake in patched parseRange: when there is A containing multiple type B nodes, and one new DOM node (parsable as type B) is appended, parseRange returns a from position pointing at the start of the (n-1) node (the last node before a new one was appended). This looks odd, and the parsed slice then contains two type B nodes instead of one. I’d guess there is an issue with the inequalities in https://github.com/ProseMirror/prosemirror-view/blob/379a5f743b1fd486551db8a4b9296f4a87b997b4/src/viewdesc.js#L278.

Edit: for example if a DOM node is added at position 57 (with node size being 9), parseRange returns 48, 57: with those values the code that follows will parse the two last DOM nodes instead of just the one that was added.

Update 3: more details !

  • when i insert one DOM node amongs a collection of identical nodes, parseBetween parses actually two DOM nodes (one that was already there, and the one inserted)
  • in readDOMChange, compare contains the new node and findDiff then proceeds on comparing [oldReparsedNode] with [oldLiveNode, newNode]
  • unfortunately oldLiveNode is rather complicated and has children with attributes that are not recreated on parsing the same node. Hence instead of jumping to the right pos, findDiff finds same inner contents between oldLiveNode and oldReparsedNode, and returns a bad position.

I am going to try work around that in my own code, however i find it odd that parseBetween does not position itself directly before the new inserted node.

Conclusion: after having dealt more properly with my bug it now works properly, and that’s cool.