Is there a way to see if a note is being linked to by another note?

This is a huge advantage of using markdown imho. I have written a script in python to do what the OP requests in Ulysses - generate a list of every page linking to a selected page (and automatically create back links) - and it relies upon being able to search the URL strings themselves.

@pete31 - Thanks once again for your very thorough and thoughtful reply. I get it now that the robust link, when visible in the actual text, is actually more accessible to other programs and scripts, and therefore usable. Now to take a deep breath and convert my entire database…

@Kourosh, I totally missed the fact that my Convert to MultiMarkdown script results in links that still point to the RTF instead of links pointing to the new Markdown records (as I used it to convert RTFs that only contained normal URLs but no DEVONthink Reference URLs…)

Here’s a script that replaces the old RTF link with the Reference URL of the new markdown record (via name).

Although it throws an error if the RTF link is inside square brackets it does replace those links too (couldn’t fix the error).

The script needs the scripting additon Satimage.osax (direct download). To install it

Either drop it onto your closed System folder and it will be installed automatically, or put it in the “Scripting Additions” folder inside your System folder (https://macscripter.net/viewtopic.php?id=24375)

-- Replace RTF links in converted MultiMarkdown records (see https://discourse.devontechnologies.com/t/script-convert-rtf-to-multimarkdown/50453) with the corresponding MultiMarkdown record Reference URL (via Name)
-- This script needs the scripting additon Satimage.osax (direct download: https://www.satimage.fr/software/downloads/Satimage411.pkg)
-- Dictionary of Satimage: https://www.satimage.fr/software/en/dictionaries/dict_satimage.html

tell application id "DNtp"
	try
		set windowClass to class of window 1
		if {viewer window, search window} contains windowClass then
			set currentRecord_s to selection of window 1
		else if windowClass = document window then
			set currentRecord_s to content record of window 1 as list
		end if
		
		repeat with thisRecord in currentRecord_s
			set theText to plain text of thisRecord
			
			set RTFLinks to (find text "(?<=\\[).*\\]\\(x-devonthink.*(?=\\))" in theText with regexp and all occurrences)
			
			repeat with thisRTFLink in RTFLinks
				set newText to plain text of thisRecord
				
				set theMatchResult to matchResult of thisRTFLink -- "matchResult" is a Satimage "find text" term
				
				set d to AppleScript's text item delimiters
				set AppleScript's text item delimiters to "]("
				set TextItems to text items of theMatchResult
				set AppleScript's text item delimiters to d
				
				set theRTFRefURL to item 2 of TextItems
				set theRTFName to item 1 of TextItems
				
				if theRTFName ends with ".rtf" then
					set theRTFNameWithoutExtension to characters 1 thru -5 in theRTFName as string
					set theMultiMarkdownRecord to (item 1 of (lookup records with file theRTFNameWithoutExtension & ".md" in current database))
					set theMultiMarkdownRefURL to reference URL of theMultiMarkdownRecord
					set theMultiMarkdownLink to theRTFNameWithoutExtension & ".md](" & theMultiMarkdownRefURL as string
				else
					set theMultiMarkdownRecord to (item 1 of (lookup records with file theRTFName & ".md" in current database))
					set theMultiMarkdownRefURL to reference URL of theMultiMarkdownRecord
					set theMultiMarkdownLink to theRTFName & "](" & theMultiMarkdownRefURL as string
				end if
				
				set replaceTheRTFLink to change (theRTFName & "\\]\\(" & theRTFRefURL) into theMultiMarkdownLink in newText with regexp
				set plain text of thisRecord to replaceTheRTFLink
				
			end repeat
		end repeat
		
	on error error_message number error_number
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
	end try
end tell

@pete31

Thanks again. I’m mainly using Find Incoming Wikilinks and a Find Incoming Direct Links scripts. I’ve now set up 2 Keyboard Maestro macros to automatically:

  • Move the current window to the left half of the screen.
  • Create a new window and move it to the right half of the screen.
  • Bring the previous window to the foreground again.
  • Run the script.

Find Incoming Links - Keyboard Maestro macros.zip (4.4 KB)

Now I I can just type Option-d or Option-w to run either!

Hey @pete31,

I put together a book on using DEVONthink that I’m releasing soon and included some of this thread. I wanted to send a thanks to you, but your profile is private. Could you send me a DM?

  • Kourosh
1 Like

@Kourosh you re using the script provided by @pete31 in your book in the chapter Finding Return Links - AppleScripts and Smart Rules.

In that section you point out that the current script for search for finding incoming WikiLinks does not yet cover aliases, and to resolve this by manually typing the alias as search.

You can also directly add these to the search query. Do note that this assumes that all aliases are separated by semicolons only (as required in the DT3 manual).

-- Find incoming links for a Markdown record via Wikilinks
-- Make sure you have two viewer windows open (with only one you'll loose the selection of the Markdown record)

tell application id "DNtp"
	
	try
		set windowClass to class of window 1
		if {viewer window, search window} contains windowClass then
			set currentRecord_s to selection of window 1
		else if windowClass = document window then
			set currentRecord_s to content record of window 1 as list
		end if
		
		if (count of currentRecord_s) = 0 then
			display notification "Please select a record"
			return
		end if
		
		if (count of viewer windows) < 2 then
			display notification "Please open a second viewer window"
			return
		end if
		
		set theRecord to item 1 of currentRecord_s
		
		if type of theRecord = markdown then
			set theName to name of theRecord
			set theAliases to aliases of theRecord
			
			-- start Insert " | " between every alias
			-- ensure double quote around each alias (for aliases of separate words) 
			-- Assumption: each alias is separated by semicolons 
			set AppleScript's text item delimiters to ";"
			set theTextItems to every text item of theAliases
			set theAliasesQuery to ""
			repeat with textItem in theTextItems
				set theAliasesQuery to theAliasesQuery & "|" & "\"" & textItem & "\""
			end repeat
			set AppleScript's text item delimiters to ""
			-- end Insert
			
			-- added theAliasesQuery to extend the search
			tell viewer window 2
				set search query to "text:" & theName & theAliasesQuery & space & "kind:markdown"
				set theResults to search results
			end tell
			
			if theResults = {} then
				display notification "No links found"
				return
			end if
			
			-- after getting the results it's possible to do other stuff, e.g. adding the reference URL of every record in the results as custom meta data of the record you started from
			
		else
			display notification "Please select a Markdown record"
			return
		end if
		
	on error error_message number error_number
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
	end try
	
	
end tell

Hey @sander2,

Thanks for that. That’s super helpful. I just gave it a run and it seems to work well. Maybe I can get it into an update.

  • Kourosh
1 Like

I think Roam Research has this function and this’s the most wonderful feature for that app.

Displaying the network of connection among those notes in DEVONthink is very useful and important for researchers and students, because if one know better on the topology of the notes, S/he would understand well on those information, moreover, based on the structure of the connection between notes, it’s beneficial to carry forward the frontier of knowledge.

1 Like

IMHO native support for showing backlinks would be a powerful upgrade to DEVONthink’s current WikiLink functionality as well as DT’s ability to help users find connections across different documents and ideas. I think most WikiLink users will welcome this feature.

To take this idea a bit further, it would also be nice to show a “local node graph” centered around the selected document, e.g. all the documents that are connected to the current document, and all the documents that are connected to those. I imagine such a local graph could have great potential to provide users insight on the current document. It’s like a graphical approach to the existing See Also & Classify functionality, but for explicit WikiLinks created by the user instead of content relevance calculated by the AI.

Recently there seems to be a surge of note taking apps that take the connections between notes seriously such as Roam Research and Obsidian, and the latter just released a Local Graph feature. I personally would be thrilled to see DEVONthink treat WikiLinks as a first class citizen, and automatic backlinks should be a very solid starting point :stuck_out_tongue:

Edit: here’s Obsidian’s Local Graph functionality in action.

3 Likes

Perhaps a solution should be to have Devonthink generating graphs similar to the ones produced in Devonagent.

I haven’t purchased DEVONagent (yet) so I looked it up. I think that is exactly what I was thinking about, good to know that DEVONagent already lets users visualize the connections. Hopefully DT will have a similar feature.

(And another reason for me to buy DEVONagent :stuck_out_tongue:)

Thanks @Kourosh for these macros. Besides the new snag (but with possible positive developments coming :wink: @cgrunenberg) in the system with respect to using the “Find incoming item links” script that @pete31 had generously provided to all (see Search for x-devonthink-item link not working), I have the curious problem on my end that when I run your macro for incoming wikilinks the script trips up at setting the record and sends me a notification “Please select a record” but when I run the same script manually from the menu it works perfectly. Any ideas…?

Hmm, that sounds odd. Instead of having it run the WikiLink script in Keyboard Maestro, what if you pointed it to an external Applescript file?

Thanks for the reply. Sorry for the delay. I went to try your suggestion and realized something else in the process. The apple script file for that (Find Incoming WikiLinks for MD.scpt) included with your book is the earlier version that doesn’t include aliases. As you mention the earlier version and an updated one on p. 257, it would seem that you had intended that script to be the updated one including aliases (right?). So I copied the script from your macro (07. Find Incoming WikiLinks), which does include the aliases and copied and pasted to create a new apple script. Then I finally was able to try your suggestion. But I got the same response error, “Please select a record”. So I copied the script above in this thread edited by @sander2 and created a new apple script file with that and again it works. Well, I guess I will just avoid this macro and run this script manually, as I don’t know enough to figure out the problem.

Along these same lines…the scripts/macros included in your book. More feedback. I have found the reverse situation with regard to the scripts/macros for @Bernardo_V’s Adding incoming back links (Return links/Back links). Both of the macros you set up to run that script 03 (04). Add Back Links to Note - With (or Without) Options work perfectly. But this time the stand alone apple script included in the book returns this for me:


So I copied and pasted the latest version (version of script A.2) (Return links/Back links) into a newly created apple script and ran that as a stand alone and it worked fine.

@kmliebo77 Thanks for letting me know about the discrepancy - I certainly must have updated one and not the other. I’ll add it to a list for an update. I’m sorry you’re having troubles with the scripts - I’ll keep my eye out for the “please select a record” issue and hopefully come up with something.

+1 for the local graph feature. DTP is already offering all the informal semantic relationships – the formal (back-)links would turn it into the most serious Zettelkasten solution out there.

1 Like

In case you’re trying to run the script I posted in this thread you’ll find that it doesn’t work in DEVONthink 3.6. That’s due to DEVONthink’s new handling of “invalide arguments”.

After the release of DEVONthink 3 I decided to continue to use “search window” in scripts so that DEVONthink 2 users could use them in, well, search windows. With version 3.6 that’s not possible anymore.

If you want to use the script you’ll have to replace this voluminous block …

set windowClass to class of window 1
if {viewer window, search window} contains windowClass then
	set currentRecord_s to selection of window 1
else if windowClass = document window then
	set currentRecord_s to content record of window 1 as list
end if

… with this neat line …

set currentRecord_s to selected records

… which does what the six lines have done. Wow, that’s great! :smiley:

Thanks for this explanation. I was always wondering if I was missing something, when I saw this seemingly complex code referring to Windows etc.

1 Like

Hey @pete31. That is awesome and works perfectly. I’m setting up an update to go out tomorrow. Cheers!

1 Like