Action

Renumber Lists

Posted by Alexander, Last update 9 months ago

Renumbers and tidies selected Markdown lists.

Features:

  • Unlimited levels.
  • Bullets will be turned into numbers.
  • Wide range of supported formats (even ones not officially supported by Markdown).
  • Works with spaces or tabs.
  • Tidies even messy lists that use different types.

Supported list formats:

4. Item
4: Item
4) Item
(4) Item
[4] Item
D. Item
D: Item
D) Item
(D) Item
[D] Item
IV. Item
IV: Item
IV) Item
(IV) Item
[IV] Item
- Item
+ Item
* Item
• Item

Auto-corrects wrongly formatted list items (e.g., missing space after dot) and removes excess white space characters immediately after the dot. List items must be indented by either 4 spaces or 1 tab per additional level. (The action uses spaces by default but switches to tabs if only a single line is indented using tabs. In that case, lines accidentally indented by spaces will be converted to tabs.)

Steps

  • script

    // Get selected text from draft and split it into lines
    const text = draft.processTemplate('[[selection_only]]')
    const lines = text.split('\n')
    
    // Parameters
    const lines_processed = []
    const lines_final = []
    const counters = []
    let indent = '    '
    let indent_length = 4
    let previous_level = 0
    let i = 0
    
    // Check if at least one line begins with a tab
    for (const line of lines) {
      // If yes, switch the entire action from spaces to tabs
      if (line.match(/^\t/)) {
        indent = '\t'
        indent_length = 1
        break
      }
    }
    
    // Process each list item
    for (let line of lines) {
      // If it's a tabbed list, convert (accidental) indentation by spaces to tabs
      if (indent === '\t') {
        line = line.replace(/^ {4,}/, function (m) { return '\t'.repeat(m.length / 4) })
      }
    
      // Remove all spaces, tabs, and list markers to isolate the content
      const content = line.replace(/^\s*([A-Za-z0-9]+(\.|\)|:)|(\[|\()[A-Za-z0-9]+(\]|\))|-|\+|\*|•) */, '')
    
      // Extract only the indentation characters so we can calculate the level
      const indent_chars = line.replace(/([A-Za-z0-9]+(\.|\)|:)|(\[|\()[A-Za-z0-9]+(\]|\))|-|\+|\*|•).*/, '')
      const level = indent_chars.length / indent_length
    
      // If the current item is outdented compared to the previous one...
      if (level < previous_level) {
        // ... reset the previous level’s counter because that level was concluded
        // (in case there's another indented list on the same level later)
        counters[previous_level] = 0
      }
    
      // Set the current level's counter
      if (counters[level] > 0) {
        counters[level] = counters[level] + 1
      } else {
        counters[level] = 1
      }
    
      // Each list item separated by content, current level, and current count
      lines_processed[i] = [content, level, counters[level]]
    
      previous_level = level
      i++
    }
    
    // Reassemble the original lines array but with correct indentation and numbering
    for (const line of lines_processed) {
      lines_final.push(indent.repeat(line[1]) + line[2] + '. ' + line[0])
    }
    
    // Put the text back together and save it to a template tag
    const text_replacement = lines_final.join('\n')
    draft.setTemplateTag('text_replacement', text_replacement)
  • insertText

    template
    [[text_replacement]]

Options

  • After Success Nothing
    Notification Error
    Log Level Error
Items available in the Drafts Directory are uploaded by community members. Use appropriate caution reviewing downloaded items before use.