Skip to content

Commit

Permalink
Add support for .watch() for simple automatic rebuilds.
Browse files Browse the repository at this point in the history
  • Loading branch information
mixu committed May 26, 2012
1 parent d7a07d6 commit 01909e8
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 26 deletions.
47 changes: 26 additions & 21 deletions lib/glue.js
Expand Up @@ -68,14 +68,13 @@ Renderer.prototype.include = function(filepath){
paths = (Array.isArray(filepath) ? filepath : [ filepath ]);

paths.forEach(function(p) {
if(p.substr(0, 2) == './') {
p = path.normalize(self.options.reqpath + '/' + p);
}
p = self._fullPath(p);
var isDirectory = fs.statSync(p).isDirectory();

if (isDirectory) {
p += (p[p.length-1] !== '/' ? '/' : '');
return fs.readdirSync(p).forEach(function (f) {
self.include((p[p.length - 1] == '/' ? p : p + '/') + f);
self.include(p + f);
});
}
self.paths.push(p);
Expand All @@ -100,16 +99,12 @@ Renderer.prototype._exclude = function() {

Renderer.prototype.render = function(done){
if(!done) return this;
if(this.options.basepath.substr(0, 2) == './') {
this.options.basepath = path.normalize(this.options.reqpath + '/' + this.options.basepath);
}
if(this.options.basepath[this.options.basepath.length -1 ] !== '/') {
this.options.basepath += '/';
}
this._exclude();
var self = this,
opt = this.options,
relpath = this.relpath(opt.main.replace(/^\.\//, ''));
opt = this.options;
opt.basepath = this._fullPath(opt.basepath);
opt.basepath += (opt.basepath[opt.basepath.length-1] !== '/' ? '/' : '');
this._exclude();
var relpath = opt.main.replace(/^\.\//, '').replace(new RegExp('^'+opt.basepath), '');

var data = '(function(){'
+ 'var global = this;'
Expand All @@ -129,21 +124,31 @@ Renderer.prototype.render = function(done){
return this;
};

Renderer.prototype.watch = function(done) {
var self = this;
this._exclude();
this.paths.forEach(function(p) {
fs.watchFile(p, { interval: 500 }, function(curr, prev) {
console.log('File changed: ' +p+' at ' + curr.mtime);
self.render(done);
});
});
this.render(done);
};

Renderer.prototype._render = function(filepath) {
var source = fs.readFileSync(filepath, 'utf8'),
relpath = this.relpath(filepath);
relpath = filepath.replace(new RegExp('^'+this.options.basepath), '');

return 'require.modules[\'' + relpath + '\'] = '
+ 'function(module, exports, require, global){\n' + source + '\n};';
};

Renderer.prototype.relpath = function(filepath) {
var base = this.options.basepath;

if (base == filepath.substr(0, base.length)) {
filepath = filepath.substr(base.length);
Renderer.prototype._fullPath = function(p) {
if(p.substr(0, 2) == './') {
p = path.normalize(this.options.reqpath + '/' + p);
}
return filepath;
};
return p;
}

module.exports = Renderer;
13 changes: 13 additions & 0 deletions lib/watch.js
@@ -0,0 +1,13 @@
var fs = require('fs');

function Watch(paths, callback) {
paths.forEach(function(p) {
fs.watchFile(p, { interval: 200 }, function(curr, prev) {
console.log('the current mtime is: ' + curr.mtime);
console.log('the previous mtime was: ' + prev.mtime);
callback(p);
});
});
}


3 changes: 1 addition & 2 deletions package.json
Expand Up @@ -6,10 +6,9 @@
"name": "Mikito Takada",
"email": "mikito.takada@gmail.com",
"url": "http://blog.mixu.net/"
},
},
"main": "lib/glue.js",
"devDependencies": {
"mocha": "1.0.x"
}
}

14 changes: 14 additions & 0 deletions readme.md
Expand Up @@ -46,6 +46,20 @@ Example: .replace('debug', function debug() { return debug() });

.render(function(err, text){ ...}): renders the result

.watch(function(err, text){ ...})

Renders the result and adds file watchers on the dependent files.

When the file changes, the callback will be called again, with the newly rendered version.

Note that this API is a bit clunky:

- there is no way to unwatch a file other than terminate the program
- on each watched file change, a console.log() message is shown
- the API uses fs.watchFile(), so you do not get notification of newly added files in directories; watches are registered on the files that were used on the first render

But it works fine for automatically rebuilding e.g. in dev.

.defaults({
reqpath: '/path/to/first/module/to/require/glue', // all relative paths are relative to this
basepath: '', // strip this string from each path (e.g. /foo/bar/baz.js with '/foo' becomes 'bar/baz.js')
Expand Down
3 changes: 0 additions & 3 deletions test/test.js

This file was deleted.

8 changes: 8 additions & 0 deletions test/watch.test.js
@@ -0,0 +1,8 @@
var Glue = require('../lib/glue.js');

new Glue()
.include('./tmp/placeholder.txt')
.export('App')
.watch(function(err, txt) {
// console.log(txt);
});

0 comments on commit 01909e8

Please sign in to comment.