Action

Process Template

Posted by Zrapata, Last update over 2 years ago

UPDATES

over 2 years ago

v1.1 - Made it possible to select a valid template while the active draft is not a valid template.

The list of tags required for the validation process can be changed editing the script, more detailed instructions can be found in the description of the action

Process Template

Quick Information

  • Latest Version: v1.1
  • Latest Update: 25-october-2021
  • Author: Zrapata
  • Description: This action makes it possible to create multiple drafts from a template file
  • Action List URL: Here

Relatad Actions

On development

  • Template Creator

What the action does

An action that allows you to create any amount of drafts from a custom template file.

New Draft: @flagged @tags(«ProyectName») {
    Just a normal markdown template [[date]]
}

New Draft - Reference: @flagged @archived

This template will ask you to give a value to the variable ProyectName and will create two drafts.

One named New Draft, flagged in the inbox, with a tag with the name of the variable with a predefined content.

And another named New Draft - Reference, flagged and archived

Format

This action uses a kind of taskpaper input, what it basically means is that you create a Draft by adding some text followed by a semi column :

New Draft:

This line will create a new Draft with a name “New Draft” with no content and no tags


You can also specify some Flags to modify the draft

Draft with Flags: @flagged

Or you can specify the Content of the draft

Draft with content: {
The content of the draft
}

Content

You can specify the content of each draft by placing the content inside braces at the end of the line

The content of the draft passes through the drafts templating system so any valid template will apply

Draft with template: {
    The date of creation is [[date]]
}

Flags

A flag is any element that starts with an @ followed by any word, and always after the semi column :

Flags are used to modify the created draft

Some flags may requiere parameters to function correctly, like in the case of the tags flag

Supported Flags

  • flagged - Makes the created draft flagged
  • archived - Archives the created draft
  • tags - Adds tags to the created draft
    • parameters - Tags separated by commas

Variables

You can have variables in the template they have to follow this format

« VariableName »

You can change the variable by one of two ways
1. Have a template tag in the current draft with the same name as the variable
2. Start the action and fill in the prompt

You can mix this two options with no problem

Creation Tag Filter

With the latest update v1.1, it made it possible to have specific tags to be used as templates, the default tags are template and drafts.

This feature is used so that you don’t need the template to be the current draft.

And in case that the current draft is not a valid template, the action will prompt you to select a valid one, according to the template requirements.

To change this defaults you have to edit the action and change the values

  1. Edit Action Process Template
  2. Steps
  3. Script Step 1
  4. Edit

You will find the following line

const requiredTags = "template,drafts"

Change the values of "template,drafts" to any tags you would like to be applied to the filtering.

For example, if you would like the tag new files to be the only tag used for the templates, the line would need to be

const requiredTags = "new files"

Known Issues

  • So far you cannot add spaces and tabs at the start of a line in the content

