Action

Renumber Watch Band Collection

Posted by @nahumck, Last update 1 day ago

UPDATES

1 day ago

Moved from Unlisted to Listed.

This action formats a draft that contains a Markdown table for my watch band collection. The code was generated entirely using ClaudeAI (Sonnet 4.5). Whenever I purchase new bands, I’d like to add them to a list in the appropriate category. Additionally, I’d like the list to be automatically renumbered and formatted correctly. This is based on the following parameters:

  1. Column widths are based on the maximum width in that particular column. The script scans the table to make this adjustment first to format the lines correctly.
  2. All columns are padded with spaces to visually look correct using a monospace font in the Drafts editor.

Below is a sample of the draft I have for my watch band collection. For my full collection, you can view it on my website.
- Band Type: this would be things like Sport, Nike Sport, Alpine Loop, Ocean Band, etc.
- Color: you can add special names, years, editions to the color names.
- Release entered by season (Fall, Winter, Spring, Summer) and 4-digit year.

Note: To get the band color names and release years, I recommend using Bandebrite. It’s a great resource for all of this information.

# Watch Band List Example

Here is a table of the current watch bands I own:

| Band Type        | Color          | Release       |
| :--------------: | :------------: | :-----------: |
| **Band Type**    |                |               |
| 01               | Color Number 1 | Season / Year |
| 02               | Color Number 2 | Season / Year |
| 03               | Color Number 3 | Season / Year |
| **Band Type**    |                |               |
| 04               | Color Number 4 | Season / Year |
| 05               | Color Number 5 | Season / Year |
| 06               | Color Number 6 | Season / Year |

Steps

  • script

    /*--- Generated using ClaudeAI ---*/
    
    // Renumber Markdown Table - Drafts Action Script
    
    function renumberMarkdownTable(tableText) {
      const lines = tableText.split('\n');
      let counter = 1;
      
      // Split all lines into columns
      const rows = lines.map(line => {
        if (line.includes('|')) {
          // Split by | and remove first/last empty elements
          const cols = line.split('|').slice(1, -1);
          return cols.map(col => col.trim());
        }
        return null;
      }).filter(row => row !== null);
      
      // Calculate maximum width for each column
      const columnWidths = [];
      if (rows.length > 0) {
        const numColumns = rows[0].length;
        for (let colIndex = 0; colIndex < numColumns; colIndex++) {
          let maxWidth = 0;
          for (let row of rows) {
            if (row[colIndex]) {
              maxWidth = Math.max(maxWidth, row[colIndex].length);
            }
          }
          columnWidths.push(maxWidth);
        }
      }
      
      // Process each line
      const renumberedLines = lines.map(line => {
        // Check if this is a numbered line (starts with | followed by spaces and digits)
        const match = line.match(/^(\|\s*)(\d+)(\s*\|.*)$/);
        
        if (match) {
          // This is a numbered row - extract all columns
          const cols = line.split('|').slice(1, -1).map(col => col.trim());
          
          // Replace first column with new number
          const newNumber = String(counter).padStart(2, '0');
          counter++;
          cols[0] = newNumber;
          
          // Rebuild the line with proper padding for each column
          const paddedCols = cols.map((col, index) => {
            const width = columnWidths[index] || col.length;
            return ' ' + col.padEnd(width, ' ') + ' ';
          });
          
          return '|' + paddedCols.join('|') + '|';
        }
        
        // For separator lines (with dashes), rebuild with proper width
        if (line.includes('---')) {
          const cols = line.split('|').slice(1, -1);
          const separatorCols = cols.map((col, index) => {
            const width = columnWidths[index] || col.trim().length;
            const trimmed = col.trim();
            
            // Check for alignment indicators
            const startsWithColon = trimmed.startsWith(':');
            const endsWithColon = trimmed.endsWith(':');
            
            // Build separator with proper alignment indicators and width
            let separator = '-'.repeat(width);
            if (startsWithColon && endsWithColon) {
              // Center aligned
              separator = ':' + '-'.repeat(width - 2) + ':';
            } else if (startsWithColon) {
              // Left aligned
              separator = ':' + '-'.repeat(width - 1);
            } else if (endsWithColon) {
              // Right aligned
              separator = '-'.repeat(width - 1) + ':';
            }
            
            return ' ' + separator + ' ';
          });
          
          return '|' + separatorCols.join('|') + '|';
        }
        
        // For other table lines (headers, category rows), reformat with consistent padding
        if (line.includes('|')) {
          const cols = line.split('|').slice(1, -1).map(col => col.trim());
          const paddedCols = cols.map((col, index) => {
            const width = columnWidths[index] || col.length;
            return ' ' + col.padEnd(width, ' ') + ' ';
          });
          
          return '|' + paddedCols.join('|') + '|';
        }
        
        // Return unchanged for non-table lines
        return line;
      });
      
      return renumberedLines.join('\n');
    }
    
    // Get the full draft content
    let content = draft.content;
    
    // Find the table in the content
    // Pattern: starts with a line containing | and continues until no more table lines
    const tableRegex = /(\|[^\n]*\|[\s\S]*?)(?=\n\n|\n*$)/;
    const match = content.match(tableRegex);
    
    if (match) {
      const originalTable = match[1];
      const renumberedTable = renumberMarkdownTable(originalTable);
      
      // Replace the original table with the renumbered one
      const newContent = content.replace(originalTable, renumberedTable);
      
      // Update the draft
      draft.content = newContent;
      draft.update();
      
      app.displayInfoMessage("Table renumbered successfully!");
    } else {
      app.displayWarningMessage("No markdown table found in draft");
    }

Options

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