diff options
author | Aaron O'Mullan <aaron.omullan@friendco.de> | 2014-05-04 12:53:24 -0700 |
---|---|---|
committer | Aaron O'Mullan <aaron.omullan@friendco.de> | 2014-05-04 12:53:24 -0700 |
commit | 96ecfd098bf897bc1cadfada99a6d221d84f8b42 (patch) | |
tree | 0a855e647caa8df5a403e7559da25d49fb2a19e6 | |
parent | f7fe976c7e6cb6984aae0050a91cd76f77d10062 (diff) | |
download | gitbook-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.js | 253 |
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, }; |