Extracting scripts from forum posts

Would it be possible to add an “Open this script in your Script Editor link” when there is a script in a post?

It would be nice. At least we can copy-and-paste without extra Web detritus being inserted.

Hey Ed,

I think someone proficient with JavaScript could manage to use Xpath and Hover/Selection to extract the text out of the code-block in Safari and perhaps Google Chrome.

I’ve seen this sort of thing done in different contexts, but I don’t have the js-chops to do it myself just yet.

A basic non-dynamic example extracting the outer-html of Shane’s code-block on this page:

--------------------------------------------------------------------------------

set jStr to "document.getElementsByClassName('hljs applescript')[0].outerHTML"
set theHTML to doJavaScriptInSafari(jStr)

--------------------------------------------------------------------------------
--» HANDLERS
--------------------------------------------------------------------------------
on doJavaScriptInSafari(javascriptStr)
   try
      tell application "Safari" to do JavaScript javascriptStr in front document
   on error e
      error "Error in handler doJavaScriptInSafari() of library NLb!" & return & return & e
   end try
end doJavaScriptInSafari
--------------------------------------------------------------------------------

-Chris

I wonder how Macscriptor does it. If I put a script in a post it automatically formats it and adds the link to open it in my script editor.

So the question is can discourse do that?

I guess they wrap the script around

applescript://com.apple.scripteditor?action=new&script=<your script percent encoded>

I think MattNeu might know something about that. :sunglasses:

So this is probably more for amusement than everyday use, but it extracts the scripts from the current Safari page, and if more than one, gives you the ugliest choose from list dialog you’ve ever seen. Because it re-downloads everything, it’s also a bit slow. But it works, and it’s a bit of fun.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "WebKit"
use scripting additions

-- This handler must be run on the main thread
on makeWebViewWithURL:thePageURL
	-- make a WebView
	set theView to current application's WebView's alloc()'s initWithFrame:{origin:{x:0, y:0}, |size|:{width:100, height:100}}
	-- tell it call delegate methods on me
	theView's setFrameLoadDelegate:me
	-- load the page
	theView's setMainFrameURL:thePageURL
end makeWebViewWithURL:

