Generate rich text note with links via AppleScript


#1

Hello, I have already tried a few things, also from the forum here, but somehow can’t get it right. I have a string in AppleScript that looks like

"<a href='http://www.example.com/link1'>Link 1</a> - <a href='http://www.example.com/link2'>Link 2<a>"

How can I assign this string as a rich text note to a project?? Within the project the note in OmniFocus should look like

Link 1 - Link 2

I would be very happy about any hint!


#2

I’ve been looking into a similar problem myself, and managed to cobble together a solution yesterday. Although all of the details are not directly relevant to your question, I thought I’d share my process here in case it helps someone else in future.

I wanted to be able to automatically generate an OmniFocus 3 Quick Entry task from selected messages in Mail, including a formatted hyperlink back to the original email(s). This can already be done via Mail > Services > OmniFocus 3: Send to Inbox, but it uses a format that isn’t quite what I wanted. Selecting multiple messages produces a different result, which is closer to what I was hoping for, however, I really wanted to be able to automatically add a tag and not pre-populate the task name. I assume this official Service isn’t customisable, so I looked into trying to create my own.

I originally tried using an omnifocus:// URL scheme after seeing one used in a Chrome extension for Gmail, but couldn’t seem to encode rich text notes in a URL so gave up on that approach (if anyone knows whether this definitely is or isn’t possible, please tell me!). I eventually discovered the magic (and pain) of AppleScript, and after several hours of struggling with a lack of documentation, I managed to piece together the following script from various other code snippets, which does exactly what I want:

--Lists to store data from messages selected in Mail
set message_subjects to {}
set message_senders to {}
set message_urls to {}

tell application "Mail"
	--Get the messages currently selected in Mail
	set selected_messages to selected messages of message viewer 0
	--If no messages are selected, alert the user via a dialogue box and quit
	if (selected_messages is equal to missing value) then
		set alert_text to "No messages selected!"
		set alert_message to "Please select at least one message to send to OmniFocus and try again."
		display alert alert_text message alert_message as critical buttons {"OK"}
		return
	end if
	--Iterate over the selected messages and store their data in the lists
	repeat with selected_message in selected_messages
		set end of message_subjects to subject of selected_message
		set end of message_senders to sender of selected_message
		set end of message_urls to "message://%3C" & message id of selected_message & "%3e"
	end repeat
end tell

tell application "OmniFocus"
	--Create object for email tag
	set email_tag to (first flattened tag of default document whose name is "Email") --Note that the "Email" tag must already exist!
	tell quick entry
		--Create new task with every field blank, except the email tag
		set new_task to make new inbox task with properties {primary tag:email_tag}
		--Insert message details into the task's note
		tell note of new_task
			--Iterate over the messages obtained from Mail
			repeat with n from 1 to count of message_subjects
				--First line: Link to message with text based on message subject
				make new paragraph with data (item n of message_subjects & return)
				set value of attribute "link" of style of paragraph (((n - 1) * 3) + 1) to (item n of message_urls)
				--Second line: message sender
				make new paragraph with data (item n of message_senders & return)
				--New line separator between messages
				make new paragraph with data return
			end repeat
			--Delete unwanted empty lines at the end of the note
			delete paragraph -1
			delete character -1
		end tell
		open
		--Expand the task's note so that the message details can be seen
		set note expanded of tree (count of trees) to true
	end tell
end tell

--Select the name field of the task so that the user can type this manually without using the mouse to select Quick Entry
tell application "System Events"
	key code 125 --Down arrow
	keystroke tab --Key code 48
end tell

This produces the following output when two messages are selected in Mail:

In summary, the script:

  1. Grabs the subject, senders, and URL of each messages currently selected in Mail
  2. Pops up an alert dialogue box and quits if no messages are selected
  3. Creates a new OmniFocus task in the Quick Entry window, with every field blank except the Email tag (which must already exist in OmniFocus)
  4. Iterates over the messages obtained from Mail, and for each:
    • Creates a link back to the message with the text set to the message subject
    • Inserts the message sender below, followed by a new line separator
  5. Expands the task’s note so the links can be seen without having to click anything
  6. Selects the task’s name field ready for me to type one in

This works nicely, but is currently quite slow. The culprit seems to be the code responsible for note generation (if I comment that part out it’s super snappy). I’m completely new to AppleScript and the OmniFocus API, so I expect the code I’ve written isn’t the best way of implementing the desired functionality. Hopefully someone more experienced can suggest improvements!

I believe you should be able to apply a similar approach to creating rich text notes for projects in OmniFocus. You can create the link text and then edit the link attribute with something like this:

set value of attribute "link" of style of first paragraph to url


#3

I made some changes to the code to make it run slightly faster. It now constructs the note in plain text in advance, then creates the task with the plain text note as a parameter. The message URLs are applied using rich text formatting once the note has been created.

--Lists to store data from messages selected in Mail
set message_subjects to {}
set message_senders to {}
set message_urls to {}

tell application "Mail"
	--Get the messages currently selected in Mail
	set selected_messages to selected messages of message viewer 0
	--If no messages are selected, alert the user via a dialogue box and quit
	if (selected_messages is equal to missing value) then
		set alert_text to "No messages selected!"
		set alert_message to "Please select at least one message to send to OmniFocus and try again."
		display alert alert_text message alert_message as critical buttons {"OK"}
		return
	end if
	--Iterate over the selected messages and store their data in the lists
	repeat with selected_message in selected_messages
		set end of message_subjects to subject of selected_message
		set end of message_senders to sender of selected_message
		set end of message_urls to "message://%3C" & message id of selected_message & "%3e"
	end repeat
end tell

tell application "OmniFocus"
	--Create object for email tag
	set email_tag to (first flattened tag of default document whose name is "Email") --Note that the "Email" tag must already exist!
	--Construct most of the note text before creating the task
	set note_text to ""
	--Iterate over the messages obtained from Mail
	repeat with n from 1 to count of message_subjects
		--First line: Link to message with text based on message subject
		--Second line: message sender
		set message_note_text to ((item n of message_subjects) & return & (item n of message_senders) & return)
		--New line separator between messages
		set note_text to note_text & message_note_text & return
	end repeat
	
	tell quick entry
		--Create new task with every field blank, except the email tag
		set new_task to make new inbox task with properties {note:note_text, primary tag:email_tag}
		--Insert message details into the task's note
		tell note of new_task
			--Add message URLs as rich text formatting
			repeat with n from 1 to count of message_subjects
				set value of attribute "link" of style of paragraph (((n - 1) * 3) + 1) to (item n of message_urls)
			end repeat
			--Delete unwanted empty lines at the end of the note
			delete paragraph -1
			delete character -1
		end tell
		open
		--Expand the task's note so that the message details can be seen
		set note expanded of tree (count of trees) to true
	end tell
end tell

--Select the name field of the task so that the user can type this manually without using the mouse to select Quick Entry
tell application "System Events"
	key code 125 --Down arrow
	keystroke tab --Key code 48
end tell

It may be possible to improve this further by creating the note entirely in rich text format in advance, then pass it as a parameter when creating the task, but I haven’t learnt enough AppleScript to figure out how to do this yet!


#4

Thank you so much for your detailed replies! Just tried your method and it works great. I placed one link text per line and added the URLs with

set value of attribute "link" of style of paragraph 1 to theURL1
set value of attribute "link" of style of paragraph 2 to theURL2

Can’t thank you enough for pushing me in the right direction.

Unfortunately the iOS versions of OmniFocus don’t display rich text notes. They show a text version instead. It is up to Omni to improve this.