×

Craft eXtension: New OmniFocus Task

This Craft extension will create a new Task in OmniFocus using the text data from the first selected block for the task title. The note of the created OmniFocus task will contain a link to the source block in the Craft document, followed by the text from all selected blocks.

(⬇ see below ) A series of selected blocks in a Craft document:

Selected blocks in Craft

(⬇ see below ) The new task in OmniFocus:

New Task
Blocks to Task
This Craft extension will create a new Task in OmniFocus using the text data from the first selected block for the task title.

eXtension File and Related Materials

Download the eXtension file and install by clicking the plus (+) button in the eXtensions pane in the current document window.

DOWNLOAD EXTENSION

An archive of the source folder containing the files used to create the eXtension:

DOWNLOAD SOURCE FILES

Manifest File

The mainfiest.json file is a JSON object record of keys and values that describe the xTension plug-in, including: id, eXtension title (name), fileName, author, author-email, description, API version (api), and the file name of the main HTML file (main)

eXtension Mainfest File


{ "id": "omni-automation-cr-of-new-task-with-block", "name": "OmniFocus Task with Block", "fileName": "of-new-task-with-block", "author": "Otto Automator", "author-email": "omni_automation@icloud.com", "description" : "Creates a new OmniFocus task using the text of the first selected block.", "api": "0.1.0", "main": "index.html" }

Icon File

The icon displayed next to the installed eXtension in the Craft eXtension panel in Craft app document, is an image in PNG format sized to 256 pixels by 256 pixels:

eXtension icon

HTML File

The main HTML file serves two purposes in the eXtension:

HTML File


<!DOCTYPE html> <html> <head> <style> /* CSS FOR THE EXTENSION INTERFACE */ body { font-family: -apple-system, Helvetica, sans-serif; font-size: 10pt; } h2 { font-family: -apple-system, Helvetica, sans-serif; font-size: 12pt; } #btn-execute { font-family: -apple-system, Helvetica, sans-serif; font-size: 12pt; background-color: lightBlue; text-transform: uppercase; padding: 4px; } #documentation-link { font-size:80%; text-decoration: none; } </style> <script> // OPEN RELEVANT DOCUMENTATION function goToDocumentation(){ craft.editorApi.openURL("https://omni-automation.com") } </script> </head> <body> <!-- EXTENSION INTERFACE --> <button id="btn-execute">Create</button> <!-- DESCRIPTION --> <h2>OmniFocus Task with Block</h2> <p>This Craft extension will create a new Task in OmniFocus using the text data from the first selected block.</p> <p>The note of the created OmniFocus task will contain a link to the source block in the Craft document, followed by the text from all selected blocks.</p> <p><a id="documentation-link" href="javascript:void(0);" onclick="goToDocumentation();">omni-automation.com</a></p> <script> // ATTACH SCRIPT TO BUTTON const button = document.getElementById("btn-execute"); button.addEventListener("click", async () => { // SCRIPT TO CREATE/SEND OMNI AUTOMATION SCRIPT URL }); </script> </body> </html>

The Passed Block Data

The getSelection() method of the Craft Editor class API (documentation) is called to return the JSON records for each of the selected blocks:

result = await craft.editorApi.getSelection()

The resulting JSON data is parsed by the Omni Automation script to retrieve the information used by the script in creating a new OmniFocus task:

Example Passed Block Data (JSON)