-- called when the WebView loads a frame
on WebView:aWebView didFinishLoadForFrame:webFrame
	-- the main frame is our interest
	if webFrame = aWebView's mainFrame() then
		-- get the web archive data 
		set theData to webFrame's dataSource()'s webArchive()'s |data|()
		-- make HTML
		set {xmlDoc, theError} to current application's NSXMLDocument's alloc()'s initWithData:theData options:(current application's NSXMLDocumentTidyHTML) |error|:(reference)
		-- extract scripts
		set theScripts to xmlDoc's nodesForXPath:".//pre/code" |error|:(missing value)
		set theSources to {}
		set theSourcesFull to {}
		if (count of theScripts) > 1 then
			repeat with aScript in theScripts
				set theSource to aScript's stringValue()
				set end of theSources to theSource as text
				set theSource to (theSource's stringByReplacingOccurrencesOfString:linefeed withString:"\\r")
				set end of theSourcesFull to (theSource's stringByReplacingOccurrencesOfString:(space & space & "+") withString:space options:(current application's NSRegularExpressionSearch) range:{0, theSource's |length|()}) as text
			end repeat
			-- pick script
			set theResult to (choose from list theSourcesFull with prompt "Choose a script")
			if theResult is false then
				beep
				error number -128
			end if
			set theResult to item 1 of theResult
			repeat with i from 1 to count of theSourcesFull
				if item i of theSourcesFull = theResult then
					set finalSource to item i of theSources
					exit repeat
				end if
			end repeat
		else
			set finalSource to (item 1 of theScripts)'s stringValue() as text
		end if
		-- make SD document
		tell application id "com.latenightsw.ScriptDebugger6" -- Script Debugger.app
			activate
			make new document
			set source text of document 1 to finalSource
			compile document 1
		end tell
	end if
end WebView:didFinishLoadForFrame:

tell application id "com.apple.Safari" -- Safari.app
	set theURL to URL of document 1
end tell
my performSelectorOnMainThread:"makeWebViewWithURL:" withObject:theURL waitUntilDone:true

Darn, it Shane. Now you’ve gone and distracted me from what I should be doing…

I think your script assumes that the CSS is defined in the header. That won’t work with web pages on sites like mine, e.g,

because it’s hosted by wordpress.com, and all CSS has to be in-line (it’s a right royal pain, and I really should migrate off of wordpress.com, but the pain barrier is just too high for me to jump).

A typical line of AppleScript looks like this:

repeat with i from 1 to count of items in aText

which renders as

repeat with i from 1 to count of items in aText

on the actual page.

I might be able to adapt your script to deal with both, though. EDIT: on second thoughts, I’m not sure I can.

And you’re right about that choose from list dialog – boy is that a pig. I don’t know why choose from list can’t have parameters to limit the vertical and horizontal sizes (I might file an ER against it in Sierra just for laughs).

Sorry, I should have been specific: it’s designed (and lightly tested) only for this forum.

Hey Folks,

This works in Safari.

Click in the code block.

Run the script with FastScripts, Keyboard Maestro, etc.

-Chris

--------------------------------------------------------------------------------
# Auth: Christopher Stone { JavaScript by @Complexpoint on the Keyboard Maestro forum }
# dCre: 2016/07/12 05:01
# dMod: 2016/07/12 05:16 
# Appl: Safari, Script Debugger
# Task: Extract Code from Code Blocks in Discourse Forums.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Safari, @Script_Debugger, @Extract, @Code, @Discourse
--------------------------------------------------------------------------------

set jsStr to "
(function () {
  var oSeln = window.getSelection(),
    nodeTable = document.evaluate(
      './ancestor-or-self::code',
      oSeln.anchorNode,
      null, 0, 0
    ).iterateNext(),
    rngDoc = nodeTable ?
      document.createRange() : null;

  if (nodeTable) {
    oSeln.removeAllRanges();
    rngDoc.selectNode(nodeTable);
    oSeln.addRange(rngDoc);
  }
})();

window.getSelection()+'';
"

tell application "Safari"
   tell front document
      set selectedText to do JavaScript jsStr
   end tell
end tell

if selectedText ≠ "" then
   tell application "Script Debugger"
      activate
      make new document with properties {source text:selectedText}
      set bounds of front window to {606, 23, 1920, 1196}
   end tell
end if

--------------------------------------------------------------------------------
Summary

This text will be hidden

Like This?

Open this Scriplet in your Editor

Hey Ed,

What scriptlet?

-Chris

Ed’s line should be a link (it is here).

The problem, though, is that the Discourse software doesn’t generally support this approach at present.

Hey Shane,

It shows as an apparent link in Safari and Chrome, but there’s nothing connected to it – even when you inspect the source.

-Chris

Ah – I could have sworn it was working earlier.

Trying again:

Open this Scriplet in your Editor:



use AppleScript version "2.4"

use scripting additions

use framework "Foundation"



timer(“Start”)


YOUR CODE

— NOTE: The below shell scripts have nothing to do with the timer() handler —



set cmdStr to "perl -e ‘use Time::HiRes qw(time); print time’"

set timeStart to do shell script cmdStr

timer(“After First Shell Script”)

set timeStop to do shell script cmdStr



timer(“STOP”)

Maybe Discourse can’t handle html in a post?

Discourse forum software does not, in general, support HTML by users in a post. There are a few exceptions, like HTML tables (requires Admin to enable). Markdown is the primary formatting system for user posts:

The Discourse software does not allow non http/https URL schemes in URLs. When something like applescript://... appears within a Markdown URL or an HTML href, Discourse strips it out.

There appears to be movement within the Discourse developers to relax this restriction in some future version of Discourse.

OK, what I would like to achieve is being able to select text in Script Debugger and run a script that grabs the selection (or the entire script) from the front window, and formats it for discourse, with all the color and style attributes, and drops it into an appleScript:// type link that displays the formatted script and when a user clicks on it, it will open the script in their script editor.

Is this doable with the current version of discourse, using HTML or Markdown?

We all share the same desire. For the time being, this is beyond our abilities for technical reasons having to do with the Discourse software. The Discourse folks are talking about fixing the issue where non-http/https URL schemes are filtered.

Once that issue is resolved, when we can generate applescript:// URLs. The final step will be to get the code which pretty-prints AppleScript for us to also generate the applescript:// URL string as well. I’m pretty confident I can make that JS/Ruby code work when the time comes.