What’s done

      Added 2 node types called listGroup and listContainer:

        listGroup maps to <ul><ol> and <blockquote> tags and listContainer maps to <li>

        listGroup can contain only listContainers as children

        listContainer is similar to blockContainer, as the first child is mandatory and it can be any blockContent, and the second optional child can be a listGroup or a blockGroup to create indentation

    Schema

      blockGroup: content: 'blockContainer+

      listGroup: content: 'listContainer+

      blockContainer and listContainer: content: 'blockContent (blockGroup | listGroup)? (block content + optional group)

    Complexity

      When interacting with a list, we constantly need to convert between group and container types

        Input rules such as “*” and “1”: Create listGroup with listContainer inside previous blockContainer

        Tab: If inside of a blockContainer but sinking into a listGroup, we need to manually build a listContainer from that blockContainer and insert it. SinkListItem command results in an invalid structure and error.

        Shift Tab: Same as tab, need to manually build and insert instead of liftListItem command.

        Backspace: Same as shift tab if at the start of list/block container or in an empty container

      So the problem is that when converting node types, instead of just using the inbuilt lift or sink commands, we need to correctly calculate and track previous and current group positions and depths, check for siblings inside the current group, check for empty nodes, etc.

      Therefore, every command that touches groups/containers needs awareness of both node types:

        updateGroup.ts: used to update listType and listLevel attributes of blockGroup. Now needs to correctly convert between node types

        nestBlock.ts: has custom sink and lift list item commands. Used with tab, shift-tab, backspace and delete keys

        splitBlock.ts: used with enter key. Command to split text node and insert it as a next node while respecting the group type and depth

        mergeBlocks.ts: used with backspace and delete keys. Command to merge the current block with the previous. Needs to respect container type and depth.

    Pros and cons

      Dedicated list node types:

      Pros:

        Semantically Correct

          Straight mapping to HTML tags (exclusively <ul> and <ol>)

          Easier to debug invalid slices on paste

        Copy/Paste

          ProseMirror default paste handling shouldn’t result in infinite indentation

          Reduces ambiguity when parsing HTML

        Future Flexibility

          We can add list-specific attributes without affecting regular groups

          Can add list-specific commands/plugins

            List node project overview

            What’s done Schema Complexity Pros and cons

            11 February 2026

      Cons:

        Needs to change 7 commands to account for new node types

        Needs thorough testing

        Requires a lot of time

        Risk of introducing bugs