Implement livereload into the watch task. Ref gruntjs/grunt-contrib-livereload#32

This commit is contained in:
Kyle Robinson Young 2013-04-30 13:08:10 -07:00
parent dbe658f4f0
commit cbb0e8e0e4
8 changed files with 203 additions and 2 deletions

View File

@ -28,7 +28,8 @@
"test": "grunt nodeunit -v"
},
"dependencies": {
"gaze": "~0.3.3"
"gaze": "~0.3.3",
"tiny-lr": "0.0.4"
},
"devDependencies": {
"grunt": "~0.4.0",

37
tasks/lib/livereload.js Normal file
View File

@ -0,0 +1,37 @@
/*
* grunt-contrib-watch
* http://gruntjs.com/
*
* Copyright (c) 2013 "Cowboy" Ben Alman, contributors
* Licensed under the MIT license.
*/
'use strict';
var tinylr = require('tiny-lr');
module.exports = function(grunt) {
var defaults = {
port: 35729
};
function LR(options) {
if (options === true) { options = defaults; }
else { options = grunt.util._.defaults(options, defaults); }
this.server = tinylr();
this.server.listen(options.port, function(err) {
if (err) { return grunt.fatal(err); }
grunt.log.verbose.writeln('Live reload server started on port: ' + options.port);
});
}
LR.prototype.trigger = function(files) {
grunt.log.verbose.writeln('Live reloading ' + grunt.log.wordlist(files) + '...');
this.server.changed({body:{files:files}});
};
return function(options) {
return new LR(options);
};
};

View File

@ -14,6 +14,8 @@ var util = require('util');
module.exports = function(grunt) {
var livereload = require('./livereload')(grunt);
// Create a TaskRun on a target
function TaskRun(target, defaults) {
this.name = target.name || 0;
@ -22,6 +24,12 @@ module.exports = function(grunt) {
this.options = target.options;
this.startedAt = false;
this.spawned = null;
this.changedFiles = Object.create(null);
// If livereload is requested
if (this.options.livereload !== false) {
this.livereload = livereload(this.options.livereload);
}
}
// Run it
@ -54,7 +62,7 @@ module.exports = function(grunt) {
}
};
// When the task has completed
// When the task run has completed
TaskRun.prototype.complete = function() {
var time = Date.now() - this.startedAt;
this.startedAt = false;
@ -62,6 +70,10 @@ module.exports = function(grunt) {
this.spawned.kill('SIGINT');
this.spawned = null;
}
// Trigger livereload if set
if (this.livereload) {
this.livereload.trigger(Object.keys(this.changedFiles));
}
return time;
};

View File

@ -39,6 +39,8 @@ module.exports = function(grunt) {
this.reload = false;
// For re-queuing arguments with the task that originally ran this
this.nameArgs = [];
// A list of changed files to feed to task runs for livereload
this.changedFiles = Object.create(null);
}
util.inherits(Runner, EE);
@ -148,6 +150,7 @@ module.exports = function(grunt) {
var tr = self._targets[name];
if (!tr) { return next(); }
if (tr.options.nospawn) { shouldComplete = false; }
tr.changedFiles = self.changedFiles;
tr.run(next);
}, function() {
if (shouldComplete) {
@ -195,6 +198,7 @@ module.exports = function(grunt) {
}
});
var elapsed = (time > 0) ? Number(time / 1000) : 0;
self.changedFiles = Object.create(null);
self.emit('end', elapsed);
};

View File

@ -23,6 +23,7 @@ module.exports = function(grunt) {
// Log which file has changed, and how.
grunt.log.ok('File "' + filepath + '" ' + changedFiles[filepath] + '.');
});
taskrun.changedFiles = changedFiles;
// Reset changedFiles
changedFiles = Object.create(null);
});
@ -68,6 +69,7 @@ module.exports = function(grunt) {
nospawn: false,
event: ['all'],
target: target,
livereload: false,
});
targets.forEach(function(target, i) {

39
test/fixtures/livereload/Gruntfile.js vendored Normal file
View File

@ -0,0 +1,39 @@
module.exports = function(grunt) {
'use strict';
grunt.initConfig({
watch: {
basic: {
files: ['lib/*.js'],
tasks: ['before'],
options: {
livereload: true,
},
},
customport: {
files: ['lib/*.js'],
tasks: ['before'],
options: {
livereload: {
port: 8675,
},
},
},
nospawn: {
files: ['lib/*.js'],
tasks: ['before'],
options: {
nospawn: true,
livereload: true,
},
},
},
});
// Load this watch task
grunt.loadTasks('../../../tasks');
grunt.registerTask('before', function() {
grunt.log.writeln('I ran before livereload.');
});
};

1
test/fixtures/livereload/lib/one.js vendored Normal file
View File

@ -0,0 +1 @@
var one = true;

View File

@ -0,0 +1,105 @@
'use strict';
var grunt = require('grunt');
var path = require('path');
var fs = require('fs');
var http = require('http');
var helper = require('./helper');
var fixtures = helper.fixtures;
function cleanUp() {
helper.cleanUp([
'livereload/node_modules',
]);
}
// Helper for requesting the live reload server
function request(port, done) {
var data = '';
var req = http.request({
hostname: 'localhost',
port: port,
}, function(res) {
res.setEncoding('utf8');
res.on('data', function(chunk) {
data += chunk;
});
res.on('end', function() {
done(data);
});
});
req.end();
}
exports.livereload = {
setUp: function(done) {
cleanUp();
fs.symlinkSync(path.join(__dirname, '../../node_modules'), path.join(fixtures, 'livereload', 'node_modules'));
done();
},
tearDown: function(done) {
cleanUp();
done();
},
basic: function(test) {
test.expect(4);
var resultData = '';
var cwd = path.resolve(fixtures, 'livereload');
var assertWatch = helper.assertTask(['watch:basic', '-v'], {cwd: cwd});
assertWatch([function() {
request(35729, function(data) {
resultData += data;
grunt.file.write(path.join(cwd, 'lib', 'one.js'), 'var one = true;');
});
}], function(result) {
helper.verboseLog(result);
test.ok(result.indexOf('I ran before livereload.') !== -1, 'task should have ran before live reload.');
test.ok(result.indexOf('Live reload server started on port: 35729') !== -1, 'live reload server should have been started on port 35729.');
test.ok(result.indexOf('Live reloading lib/one.js...') !== -1, 'live reload should have triggered on lib/one.js');
resultData = JSON.parse(resultData);
test.equal(resultData.tinylr, 'Welcome', 'tinylr server should have welcomed you.');
test.done();
});
},
customport: function(test) {
test.expect(4);
var resultData = '';
var cwd = path.resolve(fixtures, 'livereload');
var assertWatch = helper.assertTask(['watch:customport', '-v'], {cwd: cwd});
assertWatch([function() {
request(8675, function(data) {
resultData += data;
grunt.file.write(path.join(cwd, 'lib', 'one.js'), 'var one = true;');
});
}], function(result) {
helper.verboseLog(result);
test.ok(result.indexOf('I ran before livereload.') !== -1, 'task should have ran before live reload.');
test.ok(result.indexOf('Live reload server started on port: 8675') !== -1, 'live reload server should have been started on port 35729.');
test.ok(result.indexOf('Live reloading lib/one.js...') !== -1, 'live reload should have triggered on lib/one.js');
resultData = JSON.parse(resultData);
test.equal(resultData.tinylr, 'Welcome', 'tinylr server should have welcomed you.');
test.done();
});
},
nospawn: function(test) {
test.expect(4);
var resultData = '';
var cwd = path.resolve(fixtures, 'livereload');
var assertWatch = helper.assertTask(['watch:nospawn', '-v'], {cwd: cwd});
assertWatch([function() {
request(35729, function(data) {
resultData += data;
grunt.file.write(path.join(cwd, 'lib', 'one.js'), 'var one = true;');
});
}], function(result) {
helper.verboseLog(result);
test.ok(result.indexOf('I ran before livereload.') !== -1, 'task should have ran before live reload.');
test.ok(result.indexOf('Live reload server started on port: 35729') !== -1, 'live reload server should have been started on port 35729.');
test.ok(result.indexOf('Live reloading lib/one.js...') !== -1, 'live reload should have triggered on lib/one.js');
resultData = JSON.parse(resultData);
test.equal(resultData.tinylr, 'Welcome', 'tinylr server should have welcomed you.');
test.done();
});
},
};