Markdown-Style document link - script

To make a Markdown-style link on the clipboard of the current document selected in DEVONthink

tell application id "com.devon-technologies.thinkpro2"
	set theItem to (the first item of (the selection as list))
	set the clipboard to "[" & name of theItem & "](" & reference URL of theItem & ")"
end tell

Nice script. Thanks for sharing.
Now we’d only need decent native markdown support in DTP :wink:


It’s easy to use Brett Trepstra’s Marked app with DEVONthink. Personally, I don’t think using apps like this with DEVONthink is a workaround – who needs an all-in-one app anyway?

DEVONthink’s in-built editing capability is pretty rough and rudimentary, but I’d rather see DEVONtech bringing the core technology into the current decade, than than trying to compete with external editor apps.

Yes I know, there are plenty “workarounds” and quite some really good markdown editors/viewers out there.

But the point is: they all require extra steps. I do a lot of jumping around between searching, editing and browsing through groups in DTP. It defeats my workflow if I have to open an external App for each text to do viewing/editing.

It seems there is no decent solution to get the power of DTP’s organising and searching capabilities together with nice locking (and therefor fast readable) text.


** Edit Nov 22, 2012: the script is completely revised, per Rob’s suggestion and question below

I’ve extended the functionality of the Markdown-style link script to give you three options for the link that the script places on the keyboard:

  1. a link to the document in the DEVONthink database (i.e., x-devonthink-item://)
  2. a link to the document in the file system (i.e., [file://localhost](file://localhost) )
  3. same as (2) but with the embedded image prefix “!” on the link – when the Markdown is rendered as HTML the image will appear on the page
  4. If the FTnote property in the script is “true” then the script will produce a link suitable for pasting into FoldingText as a link appended to a tag

Number (3) doesn’t have the logic in the script to decide that what you selected is actually an image. If you don’t select an image file, your rendered HTML will show the question mark icon instead of an image (depending on your browser). I’ll update the logic in the script someday to trap this condition.

	WARNING: this can create links directly to files inside a database package which
	means you could damage something.  Such links will break instantly if you
	move the database anywhere. The script will ask if you understand the risk.
	If you don't want to be warned, set the warnMe property to false
	Script to put a MultiMarkDown-styled link to a DEVONthink database item on
	the clipboard.
	A optional property (set FTnote to true) will embed the styled link inside a
	FoldingText tag.  
	**If FTnote is true:
		You can have the script produce the link embedded in a FT tag or a FT property
		(See the PROPERTIES section in the script, below)
		The default property is "note : ".  This can be changed by
		setting FTtag to some other string.  Because FoldingText currently (20121122) does not
		handle links to files very well, if FTnote is true then the only result of the script
		is a link using the DEVONthink reference URL (x-devonthink-item://)
	**If FTnote is false: 
		The selected document is an image (png, tiff, jpg, jpeg, or PDF):
		You are prompted with three options: 
		(1) link using the DEVONthink reference URL,
		(2) link directly to the document in the file system (WARNING: if the document
		is not indexed, then this will create a link directly inside a database 
		package -- use at your own risk),
		(3) produce the same link as (2), but using the MultiMarkdown embedded image format
	**The document is not an image: you get options (1) and (2) only.

property FTnote : false -- set this to true or false
-- property FTtag : "@note" -- use this style if you want FoldingText link embedded in a FT tag
property FTtag : "note : " -- use this style if you want a FoldingText link embedded in a FT property
property linkOptionsEmbedded : {"Link to Document in DEVONthink", "Link to Document in File System", "Embedded Image or PDF"}
property linkOptionsNoImage : {"Link to Document in DEVONthink", "Link to Document in File System"}
property warnMe : true

tell application id "com.devon-technologies.thinkpro2"
	set theLink to ""
	set the clipboard to ""
		if the selection is {} then error
		set theItem to (the first item of (the selection as list))
		set theType to the type of theItem as string
		if not FTnote then
			if ({"PDF document", "picture"} contains theType) then
				set linkOptions to linkOptionsEmbedded
				set linkOptions to linkOptionsNoImage
			end if
			set linkType to (choose from list linkOptions with prompt "Choose the type of Markdown Link") as string
			set linkType to "DEVONthink"
		end if
		if linkType contains "File System" then
			if warnMe then
				set warned to display alert "Do you accept the danger of using this link?" buttons {"Yes", "No"} default button 2
				set answer to the button returned of warned
				if answer is "No" then error
			end if
			set myPath to the path of theItem as string
			set myURLPath to my encode(myPath)
			--			set myURLPath to my encode_text(myPath, false, false)
			set theLink to "[" & name of theItem & "](file://localhost" & myURLPath & ")"
		end if
		if linkType contains "Image" then
			set myPath to the path of theItem as string
			set myURLPath to my encode(myPath)
			--			set myURLPath to my encode_text(myPath, false, false)
			set theLink to "![" & name of theItem & "](file://localhost" & myURLPath & ")"
		end if
		if linkType contains "DEVONthink" then
			set theLink to "[" & name of theItem & "](" & reference URL of theItem & ")"
		end if
		if FTnote then set theLink to FTtag & " (" & theLink & ")"
		set the clipboard to theLink
	end try
end tell

-- Sub-routine provided by Rob Trew
on encode(strPath)
	do shell script "python -c 'import sys, urllib as ul; print ul.quote(sys.argv[1])' " & ¬
		quoted form of strPath
end encode

Why bother with all this? Over here, I do all my first drafts and note taking in plain text with Markdown tags (actually, MultiMarkdown). For projects, I keep notes collected in VoodooPad wikis, which I publish as local HTML sites. It’s helpful to have links to reference documents in the database (the first style of link) or to have links that open a reference file directly into its native editor (the second style of link), or merely display images in my notes (the third style of link).

This might be helpful for other plain text + Markdown users. Of course, these links will work in any Markdown-aware editor. I’ve found that Folding Text’s handling of file:// and image URLs is buggy, so YMMV with that editor.

WARNING: the script can be used to make a link directly into the internals of a database package. That type of link is optional if you want to open a document for editing from inside a Markdown document - and should be used only if you understand and accept the risks.

Happy Thanksgiving to all celebrants thereof !

A couple of things:
First, not sure if this is relevant here, but for URL encoding, one other approach in Applescript is to make a Python library call along the lines of:

on encode(strPath)
	do shell script "python -c 'import sys, urllib as ul; print ul.quote(sys.argv[1])' " & ¬
		quoted form of strPath
end encode

Second @korm, this reminds me of your excellent suggestion elsewhere re Markdown style links in DEVONthink-FoldingText-OmniFocus workflows:

Am I right in assuming that you are thinking of a rich text encoding in the OmniFocus note which gets exported from FoldingText, making the DT2 link clickable and hidden behind the [ReadMe] text ?


Thank you for the suggested Python approach to URL encoding. I’ve replace the old routine with your suggestion.

Yes, in the case of your FoldingText to OmniFocus script(s) – where you would parse a @note tag that has an embedded DEVONthink URL. I’ve modified my script, above, to create the predecessor to what you might choose to do. That is, my script now can be configured to put a link on the clipboard that looks like this:

@note ([test.pdf](x-devonthink-item://317B51EB-E8C7-4678-97D4-87495F4589AB))

When that is pasted into a FoldingText document you get this clickable link to open the document in DEVONthink:

which, when edited in FoldingText, is actually this

The comments in the script explain how to configure the logic to produce these results.

Thanks for all your help, Rob!

Looks good, and that raises an interesting issue about parsing FT @key(value) pairs, and closing the gap between the tag name and the following parenthesis, which I will get advice on from another forum :slight_smile:

Here is one line, @note(This **text** is the value of the note key) in the FT API
and here is another. @note(This [Search]( is no longer the value of the note key)

Re keeping or generating DevonThink notes in FoldingText format, it may work better to use the FoldingText property syntax (rather than the tag syntax) for notes which are destined for OmniFocus etc

FoldingText correctly parses MarkDown links within property values (space on both sides of a colon in a child line).

- Some text
    note : This [Search]( is the value of the note key

but currently mistakes the closing parenthesis of a markdown link for the end of a @key(value) @note(note text) tag pattern.

(I have requested, in another forum, that the FT parser counts opening and closing parenthesis in @key(value) patterns to allow for links within the value text).

This is easy enough to do with the script by changing

property FTtag : "@note"


property FTtag : "note : " 

If you don’t want “note” then use any string.

I modified the script, above, to accommodate this – just a documentation change.

(There’s a case where the user would want to insert several links in a single FT document. I believe an FT to OF parser would get confused by more than one instance of a “@note” tag or a "note : " property. My script would need further adjustment if that’s the case. I’ll save that task until there’s actually a problem. :slight_smile: )

The best way to parse FT is, of course, to use the parser which Jesse Grosjean has built into FoldingText, and which offers us a list of the tag/properties and values for each node.

Yes, the FT parser gives the day to the last of any repeated sequence of homonymous tags in the same line.

If you use the property syntax (which has to be on its own line, indented as a child beneath the main text line), you can place several links inside one note. The note can be long, and will be wrapped, but it will come to an end with any linefeed character.

- Here is an action of some kind
        note : This the action's note text [linktitle1](url1)  [linktitle2](url2) etc. 


i.e. I think you should be able to do it by editing your FTTag property to:

property FTtag : linefeed & tab & "note : "

Given this, if you would be parsing the FT document with automaton, one way is to use my script by first setting

property FTnote : false

Thus bypassing the FT tag and FT property logic.

Then, run the script and choose either the “Link to Document in DEVONthink”, or “Link to Document in File System” options. In these cases you’ll get on the clipboard something like

[John Jones](x-devonthink-item://9FB33A90-2648-42F6-97B8-1CD472017EE5)

and then you would

I agree, that’s also an option.

A reformulation might be that the best way to do this is to make sure that any FT-like text is fully compliant with the FoldingText parser, so that documents can, if required be successfully opened in FT, and in anything else compliant with its standards.

If the main goal is really to get things to move smoothly DT → OF then, of course, one could bypass an FT app stage by writing an FT parser in something like Python.

Quite a lot of edge-cases once one looks into it – not at all impossible - but would take a bit of work :slight_smile:

Actually, my main goal is to get things into VoodooPad, and MultiMarkdown Composer. The script started as a quick and dirty helper. I added the FT part as a sideshow. But, over here I stopped using FT in favor of other text tools that suit my requirements better — and waiting until it (maybe, someday) merges with TaskPaper. The script has morphed to its limit, so ill stop here.

I’ll leave the Python approach and edge cases to those more committed to FT than me. :smiley: (IMO, the emerging FT “modes” (plugin) feature might also ease the DT -> FT and the FT -> OF integration and completely bypass AppleScript’s limits.)

FT and TaskPaper are written by the same person. My understanding is that TP will not be further developed, and that each app has a different focus (according to a doc posted at the FT website).

Indeed. I know. Jesse Grosjean wrote “Long term I think FoldingText will replace TaskPaper. But that’s still a long way away.” For my purposes, I can wait. YMMV.