summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron O'Mullan <aaron.omullan@friendco.de>2014-05-04 12:53:24 -0700
committerAaron O'Mullan <aaron.omullan@friendco.de>2014-05-04 12:53:24 -0700
commit96ecfd098bf897bc1cadfada99a6d221d84f8b42 (patch)
tree0a855e647caa8df5a403e7559da25d49fb2a19e6
parentf7fe976c7e6cb6984aae0050a91cd76f77d10062 (diff)
downloadgitbook-96ecfd098bf897bc1cadfada99a6d221d84f8b42.zip
gitbook-96ecfd098bf897bc1cadfada99a6d221d84f8b42.tar.gz
gitbook-96ecfd098bf897bc1cadfada99a6d221d84f8b42.tar.bz2
Improve generate's reliability, fixes #202
This also improves speed on multi language books
-rw-r--r--lib/generate/index.js253
1 files changed, 153 insertions, 100 deletions
diff --git a/lib/generate/index.js b/lib/generate/index.js
index c6c26ca..2f635cb 100644
--- a/lib/generate/index.js
+++ b/lib/generate/index.js
@@ -18,14 +18,27 @@ var generators = {
var defaultDescription = "Book generated using GitBook";
-/*
- * Use a specific generator to convert a gitbook to a site/pdf/ebook/
- * output is always a folder
- */
-var generate = function(options) {
- var generator = null;
- var files;
+var containsFiles = function(dir, files) {
+ return Q.all(_.map(files, function(file) {
+ return fs.exists(path.join(dir, file));
+ }))
+ .then(_.all);
+};
+
+
+// Create the generator and load plugins
+var loadGenerator = function(options) {
+ var generator = new generators[options.generator](options);
+
+ return generator.loadPlugins()
+ .then(_.constant(generator));
+};
+
+
+
+var generate = function(options) {
+ // Set defaults to options
options = _.defaults(options || {}, {
// Folders to use
"input": null,
@@ -58,18 +71,87 @@ var generate = function(options) {
}
});
+ // Validate options
if (!options.input) {
return Q.reject(new Error("Need option input (book input directory)"));
}
+ // Ensure generator exists
if (!generators[options.generator]) {
return Q.reject(new Error("Invalid generator (availables are: "+_.keys(generators).join(", ")));
}
+ // Check files to get folder type (book, multilanguage book or neither)
+ return containsFiles(options.input, ['LANGS.md'])
+ .then(function(isMultiLang) {
+ // Multi language book
+ if(isMultiLang) {
+ return generateMultiLang(options);
+ }
+
+ // Book
+ return generateBook(options);
+ });
+};
+
+
+var generateMultiLang = function(options) {
options.output = options.output || path.join(options.input, "_book");
+ // Multi-languages book
+ return fs.readFile(path.join(options.input, "LANGS.md"), "utf-8")
+
+ // Generate sub-books
+ .then(function(_langsSummary) {
+ options.langsSummary = parse.langs(_langsSummary);
+
+ // Generated a book for each valid entry
+ return Q.all(
+ _.map(options.langsSummary.list, function(entry) {
+ return generate(_.extend({}, options, {
+ input: path.join(options.input, entry.path),
+ output: path.join(options.output, entry.path)
+ }));
+ })
+ );
+ })
+
+ .then(function() {
+ return loadGenerator(options);
+ })
+
+ // Generate languages index
+ .then(function(generator) {
+ return generator.langsIndex(options.langsSummary);
+ })
+
+ // Return options to caller
+ .then(_.constant(options));
+};
+
+/*
+ * Use a specific generator to convert a gitbook to a site/pdf/ebook/
+ * output is always a folder
+ */
+var generateBook = function(options) {
+ var files;
+
+ options.output = options.output || path.join(options.input, "_book");
+
+ // Check if it's a book
+ return containsFiles(options.input, ['SUMMARY.md', 'README.md'])
+
+ // Fail if not a book
+ .then(function(isBook) {
+ if(!isBook) {
+ return Q.reject(new Error("Invalid gitbook repository, need SUMMARY.md and README.md"));
+ }
+ })
+
// Clean output folder
- return fs.remove(options.output)
+ .then(function() {
+ return fs.remove(options.output);
+ })
// Read config file
.then(function() {
@@ -83,7 +165,7 @@ var generate = function(options) {
}, function() {
// No config file: not a big deal
return Q();
- })
+ });
})
// Get repo's URL
@@ -109,108 +191,78 @@ var generate = function(options) {
return fs.list(options.input)
.then(function(_files) {
files = _files;
- })
+ });
})
- // Create the generator and load plugins
.then(function() {
- generator = new generators[options.generator](options);
- return generator.loadPlugins();
+ return loadGenerator(options);
})
// Detect multi-languages book
- .then(function() {
- if (_.contains(files, "LANGS.md")) {
- // Multi-languages book
- return fs.readFile(path.join(options.input, "LANGS.md"), "utf-8")
-
- // Generate sub-books
- .then(function(_langsSummary) {
- options.langsSummary = parse.langs(_langsSummary);
-
- // Generated a book for each valid entry
- return Q.all(
- _.map(options.langsSummary.list, function(entry) {
- return generate(_.extend({}, options, {
- input: path.join(options.input, entry.path),
- output: path.join(options.output, entry.path)
- }));
- })
- );
- })
-
- // Generate languages index
- .then(function() {
- return generator.langsIndex(options.langsSummary);
+ .then(function(generator) {
+ // Generate the book
+ return Q()
+
+ // Read readme
+ .then(function() {
+ return fs.readFile(path.join(options.input, "README.md"), "utf-8")
+ .then(function(_readme) {
+ _readme = parse.readme(_readme);
+
+ options.title = options.title || _readme.title;
+ options.description = options.description || _readme.description || defaultDescription;
});
- } else if (!_.contains(files, "SUMMARY.md") || !_.contains(files, "README.md")) {
- // Invalid book
- return Q.reject(new Error("Invalid gitbook repository, need SUMMARY.md and README.md"));
- } else {
- // Generate the book
- return Q()
-
- // Read readme
- .then(function() {
- return fs.readFile(path.join(options.input, "README.md"), "utf-8")
- .then(function(_readme) {
- _readme = parse.readme(_readme);
-
- options.title = options.title || _readme.title;
- options.description = options.description || _readme.description || defaultDescription;
- });
- })
-
- // Get summary
- .then(function() {
- return fs.readFile(path.join(options.input, "SUMMARY.md"), "utf-8")
- .then(function(_summary) {
- options.summary = parse.summary(_summary);
+ })
- // Parse navigation
- options.navigation = parse.navigation(options.summary);
- });
- })
+ // Get summary
+ .then(function() {
+ return fs.readFile(path.join(options.input, "SUMMARY.md"), "utf-8")
+ .then(function(_summary) {
+ options.summary = parse.summary(_summary);
- // Skip processing some files
- .then(function() {
- files = _.filter(files, function (file) {
- return !(
- file === 'SUMMARY.md'
- );
- });
- })
+ // Parse navigation
+ options.navigation = parse.navigation(options.summary);
+ });
+ })
- // Copy file and replace markdown file
- .then(function() {
- return Q.all(
- _.chain(files)
- .map(function(file) {
- if (!file) return;
-
- if (file[file.length -1] == "/") {
- return Q(generator.transferFolder(file));
- } else if (path.extname(file) == ".md" && options.navigation[file] != null) {
- return fs.readFile(path.join(options.input, file), "utf-8")
- .then(function(content) {
- return Q(generator.convertFile(content, file));
- });
- } else {
- return Q(generator.transferFile(file));
- }
- })
- .value()
+ // Skip processing some files
+ .then(function() {
+ files = _.filter(files, function (file) {
+ return !(
+ file === 'SUMMARY.md'
);
- })
-
- // Finish generation
- .then(function() {
- return generator.finish();
- })
- .then(function() {
- return generator.callHook("finish");
});
- }
+ })
+
+ // Copy file and replace markdown file
+ .then(function() {
+ return Q.all(
+ _.chain(files)
+ .map(function(file) {
+ if (!file) return;
+
+ if (file[file.length -1] == "/") {
+ return Q(generator.transferFolder(file));
+ } else if (path.extname(file) == ".md" && options.navigation[file] != null) {
+ return fs.readFile(path.join(options.input, file), "utf-8")
+ .then(function(content) {
+ return Q(generator.convertFile(content, file));
+ });
+ } else {
+ return Q(generator.transferFile(file));
+ }
+ })
+ .value()
+ );
+ })
+
+ // Finish generation
+ .then(function() {
+ return generator.finish();
+ })
+ .then(function() {
+ return generator.callHook("finish");
+ });
})
// Return all options
@@ -281,5 +333,6 @@ module.exports = {
generators: generators,
folder: generate,
file: generateFile,
- Plugin: Plugin
+ book: generateBook,
+ Plugin: Plugin,
};