summaryrefslogtreecommitdiffstats
path: root/lib/generate
diff options
context:
space:
mode:
Diffstat (limited to 'lib/generate')
-rw-r--r--lib/generate/config.js32
-rw-r--r--lib/generate/ebook/index.js1
-rw-r--r--lib/generate/fs.js15
-rw-r--r--lib/generate/index.js36
-rw-r--r--lib/generate/page/index.js10
-rw-r--r--lib/generate/plugin.js73
6 files changed, 125 insertions, 42 deletions
diff --git a/lib/generate/config.js b/lib/generate/config.js
index 7ec0741..fb232a6 100644
--- a/lib/generate/config.js
+++ b/lib/generate/config.js
@@ -1,3 +1,4 @@
+var Q = require('q');
var _ = require('lodash');
var path = require('path');
@@ -16,9 +17,10 @@ var CONFIG = {
// Configuration file to use
"configFile": "book",
- // Book title and description (defaults are extracted from the README)
+ // Book metadats (somes are extracted from the README by default)
"title": null,
"description": null,
+ "isbn": null,
// For ebook format, the extension to use for generation (default is detected from output extension)
// "epub", "pdf", "mobi"
@@ -96,10 +98,32 @@ var CONFIG = {
}
};
+// Return complete configuration
+var defaultsConfig = function(options) {
+ return _.merge(options || {}, CONFIG, _.defaults);
+};
+
+// Read configuration from book.json
+var readConfig = function(options) {
+ options = defaultsConfig(options);
+
+ return Q()
+ .then(function() {
+ try {
+ var _config = require(path.resolve(options.input, options.configFile));
+ options = _.merge(options, _.omit(_config, 'input', 'configFile', 'defaultsPlugins', 'generator'));
+ }
+ catch(err) {
+ // No config file: not a big deal
+ return Q();
+ }
+ })
+ .thenResolve(options);
+};
+
module.exports = {
CONFIG: CONFIG,
- defaults: function(options) {
- return _.merge(options || {}, CONFIG, _.defaults);
- }
+ defaults: defaultsConfig,
+ read: readConfig
}
diff --git a/lib/generate/ebook/index.js b/lib/generate/ebook/index.js
index bc39e15..4ecccec 100644
--- a/lib/generate/ebook/index.js
+++ b/lib/generate/ebook/index.js
@@ -30,6 +30,7 @@ Generator.prototype.finish = function() {
"--cover": that.options.cover,
"--title": that.options.title,
"--comments": that.options.description,
+ "--isbn": that.options.isbn,
"--authors": that.options.author,
"--publisher": "GitBook",
"--chapter": "descendant-or-self::*[contains(concat(' ', normalize-space(@class), ' '), ' book-chapter ')]",
diff --git a/lib/generate/fs.js b/lib/generate/fs.js
index 4c232e7..50219eb 100644
--- a/lib/generate/fs.js
+++ b/lib/generate/fs.js
@@ -64,7 +64,20 @@ var getFiles = function(path) {
module.exports = {
list: getFiles,
readFile: Q.denodeify(fs.readFile),
- writeFile: Q.denodeify(fs.writeFile),
+ //writeFile: Q.denodeify(fs.writeFile),
+ writeFile: function(filename, data, options) {
+ var d = Q.defer();
+
+ try {
+ fs.writeFileSync(filename, data, options)
+ } catch(err) {
+ d.reject(err);
+ }
+ d.resolve();
+
+
+ return d.promise;
+ },
mkdirp: Q.denodeify(fsExtra.mkdirp),
copy: Q.denodeify(fsExtra.copy),
remove: Q.denodeify(fsExtra.remove),
diff --git a/lib/generate/index.js b/lib/generate/index.js
index 2118c46..de1fc0e 100644
--- a/lib/generate/index.js
+++ b/lib/generate/index.js
@@ -48,28 +48,18 @@ var loadGenerator = function(options) {
var generate = function(options) {
- // Set defaults to options
- options = defaultConfig.defaults(options);
-
- // Validate options
- if (!options.input) {
- return Q.reject(new Error("Need option input (book input directory)"));
- }
-
- // Check files to get folder type (book, multilanguage book or neither)
- return checkGenerator(options)
-
// Read config file
- .then(function() {
- try {
- var _config = require(path.resolve(options.input, options.configFile));
+ return defaultConfig.read(options)
+ .then(function(_options) {
+ options = _options;
- options = _.merge(options, _.omit(_config, 'input', 'configFile', 'defaultsPlugins'));
- }
- catch(err) {
- // No config file: not a big deal
- return Q();
+ // Validate options
+ if (!options.input) {
+ return Q.reject(new Error("Need option input (book input directory)"));
}
+
+ // Check files to get folder type (book, multilanguage book or neither)
+ return checkGenerator(options);
})
// Read readme
@@ -99,7 +89,9 @@ var generate = function(options) {
});
};
-
+/*
+ * Generate a multilanguage book by generating a book for each folder.
+ */
var generateMultiLang = function(options) {
var langsSummary;
options.output = options.output || path.join(options.input, "_book");
@@ -298,6 +290,9 @@ var generateBook = function(options) {
// Finish generation
.then(function() {
+ return generator.callHook("finish:before");
+ })
+ .then(function() {
return generator.finish();
})
.then(function() {
@@ -375,4 +370,5 @@ module.exports = {
file: generateFile,
book: generateBook,
Plugin: Plugin,
+ config: defaultConfig
};
diff --git a/lib/generate/page/index.js b/lib/generate/page/index.js
index 8e44187..a926d13 100644
--- a/lib/generate/page/index.js
+++ b/lib/generate/page/index.js
@@ -26,6 +26,9 @@ Generator.prototype.loadTemplates = function() {
this.summaryTemplate = swig.compileFile(
this.plugins.template("ebook:sumary") || path.resolve(this.options.theme, 'templates/ebook/summary.html')
);
+ this.glossaryTemplate = swig.compileFile(
+ this.plugins.template("ebook:glossary") || path.resolve(this.options.theme, 'templates/ebook/glossary.html')
+ );
};
// Generate table of contents
@@ -46,7 +49,7 @@ Generator.prototype.finish = function() {
var output = path.join(this.options.output, "index.html");
var progress = parse.progress(this.options.navigation, "README.md");
-
+
return Q()
// Write table of contents
@@ -54,6 +57,11 @@ Generator.prototype.finish = function() {
return that.writeToc();
})
+ // Write glossary
+ .then(function() {
+ return that.writeGlossary();
+ })
+
// Copy cover
.then(function() {
return that.copyCover();
diff --git a/lib/generate/plugin.js b/lib/generate/plugin.js
index 9d740a5..5ca5e92 100644
--- a/lib/generate/plugin.js
+++ b/lib/generate/plugin.js
@@ -4,6 +4,7 @@ var semver = require("semver");
var path = require("path");
var url = require("url");
var fs = require("./fs");
+var npmi = require('npmi');
var resolve = require('resolve');
var pkg = require("../../package.json");
@@ -152,33 +153,73 @@ Plugin.prototype.copyAssets = function(out, options) {
};
-// Normalize a list of plugin name to use
-Plugin.normalizeNames = function(names) {
+// Install a list of plugin
+Plugin.install = function(options) {
+ // Normalize list of plugins
+ var plugins = Plugin.normalizeList(options.plugins);
+
+ // Install plugins one by one
+ return _.reduce(plugins, function(prev, plugin) {
+ return prev.then(function() {
+ var fullname = "gitbook-plugin-"+plugin.name;
+ console.log("Install plugin", plugin.name, "from npm ("+fullname+") with version", (plugin.version || "*"));
+ return Q.nfcall(npmi, {
+ 'name': fullname,
+ 'version': plugin.version,
+ 'path': options.input,
+ 'npmLoad': {
+ 'loglevel': 'silent',
+ 'loaded': false,
+ 'prefix': options.input
+ }
+ });
+ });
+ }, Q());
+};
+
+// Normalize a list of plugins to use
+Plugin.normalizeList = function(plugins) {
// Normalize list to an array
- names = _.isString(names) ? names.split(",") : (names || []);
+ plugins = _.isString(plugins) ? plugins.split(",") : (plugins || []);
+
+ // Divide as {name, version} to handle format like "myplugin@1.0.0"
+ plugins = _.map(plugins, function(plugin) {
+ var parts = plugin.split("@");
+ return {
+ 'name': parts[0],
+ 'version': parts[1] // optional
+ }
+ });
// List plugins to remove
- var toremove = _.chain(names)
- .filter(function(name) {
- return name.length > 0 && name[0] == "-";
+ var toremove = _.chain(plugins)
+ .filter(function(plugin) {
+ return plugin.name.length > 0 && plugin.name[0] == "-";
})
- .map(function(name) {
- return name.slice(1);
+ .map(function(plugin) {
+ return plugin.name.slice(1);
})
.value();
// Merge with defaults
- names = _.chain(names)
- .concat(Plugin.defaults)
+ plugins = _.chain(plugins)
+ .concat(_.map(Plugin.defaults, function(plugin) {
+ return { 'name': plugin }
+ }))
.uniq()
.value();
- // Remove plugins starting with
- names = _.filter(names, function(name) {
- return !_.contains(toremove, name) && !(name.length > 0 && name[0] == "-");
+ // Build final list
+ plugins = _.filter(plugins, function(plugin) {
+ return !_.contains(toremove, plugin.name) && !(plugin.name.length > 0 && plugin.name[0] == "-");
});
- return names;
+ return plugins;
+};
+
+// Normalize a list of plugin name to use
+Plugin.normalizeNames = function(plugins) {
+ return _.pluck(Plugin.normalizeList(plugins), "name");
};
// Extract data from a list of plugin
@@ -196,7 +237,7 @@ Plugin.fromList = function(names, root, generator, options) {
return plugin;
});
- if (_.size(failed) > 0) return Q.reject(new Error("Error loading plugins: "+failed.join(",")));
+ if (_.size(failed) > 0) return Q.reject(new Error("Error loading plugins: "+failed.join(",")+". Run 'gitbook install' to install plugins from NPM."));
// The raw resources extracted from each plugin
var pluginResources;
@@ -276,7 +317,7 @@ Plugin.fromList = function(names, root, generator, options) {
});
};
-// Default plugins
+// Default plugins added to each books
Plugin.defaults = [
"mathjax"
];