Add PDFExpert.scpt
This commit is contained in:
parent
33f9dcdafe
commit
69e84c1880
197
PDFExpert.scpt
Normal file
197
PDFExpert.scpt
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
(*
|
||||||
|
Batch-OCR selected PDFs in DEVONthink using PDF Expert
|
||||||
|
Originally by Alex Wellerstein – adapted by ChatGPT, May 2025
|
||||||
|
Released to the public domain: absolutely no warranties, guarantees, promises, *anything*.
|
||||||
|
Tested on macOS 14.6.1 • DEVONthink 3.9.x • PDF Expert 3.10.10
|
||||||
|
*)
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- 1. COLLECT THE SELECTION FROM DEVONTHINK
|
||||||
|
------------------------------------------------------------
|
||||||
|
tell application id "DNtp" -- DEVONthink’s four-letter bundle ID
|
||||||
|
activate
|
||||||
|
set theSelection to selection
|
||||||
|
end tell
|
||||||
|
|
||||||
|
if theSelection is {} then
|
||||||
|
display dialog "Nothing is selected in DEVONthink." buttons {"Cancel"} default button 1 with icon caution
|
||||||
|
return
|
||||||
|
end if
|
||||||
|
|
||||||
|
-- Build a simple AppleScript list of POSIX paths for any *PDF* items.
|
||||||
|
set theFiles to {}
|
||||||
|
repeat with rec in theSelection
|
||||||
|
try
|
||||||
|
tell application id "DNtp"
|
||||||
|
if type of rec is PDF document then -- skip anything that isn’t a PDF
|
||||||
|
set end of theFiles to POSIX path of (path of rec as string)
|
||||||
|
end if
|
||||||
|
end tell
|
||||||
|
end try
|
||||||
|
end repeat
|
||||||
|
|
||||||
|
if theFiles is {} then
|
||||||
|
display dialog "None of the selected items is a PDF." buttons {"Cancel"} default button 1 with icon caution
|
||||||
|
return
|
||||||
|
end if
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- 2. SET UP A PROGRESS BAR
|
||||||
|
------------------------------------------------------------
|
||||||
|
set totalFiles to length of theFiles
|
||||||
|
set progress total steps to totalFiles
|
||||||
|
set progress completed steps to 0
|
||||||
|
set progress description to "Processing PDFs with PDF Expert…"
|
||||||
|
set progress additional description to "Starting…"
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
-- 3. LOOP THROUGH EACH PDF AND RUN YOUR ORIGINAL OCR ROUTINE
|
||||||
|
------------------------------------------------------------
|
||||||
|
repeat with i from 1 to totalFiles
|
||||||
|
set thePath to item i of theFiles
|
||||||
|
set progress completed steps to i
|
||||||
|
set progress additional description to "Processing " & i & " of " & totalFiles & "…"
|
||||||
|
|
||||||
|
my pdfexpert_ocr(thePath) -- run your existing handler
|
||||||
|
|
||||||
|
-- Refresh the record inside DEVONthink so its thumbnails & metadata update
|
||||||
|
try
|
||||||
|
tell application id "DNtp"
|
||||||
|
set recList to lookup records with path thePath -- returns a list (usually length 1)
|
||||||
|
repeat with r in recList
|
||||||
|
update record r without asking -- silent refresh
|
||||||
|
end repeat
|
||||||
|
end tell
|
||||||
|
end try
|
||||||
|
|
||||||
|
-- Free up RAM every ten files (same logic you had)
|
||||||
|
if i mod 10 is 0 then
|
||||||
|
tell application "PDF Expert" to quit
|
||||||
|
delay 1
|
||||||
|
end if
|
||||||
|
end repeat
|
||||||
|
|
||||||
|
log "All done!"
|
||||||
|
display dialog "OCR finished for " & totalFiles & " PDF(s)." buttons {"OK"} default button 1
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- ↓↓↓ EVERYTHING BELOW HERE IS YOUR ORIGINAL CODE, UNCHANGED ↓↓↓
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
on pdfexpert_ocr(filePath)
|
||||||
|
log ("Starting OCR for " & filePath)
|
||||||
|
do shell script "open " & quoted form of filePath -- assumes PDF Expert is the default PDF viewer
|
||||||
|
delay 0.5
|
||||||
|
activate application "PDF Expert"
|
||||||
|
delay 0.5
|
||||||
|
set fileTitle to getFilename(filePath, ".pdf")
|
||||||
|
tell application "System Events"
|
||||||
|
tell process "PDF Expert"
|
||||||
|
|
||||||
|
-- locate the window that matches the file name
|
||||||
|
set win to false
|
||||||
|
repeat with w in every window
|
||||||
|
if (title of w) is fileTitle then set win to w
|
||||||
|
end repeat
|
||||||
|
|
||||||
|
if (win is false) then
|
||||||
|
delay 2 -- give PDF Expert a moment more
|
||||||
|
repeat with w in every window
|
||||||
|
if (title of w) is fileTitle then set win to w
|
||||||
|
end repeat
|
||||||
|
end if
|
||||||
|
|
||||||
|
if (win is false) then
|
||||||
|
display dialog "Could not find window for “" & fileTitle & "” in PDF Expert." buttons {"Cancel"} default button 1 with icon stop
|
||||||
|
error number -128
|
||||||
|
end if
|
||||||
|
|
||||||
|
-- click “Recognize Text” in Scan & OCR
|
||||||
|
click my getElementByClassAndName("Recognize Text", false, entire contents of win)
|
||||||
|
|
||||||
|
-- click “Recognize…” in the side bar
|
||||||
|
tell my getElementByClassAndName("Recognize...", false, entire contents of win)
|
||||||
|
click
|
||||||
|
-- choose “All” pages when the dialog appears (if >1 page)
|
||||||
|
if exists radio button "All" of sheet 1 of win then
|
||||||
|
click radio button "All" of sheet 1 of win
|
||||||
|
click button "Apply" of sheet 1 of win
|
||||||
|
end if
|
||||||
|
end tell
|
||||||
|
|
||||||
|
delay 1 -- short head-start before polling
|
||||||
|
|
||||||
|
repeat -- poll until the progress sheet disappears
|
||||||
|
try
|
||||||
|
if not (exists win) or (count sheet of win) = 0 then exit repeat
|
||||||
|
if not (exists progress indicator 1 of sheet 1 of win) then exit repeat
|
||||||
|
on error
|
||||||
|
exit repeat -- any UI error = assume finished
|
||||||
|
end try
|
||||||
|
end repeat
|
||||||
|
|
||||||
|
delay 1 -- extra cushion
|
||||||
|
|
||||||
|
-- save & close
|
||||||
|
set fileMenu to menu "File" of menu bar item "File" of menu bar 1
|
||||||
|
click my getElementByClassAndName("Save", false, entire contents of fileMenu)
|
||||||
|
delay 1
|
||||||
|
if my isSaved(front window) then
|
||||||
|
click my getElementByClassAndName("Close Window", false, entire contents of fileMenu)
|
||||||
|
else
|
||||||
|
log "WARNING: file might not have saved!"
|
||||||
|
end if
|
||||||
|
end tell
|
||||||
|
end tell
|
||||||
|
end pdfexpert_ocr
|
||||||
|
|
||||||
|
-- utility handlers (unchanged from your original)
|
||||||
|
on getFilename(theFile, theExtension)
|
||||||
|
tell application "Finder" to set fName to name of (POSIX file theFile as alias)
|
||||||
|
if (theExtension is not "") then
|
||||||
|
return trimText(fName, theExtension, "end")
|
||||||
|
else
|
||||||
|
return fName
|
||||||
|
end if
|
||||||
|
end getFilename
|
||||||
|
|
||||||
|
on trimText(theText, theCharactersToTrim, theTrimDirection)
|
||||||
|
set theTrimLength to length of theCharactersToTrim
|
||||||
|
if theTrimDirection is in {"beginning", "both"} then
|
||||||
|
repeat while theText begins with theCharactersToTrim
|
||||||
|
try
|
||||||
|
set theText to characters (theTrimLength + 1) thru -1 of theText as string
|
||||||
|
on error
|
||||||
|
return ""
|
||||||
|
end try
|
||||||
|
end repeat
|
||||||
|
end if
|
||||||
|
if theTrimDirection is in {"end", "both"} then
|
||||||
|
repeat while theText ends with theCharactersToTrim
|
||||||
|
try
|
||||||
|
set theText to characters 1 thru -(theTrimLength + 1) of theText as string
|
||||||
|
on error
|
||||||
|
return ""
|
||||||
|
end try
|
||||||
|
end repeat
|
||||||
|
end if
|
||||||
|
return theText
|
||||||
|
end trimText
|
||||||
|
|
||||||
|
on getElementByClassAndName(targetName, targetClass, targetElements)
|
||||||
|
repeat with uiElem in targetElements
|
||||||
|
try
|
||||||
|
if (targetClass is false and name of uiElem is targetName) ¬
|
||||||
|
or (name of uiElem is targetName and class of uiElem is targetClass) then ¬
|
||||||
|
return uiElem
|
||||||
|
end try
|
||||||
|
end repeat
|
||||||
|
return false
|
||||||
|
end getElementByClassAndName
|
||||||
|
|
||||||
|
on isSaved(win)
|
||||||
|
try
|
||||||
|
set winName to name of win
|
||||||
|
if winName begins with "*" then return false
|
||||||
|
end try
|
||||||
|
return true
|
||||||
|
end isSaved
|
||||||
Loading…
x
Reference in New Issue
Block a user