diff options
Diffstat (limited to 'lib/generate')
-rw-r--r-- | lib/generate/ebook/index.js | 53 | ||||
-rw-r--r-- | lib/generate/fs.js | 13 | ||||
-rw-r--r-- | lib/generate/generator.js | 21 | ||||
-rw-r--r-- | lib/generate/index.js | 76 | ||||
-rw-r--r-- | lib/generate/page/index.js | 25 | ||||
-rw-r--r-- | lib/generate/pdf/index.js | 56 | ||||
-rw-r--r-- | lib/generate/plugin.js | 2 | ||||
-rw-r--r-- | lib/generate/site/index.js | 23 | ||||
-rw-r--r-- | lib/generate/template.js | 52 |
9 files changed, 196 insertions, 125 deletions
diff --git a/lib/generate/ebook/index.js b/lib/generate/ebook/index.js index 7416860..e3d3db4 100644 --- a/lib/generate/ebook/index.js +++ b/lib/generate/ebook/index.js @@ -7,6 +7,7 @@ var exec = require('child_process').exec; var fs = require("fs"); var parse = require("../../parse"); var BaseGenerator = require("../page"); +var stringUtils = require("../../utils/string"); /* * This generator inherits from the single page generator @@ -14,11 +15,6 @@ var BaseGenerator = require("../page"); */ var Generator = function() { BaseGenerator.apply(this, arguments); - - // Options for eBook generation - this.options = _.defaults(this.options, { - extension: "epub" - }); }; util.inherits(Generator, BaseGenerator); @@ -28,27 +24,54 @@ Generator.prototype.finish = function() { return BaseGenerator.prototype.finish.apply(this) .then(function() { var d = Q.defer(); + var format = that.options.extension || path.extname(that.options.output).replace("\.", "") || "pdf"; if (!that.options.cover && fs.existsSync(path.join(that.options.output, "cover.jpg"))) { that.options.cover = path.join(that.options.output, "cover.jpg"); } var _options = { - "--cover": that.options.cover + "--cover": that.options.cover, + "--title": that.options.title, + "--comments": that.options.description, + "--authors": that.options.author, + "--level1-toc": "descendant-or-self::*[contains(concat(' ', normalize-space(@class), ' '), ' book-chapter-1 ')]", + "--level2-toc": "descendant-or-self::*[contains(concat(' ', normalize-space(@class), ' '), ' book-chapter-2 ')]", + "--level3-toc": "descendant-or-self::*[contains(concat(' ', normalize-space(@class), ' '), ' book-chapter-3 ')]" }; + if (format == "pdf") { + var pdfOptions = _.defaults(that.options.pdf || {}, { + "fontSize": 12, + "toc": true, + "pageNumbers": false, + "paperSize": "a4", + "margin": { + "right": 62, + "left": 62, + "top": 36, + "bottom": 36 + } + }); + + _.extend(_options, { + "--margin-left": String(pdfOptions.margin.left), + "--margin-right": String(pdfOptions.margin.right), + "--margin-top": String(pdfOptions.margin.top), + "--margin-bottom": String(pdfOptions.margin.bottom), + "--pdf-add-toc": Boolean(pdfOptions.toc), + "--pdf-default-font-size": String(pdfOptions.fontSize), + "--pdf-mono-font-size": String(pdfOptions.fontSize), + "--paper-size": String(pdfOptions.paperSize), + "--pdf-page-numbers": Boolean(pdfOptions.pageNumbers) + }); + } + 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(" ") + path.join(that.options.output, "index."+format), + stringUtils.optionsToShellArgs(_options) ].join(" "); exec(command, function (error, stdout, stderr) { diff --git a/lib/generate/fs.js b/lib/generate/fs.js index 12252e3..66530f3 100644 --- a/lib/generate/fs.js +++ b/lib/generate/fs.js @@ -16,9 +16,20 @@ var getFiles = function(path) { // Add extra rules to ignore common folders ig.addIgnoreRules([ + // Skip Git stuff '.git/', '.gitignore', - '.DS_Store' + + // Skip OS X meta data + '.DS_Store', + + // Skip stuff installed by plugins + 'node_modules', + + // Skip book outputs + '*.pdf', + '*.epub', + '*.mobi', ], '__custom_stuff'); // Push each file to our list diff --git a/lib/generate/generator.js b/lib/generate/generator.js index 2c4cb44..d664eef 100644 --- a/lib/generate/generator.js +++ b/lib/generate/generator.js @@ -45,6 +45,27 @@ BaseGenerator.prototype.transferFolder = function(input) { ); }; +BaseGenerator.prototype.copyCover = function() { + var that = this; + + return Q.all([ + fs.copy(path.join(this.options.input, "cover.jpg"), path.join(this.options.output, "cover.jpg")), + fs.copy(path.join(this.options.input, "cover_small.jpg"), path.join(this.options.output, "cover_small.jpg")) + ]) + .fail(function() { + // If orignally from multi-lang, try copy from originalInput + if (!that.options.originalInput) return; + + return Q.all([ + fs.copy(path.join(that.options.originalInput, "cover.jpg"), path.join(that.options.output, "cover.jpg")), + fs.copy(path.join(that.options.originalInput, "cover_small.jpg"), path.join(that.options.output, "cover_small.jpg")) + ]); + }) + .fail(function(err) { + return Q(); + }); +}; + BaseGenerator.prototype.langsIndex = function(langs) { return Q.reject(new Error("Langs index is not supported in this generator")); }; diff --git a/lib/generate/index.js b/lib/generate/index.js index 6b75dea..444f75f 100644 --- a/lib/generate/index.js +++ b/lib/generate/index.js @@ -1,9 +1,9 @@ var Q = require("q"); var _ = require("lodash"); var path = require("path"); -var swig = require('swig'); var tmp = require('tmp'); +var swig = require('./template'); var fs = require("./fs"); var parse = require("../parse"); var Plugin = require("./plugin"); @@ -11,7 +11,6 @@ var Plugin = require("./plugin"); var generators = { "site": require("./site"), "page": require("./page"), - "pdf": require("./pdf"), "ebook": require("./ebook"), "json": require("./json") }; @@ -26,13 +25,23 @@ var containsFiles = function(dir, files) { .then(_.all); }; +// TEst if generator exists +var checkGenerator = function(options) { + if (!generators[options.generator]) { + return Q.reject(new Error("Invalid generator (availables are: "+_.keys(generators).join(", ")+")")); + } + return Q(); +}; // Create the generator and load plugins var loadGenerator = function(options) { - var generator = new generators[options.generator](options); + return checkGenerator(options) + .then(function() { + var generator = new generators[options.generator](options); - return generator.loadPlugins() - .then(_.constant(generator)); + return generator.loadPlugins() + .then(_.constant(generator)); + }); }; @@ -45,7 +54,7 @@ var generate = function(options) { "output": null, // Config file (relative to input) - "configFile": "book.json", + "configFile": "book", // Output generator "generator": "site", @@ -79,27 +88,20 @@ var generate = function(options) { 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 Q() + return checkGenerator(options) // Read config file .then(function() { - return fs.readFile(path.resolve(options.input, options.configFile)) - .then(function(_config) { - // Extend current config - _config = JSON.parse(_config); - _config = _.omit(_config, 'input', 'configFile', 'defaultsPlugins'); - - _.extend(options, _config); - }, function() { + try { + var _config = require(path.resolve(options.input, options.configFile)); + + _.extend(options, _.omit(_config, 'input', 'configFile', 'defaultsPlugins')); + } + catch(err) { // No config file: not a big deal return Q(); - }); + } }) // Read readme @@ -134,8 +136,12 @@ var generateMultiLang = function(options) { var langsSummary; options.output = options.output || path.join(options.input, "_book"); + return checkGenerator(options) + // Multi-languages book - return fs.readFile(path.join(options.input, "LANGS.md"), "utf-8") + .then(function() { + return fs.readFile(path.join(options.input, "LANGS.md"), "utf-8") + }) // Clean output folder .then(function(_langsSummary) { @@ -155,7 +161,9 @@ var generateMultiLang = function(options) { return prev.then(function() { return generate(_.extend({}, options, { input: path.join(options.input, entry.path), - output: path.join(options.output, entry.path) + output: path.join(options.output, entry.path), + originalInput: options.input, + originalOutput: options.output })); }) }, Q()); @@ -170,6 +178,17 @@ var generateMultiLang = function(options) { return generator.langsIndex(options.langsSummary); }) + // Copy cover file + .then(function() { + return Q.all([ + fs.copy(path.join(options.input, "cover.jpg"), path.join(options.output, "cover.jpg")), + fs.copy(path.join(options.input, "cover_small.jpg"), path.join(options.output, "cover_small.jpg")) + ]) + .fail(function() { + return Q(); + }) + }) + // Return options to caller .then(_.constant(options)); }; @@ -205,8 +224,15 @@ var generateBook = function(options) { options.github = null; return null; } else if(options.github) { - // Git already specified in options - return options.github; + // Git already specified in options + options.github = ( + // Support URLs in "github" entry of book.json + parse.git.githubID(options.github) || + + // Fallback + options.github + ); + return; } // Try auto detecting diff --git a/lib/generate/page/index.js b/lib/generate/page/index.js index c2f4484..bd9b233 100644 --- a/lib/generate/page/index.js +++ b/lib/generate/page/index.js @@ -2,22 +2,12 @@ var _ = require("lodash"); var util = require("util"); var path = require("path"); var Q = require("q"); -var swig = require('swig'); -var hljs = require('highlight.js'); +var swig = require("../template"); var fs = require("../fs"); var parse = require("../../parse"); var BaseGenerator = require("../site"); -// Swig filter: highlight coloration -swig.setFilter('code', function(code, lang) { - try { - return hljs.highlight(lang, code).value; - } catch(e) { - return hljs.highlightAuto(code).value; - } -}); - /* * This generator will generate a simple index.html which can be converted as a PDF @@ -61,22 +51,35 @@ Generator.prototype.convertFile = function(content, input) { }); }; +// Generate languages index +Generator.prototype.langsIndex = function(langs) { + return Q(); +}; + Generator.prototype.finish = function() { var that = this; var basePath = "."; var output = path.join(this.options.output, "index.html"); + var progress = parse.progress(this.options.navigation, "README.md"); + return Q() // Generate html .then(function(pages) { return that._writeTemplate(that.template, { pages: that.pages, + progress: progress, basePath: basePath, staticBase: path.join(basePath, "gitbook"), }, output); }) + // Copy cover + .then(function() { + return that.copyCover(); + }) + // Copy assets .then(function() { return fs.copy( diff --git a/lib/generate/pdf/index.js b/lib/generate/pdf/index.js deleted file mode 100644 index 185eabd..0000000 --- a/lib/generate/pdf/index.js +++ /dev/null @@ -1,56 +0,0 @@ -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 pdf using gitbook-pdf - */ -var Generator = function() { - BaseGenerator.apply(this, arguments); - - // Options for PDF generation - this.options = _.defaults(this.options, { - paperformat: "A4" - }); -}; -util.inherits(Generator, BaseGenerator); - -Generator.prototype.finish = function() { - var that = this; - - return BaseGenerator.prototype.finish.apply(this) - .then(function() { - var d = Q.defer(); - - var command = [ - "gitbook-pdf", - "generate", - path.join(that.options.output, "index.html"), - path.join(that.options.output, "index.pdf"), - "--format="+that.options.paperformat - ].join(" "); - - exec(command, function (error, stdout, stderr) { - if (error) { - if (error.code == 127) { - error.message = "Need to install gitbook-pdf using: npm install gitbook-pdf -g"; - } else { - error.message = error.message + " "+stdout; - } - return d.reject(error); - } - d.resolve(); - }); - - return d.promise; - }); -}; - -module.exports = Generator; diff --git a/lib/generate/plugin.js b/lib/generate/plugin.js index 19eec86..3eacc19 100644 --- a/lib/generate/plugin.js +++ b/lib/generate/plugin.js @@ -163,6 +163,7 @@ Plugin.fromList = function(names, root) { resources.html = {} _.each(plugins, function(plugin) { + if (!plugin.infos.book || !plugin.infos.book.html) return; var html = plugin.infos.book.html || {}; _.each(html, function(code, key) { if (!_.isFunction(code)) code = _.constant(code); @@ -200,7 +201,6 @@ Plugin.fromList = function(names, root) { // Default plugins Plugin.defaults = [ - "mixpanel", "mathjax" ]; diff --git a/lib/generate/site/index.js b/lib/generate/site/index.js index da65152..b59c01c 100644 --- a/lib/generate/site/index.js +++ b/lib/generate/site/index.js @@ -2,26 +2,16 @@ var util = require("util"); var path = require("path"); var Q = require("q"); var _ = require("lodash"); -var swig = require('swig'); +var swig = require("../template"); var fs = require("../fs"); var parse = require("../../parse"); var BaseGenerator = require("../generator"); - +var links = require("../../utils/links"); var indexer = require('./search_indexer'); var Manifest = require('../manifest'); -// Swig filter for returning the count of lines in a code section -swig.setFilter('lines', function(content) { - return content.split('\n').length; -}); -// Swig filter for returning a link to the associated html file of a markdown file -swig.setFilter('mdLink', function(link) { - var link = link.replace(".md", ".html"); - if (link == "README.html") link = "index.html"; - return link; -}); var Generator = function() { BaseGenerator.apply(this, arguments); @@ -63,7 +53,6 @@ Generator.prototype._writeTemplate = function(tpl, options, output, interpolate) var that = this; interpolate = interpolate || _.identity; - return Q() .then(function(sections) { return tpl(_.extend({ @@ -163,7 +152,7 @@ Generator.prototype.convertFile = function(content, _input) { content: page.sections, basePath: basePath, - staticBase: path.join(basePath, "gitbook"), + staticBase: links.join(basePath, "gitbook"), }, output, function(html) { page.content = html; @@ -199,7 +188,7 @@ Generator.prototype.copyAssets = function() { path.join(that.options.output, "gitbook") ) - // Add to cach manifest + // Add to cache manifest .then(function() { return that.manifest.addFolder(path.join(that.options.output, "gitbook"), "gitbook"); }) @@ -238,7 +227,9 @@ Generator.prototype.writeCacheManifest = function() { }; Generator.prototype.finish = function() { - var deferred = this.copyAssets().then(this.writeSearchIndex); + var deferred = this.copyAssets() + .then(this.copyCover) + .then(this.writeSearchIndex); if (this.options.cache !== false) { deferred = deferred.then(this.writeCacheManifest); diff --git a/lib/generate/template.js b/lib/generate/template.js new file mode 100644 index 0000000..9b85228 --- /dev/null +++ b/lib/generate/template.js @@ -0,0 +1,52 @@ +var path = require("path"); +var swig = require('swig'); +var hljs = require('highlight.js'); + +var links = require('../utils/').links; +var pkg = require('../../package.json'); + +swig.setDefaults({ + locals: { + gitbook: { + version: pkg.version + } + } +}); + +// Swig filter for returning the count of lines in a code section +swig.setFilter('lines', function(content) { + return content.split('\n').length; +}); + +// Swig filter for returning a link to the associated html file of a markdown file +swig.setFilter('mdLink', function(link) { + var link = link.replace(".md", ".html"); + if (link == "README.html") link = "index.html"; + return link; +}); + +// Swig filter: highlight coloration +swig.setFilter('code', function(code, lang) { + try { + return hljs.highlight(lang, code).value; + } catch(e) { + return hljs.highlightAuto(code).value; + } +}); + +// Convert a level into a deep level +swig.setFilter('lvl', function(lvl) { + return lvl.split(".").length; +}); + +// Join path +swig.setFilter('pathJoin', function(base, _path) { + return path.join(base, _path); +}); + +// Is a link an absolute link +swig.setFilter('isExternalLink', function(link) { + return links.isExternal(link); +}); + +module.exports = swig; |