Complete serve command

This commit is contained in:
Samy Pessé
2015-01-24 11:23:53 +01:00
parent 8be4304b5c
commit 2efd234824
5 changed files with 243 additions and 8 deletions
+114 -6
View File
@@ -1,9 +1,27 @@
var Q = require("q");
var _ = require("lodash");
var path = require("path");
var tinylr = require('tiny-lr-fork');
var Book = require("./book");
var Plugin = require("./plugin");
var Server = require("./utils/server");
var stringUtils = require("./utils/string");
var watch = require("./utils/watch");
var LOG_OPTION = {
name: "log",
description: "Minimum log level to display",
values: _.chain(Book.LOG_LEVELS).keys().map(stringUtils.toLowerCase).value(),
defaults: "info"
};
var FORMAT_OPTION = {
name: "format",
description: "Format to build to",
values: ["website", "json"],
defaults: "website"
};
module.exports = {
Book: Book,
@@ -11,20 +29,21 @@ module.exports = {
commands: [
// Build command that simply build a book into an output folder
{
name: "build",
name: "build [book] [output]",
description: "build a book",
options: [
FORMAT_OPTION,
LOG_OPTION
],
exec: function(args, kwargs) {
var input = args[0] || process.cwd();
var output = args[1] || path.join(input, "_book");
kwargs = _.defaults(kwargs || {}, {
format: "website"
});
var book = new Book(input, _.extend({}, {
'config': {
'output': output
},
'logLevel': Book.LOG_LEVELS[(kwargs.log || "info").toUpperCase()]
'logLevel': Book.LOG_LEVELS[(kwargs.log).toUpperCase()]
}));
return book.parse()
@@ -34,9 +53,98 @@ module.exports = {
}
},
// Build and serve a book
{
name: "serve [book]",
description: "Build then serve a gitbook from a directory",
options: [
{
name: "port",
description: "Port for server to listen on",
defaults: 4000
},
{
name: "lrport",
description: "Port for livereload server to listen on",
defaults: 35729
},
{
name: "watch",
description: "Enable/disable file watcher",
defaults: true
},
FORMAT_OPTION,
LOG_OPTION
],
exec: function(args, kwargs) {
var input = args[0] || process.cwd();
var server = new Server();
// Init livereload server
var lrServer = tinylr({});
var lrPath = undefined;
var generate = function() {
if (server.isRunning()) console.log("Stopping server");
return server.stop()
.then(function() {
var book = new Book(input, _.extend({}, {
'config': {
'defaultsPlugins': ["livereload"]
},
'logLevel': Book.LOG_LEVELS[(kwargs.log).toUpperCase()]
}));
return book.parse()
.then(function() {
return book.generate(kwargs.format);
})
.thenResolve(book);
})
.then(function(book) {
console.log();
console.log('Starting server ...');
return server.start(book.options.output, kwargs.port)
.then(function() {
console.log('Serving book on http://localhost:'+kwargs.port);
if (lrPath) {
// trigger livereload
lrServer.changed({
body: {
files: [lrPath]
}
});
}
if (!kwargs.watch) return;
return watch(book.root)
.then(function(filepath) {
// set livereload path
lrPath = filepath;
console.log("Restart after change in files");
console.log('');
return generate();
})
})
});
};
return Q.nfcall(lrServer.listen.bind(lrServer), kwargs.lrport)
.then(function() {
console.log('Live reload server started on port:', kwargs.lrport);
console.log('Press CTRL+C to quit ...');
console.log('')
return generate();
});
}
},
// Install command that install plugins needed by a book
{
name: "install",
name: "install [book]",
description: "install plugins dependencies",
exec: function(args, kwargs) {
var input = args[0] || process.cwd();
+96
View File
@@ -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;
+2 -1
View File
@@ -22,5 +22,6 @@ function optionsToShellArgs(options) {
module.exports = {
escapeShellArg: escapeShellArg,
optionsToShellArgs: optionsToShellArgs
optionsToShellArgs: optionsToShellArgs,
toLowerCase: String.prototype.toLowerCase.call.bind(String.prototype.toLowerCase)
};
+27
View File
@@ -0,0 +1,27 @@
var Q = require('q');
var path = require('path');
var Gaze = require('gaze').Gaze;
function watch(dir) {
var d = Q.defer();
dir = path.resolve(dir);
var gaze = new Gaze("**/*.md", {
cwd: dir
});
gaze.once("all", function(e, filepath) {
gaze.close();
d.resolve(filepath);
});
gaze.once("error", function(err) {
gaze.close();
d.reject(err);
});
return d.promise;
}
module.exports = watch;
+4 -1
View File
@@ -21,7 +21,10 @@
"npmi": "0.1.1",
"cheerio": "0.18.0",
"gitbook-plugin-mathjax": "0.0.6",
"gitbook-plugin-livereload": "0.0.1"
"gitbook-plugin-livereload": "0.0.1",
"gaze": "~0.5.1",
"send": "0.2.0",
"tiny-lr-fork": "0.0.5"
},
"devDependencies": {
"mocha": "1.18.2",