PDF Expert integration scripts

it seems that you have to try the different possibilities and look what works for you…

For me, deep linking is working (and also opening these deep-links).

I am using the scipts posted by lawyerboy (post) but i had to edit them slightly, to get deep linking working again.

I think i only changed the getPageDetails() function, but i will just post my current config

openItem
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

property NSURLComponents : a reference to current application's NSURLComponents
property NSURLQueryItem : a reference to current application's NSURLQueryItem
property NSMutableDictionary : a reference to current application's NSMutableDictionary
property NSFileManager : a reference to current application's NSFileManager's defaultManager
property NSURL : a reference to current application's NSURL

on getPDFExpertName()
	tell application "System Events" to return name of first window of process "PDF Expert"
end getPDFExpertName

on replaceText(this_text, search_string, replacement_string)
	set str to current application's NSString's stringWithString:this_text
	return (str's stringByReplacingOccurrencesOfString:search_string withString:replacement_string) as string
end replaceText

on cleanURL(fullURL)
	--Clean up historic bad encodings
	if fullURL contains "%2520" then
		set fullURL to replaceText(fullURL, "%25", "%")
		set fullURL to replaceText(fullURL, "%23", "#")
		set fullURL to replaceText(fullURL, "&#40", "(")
		set fullURL to replaceText(fullURL, "&#41", ")")
	end if
	set fullURL to replaceText(fullURL, ".pdf&", ".pdf?")
	
	set urlObj to NSURLComponents's componentsWithString:fullURL
	
	--Handle Hook file URLs by stripping the '/file:/' component from the start of the path
	set AppleScript's text item delimiters to "file:/"
	get (urlObj's |path| as string)'s text items
	try
		if (urlObj's |path| as string)'s second text item is not "" then set urlObj's |path| to (urlObj's |path| as string)'s second text item
	end try
	
	--Handle old-style paths (which appear with a leading / ...)
	if ((urlObj's |path|) as string) contains ":Users:" then set urlObj's |path| to (POSIX path of (text 2 thru end of (urlObj's |path| as string)))
	
	--Optional: search for files where there is no match
	if not (NSFileManager's fileExistsAtPath:(urlObj's |path|)) then
		set newObj to findItemURL(urlObj)
		if newObj is not missing value then set urlObj's |path| to newObj's |path|
	end if
	
	return urlObj
end cleanURL

to findItemURL(urlObj)
	set {urlObj's |scheme|, urlObj's |host|} to {"file", ""}
	set filename to urlObj's |URL|'s lastPathComponent
	set searchResults to do shell script "mdfind -name " & quoted form of (filename as string)
	set searchResultURLs to {}
	repeat with searchResult in paragraphs of searchResults
		set end of searchResultURLs to (NSURL's fileURLWithPath:searchResult isDirectory:false relativeToURL:(urlObj's |URL|))
	end repeat
	set ourPathComponents to urlObj's |URL|'s pathComponents
	set leadingCandidate to {_URL:missing value, penalty:999999}
	repeat with searchResultURL in searchResultURLs
		set diff to ((searchResultURL's pathComponents)'s differenceFromArray:ourPathComponents)
		set penalty to (count of (diff's insertions)) + (count of (diff's removals))
		if penalty < leadingCandidate's penalty then set leadingCandidate to {_URL:searchResultURL, penalty:penalty}
	end repeat
	return contents of leadingCandidate's _URL
end findItemURL

on getKvs(fromURLComponents)
	if fromURLComponents's query() is missing value then
		set fromURLComponents's query to fromURLComponents's fragment()
		set fromURLComponents's fragment to ""
	end if
	set dict to NSMutableDictionary's new()
	try
		repeat with queryItem in fromURLComponents's queryItems
			(dict's setValue:(queryItem's value as string) forKey:(queryItem's |name|))
		end repeat
	end try
	return dict as record
end getKvs

on moveViewToPage(pageNo)
	set enabledViewElements to missing value
	
	tell application "PDF Expert" to activate
	tell application "System Events"
		tell application process "PDF Expert"
			if role description of value of attribute "AXFocusedUIElement" is "text field" then --Search bar taking focus?
				key code 53
			end if
			tell menu bar 1
				set goToPage to menu item "Go to Page..." of menu "Go"
				
				if goToPage's enabled is not true then
					--Side bar taking focus?
					set enabledViewElements to every UI element of menu "View" whose (value of attribute "AXMenuItemMarkChar" of it) is equal to "✓"
					keystroke "5" using {command down, option down} --faster than click UI element "No Left Panel" of menu "View"
				end if
				
				click goToPage
				delay 0.05
				keystroke pageNo
				keystroke return
				
				--Restore side bar if necessary
				if enabledViewElements is not missing value then
					repeat with element in enabledViewElements
						if element's name is in {"Bookmarks", "Outline", "Annotation Summary", "Thumbnails Panel"} then
							click element
							exit repeat
						end if
					end repeat
				end if
			end tell
		end tell
	end tell
end moveViewToPage

on openItem(fullURL)
	set urlObj to cleanURL(fullURL)
	
	--Test if file exists
	if not (NSFileManager's fileExistsAtPath:(urlObj's |path|)) then
		display dialog "Unable to find file for URL " & fullURL & " looking at path " & urlObj's |path| with title "Hook PDF Expert Integration" buttons {"OK"} default button 1 cancel button 1 giving up after 2
		return urlObj's |path|
	end if
	
	--Convert URL to file URL
	set {urlObj's |scheme|, urlObj's |host|} to {"file", ""}
	set furl to urlObj's |URL| as «class furl»
	
	tell application "PDF Expert" to open location furl
	
	-- Get page number
	set pageRefs to getKvs(urlObj) & {p:missing value, page:missing value} --Neuberg p. 241
	if pageRefs's p is missing value then set pageRefs's p to pageRefs's page
	set p to pageRefs's p
	if p is missing value then return
	--display dialog "Go to page " & p giving up after 1
	
	-- Get file name
	tell application "Finder" to set pdfName to displayed name of (info for furl)
	set AppleScript's text item delimiters to ".pdf"
	set pdfName to pdfName's first text item
	
	-- Move to page
	set counter to 30
	repeat while counter is greater than 0
		if getPDFExpertName() contains pdfName then
			moveViewToPage(p)
			return
		else
			delay 0.1
		end if
		set counter to counter - 1
	end repeat
end openItem

openItem("$0")
getName
set oldDelimiters to applescript's text item delimiters
to getPageNo()
	try
		tell application "System Events"
			tell process "PDF Expert"
				set pageText to value of static text 1 of splitter group 1 of window 1
			end tell
		end tell
	
		set AppleScript's text item delimiters to {" of "}
		get pageText's first text item
	end try
	
end getPageNo


tell application "System Events"
	set fileName to name of first window of process "PDF Expert"
end tell

set fullName to fileName & " p. " & getPageNo()

set applescript's text item delimiters to oldDelimiters
get fullName
getAddress

use AppleScript version “2.4” – Yosemite (10.10) or later
use framework “Foundation”
use scripting additions

property NSURLComponents : a reference to current application’s NSURLComponents
property NSURLQueryItem : a reference to current application’s NSURLQueryItem
property NSMutableDictionary : a reference to current application’s NSMutableDictionary
property NSFileManager : a reference to current application’s NSFileManager’s defaultManager
property NSURL : a reference to current application’s NSURL

–Get Address

on getPDFExpertFileURL()
local fileURL
set fileURL to missing value
tell application “System Events”
activate application “PDF Expert”
tell process “PDF Expert” to set showInFinder to menu item “Show in Finder” of menu 1 of menu bar item “File” of menu bar 1
set isEnabled to showInFinder’s enabled
end tell
if isEnabled then
tell application “System Events” to tell process “PDF Expert” to click showInFinder
delay 0.1
tell application “Finder”
set openWindows to id of every window
set fileURL to URL of (selection as alias)
close (get (every window whose id of it is not in openWindows))
end tell
end if
tell application “System Events” to activate application “PDF Expert”
return fileURL
end getPDFExpertFileURL

on getPDFExpertName()
tell application “System Events” to return name of first window of process “PDF Expert”
end getPDFExpertName

on getPageDetails()
set {pageNo, pageLabel} to {missing value, missing value}
try --Get the details we need
tell application “System Events” to tell process “PDF Expert”
set frontmost to true
click menu item “Go to Page…” of menu 1 of menu bar item “Go” of menu bar 1
click menu item “Copy” of menu 1 of menu bar item “Edit” of menu bar 1
tell application “System Events” to key code 53
set pageNo to the clipboard
set pageLabel to the clipboard
end tell
end try
return {pageNo, pageLabel}
end getPageDetails

on getAddress()
set urlBuilder to NSURLComponents’s new’s initWithString:getPDFExpertFileURL()
set {urlBuilder’s |scheme|, urlBuilder’s |host|} to {“pdfexpert”, “”}

set title to getPDFExpertName()
set {pageNo, pageLabel} to getPageDetails()

if pageNo is not missing value then
	set title to title & " p. " & pageLabel
	set urlBuilder's queryItems to {NSURLQueryItem's queryItemWithName:"p" value:pageNo}
	--set urlBuilder's fragment to "page=" & pageNo --necessary for file:/ scheme
end if

return "[" & title & "](" & (urlBuilder's |string| as string) & ")"

end getAddress

getAddress()

1 Like

Thanks much count_zero!.. Can you also let me know exactly what you’re putting in the “scheme” window?

:laughing: oh, i never even saw the “scheme” input field on the “Open Item” tab. I didn’t change it.

pdfexpert

Thanks again… at this point, for me, PDF Expert just not even seeing it (no linkable item found in PDF Expert)… seems like I will need to move to PDF Pen Pro, as it seems to just work consistently.

I modified it a little, and this works for me.

Open Item

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

property NSURLComponents : a reference to current application's NSURLComponents
property NSURLQueryItem : a reference to current application's NSURLQueryItem
property NSMutableDictionary : a reference to current application's NSMutableDictionary
property NSFileManager : a reference to current application's NSFileManager's defaultManager
property NSURL : a reference to current application's NSURL

on getPDFExpertName()
	tell application "System Events" to return name of first window of process "PDF Expert"
end getPDFExpertName

on replaceText(this_text, search_string, replacement_string)
	set str to current application's NSString's stringWithString:this_text
	return (str's stringByReplacingOccurrencesOfString:search_string withString:replacement_string) as string
end replaceText

on cleanURL(fullURL)
	--Clean up historic bad encodings
	if fullURL contains "%2520" then
		set fullURL to replaceText(fullURL, "%25", "%")
		set fullURL to replaceText(fullURL, "%23", "#")
		set fullURL to replaceText(fullURL, "&#40", "(")
		set fullURL to replaceText(fullURL, "&#41", ")")
	end if
	set fullURL to replaceText(fullURL, ".pdf&", ".pdf?")
	
	set urlObj to NSURLComponents's componentsWithString:fullURL
	
	--Handle Hook file URLs by stripping the '/file:/' component from the start of the path
	set AppleScript's text item delimiters to "file:/"
	get (urlObj's |path| as string)'s text items
	try
		if (urlObj's |path| as string)'s second text item is not "" then set urlObj's |path| to (urlObj's |path| as string)'s second text item
	end try
	
	--Handle old-style paths (which appear with a leading / ...)
	if ((urlObj's |path|) as string) contains ":Users:" then set urlObj's |path| to (POSIX path of (text 2 thru end of (urlObj's |path| as string)))
	
	--Optional: search for files where there is no match
	if not (NSFileManager's fileExistsAtPath:(urlObj's |path|)) then
		set newObj to findItemURL(urlObj)
		if newObj is not missing value then set urlObj's |path| to newObj's |path|
	end if
	
	return urlObj
end cleanURL

to findItemURL(urlObj)
	set {urlObj's |scheme|, urlObj's |host|} to {"file", ""}
	set filename to urlObj's |URL|'s lastPathComponent
	set searchResults to do shell script "mdfind -name " & quoted form of (filename as string)
	set searchResultURLs to {}
	repeat with searchResult in paragraphs of searchResults
		set end of searchResultURLs to (NSURL's fileURLWithPath:searchResult isDirectory:false relativeToURL:(urlObj's |URL|))
	end repeat
	set ourPathComponents to urlObj's |URL|'s pathComponents
	set leadingCandidate to {_URL:missing value, penalty:999999}
	repeat with searchResultURL in searchResultURLs
		set diff to ((searchResultURL's pathComponents)'s differenceFromArray:ourPathComponents)
		set penalty to (count of (diff's insertions)) + (count of (diff's removals))
		if penalty < leadingCandidate's penalty then set leadingCandidate to {_URL:searchResultURL, penalty:penalty}
	end repeat
	return contents of leadingCandidate's _URL
end findItemURL

on getKvs(fromURLComponents)
	if fromURLComponents's query() is missing value then
		set fromURLComponents's query to fromURLComponents's fragment()
		set fromURLComponents's fragment to ""
	end if
	set dict to NSMutableDictionary's new()
	try
		repeat with queryItem in fromURLComponents's queryItems
			(dict's setValue:(queryItem's value as string) forKey:(queryItem's |name|))
		end repeat
	end try
	return dict as record
end getKvs

on moveViewToPage(pageNo)
	set enabledViewElements to missing value
	
	tell application "PDF Expert" to activate
	tell application "System Events"
		tell application process "PDF Expert"
			if role description of value of attribute "AXFocusedUIElement" is "text field" then --Search bar taking focus?
				key code 53
			end if
			tell menu bar 1
				set goToPage to menu item "Go to Page..." of menu "Go"
				
				if goToPage's enabled is not true then
					--Side bar taking focus?
					set enabledViewElements to every UI element of menu "View" whose (value of attribute "AXMenuItemMarkChar" of it) is equal to "✓"
					keystroke "5" using {command down, option down} --faster than click UI element "No Left Panel" of menu "View"
				end if
				
				click goToPage
				delay 0.05
				keystroke pageNo
				keystroke return
				
				--Restore side bar if necessary
				if enabledViewElements is not missing value then
					repeat with element in enabledViewElements
						if element's name is in {"Bookmarks", "Outline", "Annotation Summary", "Thumbnails Panel"} then
							click element
							exit repeat
						end if
					end repeat
				end if
			end tell
		end tell
	end tell
end moveViewToPage

on openItem(fullURL)
	set urlObj to cleanURL(fullURL)
	
	--Test if file exists
	if not (NSFileManager's fileExistsAtPath:(urlObj's |path|)) then
		display dialog "Unable to find file for URL " & fullURL & " looking at path " & urlObj's |path| with title "Hook PDF Expert Integration" buttons {"OK"} default button 1 cancel button 1 giving up after 2
		return urlObj's |path|
	end if
	
	--Convert URL to file URL
	set {urlObj's |scheme|, urlObj's |host|} to {"file", ""}
	set furl to urlObj's |URL| as «class furl»
	
	tell application "PDF Expert" to open location furl
	
	-- Get page number
	set pageRefs to getKvs(urlObj) & {p:missing value, page:missing value} --Neuberg p. 241
	if pageRefs's p is missing value then set pageRefs's p to pageRefs's page
	set p to pageRefs's p
	if p is missing value then return
	--display dialog "Go to page " & p giving up after 1
	
	-- Get file name
	tell application "Finder" to set pdfName to displayed name of (info for furl)
	set AppleScript's text item delimiters to ".pdf"
	set pdfName to pdfName's first text item
	
	-- Move to page
	set counter to 30
	repeat while counter is greater than 0
		if getPDFExpertName() contains pdfName then
			moveViewToPage(p)
			return
		else
			delay 0.1
		end if
		set counter to counter - 1
	end repeat
end openItem

openItem("$0")

Get address

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

property NSURLComponents : a reference to current application's NSURLComponents
property NSURLQueryItem : a reference to current application's NSURLQueryItem
property NSMutableDictionary : a reference to current application's NSMutableDictionary
property NSFileManager : a reference to current application's NSFileManager's defaultManager
property NSURL : a reference to current application's NSURL

--Get Address

on getPDFExpertFileURL()
	local fileURL
	set fileURL to missing value
	tell application "System Events"
		activate application "PDF Expert"
		tell process "PDF Expert" to set showInFinder to menu item "Show in Finder" of menu 1 of menu bar item "File" of menu bar 1
		set isEnabled to showInFinder's enabled
	end tell
	if isEnabled then
		tell application "System Events" to tell process "PDF Expert" to click showInFinder
		delay 0.1
		tell application "Finder"
			set openWindows to id of every window
			set fileURL to URL of (selection as alias)
			close (get (every window whose id of it is not in openWindows))
		end tell
	end if
	tell application "System Events" to activate application "PDF Expert"
	return fileURL
end getPDFExpertFileURL

on getPDFExpertName()
	tell application "System Events" to return name of first window of process "PDF Expert"
end getPDFExpertName

on getPageDetails()
	set {pageNo, pageLabel} to {missing value, missing value}
	try --Get the details we need
		tell application "System Events" to tell process "PDF Expert"
			set frontmost to true
			click menu item "Go to Page..." of menu 1 of menu bar item "Go" of menu bar 1
			click menu item "Copy" of menu 1 of menu bar item "Edit" of menu bar 1
			tell application "System Events" to key code 53
			set pageNo to the clipboard
			set pageLabel to the clipboard
		end tell
	end try
	return {pageNo, pageLabel}
end getPageDetails

on getAddress()
	set urlBuilder to NSURLComponents's new's initWithString:getPDFExpertFileURL()
	set {urlBuilder's |scheme|, urlBuilder's |host|} to {"file", ""}
	
	set title to getPDFExpertName()
	set {pageNo, pageLabel} to getPageDetails()
	
	if pageNo is not missing value then
		set title to title & " p. " & pageLabel
		set urlBuilder's queryItems to {NSURLQueryItem's queryItemWithName:"p" value:pageNo}
		--set urlBuilder's fragment to "page=" & pageNo --necessary for file:/ scheme
	end if
	
	return "[" & title & "](" & (urlBuilder's |string| as string) & "#p=" & pageNo & ")"
end getAddress

getAddress()
1 Like

That is awesome!! Works great now- thanks!

1 Like

I have changed the script (Get address) a little bit, and this time it can auto close the opened finder window.
But it seems that if the file name contains other languages like Chinese, then it will fail to go to the specific page. I don’t know how to improve it. Hope someone can improve it.

Get address

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

property NSURLComponents : a reference to current application's NSURLComponents
property NSURLQueryItem : a reference to current application's NSURLQueryItem
property NSMutableDictionary : a reference to current application's NSMutableDictionary
property NSFileManager : a reference to current application's NSFileManager's defaultManager
property NSURL : a reference to current application's NSURL

--Get Address

on getPDFExpertFileURL()
	local fileURL
	set fileURL to missing value
	tell application "System Events"
		activate application "PDF Expert"
		tell process "PDF Expert" to set showInFinder to menu item "Show in Finder" of menu 1 of menu bar item "File" of menu bar 1
		set isEnabled to showInFinder's enabled
	end tell
	if isEnabled then
		tell application "System Events" to tell process "PDF Expert" to click showInFinder
		delay 0.1
		tell application "Finder"
			set openWindows to id of every window
			set fileURL to URL of (selection as alias)
			close(get (every window whose id of it is not in openWindows))
		end tell

		tell application "Finder"
			close Finder window 1
		end tell
	end if
	tell application "System Events" to activate application "PDF Expert"
	return fileURL
end getPDFExpertFileURL

on getPDFExpertName()
	tell application "System Events" to return name of first window of process "PDF Expert"
end getPDFExpertName

on getPageDetails()
	set {pageNo, pageLabel} to {missing value, missing value}
	try --Get the details we need
		tell application "System Events" to tell process "PDF Expert"
			set frontmost to true
			click menu item "Go to Page..." of menu 1 of menu bar item "Go" of menu bar 1
			click menu item "Copy" of menu 1 of menu bar item "Edit" of menu bar 1
			tell application "System Events" to key code 53
			set pageNo to the clipboard
			set pageLabel to the clipboard
		end tell
	end try
	return {pageNo, pageLabel}
end getPageDetails

on getAddress()
	set urlBuilder to NSURLComponents's new's initWithString:getPDFExpertFileURL()
	set {urlBuilder's |scheme|, urlBuilder's |host|} to {"file", ""}
	
	set title to getPDFExpertName()
	set {pageNo, pageLabel} to getPageDetails()
	
	if pageNo is not missing value then
		set title to title & " p. " & pageLabel
		set urlBuilder's queryItems to {NSURLQueryItem's queryItemWithName:"p" value:pageNo}
		--set urlBuilder's fragment to "page=" & pageNo --necessary for file:/ scheme
	end if
	
	return "[" & title & "](" & (urlBuilder's |string| as string) & "#p=" & pageNo & ")"
end getAddress

getAddress()
5 Likes

It works!
You’re a lifesaver and you’ve also solved the problem Finder window issue.
Thank you so much.

1 Like

Thanks a lot for the scrip! Unfortunately I cannot get it running. Are newer versions not working? The post is from 2019. Any experiences or hints?

Similarly hoping for some updates here - I also can’t seem to get this to work.