Skip to content

Instantly share code, notes, and snippets.

@subtleGradient
Created June 16, 2010 18:51
Show Gist options
  • Save subtleGradient/441101 to your computer and use it in GitHub Desktop.
Save subtleGradient/441101 to your computer and use it in GitHub Desktop.
Node.js JavaScript for Mac OS X. Uses osascript AppleScript to control Safari. Remote control Safari from the terminal!
#!/usr/bin/env node #// -*- Mode: Node.js JavaScript; tab-width: 4; -*-
/*
---
url: http://gist.github.com/441101
name : safari-get-html
description : safari-get-html will rock your socks!
authors : Thomas Aylott
copyright : © 2010 Thomas Aylott
license : MIT
provides:
- AppleScriptApp
- Safari
- String.escapeShell
- String.escapeAppleScript
requires:
- Node.js/sys.p
- Node.js/sys.debug
- Node.js/child_process.exec
environment:
- osx
- osascript
- Safari.app
...
*/
var sys = require('sys');
// escape text to make it useable in a shell script as one “word” (string)
// Based on TextMate.app/Contents/SharedSupport/Support/lib/escape.rb e_sh
String.escapeShell = function(str){
// Ruby: str.to_s.gsub(/(?=[^a-zA-Z0-9_.\/\-\x7F-\xFF\n])/n, '\\').gsub(/\n/, "'\n'").sub(/^$/, "''")
return (''+str).replace(/(?=[^a-zA-Z0-9_.\/\-\x7F-\xFF\n])/gm, '\\').replace(/\n/g, "'\n'").replace(/^$/, "''");
}
// escape text for use in an AppleScript string
// Based on TextMate.app/Contents/SharedSupport/Support/lib/escape.rb e_as
String.escapeAppleScript = function(str){
// str.to_s.gsub(/(?=["\\])/, '\\')
return (''+str).replace(/(?=["\\])/g, '\\');
}
function AppleScriptApp(appName){
if (!(this instanceof AppleScriptApp)) throw new Error("Usage: `new AppleScriptApp(appName:String)`");
this.appName = ''+appName;
}
AppleScriptApp.prototype.exec = require('child_process').exec;
// AppleScriptApp.prototype.exec = require('sys').print;
AppleScriptApp.prototype.tell = function(script){
var command = 'osascript -e '
+ String.escapeShell('tell application "' + this.appName + '"')
+ ' -e '
+ String.escapeShell(script)
+ ' -e '
+ 'end tell'
;
sys.debug(command);
return this.exec(
command
,
{ encoding: 'utf8'
, timeout: 120 *1000
, maxBuffer: 10240 *1024
//, killSignal: 'SIGKILL'
}
,
this.handleExec
);
}
AppleScriptApp.prototype.handleExec = function(error, stdout, stderr){
sys.print(stdout);
sys.debug(stderr);
if (error !== null) sys.p(error);
};
function Safari(){
if (!(this instanceof Safari)) throw new Error("Usage: `new Safari`");
}
Safari.prototype = new AppleScriptApp('Safari');
Function.uneval = function(fn){
fn = ''+fn;
var string = '';
if (/^function\b/.test(fn)) string += '(' + fn + ')()';
else return fn;
return string;
}
Safari.prototype.doJavaScript = function(js){
js = Function.uneval(js);
return this.tell('tell the first document to do javascript "' + String.escapeAppleScript(js) +'"');
}
Safari.prototype.getSource = function(){
return this.tell('get the source of the first document');
}
// Safari.prototype.getHTML = function(){}
var safari = new Safari;
// safari.doJavaScript('document.documentElement.outerHTML');
safari.doJavaScript(function(){
return document.documentElement.outerHTML;
});
// safari.getSource();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment