mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-21 01:53:26 +00:00
Merge pull request #42 from GitbookIO/feature/ebook
Fix #10: Add generation to ebook
This commit is contained in:
@@ -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```.
|
||||
|
||||
|
||||
+62
-3
@@ -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;
|
||||
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
|
||||
};
|
||||
+27
-58
@@ -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,59 +55,32 @@ 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
|
||||
);
|
||||
};
|
||||
|
||||
// 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);
|
||||
});
|
||||
})
|
||||
|
||||
function(dir, output, options) {
|
||||
build.files(dir, output, options, {
|
||||
extension: "pdf",
|
||||
format: "pdf",
|
||||
options: {
|
||||
paperformat: options.paperformat
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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;
|
||||
@@ -11,6 +11,7 @@ var generators = {
|
||||
"site": require("./site"),
|
||||
"page": require("./page"),
|
||||
"pdf": require("./pdf"),
|
||||
"ebook": require("./ebook"),
|
||||
"json": require("./json")
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user