PDF Expert integration scripts

Oh no, do not work again. Thanks anyway man.
Did I miss any step? Is copying & pasting all I need to do ?

For linking to entire PDFs (rather than deep linking): If you can manually get a link to the PDF in PDFExpert, then you could use the Focus on Link in Clipboard command in the clipboard to set Hook’s title bar to this document. From that point on you could hook items to the document.

I modified lawyerboy’s Get Address script so Hook can use his Open Item script.

But the bad thing about the change is the page number can’t be appended to the file name.

If you find the script is not working for you, e.g., you get No linkable item found error, you can change the number at line 23 of Get Address script, increase it by 0.1 each time and see it solves the problem:
line 23: delay 0.3

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.3
		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 pageNoText to value of static text 1 of splitter group 1 of window 1
			set pageLabelText to value of static text 2 of splitter group 1 of window 1
		end tell
	end try
	try --Set pageNo
		set AppleScript's text item delimiters to {" of "}
		set pageNo to pageNoText's first text item
	end try
	try --Only try setting pageLabel if the value may make sense
		if (pageLabelText starts with "Back to ") or (pageLabelText starts with "Go to") or (pageLabelText = "") or (pageLabelText is missing value) then error
		set pageLabel to pageLabelText
	on error
		set pageLabel to pageNo
	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()
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")

2 Likes

It works great!

Thank you so much. God bless you.

1 Like

Welcome to the Hook Productivity Forum , @shawn. Delighted it works for you.

1 Like

If i open Hook(⌃ + H) on the ‘PDF Expert’ , the ‘Finder’ shows up together, can i prevent it?
The process may be running behind the scenes, but don’t want the window to pop up.

In this question, It’s just about copy specific pdf page markdown link to paste it.
I’d greatly appreciate any help you can offer.

PDF Expert lacks automation for linking. It does a linkable app in the sense defined by Mac developers here: Manifesto for Ubiquitous Linking. The script above uses a work-around involving the Finder. It is a problem with Readdle, you could ask them to take a few minutes to implement an API for linking: Contacting Developers of Other Apps and Information for Developers; it normally takes a dev less than a day to do it. Or you could choose from their competitors that are linkable (there are several to choose from).

1 Like

It is very kind of you to make an e-mail form. Thank you. I’ll send an email right away.

1 Like

I have contacted Readdle with the request letter template and links, as I’m sure many others have done. I received a not so encouraging reply. It would be nice if those who have implemented an API would offer a discount for switching!

1 Like

How to set this up in Hook? I’m a newbie here, can you tell me how to do this?

Starting from yesterday suddenly the get address script

  • forces an about every 3 sec flashing of a Finder window on top of Pdfexpert making it annoying or even impossible to use further. The flash is so short that I can’t even see the window content. Only that the menu bar changes to Finder.

I still had the adapted script from lawyerboy in use from last year running w/o complaint.
Now tried your update, without avail though - the flashing continues.

Did not change anything on my part but there probably where updates on the side of PdfExpert. But, as of now and just checked, PdfExpert still is not scriptable.

Did that flashing problem happen to anyone else?

Sorry for the trouble.

Could you please let us know your macOS version, Hook version and PDF expert version?
I just tried the latest PDF expert and latest Hook. But I don’t see the every 3 secs flashes.

What does your menubar icon look like?

Could you please check the status of the preference for “Show current item’s number of hooks in menu bar icon” ? You can find it in Hook preferences window->General. If it is on, please turn it off and see if it makes any difference.

Thank you

Thank you for responding.

I’m using

  • macOS 12.4 on an M1 MBA
  • PDFExpert Version 3.0.22 (8430)
  • Hook Version 3.7 (4861; Integration v. 225)
  • The “Show current item’s number of hooks in menu bar icon” is on and I remember that it was showing a red question mark since a few days but sometimes gone. After I reinserted the “get address” script it came back
  • after disabling the “Show current item’s number of hooks in menu bar icon” PDFexpert seems peaceful so far. I hold my breath :slight_smile:

Possibly this problem appeared for me right after the latest Hook-update …

Maybe this helps you to shed some more lightt on this.

Would you mind sharing your get address script with us? You can send the script to support@cogsciapps.com .

When the following happens, does Menu bar icon has a red question mark?
" forces an about every 3 sec flashing of a Finder window on top of Pdfexpert making it…"

Thank you

Would you mind sharing your get address script with us?

my script is no secret, in fact it is all literal the one I copied from your kind recent post in this chat:
PDF Expert integration scripts - #45 by bchend

When the following happens, does Menu bar icon has a red question mark?
" forces an about every 3 sec flashing of a Finder window on top of Pdfexpert making it…"
Yes. In deed.

  • and the issue is reproducible. Just did.

    Screenshot of ScreenFloat

Hi folks,

i don’t know if i did anything wrong, but the getPageNo() function did’t work for me ( i think in the 1st version i always got the wrong page number) so i had to alter it.
In the current version, the result of this function (without my change) is always empty for me.

Today i read sth. of “better pdf reader support” in the release notes and so i did the update and also updated the hook scripts for pdfExpert (manually, like c&p). But after that, linking didn’t work anymore…

First, i realized that if i have an open finder window, it didn’t work at all (i also get an error if trying to run the script in script editor with an already open finder window).
When i have no open finder window, it works only for the whole pdf (no deep linking possible).
Then i remembered that i changed the getPageNo() function - and after i changed this function again (in the Get-Address script), deep-linking in pdf expert works again (also with open finder windows…).

In case someone has problems with the original script version maybe it is worth a try :slight_smile:
Dont use it if everthing works :wink:

The changed getPageNo() function is kind of (ugly) slow, because it has to open and interact with one window of pdf Expert to copy the current page number to clipboard…

changed getPageNo() function (was used in the old version of get address posted by lawyerboy)

on getPageNo()
	try
		tell application "System Events"
			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 pageText to the clipboard
			end tell
		end tell
		return pageText
	on error
		return ""
	end try
end getPageNo

changed getPageDetails() function (used in new version of get address posted by lawyerboy)
i didn’t look into why the var pageLabel is used - just did enough change to make it working for me again :slight_smile:

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

Hi @bchend. Using your exact scripts. For whatever happened between now and then (Hook tossed the “number of …” in the icon, PdfExpert may have had some update etc ), now the script have turned dysfunctional to me. creates a simple link to the App. That’s all. no matter of me having pdf layout structure of not, bookmarking or not.

This file, like many of mine, happens to be printed into pdf and had no page numbers originally. PDFexpert has a page numbering option. did that. No avail.

Any clue?

Than tried @count_zero 's rendition of the getpageDetail function. This at least comes up with something that looks like a qualified link with the page number at the end. The open item script, however, does not know what to do with it and just opens the document (at least not only the app) but remains indifferent to page numbers.

Any one else running into this ?

Hey Cmon,

have you tried to debug your issue with Script Editor? If you have no experience with it, i could help you to get started. Maybe we get a hint which part of the script fails then…

Switched to PenPro a few months ago. Integration friendly is now on my “won’t get without it list”.

Hi Folks… Haven’t tried hook for more than 2 years, but back giving it a whirl. I see they’ve made many improvements. That said, I also see there are still “challenges” with PDF Expert… Looking back, I was on this thread in 2019!

I have both PDF Expert and Pen Pro. I prefer PDF Expert (especially on iPad). I’m wondering if someone could do me a favor and post what the “best” script to use is at this point, and if it does or does not support deep linking (to page).

I’m also a bit on the fence about just giving up and moving “full time” to PDF Pen Pro… Thanks much!