Use jsonschema to valid and default plugins config

This commit is contained in:
Samy Pessé
2015-10-13 13:56:46 +02:00
parent 2870155c0b
commit df5d27ab61
5 changed files with 79 additions and 25 deletions
+15
View File
@@ -194,6 +194,21 @@ Configuration.prototype.get = function(key, def) {
return _.get(this.options, key, def);
};
// Update a configuration
Configuration.prototype.set = function(key, value) {
return _.set(this.options, key, value);
};
// Return a configuration for a plugin
Configuration.prototype.getForPlugin = function(pluginName) {
return this.get('pluginsConfig.'+pluginName, {});
};
// Set a configuration for a plugin
Configuration.prototype.setForPlugin = function(pluginName, config) {
return this.get('pluginsConfig.'+pluginName, config);
};
// Default configuration
Configuration.DEFAULT = DEFAULT_CONFIG;
+27 -2
View File
@@ -5,6 +5,8 @@ var path = require('path');
var url = require('url');
var fs = require('./utils/fs');
var resolve = require('resolve');
var jsonschema = require('jsonschema');
var jsonSchemaDefaults = require('json-schema-defaults');
var pkg = require('../package.json');
@@ -20,7 +22,7 @@ var Plugin = function(book, name) {
_.each([
'gitbook-plugin-'+name,
'gitbook-'+name,
name,
name
], function(_name) {
// Load from the book
if (this.load(_name, book.root)) return false;
@@ -44,7 +46,7 @@ Plugin.prototype.load = function(name, 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) {
@@ -139,6 +141,29 @@ Plugin.prototype.isValid = function() {
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.type = 'object';
// Validate and throw if invalid
var v = new jsonschema.Validator();
v.validate(config, schema);
// Insert default values
var defaults = jsonSchemaDefaults(schema);
return _.merge(defaults, config);
});
};
// Resolve file path
Plugin.prototype.resolveFile = function(filename) {
return path.resolve(this.baseDir, filename);
+33 -21
View File
@@ -78,34 +78,46 @@ PluginsList.prototype.load = function(plugin) {
that.list.push(plugin);
}
// Extract filters
that.book.template.addFilters(plugin.getFilters());
return Q()
// Extract blocks
that.book.template.addBlocks(plugin.getBlocks());
// Validate and normalize configuration
.then(function() {
var config = that.book.config.getForPlugin(plugin.name);
return plugin.validateConfig(config);
})
.then(function(config) {
// Update configuration
that.book.config.getForPlugin(plugin.name, config);
return _.reduce(_.keys(that.namespaces), function(prev, namespaceName) {
return prev.then(function() {
return plugin.getResources(namespaceName)
.then(function(plResources) {
var namespace = that.namespaces[namespaceName];
// Extract filters
that.book.template.addFilters(plugin.getFilters());
// Extract js and css
_.each(Plugin.RESOURCES, function(resourceType) {
namespace.resources[resourceType] = (namespace.resources[resourceType] || []).concat(plResources[resourceType] || []);
});
// Extract blocks
that.book.template.addBlocks(plugin.getBlocks());
// Map of html resources by name added by each plugin
_.each(plResources.html || {}, function(value, tag) {
// Turn into function if not one already
if (!_.isFunction(value)) value = _.constant(value);
return _.reduce(_.keys(that.namespaces), function(prev, namespaceName) {
return prev.then(function() {
return plugin.getResources(namespaceName)
.then(function(plResources) {
var namespace = that.namespaces[namespaceName];
namespace.html[tag] = namespace.html[tag] || [];
namespace.html[tag].push(value);
// Extract js and css
_.each(Plugin.RESOURCES, function(resourceType) {
namespace.resources[resourceType] = (namespace.resources[resourceType] || []).concat(plResources[resourceType] || []);
});
// Map of html resources by name added by each plugin
_.each(plResources.html || {}, function(value, tag) {
// Turn into function if not one already
if (!_.isFunction(value)) value = _.constant(value);
namespace.html[tag] = namespace.html[tag] || [];
namespace.html[tag].push(value);
});
});
});
});
}, Q());
}, Q());
});
};
// Call a hook
+3 -1
View File
@@ -36,7 +36,9 @@
"dom-serializer": "0.1.0",
"spawn-cmd": "0.0.2",
"escape-string-regexp": "1.0.3",
"juice": "1.5.0"
"juice": "1.5.0",
"jsonschema": "1.0.2",
"json-schema-defaults": "0.1.1"
},
"devDependencies": {
"eslint": "1.5.0",
+1 -1
View File
@@ -93,7 +93,7 @@ describe('Plugins', function () {
// There is resources from highlight plugin and this plugin
resources.css.should.have.lengthOf(2);
should.exist(_.find(resources.css, {
path: './resources/test'
path: 'gitbook-plugin-resources/test'
}));
});
});