summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamy Pessé <samypesse@gmail.com>2014-04-25 16:23:13 +0200
committerSamy Pessé <samypesse@gmail.com>2014-04-25 16:23:13 +0200
commit83d8c16853a056ef34360150a805b2a7ac52dd4f (patch)
tree740c72fc044d30750b0a127250bd55d6f6dbdb68
parent47e9506397afb37fea8f164e1fc41b625fdcd1bc (diff)
downloadgitbook-83d8c16853a056ef34360150a805b2a7ac52dd4f.zip
gitbook-83d8c16853a056ef34360150a805b2a7ac52dd4f.tar.gz
gitbook-83d8c16853a056ef34360150a805b2a7ac52dd4f.tar.bz2
Add file watcher in "gitbook serve" command (Fix #47, #89, #140)
-rw-r--r--bin/build.js2
-rwxr-xr-xbin/gitbook.js43
-rw-r--r--bin/server.js96
-rw-r--r--bin/utils.js41
-rw-r--r--package.json1
5 files changed, 148 insertions, 35 deletions
diff --git a/bin/build.js b/bin/build.js
index 6f90e1d..37415bd 100644
--- a/bin/build.js
+++ b/bin/build.js
@@ -44,7 +44,7 @@ var makeBuildFunc = function(converter) {
})
.then(function(repoID) {
return converter(
- _.extend(options || {}, {
+ _.extend({}, options || {}, {
input: dir,
output: outputDir,
title: options.title,
diff --git a/bin/gitbook.js b/bin/gitbook.js
index 88ba5e2..c2f0ed1 100755
--- a/bin/gitbook.js
+++ b/bin/gitbook.js
@@ -12,6 +12,7 @@ var fs = require('../lib/generate/fs');
var utils = require('./utils');
var build = require('./build');
+var Server = require('./server');
// General options
prog
@@ -24,19 +25,39 @@ build.command(prog.command('build [source_dir]'))
build.command(prog.command('serve [source_dir]'))
.description('Build then serve a gitbook from a directory')
.option('-p, --port <port>', 'Port for server to listen on', 4000)
+.option('--no-watch', 'Disable restart with file watching')
.action(function(dir, options) {
- build.folder(dir, options || {})
- .then(function(_options) {
- console.log();
- console.log('Starting server ...');
- return utils.serveDir(_options.output, options.port)
+ var server = new Server();
+
+ var generate = function() {
+ if (server.isRunning()) console.log("Stopping server");
+
+ server.stop()
+ .then(function() {
+ return build.folder(dir, options);
+ })
+ .then(function(_options) {
+ console.log();
+ console.log('Starting server ...');
+ return server.start(_options.output, options.port)
+ .then(function() {
+ console.log('Serving book on http://localhost:'+options.port);
+
+ if (!options.watch) return;
+ return utils.watch(_options.input)
+ .then(function(filepath) {
+ console.log("Restart after change in "+path.relative(dir, filepath));
+ console.log('');
+ return generate();
+ })
+ })
+ })
.fail(utils.logError);
- })
- .then(function() {
- console.log('Serving book on http://localhost:'+options.port);
- console.log();
- console.log('Press CTRL+C to quit ...');
- });
+ };
+
+ console.log('Press CTRL+C to quit ...');
+ console.log('')
+ generate();
});
build.command(prog.command('pdf [source_dir]'))
diff --git a/bin/server.js b/bin/server.js
new file mode 100644
index 0000000..2b97fe8
--- /dev/null
+++ b/bin/server.js
@@ -0,0 +1,96 @@
+var Q = require('q');
+var _ = require('lodash');
+
+var events = require('events');
+var http = require('http');
+var send = require('send');
+var util = require('util');
+var url = require('url');
+
+var Server = function() {
+ this.running = null;
+ this.dir = null;
+ this.port = 0;
+ this.sockets = [];
+};
+util.inherits(Server, events.EventEmitter);
+
+// Return true if the server is running
+Server.prototype.isRunning = function() {
+ return this.running != null;
+};
+
+// Stop the server
+Server.prototype.stop = function() {
+ var that = this;
+ if (!this.isRunning()) return Q();
+
+ var d = Q.defer();
+ this.running.close(function(err) {
+ that.running = null;
+ that.emit("state", false);
+
+ if (err) d.reject(err);
+ else d.resolve();
+ });
+
+ for (var i = 0; i < this.sockets.length; i++) {
+ this.sockets[i].destroy();
+ }
+
+ return d.promise;
+};
+
+Server.prototype.start = function(dir, port) {
+ var that = this, pre = Q();
+ port = port || 8004;
+
+ if (that.isRunning()) pre = this.stop();
+ return pre
+ .then(function() {
+ var d = Q.defer();
+
+ that.running = http.createServer(function(req, res){
+ // Render error
+ function error(err) {
+ res.statusCode = err.status || 500;
+ res.end(err.message);
+ }
+
+ // Redirect to directory's index.html
+ function redirect() {
+ res.statusCode = 301;
+ res.setHeader('Location', req.url + '/');
+ res.end('Redirecting to ' + req.url + '/');
+ }
+
+ // Send file
+ send(req, url.parse(req.url).pathname)
+ .root(dir)
+ .on('error', error)
+ .on('directory', redirect)
+ .pipe(res);
+ });
+
+ that.running.on('connection', function (socket) {
+ that.sockets.push(socket);
+ socket.setTimeout(4000);
+ socket.on('close', function () {
+ that.sockets.splice(that.sockets.indexOf(socket), 1);
+ });
+ });
+
+ that.running.listen(port, function(err) {
+ if (err) return d.reject(err);
+
+ that.port = port;
+ that.dir = dir;
+ that.emit("state", true);
+ d.resolve();
+ });
+
+ return d.promise;
+ });
+}
+
+module.exports = Server;
diff --git a/bin/utils.js b/bin/utils.js
index 4d45e29..45bc7d5 100644
--- a/bin/utils.js
+++ b/bin/utils.js
@@ -4,8 +4,11 @@ var _ = require('lodash');
var http = require('http');
var send = require('send');
-var url = require('url');
var cp = require('child_process');
+var path = require('path');
+var url = require('url');
+
+var Gaze = require('gaze').Gaze;
// Get the remote of a given repo
@@ -55,32 +58,24 @@ function titleCase(str)
return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}
-function serveDir(dir, port) {
+function watch(dir) {
var d = Q.defer();
+ dir = path.resolve(dir);
- var server = http.createServer(function(req, res){
- // Render error
- function error(err) {
- res.statusCode = err.status || 500;
- res.end(err.message);
- }
+ var gaze = new Gaze("**/*.md", {
+ cwd: dir
+ });
- // Redirect to directory's index.html
- function redirect() {
- res.statusCode = 301;
- res.setHeader('Location', req.url + '/');
- res.end('Redirecting to ' + req.url + '/');
- }
+ gaze.once("all", function(e, filepath) {
+ gaze.close();
- // Send file
- send(req, url.parse(req.url).pathname)
- .root(dir)
- .on('error', error)
- .on('directory', redirect)
- .pipe(res);
- }).listen(port);
+ d.resolve(filepath);
+ });
+ gaze.once("error", function(err) {
+ gaze.close();
- d.resolve(server);
+ d.reject(err);
+ });
return d.promise;
}
@@ -96,6 +91,6 @@ module.exports = {
gitURL: gitURL,
githubID: githubID,
titleCase: titleCase,
- serveDir: serveDir,
+ watch: watch,
logError: logError
};
diff --git a/package.json b/package.json
index 0ba9156..4eaae38 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
"highlight.js": "8.0.0",
"tmp": "0.0.23",
"semver": "2.2.1",
+ "gaze": "0.6.4",
"gitbook-plugin": "0.0.2",
"gitbook-plugin-mixpanel": "0.0.2",