Ordered/Bullet Lists Text Only

I learned you cannot have ordered/bullet lists with text only if you want to allow nested lists. Example:

<ol>
  <li>This is the first</li>
  <li>This is the second
    <ol>
      <li>A sub-second</li>
    </ol>
  </li>
</ol>

The reason is because schema “content” cannot have inline and block items together. You cannot set your list content to “inline<_>* (ordered_list | bullet_list)?”. The solution is simple and works with the existing list commands provided by the schema-list module.

Set your list content to “paragraph (ordered_list | bullet_list)?”. This will ensure only one paragraph per item and optionally a sublist. This keeps headings, blockquotes, and other block types out of your lists (if that is what you want). And you can style “li p { margin: 0 }” so that list paragraphs look like regular content.

<ol>
  <li><p>This is the first</p></li>
  <li><p>This is the second</p>
    <ol>
      <li><p>A sub-second</p></li>
    </ol>
  </li>
</ol>

If you really don’t want a paragraph type inside your list items, you can create your own block type. A div, even a span that you specify as a block in the schema, can work as long as the schema can treat it as a block with text content inside.

Happy listing!

@jacwright I ended up with the same content paragraph (ordered_list | bullet_list)? but it breaks with Backspace: pressing backspace will either create a nested list or select the parent node instead of deleting the node and merging it with the parent.

I don’t have anything bound on the Backspace on my keymaps, are you not running in the same issue?

Edit: just to give more information after looking into it a bit:

The schema has the following:

  ordered_list: add(orderedList, {content: "list_item+", group: "block"}),
  bullet_list: add(bulletList, {content: "list_item+", group: "block"}),
  list_item: add(listItem, {content: "paragraph (ordered_list|bullet_list)?"}),

and everything else is the default. On backspace, the default keymap causes joinBackward of prosemirror-commands to be called which then calls deleteBarrier and then dispatches a transaction with 1 step: ReplaceAroundStep.

The current behaviour of my editor is the following:

  • create a new list
  • write a few chars
  • press Enter to add a new bullet
  • press Backspace: it will indent the bullet point and transform it into an ordered list
  • press Backspace again: it will select the parent list item

The ordered iist seems to come from the content paragraph (ordered_list|bullet_list)? as if I set it to paragraph (bullet_list|ordered_list)? things will work fine, I’m guessing due to the order of the nodes above?

I’ve been in the middle of some refactors and after learning the best way to work with lists in my app I haven’t come back to it. I’m planning on doing thorough testing once everything is in place.

This may be a bug (or more likely a needed enhancement). With how ProseMirror is structured, it is impossible to have sub-lists without the list item text being wrapped in a paragraph. So using paragraphs is a must. But we can create a command to make backspace work correctly. I’m not thrilled with how the default list handling works, but we have the tools to make it work the way we want. I just don’t have time to do it ATM.

After the patch linked in https://github.com/ProseMirror/prosemirror/issues/682, it seems to work perfectly.

EDIT: nevermind, the backspace is still broken I somehow didn’t test that