summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--bin/build.js65
-rwxr-xr-xbin/gitbook.js83
-rw-r--r--lib/generate/ebook/index.js70
-rw-r--r--lib/generate/index.js1
5 files changed, 160 insertions, 60 deletions
diff --git a/README.md b/README.md
index 866979a..810dfa6 100644
--- a/README.md
+++ b/README.md
@@ -46,6 +46,7 @@ GitBook can generate your book in the following formats:
* **Static Website**: This is the default format, it generates a complete interactive static website that can be for example hosted on GitHub Pages.
* **PDF**: A complete PDF book with exercise solutions at the end of the book. Generate to this format using: ```gitbook pdf ./myrepo```, you need to have [gitbook-pdf](https://github.com/GitbookIO/gitbook-pdf) installed.
+* **eBook**: A complete eBook with exercise solutions at the end of the book. Generate to this format using: ```gitbook ebook ./myrepo```, you need to have [ebook-convert](http://manual.calibre-ebook.com/cli/ebook-convert.html) installed.
* **Single Page**: The book will be stored in a single printable HTML page, this format is used for conversion to PDF or eBook. Generate to this format using: ```gitbook build ./myrepo -f page```.
* **JSON**: This format is used for debugging or extracting metadata from a book. Generate to this format using: ```gitbook build ./myrepo -f json```.
diff --git a/bin/build.js b/bin/build.js
index bea8ff9..6050b88 100644
--- a/bin/build.js
+++ b/bin/build.js
@@ -1,11 +1,13 @@
var path = require('path');
var Q = require('q');
var _ = require('lodash');
+var tmp = require('tmp');
var utils = require('./utils');
var generate = require("../lib/generate");
var parse = require("../lib/parse");
+var fs = require('../lib/generate/fs');
var generators = require("../lib/generate").generators;
var buildFunc = function(dir, options) {
@@ -34,7 +36,7 @@ var buildFunc = function(dir, options) {
var title = options.title || utils.titleCase(repo);
return generate.folder(
- {
+ _.extend(options.options || {}, {
input: dir,
output: outputDir,
title: title,
@@ -42,7 +44,7 @@ var buildFunc = function(dir, options) {
github: githubID,
generator: options.format,
theme: options.theme
- }
+ })
);
})
.then(function(output) {
@@ -51,4 +53,61 @@ var buildFunc = function(dir, options) {
}, utils.logError);
};
-module.exports = buildFunc; \ No newline at end of file
+var buildFiles = function(dir, outputFile, options, masterOptions) {
+ var ext = masterOptions.extension;
+
+ outputFile = outputFile || path.resolve(dir, "book."+ext);
+
+ Q.nfcall(tmp.dir)
+ .then(function(tmpDir) {
+ return buildFunc(
+ dir,
+ _.extend(options, {
+ output: tmpDir,
+ format: masterOptions.format,
+ options: masterOptions.options
+ })
+ )
+ .then(function(_options) {
+ var copyPDF = function(lang) {
+ var _outputFile = outputFile;
+ var _tmpDir = tmpDir;
+
+ if (lang) {
+ _outputFile = _outputFile.slice(0, -path.extname(_outputFile).length)+"_"+lang+path.extname(_outputFile);
+ _tmpDir = path.join(_tmpDir, lang);
+ }
+
+ console.log("Generating in", _outputFile);
+ return fs.copy(
+ path.join(_tmpDir, "index."+ext),
+ _outputFile
+ );
+ };
+
+ // Multi-langs book
+ return Q()
+ .then(function() {
+ if (_options.langsSummary) {
+ console.log("Generating for all the languages");
+ return Q.all(
+ _.map(_options.langsSummary.list, function(lang) {
+ return copyPDF(lang.lang);
+ })
+ );
+ } else {
+ return copyPDF();
+ }
+ })
+ .then(function() {
+ return fs.remove(tmpDir);
+ })
+ .fail(utils.logError);
+ });
+ })
+};
+
+module.exports = {
+ folder: buildFunc,
+ files: buildFiles
+}; \ No newline at end of file
diff --git a/bin/gitbook.js b/bin/gitbook.js
index 03d6bef..ab6e043 100755
--- a/bin/gitbook.js
+++ b/bin/gitbook.js
@@ -4,14 +4,13 @@ var Q = require('q');
var _ = require('lodash');
var path = require('path');
var prog = require('commander');
-var tmp = require('tmp');
var pkg = require('../package.json');
var generators = require("../lib/generate").generators;
var fs = require('../lib/generate/fs');
var utils = require('./utils');
-var buildFunc = require('./build');
+var build = require('./build');
// General options
prog
@@ -29,19 +28,16 @@ var buildCommand = function(command, action) {
.action(action);
}
-
-var buildFunc;
-
buildCommand(prog
.command('build [source_dir]')
-.description('Build a gitbook from a directory'), buildFunc);
+.description('Build a gitbook from a directory'), build.folder);
buildCommand(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),
function(dir, options) {
- buildFunc(dir, options)
+ build.folder(dir, options)
.then(function(_options) {
console.log();
console.log('Starting server ...');
@@ -59,60 +55,33 @@ buildCommand(prog
.command('pdf [source_dir] [output_file]')
.description('Build a gitbook as a PDF')
.option('-pf, --paperformat <format>', 'PDF paper format (default is A4): "5in*7.5in", "10cm*20cm", "A4", "Letter"'),
-function(dir, outputFile, options) {
- outputFile = outputFile || path.resolve(dir, "book.pdf");
-
- Q.nfcall(tmp.dir)
- .then(function(tmpDir) {
- return buildFunc(
- dir,
- _.extend(options, {
- output: tmpDir,
- format: "pdf"
- })
- )
- .then(function(_options) {
- var copyPDF = function(lang) {
- var _outputFile = outputFile;
- var _tmpDir = tmpDir;
-
- if (lang) {
- _outputFile = _outputFile.slice(0, -path.extname(_outputFile).length)+"_"+lang+path.extname(_outputFile);
- _tmpDir = path.join(_tmpDir, lang);
- }
-
- console.log("Generating PDF in", _outputFile);
- return fs.copy(
- path.join(_tmpDir, "index.pdf"),
- _outputFile
- );
- };
+function(dir, output, options) {
+ build.files(dir, output, options, {
+ extension: "pdf",
+ format: "pdf",
+ options: {
+ paperformat: options.paperformat
+ }
+ });
+});
- // Multi-langs book
- return Q()
- .then(function() {
- if (_options.langsSummary) {
- console.log("Generating PDFs for all the languages");
- return Q.all(
- _.map(_options.langsSummary.list, function(lang) {
- return copyPDF(lang.lang);
- })
- );
- } else {
- return copyPDF();
- }
- })
- .then(function() {
- return fs.remove(tmpDir);
- })
- .fail(utils.logError);
- });
- })
+buildCommand(prog
+.command('ebook [source_dir] [output_file]')
+.description('Build a gitbook as a eBook')
+.option('-c, --cover <path>', 'Cover image, default is cover.png if exists'),
+function(dir, output, options) {
+ var ext = output ? path.extname(output) : "epub";
+ build.files(dir, output, options, {
+ extension: ext,
+ format: "ebook",
+ options: {
+ extension: ext,
+ cover: options.cover
+ }
+ });
});
-
-
// Parse and fallback to help if no args
if(_.isEmpty(prog.parse(process.argv).args) && process.argv.length === 2) {
prog.help();
diff --git a/lib/generate/ebook/index.js b/lib/generate/ebook/index.js
new file mode 100644
index 0000000..4a69ca6
--- /dev/null
+++ b/lib/generate/ebook/index.js
@@ -0,0 +1,70 @@
+var util = require("util");
+var path = require("path");
+var Q = require("q");
+var _ = require("lodash");
+var exec = require('child_process').exec;
+
+var fs = require("fs");
+var parse = require("../../parse");
+var BaseGenerator = require("../page");
+
+/*
+ * This generator inherits from the single page generator
+ * and convert the page output to ebook
+ */
+var Generator = function() {
+ BaseGenerator.apply(this, arguments);
+
+ // Options for eBook generation
+ this.options = _.defaults(this.options, {
+ extension: "epub"
+ });
+
+ if (!this.options.cover && fs.existsSync(path.join(this.options.input, "cover.png"))) {
+ this.options.cover = path.join(this.options.input, "cover.png")
+ }
+};
+util.inherits(Generator, BaseGenerator);
+
+Generator.prototype.finish = function() {
+ var that = this;
+
+ return BaseGenerator.prototype.finish.apply(this)
+ .then(function() {
+ var d = Q.defer();
+
+ var _options = {
+ "--cover": that.options.cover
+ };
+
+ var command = [
+ "ebook-convert",
+ path.join(that.options.output, "index.html"),
+ path.join(that.options.output, "index."+that.options.extension),
+ _.chain(_options)
+ .map(function(value, key) {
+ if (value == null) return null;
+ return key+"="+value;
+ })
+ .compact()
+ .value()
+ .join(" ")
+ ].join(" ");
+
+ exec(command, function (error, stdout, stderr) {
+ if (error) {
+ if (error.code == 127) {
+ error.message = "Need to install ebook-convert from Calibre";
+ } else {
+ error.message = error.message + " "+stdout;
+ }
+ return d.reject(error);
+ }
+ d.resolve();
+ });
+
+ return d.promise;
+ });
+};
+
+module.exports = Generator;
diff --git a/lib/generate/index.js b/lib/generate/index.js
index b0456f7..03d826c 100644
--- a/lib/generate/index.js
+++ b/lib/generate/index.js
@@ -11,6 +11,7 @@ var generators = {
"site": require("./site"),
"page": require("./page"),
"pdf": require("./pdf"),
+ "ebook": require("./ebook"),
"json": require("./json")
};