[ { "color": "text", "spaceId": "859c432e-33f3-7983-7c20-67a12bd618aa", "content": [ { "isItalic": false, "isStrikethrough": false, "text": "Risus Nibh Amet Tristique:", "isCode": false, "isBold": false } ], "indentationLevel": 0, "subblocks": [ ], "listStyle": { "type": "none" }, "style": { "fontStyle": "system", "alignmentStyle": "left", "textStyle": "heading" }, "hasFocusDecoration": false, "documentId": "33B4539F-2FD2-4256-9534-103AFF9A9B58", "hasBlockDecoration": false, "id": "133DEA1F-598E-4C06-B3FF-56FC14DD023B", "type": "textBlock" }, { "listStyle": { "type": "bullet" }, "indentationLevel": 0, "style": { "fontStyle": "system", "alignmentStyle": "left", "textStyle": "body" }, "id": "D0F05D12-1A9A-4B73-90DB-CD450D9F6ADF", "color": "text", "spaceId": "859c432e-33f3-7983-7c20-67a12bd618aa", "documentId": "33B4539F-2FD2-4256-9534-103AFF9A9B58", "type": "textBlock", "hasBlockDecoration": false, "hasFocusDecoration": false, "content": [ { "isItalic": false, "isStrikethrough": false, "text": "Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.", "isCode": false, "isBold": false } ], "subblocks": [ ] }, { "hasBlockDecoration": false, "hasFocusDecoration": false, "spaceId": "859c432e-33f3-7983-7c20-67a12bd618aa", "style": { "fontStyle": "system", "alignmentStyle": "left", "textStyle": "body" }, "documentId": "33B4539F-2FD2-4256-9534-103AFF9A9B58", "content": [ { "isItalic": false, "isStrikethrough": false, "text": "Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.", "isCode": false, "isBold": false } ], "indentationLevel": 0, "listStyle": { "type": "bullet" }, "id": "814C3FB2-BBDC-44BE-861D-0063F9623CCC", "subblocks": [ ], "color": "text", "type": "textBlock" }, { "color": "text", "spaceId": "859c432e-33f3-7983-7c20-67a12bd618aa", "style": { "fontStyle": "system", "alignmentStyle": "left", "textStyle": "body" }, "indentationLevel": 0, "listStyle": { "type": "bullet" }, "hasBlockDecoration": false, "type": "textBlock", "id": "0A38F715-3788-4428-B29A-4AC6C2C1A8F0", "documentId": "33B4539F-2FD2-4256-9534-103AFF9A9B58", "content": [ { "isItalic": false, "isStrikethrough": false, "text": "Sed posuere consectetur est at lobortis.", "isCode": false, "isBold": false } ], "hasFocusDecoration": false, "subblocks": [ ] } ]

The Main Script

The main script incorporates a script design detailed in the documentation for creating Omni Automation Script URLs.

This script design allows the for secure execution of the script, without requiring subsequent approvals of the executing script, by separating the code to be run from the data to be processed.

 2-8  Retrieve Data • The getSelection() method of the Craft Editor class API (documentation) is called to return an array of the JSON records for each of the selected blocks.

 11-38  Passed Function • A Omni Automation function targeting the OmniFocus application is created containing the code for parsing the passed-in JSON data and using the data to create and display a new task.

 40-44  Convert to Encoded Strings • Generate URL encoded versions of the JSON data and the OmniFocus function to be added to the Omni Automation script URL targeting the OmniFocus application.

 46-50  Script URL • The Omni Automation script URL, targeting the OmniFocus application, will transfer the retrieved data and create the task.

 53  Execute URL • The script URL is executed by calling the openURL() of the Craft Editor API.

The Main Script


try { // GET THE SELECTED TEXT result = await craft.editorApi.getSelection() if (result.status !== "success") { throw new Error(result.message) } else { var selectedBlockData = result.data } if(selectedBlockData !== ""){ // FUNCTION TO BE EXECUTED BY OMNIFOCUS function newOmniFocusTask(passedData){ console.log(JSON.stringify(passedData)) blockID = passedData[0].id spaceID = passedData[0].spaceId documentID = passedData[0].documentId blockType = passedData[0].type blockText = passedData[0].content[0].text if (blockText.length > 32){ taskTitle = blockText.substring(0, 32) + "..." } else { taskTitle = blockText } linkURL = `craftdocs://open?blockId=${blockID}&spaceId=${spaceID}` tsk = new Task(taskTitle) passedData.forEach((block, index) => { if(block.listStyle.type !== "none"){ prefix = " - " } else {prefix = ""} if (index === 0){ noteText = prefix + block.content[0].text } else { noteText = noteText + "\n" + prefix + block.content[0].text } }) tsk.note = linkURL + "\n\n" + noteText URL.fromString(`omnifocus://task/${tsk.id.primaryKey}`).open() } // CREATE FUNCTION AND CONTENT STRINGS contentString = JSON.stringify(selectedBlockData) encodedContent = encodeURIComponent(contentString) functionString = newOmniFocusTask.toString() encodedFunction = encodeURIComponent(functionString) // CREATE SCRIPT URL url = 'omnifocus://localhost/omnijs-run?script=' + '%28' + encodedFunction + '%29' + '%28' + 'argument' + '%29' + '&arg=' + encodedContent // EXECUTE THE URL await craft.editorApi.openURL(url) } else { throw new Error("No text is selected.") } } catch(err){ throw `${err.name}\n${err.message}` }

Transforming Bundle into eXtension

The Craft application provides access and control of document data through the use of plug-ins called eXtensions that are JavaScript bundles (a zipped folder with file extension) containing (at a minimum):

An eXtension (with the “.craftx” file extension) is generated from the created files using a variation of the following Terminal command-line script (replace the red text):

Terminal Command for Generating an exTension bundle


cd /path-to-the-folder-containing-the-files zip -vr name-for-extension.craftx icon.png index.html manifest.json

Detailed documentation regarding the construction of exTensions and use of the Craft API is provided on the Craft website.