I found a way to solve your problem using only KM actions (I don't mind if you prefer using the Javascript solution provided above, but for personal reasons I had to find a solution that uses KM.) I can't guarantee it will work with your app because I didn't test your app's links. But here's how it works for me using hyperlinks created from web browsers placed into the system clipboard:
The trick was finding a way that produced both the hyperlink and its display name. My solution was to write the clipboard to a file specifying plaintext output, and then reading the file back in. But some forms of reading didn't work, like the KM action. My method works, but I don't really understand why. I may be able to simplify it, but this is pretty simple.
As you can see my method extracts the link using a regex. I'm not sure if this method will work for you because I can't see the details of your app's links. And my method may not work for any link whose display name or hyperlink contains a double quote. But it should work for the majority of cases. If you want to fine tune it, we can try that later.
OOPS there appears to be a filename typo. I'll fix that. It's fixed.
I agree that Apple Script is hard to read. I'm a recovering programmer and while I can this code, I couldn't have written.
That said it does the job. I almost wonder if I should refactor into a "library" like function for general use in KM. That said I've always like the rule of '3' from the Gang of Four patterns book. You need to see something in use three times before attempting to generalize.
True. I still managed to parse it. I think it was the use of NSObject, etc which my brain sees as very mac like. Caveat emptor, I last coded on Mac professionally when munger was a function.
It's JavaScript, or more technically, JavaScript for Automation, otherwise known as "JXA". It uses a call to the Objective-C library available in JXA, which is what makes it look so strange.
Yes it's a good idea to take code like this and stick it in a subroutine-type of macro.
If I want to make a piece of copied text plain text without any embedded links etc, I make it into a Variable. Variables are plain text with no other info such as styles or links.
Using that Set Variable action on a link strips out the hyperlink rather than stripping out the link's visible text, which is the opposite of what needs to be done in this case.
If I recall, it took me four hours to come up with a solution that strips out the visible text instead of the hyperlink. It was a tough problem.
I did try a version of that early on and it didn't work. Since I can't easily tell the state of the clipboard from visual inspection I couldn't tell the why.
I almost wish that @peternlewis would give us an assertion facility for KM. Then I could assert that the clipboard was in a known state, the assertion would fail and I would iterate.
(Can you tell I spent 20+ yrs writing code and was one of the earliest adopters of both JUnit and NUnit
Ah. I had missunderstood. I thought he wanted to turn the copied text into plain text and strip out a hyperlink. In my defence that’s what he seemed to be asking
When you copy a selection in a macOS application, the pasteboard typically contains material of various different types.
If I copy from Chrome for example,
There is public.html content,
but also, separately and simultaneously public.utf8-plain-text
if I copy some text in OmniGraffle, then the types of content in the pasteboard may include, simultaneously, and inter alia:
public.rtf
public.utf8-plain-text
public.utf16-external-plain-text
i.e. the question is not what the type of the clipboard 'is', but how many different pasteboard items it contains, and what the type of each of them is.
Through osascript (in AppleScript or JS idioms) you can get a listing with incantations like:
(() => {
"use strict";
ObjC.import("AppKit");
const main = () =>
clipTextLR();
// --------------------- GENERIC ---------------------
// clipTextLR :: () -> Either String String
const clipTextLR = () => {
// Either a message, (if no clip text is found),
// or the string contents of the clipboard.
const
v = ObjC.unwrap(
$.NSPasteboard.generalPasteboard
.stringForType($.NSPasteboardTypeString)
);
return Boolean(v) && 0 < v.length ? (
Right(v)
) : Left("No utf8-plain-text found in clipboard.");
};
// Left :: a -> Either a b
const Left = x => ({
type: "Either",
Left: x
});
// Right :: b -> Either a b
const Right = x => ({
type: "Either",
Right: x
});
return main();
})();
Wow. I feel like I've just walked in to some famous building of great antiquity, like the Taj Mahal, or Westminster Abbey, or St Basil's Cathedral, or St Peter's Basilica, or Petra. "I've never seen anything like this before."