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.