Copy selected link(s) from browser as markdown?

From Applescript you would essentially create a record with two fields:

  • Unicode Text :
  • «class RTF » : «data RTF »

and then set the clipboard contents to that record.

Skipping the details of obtaining hex-encoded RTF:

set strText to "hello world!"
set strRTF to "{\\rtf1\\ansi\\ansicpg1252\\cocoartf1348\\cocoasubrtf170
{\\fonttbl\\f0\\fswiss\\fcharset0 Helvetica;}
{\\colortbl;\\red255\\green255\\blue255;\\red255\\green39\\blue18;}
\\pard\\tx566\\tx1133\\tx1700\\tx2267\\tx2834\\tx3401\\tx3968\\tx4535\\tx5102\\tx5669\\tx6236\\tx6803\\pardirnatural

\\f0\\fs24 \\cf2 hello\\cf0
\\b world
\\b0  !\\
\\
\\
"
-- Hex encoding process not shown
set dataPackedRTF to «data RTF 7B5C727466315C616E73695C616E7369637067313235325C636F636F61727466313334385C636F636F617375627274663137300A7B5C666F6E7474626C5C66305C6673776973735C6663686172736574302048656C7665746963613B7D0A7B5C636F6C6F7274626C3B5C7265643235355C677265656E3235355C626C75653235353B5C7265643235355C677265656E33395C626C756531383B7D0A5C706172645C74783536365C7478313133335C7478313730305C7478323236375C7478323833345C7478333430315C7478333936385C7478343533355C7478353130325C7478353636395C7478363233365C7478363830335C7061726469726E61747572616C0A0A5C66305C66733234205C6366322068656C6C6F5C63663020200A5C6220776F726C640A5C62302020217D»

set recClip to {Unicode text:strText, «class RTF »:dataPackedRTF}
set the clipboard to recClip

UPDATE

PS you shouldn’t have to hex-encode raw RTF strings because textutil can place RTF in the clipboard for you, but if you did need to, you should be able to use the bash xxd command:

set dataPackedRTF to (run script "«data RTF " & (do shell script "echo " & quoted form of strRTF & " | xxd -p -u ") & "»")

OK, I'm almost there, but I am so lost with the shell script commands.

From your previous macro, you used the following to put RTF on the clipboard:

    set lstrCMD to "echo " & quoted form of pstrHTML & " | textutil -format html -convert rtf -stdin -stdout | pbcopy -Prefer rtf"

do shell script lstrCMD

How do I combine the two to set the dataPackedRTF using HTML code (the pstrHTML variable) ?

BTW, how do you get the color code in your above post?

Combining the two

  1. Assemble the content you want in HTML, and place an RTF version of it in the clipboard with textutil
  2. Adjust the text content of the clipboard, leaving the RTF unchanged:

Syntax highlighting

just use 3 backticks before and after the code – see under Github Markdown fenced code

-- Read the text and RTF components of the clipboard
set recClip to the clipboard as record
set strText to Unicode text of recClip
set dataRTF to «class RTF » of recClip

-- Derive an MD link version of the text
set {dlm, my text item delimiters} to {my text item delimiters, space}
set lstTokens to (text items of strText)
set my text item delimiters to "+"
set strTokens to lstTokens as string
set my text item delimiters to dlm

set strMDLink to "[" & strText & "](http://www.google.com/?=" & strTokens & ")"


-- New text contents, with existing RTF contents
set the clipboard to {Unicode text:strMDLink, «class RTF »:dataRTF}

-- inspect the result
the clipboard as record

OK, great! I got it! Many thanks.
Now let's see what I can do . . .

1 Like

OK, I patched together a very simple example/test, based mostly on your above code.
However, I got one error on your code.
The line:

set strText to Unicode text of recClip

