How to control gapcursor

Ok, I stepped through it.

bodyNode.contentMatchAt(bodyNode.childCount).findWrapping(schema.nodes.text) does work and give a correct result. But in the replaceStep function it looks for wrapping it into the top node (doc) and not the body node, specified in https://github.com/ProseMirror/prosemirror-transform/blob/master/src/replace.js#L280, and for that it cannot come up with a wrapping node. Should I debug this further?

I am open to other solutions. In our case, we just don’t ever want cursors in the top two levels (doc, article), so the solution just lowers the “ceiling” two levels. I have been thinking about what would happen in cases where say part of the document allows the gapcursor starting level 2 and in other parts in level 3, but I could not come up with a concrete example of where this would be a problem. What do you suggest we do?

Not sure if this directly is the bug – I assume it was meant to find the wrapping within the parent node (body), not the top node (doc). But if it is correct that it is the top node, then the problem is probably that the content definition of the top nodes (doc and article) only allow very specific nodes in a specific order. For doc:

content: "article"

For article:

content: "title subtitle authors abstract keywords body"

Hi Johannes,

I’ve further tweaked the way gap cursors work in an attempt to better fit your use case. The new approach is that they are allowed everywhere where the default content is a textblock. You can still override this with allowGapCursor, but this is needed less often.

Assuming your body allows textblocks, and those appear first in the relevant content expression (i.e. not "(blockquote | paragraph)" but "(paragraph | blockquote)" — and in case they form a group, paragraph appearing first in the schema’s list of nodes), I think the cursor should be appearing the right place now.

1 Like

Thank you! This is much better. In cases where there is a table at the end of the body, it does now work as expected.

One thing that still does not work with this either is placing the caret before the table. So take this situation:

doc(article(title(...),...,keywords(...),body(table(|...))))

The caret is at the beginning of the first cell of a table. The user preses arrow-up or arrow-left to try to add some content within the body node before the table. Instead, the caret jumps into the keywords node. It looks like the user cannot add content into the body node before the table without deleting the table and then later re-adding it.

Right, if there is a textblock directly before the position (i.e. without any non-textblock leaf nodes in the way) the addon doesn’t consider that a valid gapcursor position—it if did, it would also start putting gap cursors at the end of blockquotes and so on, which wouldn’t be good.

I’m not quite sure yet how to address that.

I see. Not entirely sure if this covers it exactly how you envisioned it, but we could for example take the defining attribute as being of higher priority than the fact whether it is a textblock [1]. If defining doesn’t cover it, maybe another attribute?

[1] https://github.com/johanneswilm/prosemirror-gapcursor/commit/a53becce6d5727a3c6679cad3691d210ef745b29