I frequently find myself copying links to specific pages of documents to include them in my notes. This way I can easily access the relevant passages on later review.
Though, I prefer to annotate with PDF Expert. This often entails finding the pdf in dt3, going to the corresponding page and copying the item link in order to get the referencing URL. I’d like to evade those steps.
While working on a solution I came across this thread: Script: Open DEVONthink record for PDF Expert tab. Thanks @pete31 for this! Makes for a feasible result. Here’s my derivative script:
-- Get the x-devonthink-item URL for the active document's page in PDF Expert
--
-- Via "Open DEVONthink record for current PDF Expert tab"
-- https://discourse.devontechnologies.com/t/script-open-devonthink-record-for-pdf-expert-tab/47243
-- solution for umlauts ("iconv -t UTF8-MAC") found here: https://stackoverflow.com/questions/23219482/bash-ps-grep-for-process-with-umlaut-os-x/23226449#23226449
tell application "System Events"
activate application "PDF Expert"
delay 1
tell process "PDF Expert"
click menu item "Gehe zu Seite..." of menu 1 of menu bar item "Gehe zu" of menu bar 1
end tell
tell application "System Events" to keystroke "c" using {command down}
delay 1
set pageNum to the clipboard
tell application "System Events"
key code 53
-- esc
end tell
delay 1
try
tell application process "PDF Expert"
tell window 1
set theFileName to value of attribute "AXTitle" & ".pdf"
if theFileName starts with "* " then set theFileName to characters 3 thru -1 in theFileName as string
end tell
set PID to unix id
end tell
on error error_message number error_number
if the error_number is not -128 then
display alert "System Events" & space & error_number message error_message as warning
return
end if
end try
end tell
set theOpenFiles to (do shell script "lsof -p " & PID)
set convertedOutput to (do shell script "iconv -t UTF8-MAC <<<$" & quoted form of theOpenFiles)
set theLines to paragraphs of convertedOutput
repeat with thisLine in theLines
if thisLine contains theFileName then
set thePath to characters (offset of "/" in thisLine) thru -1 in thisLine as string
exit repeat
end if
end repeat
tell application id "DNtp"
try
set theDatabases to databases
set theResults to {}
repeat with thisDatabase in theDatabases
set thisDatabasesResults to lookup records with path thePath in thisDatabase
set theResults to theResults & thisDatabasesResults
end repeat
if theResults = {} then
display notification "Dokumentpfad nicht in geöffneten Datenbanken enthalten!" with title "Lookup DEVONthink"
return
else
set theUUID to uuid of (item 1 of theResults)
set callback to "x-devonthink-item://" & theUUID & "?page=" & pageNum
set the clipboard to callback
display notification callback with title ("x-devonthink-item URL")
end if
on error error_message number error_number
if the error_number is not -128 then
display alert "DEVONthink Pro" & space & error_number message error_message as warning
return
end if
end try
end tell
2 Likes
I like the idea, but when you get the page with this method via PDF Expert, sometimes you’ll get the printed page number, but not the actual page DT3 needs for the link.
Just now I tested it on a PDF. The printed page number (and the number displayed by PDF Expert and DT3) was 47. But when I use the copy page URL command in DT3, the page number was 57. This because the pdf is not computing the pages numbered i to x.
This here will work with Adobe Acrobat and with Skim.
set thePage to ""
set thePath to ""
set front_app to (path to frontmost application as Unicode text)
if front_app contains "Acrobat" then
tell application "Adobe Acrobat"
-- activate
set theDoc to item 1 of PDF Windows
set thePage to get page number of theDoc
set thePage to thePage - 1
set thePath to file alias of front document
set thePath to POSIX path of thePath
end tell
end if
if front_app contains "Skim" then
tell application "Skim"
-- activate
set theDoc to front document
set thePage to get index for current page of theDoc
set thePage to thePage - 1
set thePath to the path of theDoc
end tell
end if
if thePage is not "" then
tell application id "DNtp"
try
set theDatabases to databases
set theResults to {}
repeat with thisDatabase in theDatabases
set thisDatabasesResults to lookup records with path thePath in thisDatabase
set theResults to theResults & thisDatabasesResults
end repeat
if theResults = {} then
display notification "Document could not be found in open databases" with title "Lookup DEVONthink"
return
else
set theUUID to uuid of (item 1 of theResults)
set callback to "x-devonthink-item://" & theUUID & "?page=" & thePage
set the clipboard to callback
display notification callback with title ("x-devonthink-item URL")
end if
on error error_message number error_number
if the error_number is not -128 then
display alert "DEVONthink Pro" & space & error_number message error_message as warning
return
end if
end try
end tell
end if
1 Like
Hey Bernardo,
thanks for pointing that out! While for most cases that won’t cause a problem for me, it would be nice to have a workaround. Just in case.
I observed something: Assume you have a document with pages i-v followed by pages 1-10: A pair of two ranges <i-v,1-10>, say the curated page count, at 15 pages total, say the actual page count.
If I run the script on the document viewed in PDF Expert on page 6 (of the curated page count), the reference URL will bring me to page 1 (curated) in dt3 or page 6 (actual) respectively, just as you pointed out (the desired position in the actual page count’s range is 11). Now the observation: If I click on the current page/ page count indicator[^1] in dt3 and enter ‘6’, it brings me to the correct (curated) page. Dt3 handles the alphanumerical mix just fine. If I’m in the range <i-v> the indicator also displays, e.g. “iv”.
So, the record must have the relevant information as one of its properties, right? If we had access to it, then there was a workaround. What we can access however, as far as I can tell, is just this:
page count (integer, r/o) : The page count of a record. Currently only supported by PDF documents.
With information about both sides of the pair we could simply add the left range to the current page position (if >= 1) and had the correct reference URL. Could this be done, developers?
[^1]: 
I found a different workaround:
-- Get the x-devonthink-item URL for the active document's page in PDF Expert v.2
--
-- Via "Open DEVONthink record for current PDF Expert tab"
-- https://discourse.devontechnologies.com/t/script-open-devonthink-record-for-pdf-expert-tab/47243
-- solution for umlauts ("iconv -t UTF8-MAC") found here: https://stackoverflow.com/questions/23219482/bash-ps-grep-for-process-with-umlaut-os-x/23226449#23226449
tell application "System Events"
activate application "PDF Expert"
delay 1
tell process "PDF Expert"
click menu item "Gehe zu Seite..." of menu 1 of menu bar item "Gehe zu" of menu bar 1
end tell
tell application "System Events" to keystroke "c" using {command down}
delay 1
set pageNum to the clipboard
tell application "System Events"
key code 53
-- esc
end tell
delay 1
tell process "PDF Expert"
click menu item "Letzte Seite" of menu 1 of menu bar item "Gehe zu" of menu bar 1
delay 1
click menu item "Gehe zu Seite..." of menu 1 of menu bar item "Gehe zu" of menu bar 1
end tell
tell application "System Events" to keystroke "c" using {command down}
delay 1
set lastPageCurated to the clipboard
set the clipboard to pageNum
tell application "System Events" to keystroke "v" using {command down}
tell application "System Events"
key code 36
-- esc
end tell
delay 1
try
tell application process "PDF Expert"
tell window 1
set theFileName to value of attribute "AXTitle" & ".pdf"
if theFileName starts with "* " then set theFileName to characters 3 thru -1 in theFileName as string
end tell
set PID to unix id
end tell
on error error_message number error_number
if the error_number is not -128 then
display alert "System Events" & space & error_number message error_message as warning
return
end if
end try
end tell
set theOpenFiles to (do shell script "lsof -p " & PID)
set convertedOutput to (do shell script "iconv -t UTF8-MAC <<<$" & quoted form of theOpenFiles)
set theLines to paragraphs of convertedOutput
repeat with thisLine in theLines
if thisLine contains theFileName then
set thePath to characters (offset of "/" in thisLine) thru -1 in thisLine as string
exit repeat
end if
end repeat
tell application id "DNtp"
try
set theDatabases to databases
set theResults to {}
repeat with thisDatabase in theDatabases
set thisDatabasesResults to lookup records with path thePath in thisDatabase
set theResults to theResults & thisDatabasesResults
end repeat
if theResults = {} then
display notification "Dokumentpfad nicht in geöffneten Datenbanken enthalten!" with title "Lookup DEVONthink"
return
else
set theUUID to uuid of (item 1 of theResults)
set totalPageCount to page count of (item 1 of theResults)
if lastPageCurated is not equal to totalPageCount then
set alphaNum to (totalPageCount - lastPageCurated)
set pageNum to (pageNum + alphaNum)
end if
set callback to "x-devonthink-item://" & theUUID & "?page=" & (pageNum - 1)
set the clipboard to callback
display notification callback with title ("URL copied to clipboard:")
end if
on error error_message number error_number
if the error_number is not -128 then
display alert "DEVONthink Pro" & space & error_number message error_message as warning
return
end if
end try
end tell
Btw. the x-devonthink-item URL is zero-based on purpose, right (and will always stay that way)?
1 Like
Yes, the page parameter in an item link is zero-based.