Ordered list continue numbering

Hi All,

I’m trying to implement a feature that allows users to “continue” the numbering of an ordered list. For example:

<ol>
  <li>One</li>
  <li>Two</li>
<ol>
<p>Inbetween</p>
<ol start="3">
  <li>Three</li>
  <li>Four</li>
</ol>

Would result in:

1. One
2. Two
Inbetween
3. Three
4. Four

Ideally, users can toggle whether a given <ol> should “continue” or not and the start attribute should be computed automatically.

Previously we had implemented the feature using CSS counters, but we are no longer able to use them so I’m looking for an alternative.

Would there be a good way to write a plugin so that I can compute the start attribute of a given <ol>?

Thanks.

If this would be an attribute on the list node type (opting in to continued numbering), you could have a plugin with an appendTransaction hook check for inconsistent numbering and patch it up after every transaction, I guess.

This how I handle both a table of contents node and footnotes and it works well, but as Marijn warned in a different thread, you’ll have to watch out for race conditions between plugins. Here’s a simplified version of our footnotes plugin if that’s helpful.

import {Plugin} from "prosemirror-state"

// Search out all Footnote nodes and make sure they're numbered correctly
let findTheFoot = (state) => {
  let counter = 0;
  let transaction = state.tr

  state.doc.descendants((node, pos) => {
    if(node.type.name !== 'apm_footnote') return true
    counter = counter + 1

    if (node.attrs.number !== counter) {
      let newAttrs = Object.assign({}, node.attrs, { number: counter } )
      transaction.setNodeMarkup(pos, null, newAttrs)
    }

    return true;
  })

  if (transaction.docChanged) return transaction
}

export function createFootNotesPlugin() {
  return new Plugin({
    appendTransaction: (transactions, oldState, newState) => {
      // bail if no change
      if (transactions.find(tr => tr.docChanged )){
        return findTheFoot(newState)
      }
    }
  })
}

Thanks! This looks like it could solve my problem.

@marijn can you comment on the “race conditions”? I wouldn’t normally expect to deal with race conditions in a JS library. Is there something I need to be aware of/look out for?

I think what was meant is infinite loops where two plugins keep reacting to each other’s appended transactions by appending more transactions.

I think what was meant is infinite loops where two plugins keep reacting to each other’s appended transactions by appending more transactions.

Yep, my bad.

Fair enough!

What would be best practice to try and prevent this? I only really need to run the plugin code when a new <li> is created or when an <ol> is toggled, and the code only needs to affect sibling lists (it doesn’t need to traverse the document tree).

Is it reasonable to inspect the transactions to try and determine what changes were made?

Yes, that’s exactly how to do this.