Splitting a todo list item

I have a custom todo list item spec, which looks almost identical to the list item from prosemirror-schema-list. The only difference is that it has an attribute:

  attrs: {
    done: { default: false },
  },

When splitting this item with the standard split function, it basically works, with the unwanted side effect that the item’s done state is copied over. When splitting a done todo, the todo that is created on the next line is also done, which is not exactly userfriendly. Another usecase is, that when splitting right at the beginning of the paragraph of that item, the original item shall be made undone, while the newly created item shall inherit the done state.

To work around that, i copy-pasted the splitListItem and made a little tweak. Here’s the relevant part (my modification starts at the comment “modification start”):

    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}] : undefined
    if (!canSplit(tr.doc, $from.pos, 2, types)) return false

    // modification start
    const isAtStartOfParagraph = $from.parentOffset === 0

    if (isAtStartOfParagraph) {
      tr = tr.setNodeMarkup($from.pos - 2, null, {done: false})
    } 

    const done = isAtStartOfParagraph ? grandParent.attrs.done : false

    types = nextType 
      ? [
          {type: itemType, attrs: { done }} as any, 
          {type: nextType}
        ] 
      : [
          {type: itemType, attrs: { done }} as any
        ] 
    // modification end

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

This approach basically works, and i have two questions.

Question 1

As you can see, i’m overwriting the types variable, even though it was previously used in the canSplit check. canSplit will return false otherwise. Is my approach ok, or do you have any suggestions how this could be improved?

Question 2

Do you think it would make sense to extend the API of splitListItem so this kind of hack could be avoided? I see two approaches:

  1. The first part of the function is extracted to a separate, reusable function, and exported to the packages’s api
  2. The user of the function could be allowed to pass some kind of option (e.g. a callback function) where the logic i’ve implemented could be executed
2 Likes