Action

new drafts from list

Posted by @jsamlarose, Last update 2 days ago

Creates a new draft for each line in the current draft, with optional tagging support.
Format:

Title (ignored)
#globalTag1, #globalTag2 (optional — applied to all drafts)
Item one #tag1, #tag2
Item two #tag3
Item three

Rules:
- The first line is treated as a title and ignored.
- If the second line consists entirely of #-prefixed tags (comma or space-separated), those tags are applied to every draft created, and the line itself is not turned into a draft.
- Each subsequent non-empty line becomes a new draft. Any #-prefixed strings after the content are added as tags for that draft, separated by commas or spaces before each #.
- Empty lines are ignored.

Example input:

# Summer Reading List
#reading, #2026
The Left Hand of Darkness, Ursula K. Le Guin #sci-fi, #novel
Citizen: An American Lyric, Claudia Rankine #poetry, #essential
How to Do Nothing, Jenny Odell #non-fiction, #attention
Several Short Sentences About Writing, Verlyn Klinkenborg #craft, #writing
The Hatred of Poetry, Ben Lerner #poetry, #essay
Parable of the Sower, Octavia Butler #sci-fi, #novel
In the Dream House, Carmen Maria Machado #memoir, #non-fiction

Result: 7 drafts, all tagged reading and 2026, each individually tagged by genre/category.

Steps

  • script

    // Get current draft content
    let lines = draft.content.split("\n");
    
    // Skip title (first line)
    lines.shift();
    
    // Check if second line is a global tags line
    let globalTags = [];
    if (lines.length > 0) {
        let secondLine = lines[0].trim();
        if (secondLine.startsWith("#")) {
            // Check if entire line is just tags (no non-tag content)
            let isAllTags = secondLine.split(/,\s*|\s+#/).every(part => {
                let cleaned = part.replace(/^#/, "").trim();
                return cleaned.length > 0;
            });
            if (isAllTags && !secondLine.includes(" ") || isAllTags && secondLine.match(/^#\S+(\s*,\s*#?\S+|\s+#\S+)*$/)) {
                // Parse global tags
                let tagString = secondLine;
                // Split on comma or " #"
                let parts = tagString.split(/,\s*|\s+(?=#)/);
                for (let part of parts) {
                    let tag = part.replace(/^#/, "").trim();
                    if (tag.length > 0) {
                        globalTags.push(tag);
                    }
                }
                lines.shift(); // Remove global tags line from processing
            }
        }
    }
    
    let count = 0;
    
    for (let line of lines) {
        if (line.trim() === "") continue;
    
        let lineTags = [];
        let content = line;
    
        // Find the first # that represents a tag (not part of content)
        let tagMatch = content.match(/\s+#/);
        if (tagMatch) {
            let tagStartIndex = tagMatch.index;
            let tagPortion = content.substring(tagStartIndex);
            content = content.substring(0, tagStartIndex).trim();
    
            // Parse tags from the tag portion - split on comma or " #"
            let parts = tagPortion.split(/,\s*|\s+(?=#)/);
            for (let part of parts) {
                let tag = part.replace(/^#/, "").trim();
                if (tag.length > 0) {
                    lineTags.push(tag);
                }
            }
        }
    
        // Check if the entire line starts with # (meaning it's all tags, no content)
        // In that case, skip it as there's no content for a draft
        if (content.trim() === "" || content.trim().startsWith("#")) {
            // If content is empty or only tags remain, try to use the original line
            if (content.trim() === "") {
                // All was tags - create draft with tag text as content? 
                // Skip if no real content
                continue;
            }
        }
    
        let d = new Draft();
        d.content = content;
    
        // Apply global tags
        for (let tag of globalTags) {
            d.addTag(tag);
        }
    
        // Apply line-specific tags
        for (let tag of lineTags) {
            d.addTag(tag);
        }
    
        d.update();
        count++;
    }
    
    app.displayInfoMessage(count + " draft" + (count !== 1 ? "s" : "") + " created.");
    

Options

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