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.
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.
An archive of the source folder containing the files used to create the eXtension:
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:
HTML File
The main HTML file serves two purposes in the eXtension:
- It contains the HTML code controlling the display of content in the eXtension pane in the document interface.
- It contains an pair of HTML <script>...</script> tags enclosing the main JavaScript code for interacting with the Craft and 3rd-party application like OmniFocus.
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.
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 icon image file (PNG 256x256) (icon.png)
- A JSON manifest file (manifest.json) listing the metadata for the eXtenison
- An HTML file (index.html) that contains both the HTML code for displaying descriptions and controls for the exTension, as well as the JavaScript script code to be executed by the plug-in.
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.