Skip to content

Commit

Permalink
Added support for Chrome. Extracted common functionality to jsreload.js.
Browse files Browse the repository at this point in the history
  • Loading branch information
rauschma committed Aug 24, 2012
1 parent 485c493 commit c441d9f
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 130 deletions.
25 changes: 20 additions & 5 deletions README.md
@@ -1,12 +1,27 @@
# JSReload # JSReload


This project contains several scripts that help with automatically reloading a tab in Safari whenever a file changes: This project contains several scripts that help with automatically reloading a tab in a browser whenever a file changes:


1. `tools/watchdir.js` watches all .html and .css files in a directory and reloads the first tab in the first window when one of them changes. 1. `tools/watchdir.js` watches all webdev files (.html, .css, .js) in a directory and reloads the first tab of the frontmost browser window when one of them changes.
2. `grunt.js` watches all .asc files in its directory. If one of them changes, it converts it to HTML via the `asciidoc` command and then reloads Safari. 2. `tools/watchfile.js` opens a file in a web browser, watches it and reloads the first tab of the frontmost browser window if it changes.
3. `grunt.js` is a Grunt build script. You put it inside a project directory. Its `watch` task is invoked as follows.


Prerequisites: grunt watch
This task watches all .asc files in the project directory. If one of them changes, it is converted to HTML via the `asciidoc` command. Afterwards, the first tab of the frontmost browser window is reloaded.


All scripts depend on `node_modules/jsreload`. Safari is currently used by the scripts, but that can easily be changed to Chrome by replacing

jsreload.runReloadSafari(...);

with

jsreload.runReloadChrome(...);

## Requirements

- Supported browsers: Safari, Chrome
- Mac OS X (reloading a browser currently depends on AppleScript)
- Node.js - Node.js
- Package: underscore (trivial to install via npm)
- [Grunt](http://gruntjs.com/) (only needed for option #2) - [Grunt](http://gruntjs.com/) (only needed for option #2)
- Mac OS X (reloading Safari is done via AppleScript)
139 changes: 139 additions & 0 deletions node_modules/jsreload.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions tasks/reloadchrome.js
@@ -0,0 +1,9 @@
module.exports = function(grunt) {

var jsreload = require('jsreload');

grunt.registerTask('reloadchrome', 'Reloads the first tab of the first window of Google Chrome', function() {
var taskDone = this.async();
jsreload.runReloadChrome(taskDone);
});
};
35 changes: 2 additions & 33 deletions tasks/reloadsafari.js
@@ -1,40 +1,9 @@
module.exports = function(grunt) { module.exports = function(grunt) {


var spawn = require('child_process').spawn; var jsreload = require('jsreload');


grunt.registerTask('reloadsafari', 'Reloads the first tab of the first window of Safari', function() { grunt.registerTask('reloadsafari', 'Reloads the first tab of the first window of Safari', function() {
var taskDone = this.async(); var taskDone = this.async();
reloadSafari(taskDone); jsreload.runReloadSafari(taskDone);
}); });

// Inspiration: http://brettterpstra.com/watch-for-file-changes-and-refresh-your-browser-automatically/
var code = '\
tell application "Safari"\n\
set mytab to first tab of first window\n\
tell mytab to do javascript "window.location.reload()"\n\
end tell\n\
';
function reloadSafari(callback) {
var osa = spawn("osascript", ["-e", code]);
var out = "";
var err = "";
osa.stdout.on('data', function (data) {
out += data;
});
osa.stderr.on('data', function (data) {
err += data;
});
osa.on('exit', function (code) {
// Ignore stdout (which shows the return value of the AppleScript code)
if (err.length > 0) {
grunt.log.error("STDERR: "+err);
}
callback();
});
}

}; };




94 changes: 2 additions & 92 deletions tools/watchdir.js
@@ -1,96 +1,6 @@
#!/usr/bin/env node #!/usr/bin/env node


var fs = require('fs'); var jsreload = require("jsreload");
var spawn = require('child_process').spawn;
var path = require('path');
var _ = require("underscore");

var extensions = {
".html": 1,
".css": 1,
};
var mtimes = {};
var watchers = {};


var dirname = process.argv[2]; var dirname = process.argv[2];
traverseFiles(dirname); jsreload.watchDir(dirname, jsreload.runReloadSafari);

function traverseFiles(dir) {
fs.readdirSync(dir).forEach(function (filename) {
var absolute = path.resolve(dir, filename);

var stats = fs.statSync(absolute);
if (stats.isDirectory()) {
traverseFiles(absolute);
} else if (stats.isFile()) {
if (path.basename(absolute).indexOf(".") !== 0 && path.extname(absolute) in extensions) {
console.log("WATCH: "+absolute);
watchFile(absolute);
}
}
});
}

function watchFile(filename) {
// Most editors trigger a series of events whenever a single file is saved
// Via debouncing, we only take action after the last event.
watchers[filename] = fs.watch(filename, _.debounce(handleFileChanges.bind(null, filename), 250));
}

function handleFileChanges(absName, event, filename) {
// On Mac OS X, filename is always null

switch (event) {
case 'rename':
// Some editors (vi) rename the file when swapping it with the new version
watchers[absName].close();
if (fs.existsSync(absName)) {
watchFile(absName);
} else {
// With debouncing, this shouldn’t happen, warn about it
console.log("STOPPED WATCHING: "+absName);
return;
}
fileChanged(event, absName);
break;
case 'change':
fileChanged(event, absName);
break;
}
}

function fileChanged(event, absName) {
// Check the date of last modification to make sure that there really was a change
var mtime = +fs.statSync(absName).mtime;
if (mtime !== mtimes[absName]) {
mtimes[absName] = mtime;
console.log(event.toUpperCase()+": "+absName);
reloadSafari();
}
}

// Inspiration: http://brettterpstra.com/watch-for-file-changes-and-refresh-your-browser-automatically/
var code = '\
tell application "Safari"\n\
set mytab to first tab of first window\n\
tell mytab to do javascript "window.location.reload()"\n\
end tell\n\
';
function reloadSafari() {
var osa = spawn("osascript", ["-e", code]);
var out = "";
var err = "";
osa.stdout.on('data', function (data) {
out += data;
});
osa.stderr.on('data', function (data) {
err += data;
});
osa.on('exit', function (code) {
// Ignore stdout (which shows the return value of the AppleScript code)
if (err.length > 0) {
console.log("STDERR: "+err);
}
console.log("RELOADED");
});
}
7 changes: 7 additions & 0 deletions tools/watchfile.js
@@ -0,0 +1,7 @@
#!/usr/bin/env node

var jsreload = require("jsreload");
var fileName = process.argv[2];
jsreload.runOpen(jsreload.safariAppName, fileName, function () {
jsreload.watchFile(fileName, jsreload.runReloadSafari);
});

0 comments on commit c441d9f

Please sign in to comment.