summaryrefslogtreecommitdiffstats
path: root/lib/generate/plugin.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/generate/plugin.js')
-rw-r--r--lib/generate/plugin.js178
1 files changed, 111 insertions, 67 deletions
diff --git a/lib/generate/plugin.js b/lib/generate/plugin.js
index 3eacc19..cf24bc0 100644
--- a/lib/generate/plugin.js
+++ b/lib/generate/plugin.js
@@ -10,11 +10,15 @@ var pkg = require("../../package.json");
var RESOURCES = ["js", "css"];
-var Plugin = function(name, root) {
+var Plugin = function(name, root, generator) {
this.name = name;
this.root = root;
this.packageInfos = {};
this.infos = {};
+ this.generator = generator;
+
+ // Bind methods
+ _.bindAll(this);
_.each([
"gitbook-plugin-"+name,
@@ -43,28 +47,50 @@ Plugin.prototype.load = function(name, baseDir) {
}
};
+Plugin.prototype.normalizeResource = function(resource) {
+ // Parse the resource path
+ var parsed = url.parse(resource);
+
+ // This is a remote resource
+ // so we will simply link to using it's URL
+ if (parsed.protocol) {
+ return {
+ "url": resource
+ };
+ }
+
+ // This will be copied over from disk
+ // and shipped with the book's build
+ return { "path": this.name+"/"+resource };
+};
+
// Return resources
-Plugin.prototype.getResources = function(resource) {
- if (!this.infos.book || !this.infos.book[resource]) {
- return [];
+Plugin.prototype.getResources = function() {
+ var book = this.infos.book;
+
+ // Nothing specified, fallback to default
+ if (!book) {
+ return Q({});
}
- return _.chain(this.infos.book[resource])
- .map(function(resource) {
- var parsed = url.parse(resource);
- if (parsed.protocol) return {"url": resource}
- else return { "path": this.name+"/"+resource };
- }.bind(this))
- .value();
+
+ // Dynamic function
+ if(typeof book === "function") {
+ // Call giving it the context of our generator
+ return Q().then(book.bind(this.generator));
+ }
+
+ // Plain data object
+ return Q(book);
};
// Test if it's a valid plugin
Plugin.prototype.isValid = function() {
return (
- this.packageInfos
- && this.packageInfos.name
- && this.packageInfos.engines
- && this.packageInfos.engines.gitbook
- && semver.satisfies(pkg.version, this.packageInfos.engines.gitbook)
+ this.packageInfos &&
+ this.packageInfos.name &&
+ this.packageInfos.engines &&
+ this.packageInfos.engines.gitbook &&
+ semver.satisfies(pkg.version, this.packageInfos.engines.gitbook)
);
};
@@ -74,7 +100,10 @@ Plugin.prototype.resolveFile = function(filename) {
};
// Resolve file path
-Plugin.prototype.callHook = function(name, context, data) {
+Plugin.prototype.callHook = function(name, data) {
+ // Our generator will be the context to apply
+ var context = this.generator;
+
var hookFunc = this.infos.hooks? this.infos.hooks[name] : null;
data = data || {};
@@ -114,7 +143,7 @@ Plugin.normalizeNames = function(names) {
return name.length > 0 && name[0] == "-";
})
.map(function(name) {
- return name.slice(1)
+ return name.slice(1);
})
.value();
@@ -133,69 +162,84 @@ Plugin.normalizeNames = function(names) {
};
// Extract data from a list of plugin
-Plugin.fromList = function(names, root) {
+Plugin.fromList = function(names, root, generator) {
var failed = [];
// Load plugins
var plugins = _.map(names, function(name) {
- var plugin = new Plugin(name, root);
+ var plugin = new Plugin(name, root, generator);
if (!plugin.isValid()) failed.push(name);
return plugin;
});
if (_.size(failed) > 0) return Q.reject(new Error("Error loading plugins: "+failed.join(",")));
- // Get all resources
- var resources = _.chain(RESOURCES)
- .map(function(resource) {
- return [
- resource,
- _.chain(plugins)
- .map(function(plugin) {
- return plugin.getResources(resource);
- })
+ // Get resources of plugins
+ return Q.all(_.map(plugins, function(plugin) {
+ return plugin.getResources();
+ }))
+ // Extract resources out
+ // css, js, etc ...
+ .then(function(resources) {
+ // Group by resource types
+ return _.chain(RESOURCES)
+ .map(function(resourceType) {
+ // Get resources from all the plugins for this current type
+ return _.chain(resources)
+ .pluck(resourceType)
+ .compact()
.flatten()
- .value()
- ];
- })
- .object()
- .value();
- 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);
- if (!resources.html[key]) resources.html[key] = [];
- resources.html[key].push(code);
+ .value();
})
- });
-
- return Q({
- 'list': plugins,
- 'resources': resources,
- 'hook': function(name, context, data) {
- return _.reduce(plugins, function(prev, plugin) {
- return prev.then(function(ret) {
- return plugin.callHook(name, context, ret);
- })
- }, Q(data));
- },
- 'template': function(name) {
- var withTpl = _.find(plugins, function(plugin) {
- return (plugin.infos.templates
- && plugin.infos.templates[name]);
+ .object()
+ .value();
+ })
+ // Extract html snippets
+ .then(function(resources) {
+ // Map of html resources by name added by each plugin
+ resources.html = plugins.reduce(function(accu, plugin) {
+ var html = plugin.infos.book.html || {};
+ _.each(html, function(code, key) {
+ // Turn into function if not one already
+ if (!_.isFunction(code)) code = _.constant(code);
+ // Append
+ accu[key] = (accu[key] || []).concat([code]);
});
- if (!withTpl) return null;
- return withTpl.resolveFile(withTpl.infos.templates[name]);
- },
- 'html': function(tag, context, options) {
- return _.map(resources.html[tag] || [], function(code) {
- return code.call(context, options);
- }).join("\n");
- }
+ return accu;
+ }, {});
+
+ return resources;
+ })
+ // Return big multi-plugin object
+ .then(function(resources) {
+ return {
+ 'list': plugins,
+ 'resources': resources,
+ 'hook': function(name, data) {
+ return _.reduce(plugins, function(prev, plugin) {
+ return prev.then(function(ret) {
+ return plugin.callHook(name, ret);
+ });
+ }, Q(data));
+ },
+ 'template': function(name) {
+ var withTpl = _.find(plugins, function(plugin) {
+ return (
+ plugin.infos.templates &&
+ plugin.infos.templates[name]
+ );
+ });
+
+ if (!withTpl) return null;
+ return withTpl.resolveFile(withTpl.infos.templates[name]);
+ },
+ 'html': function(tag, context, options) {
+ return _.map(resources.html[tag] || [], function(code) {
+ return code.call(context, options);
+ }).join("\n");
+ }
+ };
});
};