How to retrieve PDF Page Link from Keyboard Maestro?

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?

This script copies the Reference URL

-- 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

There is an alternate command in the Edit menu when holding the Shift key.

1 Like

Can’t find that menu. Pressing ⌥ in the Edit menu also doesn’t alternate Copy Item Link.

I modified my post to reflect it’s the Edit menu.

@cgrunenberg: The menu command requires explictly focusing the view/edit pane. Not sure if that’s intentional.

1 Like

That’s the second time today :smile:

What’s the second time today ?

That focusing the view/edit pane is needed: Editing Bar and URL field .

However the Copy Item Link menu doesn’t change over here even I use the contextual menu inside the view/edit pane.

Ugh - I need a nap. Shift key.

1 Like

Me too. The contextual menu in the view/edit pane shows Copy Page Link by default. No modifier needed.

Perhaps an issue in my internal build.

That’s what I needed. Thanks!

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.

FWIW I’ve also updated the generic Copy As Markdown Link macro for Keyboard Maestro to include the ?page= attribute when copying from DEVONthink 3

3 Likes

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.