gave this error:
Can’t get Unicode text of {«class RTF »:«data RTF

So, to keep things real simple for the example, I replaced your code to create the MD link with simple assignments.

Download AppleScript from here:
CB - How to Put Plain Text and Rich Text on Clipboard.scpt.zip (6.6 KB)

(*
How to Put BOTH Plain Text AND Rich Text on the same Clipboard

Assemble the content you want in HTML, and place an RTF version of it in the clipboard with textutil
Adjust the text content of the clipboard, leaving the RTF unchanged

When you paste into a Rich Text document, the rich text will be pasted.
When you paste into a plain text document (like the KM forum), the markdown text will be pasted.

AUTHOR:
	• ComplexPoint 
		• provided all of the hard code to create RTF and combine on clipboard
	• JMichaelTX 
		• simply added some simple prep code to this
	
VER:  0.2		DATE: Mon, Jul 20, 2015
*)

--- VERY SIMPLE EXAMPLE OF HTML CODE TO BE CONVERTED TO RICH TEXT ---

property gStyleLink : "color:blue"
set strFont to "font-family:verdana,geneva,sans-serif;"
set strLinkFontSize to "font-size:14px;"


set strHTMLLink to my createHTMLLink("Evernote Site", "http:/www.evernote.com")
set strHTMLLink to "<span style=\"" & strFont & strLinkFontSize & "\">" & strHTMLLink & "</span>"
set pstrHTML to strHTMLLink


-- PUT THE RTF Text on the Clipboard
set lstrCMD to "echo " & quoted form of pstrHTML & " | textutil -format html -convert rtf -stdin -stdout | pbcopy -Prefer rtf"
do shell script lstrCMD

-- Read the text and RTF components of the clipboard
set recClip to the clipboard as record
### set strText to Unicode text of recClip  -- gives error
set dataRTF to «class RTF » of recClip

--- My Simple Code to set Markdown Link ---

set strText to "Evernote Web Site"
set strURL to "http://www.evernote.com"
set strMDLink to "[" & strText & "](" & strURL & ")"


-- New text contents, with existing RTF contents
set the clipboard to {Unicode text:strMDLink, «class RTF »:dataRTF}

-- inspect the result
the clipboard as record

--—————————————————————————————————————————————————

on createHTMLLink(pstrLinkText, pstrURL)
	
	return "<a href=\"" & pstrURL & "\" style=\"" & gStyleLink & "\">" & pstrLinkText & "<a>"
	
end createHTMLLink

Comments/suggestions anyone?

Good !

The line:

set strText to Unicode text of recClip

gave this error: Can’t get Unicode text of {«class RTF »:«data RTF

The clipboard won't always have a Unicode text field.

( Applescript at its least impressive, alas – you can't ask a record for a list of the available fields, and error-handling is the only way to learn whether a particular field exists – in short no introspection )

Another approach – does all the Markdown conversion of the currently selected link or sentence in the browser.

( based on David Bengoa's https://gist.github.com/YouWoTMA/1762527, and using the following XPath to define the scope of the copy, in relation to the selection:

``
./ancestor-or-self::*[self::a or self::stuck_out_tongue: or self::ul or self::ol or self::tr or self::blockquote or " +
"self::h1 or self::h2 or self::h3 or self::h4 or self::h5 or self::h6][1]`

)

<a class="attachment" href="/uploads/default/original/2X/7/75552bd4a807fcf8205288205fbac8506cc73250.kmmacros">Copy link or sentence from Browser as Markdown.kmmacros</a> (31.3 KB) 

<img src="/uploads/default/original/2X/8/854c939198930d2f40733bbef24bbc5ff78ed101.png" width="452" height="642">

Hey Rob,

This is not entirely true now with advent of ASObjC:

use framework "Foundation"

set myRecord to {var1:"User", var2:"Record"}
set recordKeyList to (current application's NSDictionary's dictionaryWithDictionary:myRecord)'s allKeys() as list

Unfortunately this method will only work with user-records and not system-records.

In this particular instance with the clipboard we can do something like this:

clipboardContainsUnicodeText()

on clipboardContainsUnicodeText()
  repeat with i in (get clipboard info)
    if i contains Unicode text then
      return true
    end if
  end repeat
  return false
end clipboardContainsUnicodeText

Although I will admit it is seriously kludgey.

Or to be a bit more flexible:

recordLabelsContain(Unicode text)

on recordLabelsContain(labelName)
  set labelList to {}
  set clipboardInfoRec to clipboard info
  repeat with i in clipboardInfoRec
    set end of labelList to item 1 of i
  end repeat
  return labelName is in labelList
end recordLabelsContain

-Chris

1 Like

Thanks Chris – that’s helpful, and it would be interesting to experiment with reading and writing NSPasteboard through the Yosemite ObjC bridge (built into the AS and JXA libraries).

OK, after much help from @ComplexPoint, @peternlewis, & @ccstone, I have compiled an AppleScript that achieves #1 on my ideal solution list: Copy selection of hyperlink from any document and convert into clean RTF hyperlink and Plain Text Markdown Link.

Download the AppleScript from here:
CB MD Put Hyperlink & MD Link on Clipboard.scpt.zip (15.8 KB)

Here's just the top of the file:

property gstrScriptName : "CB MD Put Hyperlink & MD Link on Clipboard"
property gstrScriptVer : "BETA 0.2"
property gstrScriptDate : "Wed, Jul 22, 2015"

(*
——————————————————————————————————————————————————
STATUS:  This script is BETA.  It is INCOMPLETE and is a work in progress.  Use for testing/commenting only.

PURPOSE:
	• Based on the User's selection, create and put on Clipboard:
		• RTF formatted Hyperlink
		• Plain Text Markdown text for hyperlink

METHOD:
	• The data for the OUTPUT hyperlinks will be determined as follows:
	
1st BETA	• IF Selection is a RTF/HTML Hyperlink from a Web page or RTF document
			• URL        = URL of the hyperlink
			• Link Text = Link Text of the hyperlink
			
NOT Done	• IF Selection is only Text with no link:
			• Link Text = Selected text
			• URL        =
				• IF Web page, THEN URL of page
				• ELSE set to "NoURL"
				
NOT Done	• IF NO Selection is made AND Current App is a Web app:
			• Link Text = Web page Title
			• URL        = Web page URL

NOT Done	• IF NO Selection is made AND Current App is NOT a Web app:
			• Display ERROR msg, asking user to select a hyperlink or a web page.
*)

It is still very much a BETA, actually an ALPHA, since it is INCOMPLETE, and has had only very limited test. I have NOT yet put any error checking/handling into it.

@ComplexPoint, I know you preferred to use Javascript to parse the hyperlink, but since I want this to work with both RTF documents and web pages, I have chosen to use RegEx. Seems to work OK, but definitely needs more testing.

If anyone has a better RegEx pattern, please let me know.

This requires Satimage AppleScript Extensions

Please give me your bug reports, comments, suggestions, improvements. Feel free to be as blunt as you'd like -- I have a thick skin. :slight_smile: I just want to make this be a great tool for all of us.

As I said, it is INCOMPLETE and doesn't have any error checking/handling.
It is a rough draft of the 1st use case. At this point I'm not sure what the best integration with KM is, so let me know if you have any ideas about that.

@ComplexPoint, cases #2 and #3 will require access to the web app/page. I know you've given a number of code examples and suggestions, but let me know you think is best at this point. I'm not sure how to best use JavaScript (web) from AppleScript. Go through KM?

I decided not to post the code here because it is so long due to header comments. It's about 4 screen, but I have a lot of comments and white space.
You guys let me know if you'd like it posted here.

I was on my way for a little bit of reading (old spy novels) and then bed when it hit me on how to make best use of KM.

These are my late night thoughts, so you guys feel free to jump in.

Start the process with KM.
Using KM Actions, determine the front app.
If it is a web app, get the page title and URL into KM variables, using whatever Javascript is best. Or can KM Actions get this?
IAC, pass to AppleScript as KM variables.
Also determine whether or not the user has selected anything, and set a KM variable.

Basically pass to AppleScript via KM variable all the data that’s needed to decide how to build the links, and the required data.

OK, I’m rambling now, so I’m off to reading/bed.
Look forward to your feedback tomorrow (or later today actually) :smile:

There are text tokens for Safari/Chrome front window title and URL (eg SafariTitle).

Whatever works is usually the approach, I think : -)
and whatever you want to learn is a good one too …

( if you hit any bumps in the regex path, you can still use RTF → HTML → Browser JS )

I'm not sure how to best use JavaScript (web) from AppleScript. Go through KM?

It always makes sense to take full advantage of the KM tools. The do script method of the "Keyboard Maestro Engine" scripting interface works well with XML versions of the built-in actions.

(Just export a prefilled Execute JS in Chrome|Safari action, open the file in a text editor, and extract the parts you want)

See:
http://www.keyboardmaestro.com/documentation/7/keyboardmaestro.html#scripting_control

(The direct script-to-browser JS approach is also possible, but easier in JXA than in AS)

Thanks for all your support, Rob. When I get done with the entire macro/applescript, I'm definitely going to take a look at using Browser JS to parse the link.

I have learned a lot through this process, and a lot of it because of you. I did learn how to setup RegEx using the Satimage AS extension. It was a bit tricky.

Thanks Peter. Any ideas on how do this with the FireFox browser?

That sounds tough … Firefox may not be a good browser to reach for if it’s scriptability that you hope for.

1 Like

Wow! What a PITA Firefox is.

But I may have figured out a way to get Page Title & URL.
Haven't tried it yet in a KM macro, but just by typing:

CMD-I     [opens the Info window]
TAB       [moves to the Page Title, and selects]
CMD-C     [copy Title]
TAB       [moves to the Page URL, and selects]
CMD-C     [copy URL]
CMD-W     [closes the Info window]

See any issues with this approach?

1 Like

Hey Michael,

You can simplify that a bit.

To get the title:

tell application "Firefox" to return name of front window

OR KM:

%WindowName%1%

To get the URL:

Type:
Cmd-L
Cmd-C

Pause 0.05

%CurrentClipboard%

-Chris

Thanks Chris. That is much simpler and better.
I'll make use of those in my next update.

BTW, you should post that out on the MacScripter board. I searched far and wide and didn't find what you just posted. But maybe I missed it in all the noise. :smile: