summaryrefslogtreecommitdiffstats
path: root/lib/plugin.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/plugin.js')
-rw-r--r--lib/plugin.js107
1 files changed, 83 insertions, 24 deletions
diff --git a/lib/plugin.js b/lib/plugin.js
index 5e1c427..b4d4aa1 100644
--- a/lib/plugin.js
+++ b/lib/plugin.js
@@ -1,16 +1,28 @@
-var _ = require("lodash");
-var Q = require("q");
-var semver = require("semver");
-var path = require("path");
-var url = require("url");
-var fs = require("./utils/fs");
-var resolve = require("resolve");
+var _ = require('lodash');
+var Q = require('q');
+var semver = require('semver');
+var path = require('path');
+var url = require('url');
+var fs = require('./utils/fs');
+var resolve = require('resolve');
+var mergeDefaults = require('merge-defaults');
+var jsonschema = require('jsonschema');
+var jsonSchemaDefaults = require('json-schema-defaults');
+
+var pkg = require('../package.json');
+
+var PLUGIN_PREFIX = 'gitbook-plugin-';
+
+// Return an absolute name for the plugin (the one on NPM)
+function absoluteName(name) {
+ if (name.indexOf(PLUGIN_PREFIX) === 0) return name;
+ return [PLUGIN_PREFIX, name].join('');
+}
-var pkg = require("../package.json");
var Plugin = function(book, name) {
this.book = book;
- this.name = name;
+ this.name = absoluteName(name);
this.packageInfos = {};
this.infos = {};
@@ -18,9 +30,8 @@ var Plugin = function(book, name) {
_.bindAll(this);
_.each([
- "gitbook-plugin-"+name,
- "gitbook-"+name,
- name,
+ absoluteName(name),
+ name
], function(_name) {
// Load from the book
if (this.load(_name, book.root)) return false;
@@ -31,20 +42,27 @@ var Plugin = function(book, name) {
};
// Type of plugins resources
-Plugin.RESOURCES = ["js", "css"];
+Plugin.RESOURCES = ['js', 'css'];
Plugin.HOOKS = [
- "init", "finish", "finish:before", "page", "page:before"
+ 'init', 'finish', 'finish:before', 'config', 'page', 'page:before'
];
+// Return the reduce name for the plugin
+// "gitbook-plugin-test" -> "test"
+// Return a relative name for the plugin (the one on GitBook)
+Plugin.prototype.reducedName = function() {
+ return this.name.replace(PLUGIN_PREFIX, '');
+};
+
// Load from a name
Plugin.prototype.load = function(name, baseDir) {
try {
- var res = resolve.sync(name+"/package.json", { basedir: baseDir });
+ var res = resolve.sync(name+'/package.json', { basedir: baseDir });
this.baseDir = path.dirname(res);
this.packageInfos = require(res);
this.infos = require(resolve.sync(name, { basedir: baseDir }));
- this.name = name;
+ this.name = this.packageInfos.name;
return true;
} catch (e) {
@@ -62,13 +80,13 @@ Plugin.prototype.normalizeResource = function(resource) {
// so we will simply link to using it's URL
if (parsed.protocol) {
return {
- "url": resource
+ 'url': resource
};
}
// This will be copied over from disk
// and shipped with the book's build
- return { "path": this.name+"/"+resource };
+ return { 'path': this.name+'/'+resource };
};
// Return resources
@@ -77,7 +95,7 @@ Plugin.prototype._getResources = function(base) {
var book = this.infos[base];
// Compatibility with version 1.x.x
- if (base == "website") book = book || this.infos.book;
+ if (base == 'website') book = book || this.infos.book;
// Nothing specified, fallback to default
if (!book) {
@@ -85,7 +103,7 @@ Plugin.prototype._getResources = function(base) {
}
// Dynamic function
- if(typeof book === "function") {
+ if(typeof book === 'function') {
// Call giving it the context of our book
return Q().then(book.bind(this.book));
}
@@ -133,12 +151,43 @@ Plugin.prototype.isValid = function() {
// Valid hooks
_.each(this.infos.hooks, function(hook, hookName) {
if (_.contains(Plugin.HOOKS, hookName)) return;
- that.book.log.warn.ln("Hook '"+hookName+" 'used by plugin '"+that.packageInfos.name+"' has been removed or is deprecated");
+ that.book.log.warn.ln('Hook "'+hookName+'"" used by plugin "'+that.packageInfos.name+'" has been removed or is deprecated');
});
return isValid;
};
+// Normalize, validate configuration for this plugin using its schema
+// Throw an error when shcema is not respected
+Plugin.prototype.validateConfig = function(config) {
+ var that = this;
+
+ return Q()
+ .then(function() {
+ var schema = that.packageInfos.gitbook || {};
+ if (!schema) return config;
+
+ // Normalize schema
+ schema.id = '/pluginsConfig.'+that.reducedName();
+ schema.type = 'object';
+
+ // Validate and throw if invalid
+ var v = new jsonschema.Validator();
+ var result = v.validate(config, schema, {
+ propertyName: 'pluginsConfig.'+that.reducedName()
+ });
+
+ // Throw error
+ if (result.errors.length > 0) {
+ throw new Error('Configuration Error: '+result.errors[0].stack);
+ }
+
+ // Insert default values
+ var defaults = jsonSchemaDefaults(schema);
+ return mergeDefaults(config, defaults);
+ });
+};
+
// Resolve file path
Plugin.prototype.resolveFile = function(filename) {
return path.resolve(this.baseDir, filename);
@@ -154,8 +203,8 @@ Plugin.prototype.callHook = function(name, data) {
if (!hookFunc) return Q(data);
- this.book.log.debug.ln("call hook", name);
- if (!_.contains(Plugin.HOOKS, name)) this.book.log.warn.ln("hook '"+name+"' used by plugin '"+this.name+"' is deprecated, and will be removed in the coming versions");
+ this.book.log.debug.ln('call hook', name);
+ if (!_.contains(Plugin.HOOKS, name)) this.book.log.warn.ln('hook "'+name+'" used by plugin "'+this.name+'" is deprecated, and will be removed in the coming versions');
return Q()
.then(function() {
@@ -168,7 +217,7 @@ Plugin.prototype.copyAssets = function(out, base) {
var that = this;
return this.getResources(base)
- .get("assets")
+ .get('assets')
.then(function(assets) {
// Assets are undefined
if(!assets) return false;
@@ -180,4 +229,14 @@ Plugin.prototype.copyAssets = function(out, base) {
}, _.constant(false));
};
+// Get config from book
+Plugin.prototype.getConfig = function() {
+ return this.book.config.get('pluginsConfig.'+this.reducedName(), {});
+};
+
+// Set configuration for this plugin
+Plugin.prototype.setConfig = function(values) {
+ return this.book.config.set('pluginsConfig.'+this.reducedName(), values);
+};
+
module.exports = Plugin;