Confused about typesAfter in split, and how to disable attrs inheriting

Hi!

I’m trying to build a list-focused editor.

I managed to use a plugin to generate unique ids for every list_item.

The issue is, when creating a new list item, it inherits the same item_id in attrs.

I tracked the issue to function splitListItem in prosemirror-commands, split in prosemirror-state, and eventually found out about the typesAfter argument.

The thing is, I’m still confused about this typesAfter parameter.

In this line in splitListItem,

    if (dispatch) dispatch(tr.split($from.pos, 2, types).scrollIntoView())

Why is types being [null, {type: paragraph}], and how can I disable the new <li> from inheriting a specific item_id in attrs?

I tried to set types [null, {type: paragraph, attrs: {}] yet it has no effect.

Thanks!

You’ll need to create a custom implementation of splitListItem or chain in a new action for enter keypress that runs custom logic when list items are split. A lot of the code may be similar to the existing splitListItem though.

The null is a special flag for using the existing type / attrs. So if you wanted to create a new ID for the list_item node, you’d do something like:

// In place of `null` in `[null, {type: paragraph}]`, override the inherited attributes for the wrapper node.
[   
   {type: 'list_item', attrs: { id: 'new_id'}},   
   {type: paragraph}   
]

I just checked this out in my code and it looks to be working as expected.

Thank you, good sir, it helps a lot!

Still a little confused about the order of values in typesAfter, gonna do a little more digging into the code.

I hijacked the splitListItem like this

    let nextType = $to.pos == $from.end() ? grandParent.contentMatchAt(0).defaultType : null
    let tr = state.tr.delete($from.pos, $to.pos)

    //let types = nextType && [null, {type: nextType}]
    let types = nextType && [{type: itemType}, {type: nextType}]

    if (!canSplit(tr.doc, $from.pos, 2, types)) return false
    if (dispatch) dispatch(tr.split($from.pos, 2, types).scrollIntoView())

After the change, the canSplit returns false instead of true, still trying to determine the issue.

Yep I saw the same, but got around it (in probably an insecure way) by not using the new attribute syntax for the canSplit check. Seemed relatively safe if the only change is an overridden attribute.

I was going to check this but you could also. Make sure you are adding any required default attributes for the list_item, {type: itemType, attrs: {...}}.

null may just use the existing ones but when passing in a custom value, type and attrs might need to pass some type checks.

Ouch, after the hack, splitting a list item leaves corrupted content

  • foo<press enter here>bar

leaves a

  • foo
  • bar

in the editor, yet the actual value of the doc is like

  • bar
  • bar

Any more clarification on what actually happened @namiwang? What do you mean the document is corrupt? It renders in the EditorView correctly? But when you serialize it is incorrect?

Ah sorry, forgot to update.

That’s a false alarm. There was a bug around handling types which has already been fixed.

But the issue is not solved, I still have to modify types after canSplit check, obviously a dirty hack.