Steps

  • script

    /*
    actionVersion: v1.1
    lastUpdate: 25/oct/21
    author: Zrapata
    description: This action makes it possible to create multiple drafts from a template file
    draftsActionURL: https://actions.getdrafts.com/a/1rc#%23Flags
    */
    
    const requiredTags = "template,drafts"
    var tagsArray = requiredTags.split(",")
    
    var currentDraft = testTags()
    var text
    if (currentDraft != false) {
    	text = currentDraft.content
    	var matches = text.match(/«.+?»/g)
    }
    
    var unNamedKeys = []
    var allKeys = []
    
    // MARK: Apply Template
    
    function applyTemplate() {
    	if(matches) {
    		const result = evaluateValues()
    		if (!result) { return false }
    		replaceValues(result)
    	}
    	processTemplate()
    }
    
    // Mark: Create Draft
    function createDraft(results) {
    	var d = new Draft()
    	d.content = d.processTemplate(results['content'] ?? '')
    	d.isFlagged = results['flagged'] ?? false
    	results['tags'].split(',').forEach(newTag => {
    		d.addTag(newTag.trim())
    	})
    	d.isArchived = results['archived'] ?? false
    	
    	d.update()
    }
    
    // Mark: Crate Conent
    function createContent(title, content) {
    	const newTitle = '# ' + title
    	let newContent = []
    	
    	if(content != undefined) {
    		content.split('\n').forEach(newLine => {
    			newContent.push(newLine.trim())
    		})
    	}
    
    	return newTitle + '\n' + newContent.join('\n')
    }
    
    // Mark: Process Template
    function processTemplate() {
    	const templateRegex = /(.*):\s*(@[\w].*[\w\)] ?)*(?:\{([\s\S]+?)\})?/g
    	let draftMatch
    	while(draftMatch = templateRegex.exec(text)) {
    		let results = decodeTags(draftMatch[2])
    		results['content'] = createContent(draftMatch[1], draftMatch[3])
    		createDraft(results)
    	}
    }
    
    // Mark: Process Tags
    function decodeTags(stringed) {
    	const tagRegex = /@(\w*)(?:\(([\s\S]+?)\))?/g
    	const tagMatches = stringed.match(tagRegex)
    
    	var thisTagMatch
    	var results = {}
    
    	while(thisTagMatch = tagRegex.exec(stringed)) {
    		const thisTagKey = thisTagMatch[1]
    		const thisTagValue = thisTagMatch[2]
    
    		results[thisTagKey] = thisTagValue ?? true
    	}
    
    	return results
    }
    
    // Mark: Evaluate Values
    function evaluateValues() {
    	const matches = askValues()
    	if(!matches) { return false }
    	
    	const matchedValues = Object.values(matches)
    
    	if(unNamedKeys.length != 0) {
    		app.displayWarningMessage('Please fill All the Values or Cancel the Operation')
    		evaluateValues()
    	}
    	return matches
    }
    
    // MARK: Replace values
    function replaceValues(matches) {
    	allKeys.forEach(key => {
    		text = text.replaceAll(key, matches[key])
    	})
    }
    
    // MARK: Create Prompt and Add Values
    
    function askValues() {
    	matches.forEach(match => {
    		if (!unNamedKeys.includes(match)) { unNamedKeys.push(match) }
    	})
    
    	allKeys = unNamedKeys
    
    	var result = readFromTemplate()
    	if(unNamedKeys == '') { return result }
    	
    	var p = new Prompt()
    	p.title = "Add Values"
    	p.message = "Chage the default values to something"
    
    	unNamedKeys.forEach(value => {
    		p.addTextField(value, value, "")
    	})
    	p.addButton("Confirm")
    	if(p.show()) {
    
    		unNamedKeys.forEach(value => {
    			const writtenValue = p.fieldValues[value].trim()
    			if (writtenValue == '') { return }
    			result[value] = writtenValue
    
    			let index = unNamedKeys.indexOf(value)
    			unNamedKeys = unNamedKeys.splice(index, 0)
    		})
    		return result
    	} else { return false }
    }
    
    // Mark: Read from Template Tag
    function readFromTemplate() {
    	let result = {}
    	unNamedKeys.forEach(value => {
    		let newValue = value.replaceAll('«', '').replaceAll('»', '')
    		let taggedValue = draft.getTemplateTag(newValue)
    
    		if(taggedValue != '') {
    			result[value] = taggedValue
    
    			let index = unNamedKeys.indexOf(value)
    			unNamedKeys = unNamedKeys.splice(index, 0)
    		}
    	})
    
    	return result
    }
    
    function callError(message) {
    	app.displayErrorMessage(message)
    }
    
    // ---- Mark: ----
    
    function testTags() {
    	for (const newTag of tagsArray) {
    		if(!draft.hasTag(newTag)) {
    			return selectTemplate()
    		}
    	}
    	return draft
    }
    
    function selectTemplate() {
    	let thisDrafts = getDraftsFromTags()
    	
    	let p = new Prompt()
    	p.title = "Elige una Plantilla"
    	thisDrafts.forEach(d => {
    		p.addButton(d.displayTitle, d)
    	})
    	p.addLabel("searchQuery", "Query by: " + capitalizeTags())
    	if(p.show() == false) { return false }
    	return p.buttonPressed
    }
    
    function getDraftsFromTags() {
    	let thisWorkspace = new Workspace()
    	thisWorkspace.tagFilter = requiredTags
    	thisWorkspace.tagFilterRequireAll = true
    	return thisWorkspace.query("inbox")
    }
    
    function capitalize(str) {
    	const lower = str.toLowerCase()
    	return str.charAt(0).toUpperCase() + lower.slice(1)
    }
    function capitalizeTags() {
    	let thisTags = []
    	tagsArray.forEach(newTag => {
    		thisTags.push(capitalize(newTag))
    	})
    	return thisTags.join(", ")
    }
    
    if(currentDraft != false) {
    	applyTemplate()
    }
    
    // ---- Another Mark: ----
    
    //doAction()
    //if(currentDraft.hasTag("template") && currentDraft.hasTag("drafts")) {
    //	applyTemplate()
    //} else {
    //	let action = Action.find("Copy");
    //	callError("The current draft need to be a template for drafts")
    //}
    

Options

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