In order to use Keyboard Maestro with PDFs in DEVONthink, I would like to retrieve the PDF Page Link from the currently active PDF. The only way to find this that I am aware of is in the right-click context menu:
I am unable to trigger that menu item using KBM. Is there a way to get the same “Copy Page Link” entry in an application-level menu, perhaps in the scripts section?
-- Copy Reference URL
tell application id "DNtp"
try
if not (exists think window 1) then
error "Please open a window"
else
set theWindow to think window 1
end if
set theRecord to content record of theWindow
if theRecord ≠ missing value then
set thePage to current page of theWindow
if thePage ≠ -1 then
set theRefURL to reference URL of theRecord & "?page=" & thePage
else
set theRefURL to reference URL of theRecord
end if
else
error "Please select a record"
end if
set the clipboard to theRefURL as string
display notification "Copied" with title "DEVONthink"
on error error_message number error_number
if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
return
end try
end tell
A variant which copies the URL (with any page attribute), as a Markdown link in the [Title](url) format:
(For testing in Script Editor, choose JavaScript from the top left language selector)
JS Source
(() => {
'use strict';
// Copy DEVONthink 3 URL as Markdown [title](link)
// ( including any ?page=nn attribute in a content record)
// For multiple selections outside content records,
// copies several md links.
// Rob Trew @2020
// Ver 0.2
ObjC.import('AppKit');
// main :: IO ()
const main = () => {
const
think = Application('DEVONthink 3'),
windows = think.thinkWindows,
sa = Object.assign(Application.currentApplication(), {
includeStandardAdditions: true
});
return either(
msg => sa.displayNotification(msg, {
withTitle: 'Copy reference URL'
})
)(
url => (
copyText(url),
Application('Keyboard Maestro Engine')
.setvariable('mdLink', {
to: url
}),
sa.displayNotification(url, {
withTitle: 'Reference URL copied.'
}),
url
)
)(
bindLR(
0 < windows.length ? (
Right(windows.at(0))
) : Left('No windows open.')
)(
window => {
const record = window.contentRecord();
return null !== record ? (() => {
const
title = record.name(),
page = window.currentPage(),
pageString = -1 !== page ? (
`?page=${page}`
) : '';
return Right(
`[${title}]` + (
`(${record.referenceURL()}${pageString})`
)
);
})() : (() => {
const selections = think.selection();
return 0 < selections.length ? (
Right(
selections.map(
x => `[${x.name()}](${x.referenceURL()})`
).join('\n')
)
) : Left('Nothing selected in DEVONthink.');
})();
}
));
};
// ----------------------- JXA -----------------------
// copyText :: String -> IO String
const copyText = s => {
const pb = $.NSPasteboard.generalPasteboard;
return (
pb.clearContents,
pb.setStringForType(
$(s),
$.NSPasteboardTypeString
),
s
);
};
// --------------------- GENERIC ---------------------
// Left :: a -> Either a b
const Left = x => ({
type: 'Either',
Left: x
});
// Right :: b -> Either a b
const Right = x => ({
type: 'Either',
Right: x
});
// bindLR (>>=) :: Either a ->
// (a -> Either b) -> Either b
const bindLR = m =>
mf => undefined !== m.Left ? (
m
) : mf(m.Right);
// either :: (a -> c) -> (b -> c) -> Either a b -> c
const either = fl =>
// Application of the function fl to the
// contents of any Left value in e, or
// the application of fr to its Right value.
fr => e => 'Either' === e.type ? (
undefined !== e.Left ? (
fl(e.Left)
) : fr(e.Right)
) : undefined;
// MAIN ---
return main();
})();
UPDATED
If there is no active content record, now copies a markdown link for each of the selected records.
Hat tip - I was just starting to use DevonThink with the Brain a few a days ago. I made a note describing this as problem and wondered how I could solve it. Voila. Bonus your applet solves a bigger version of this than I had imagine CMD+OPT+M is now embedded in my brain.