This blog post explains how to use Node.js to reload a tab in Safari whenever a file changes. Alas, this solution only works on a Mac, because it relies on AppleScript to remotely control Safari. You can download it as project JSReload on GitHub.
The problem
I’m currently evaluating whether to switch from TextMate to Sublime Text. The only feature I miss on Sublime is a live preview of HTML files (or files that can be converted to HTML via a script – think Markdown).The solutions
We’ll look at two solutions:- A shell script (powered by Node.js) that watches a directory. It reloads Safari whenever one of the .html or .css files in the directory changes. In some ways that’s better than TextMate, because you can edit a CSS file and the corresponding HTML file is reloaded in Safari.
- A Grunt script that serves a different purpose: It watches a directory with AsciiDoc (.asc) files. When a file changes, that file is compiled to HTML and then Safari is reloaded.
Shell script
The shell script watchdir.js is written in JavaScript, via Node.js [1]. We use the Node.js function fs.watch() to be notified if a file changes:
fs.watch(filename, [options], [listener])
The listener is called whenever the file changes whose name is filename. fs.watch has a few quirks on Mac OS X, but it mostly works. Then we still need to reload Safari. And AppleScript lets us do that:
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\
';
We execute the AppleScript program in the variable code via the shell command osascript:
spawn("osascript", ["-e", code])
Node.js makes sure that everything is properly quoted and escaped.
It is unfortunate that we have to resort to JavaScript inside the AppleScript, but that seems to be the only way to reload. A pure AppleScript solution is to set the URL of the tab to what it already is. That also reloads, but then the viewport jumps to the beginning of the file. With a true reload, the current viewport position is preserved.
Grunt
Grunt is similar to build tools such as Make and Ant. But it is based on JavaScript and Node.js, which makes it a very elegant solution. The following is a snippet from the build file grunt.js:
grunt.initConfig({
asciidoc: {
files: [ '**/*.asc' ]
},
watch: {
files: '<config:asciidoc.files>',
tasks: 'asciidoc reloadsafari'
},
});
We watch all AsciiDoc files (as specified via asciidoc.files). If one of them changes, we first convert it to HTML via the asciidoc shell command and then reload Safari. Both asciidoc and reloadsafari are custom Grunt tasks (included in the GitHub project). Hence, it should be easy to adapt this solution to different needs (e.g. Markdown).
Other browsers
Safari is perfect for previewing files for me, because I don’t use it for anything else. But other browsers can probably be remote-controlled via Node.js, too. For example, via the following mechanisms:- Remote Control add-on for Firefox
- Remote debugging protocol of the Chrome Developer Tools
Conclusion: an app wish
The presented solution works quite well. But Sublime Text should really provide its own preview functionality. There seems to be an aversion to putting too much functionality into Sublime. Then how about a separate application? It would show a single browser window and watch a directory. You would be able to configure what files are watched and how they are converted to HTML. It should be possible to optionally make that conversion without creating files, by writing to stdout. Example configurations:- HTML: Watch all .html and .css files. If one of them changes, reload the browser window.
- AsciiDoc: Watch all .asc files. If one of them changes, convert it to an HTML file and reload the browser window.
- Markdown: Watch all .md, .mdown and .markdown files. If one of them changes, translate it to HTML and pipe the result to the browser window.
8 comments:
There is also http://tin.cr/ Chrome extension
Sublime text 2 + code kit = match made in heaven. I am definitely an advocate for not putting too much functionality into an editor. It's what makes sublime so fast and so different to other editors such as Coda. Sublime 2 being simple is why so many developers have decided to leave their beloved IDE's.
I tried it out, but it didn’t work on my Mac with file: URLs.
My Este.js approach https://github.com/Steida/este/blob/master/assets/js/dev/livereload.coffee
I use it with config file on Mac and it wotks just fine. Show me your setup maby I'll be able to help with it.
live.js is the best choice for me. well it works on WAMP. thanks for this great article :D
Thanks for offering, don’t need it at the moment.
This is a little bit different but did you know about https://github.com/dz0ny/LiveReload-sublimetext2 ? When used in conjunction with Markdown-Preview in Sublime Text 2, the browser reloads the html everytime the Markdown file is saved.
Post a Comment