Puzzling behavior with a simple schema/keymap

I’m running into some surprising behavior in a simple ProseMirror editor. I suspect the bug is on my end, but after a few days of tinkering I can’t seem to figure it out so I wanted to ask here.

I’m trying to craft an editor in which pressing Enter will insert a new item after the selection and move the selection to the new item. This is with the following schema:

  • a doc consists of one or more items (item+)
  • an item consists of a note (note)
  • a note contains text (text*)

Here’s what happens when I press Enter four times:

Kapture 2021-09-23 at 15.06.46

The cursor moves on the third of every four Enter presses, and two list items are inserted instead of one on every fourth Enter press.

I have a minimal reproduction here in an Observable notebook.

Here’s the single keymap entry:

Enter: (state, dispatch) => {
  let sel = state.selection, { $from, $to } = sel;
  if (dispatch) {
    let type = schema.nodes.item;
    let tr = state.tr.insert($to.pos, type.createAndFill());
    tr.setSelection(PM.State.TextSelection.create(tr.doc, $to.pos + 1));
  return true;

Inserting a full node in the middle of another node of the same type will (unless the node can contain itself) split the outer node in two and insert the new one between the halves, which indeed produces two more nodes than the original document had. You may want to use Transform.split instead here.

The unpredictable behavior may be caused by your code creating invalid TextSelections (they should always point at an inline position, which isn’t being guaranteed here, since $to.pos + 1 is likely going to point after the end of the first half of the split block).

1 Like