summaryrefslogtreecommitdiffstats
path: root/lib/config/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/config/index.js')
-rw-r--r--lib/config/index.js132
1 files changed, 132 insertions, 0 deletions
diff --git a/lib/config/index.js b/lib/config/index.js
new file mode 100644
index 0000000..7f75733
--- /dev/null
+++ b/lib/config/index.js
@@ -0,0 +1,132 @@
+var _ = require('lodash');
+var semver = require('semver');
+
+var gitbook = require('../gitbook');
+var Promise = require('../utils/promise');
+var validator = require('./validator');
+var plugins = require('./plugins');
+
+// Config files to tested (sorted)
+var CONFIG_FILES = [
+ 'book.js',
+ 'book.json'
+];
+
+/*
+Config is an interface for the book's configuration stored in "book.json" (or "book.js")
+*/
+
+function Config(book, baseConfig) {
+ this.book = book;
+ this.fs = book.fs;
+ this.log = book.log;
+ this.path = '';
+
+ this.baseConfig = baseConfig || {};
+ this.replace({});
+}
+
+// Load configuration of the book
+// and verify that the configuration is satisfying
+Config.prototype.load = function() {
+ var that = this;
+ var isLanguageBook = this.book.isLanguageBook();
+
+ // Try all potential configuration file
+ return Promise.some(CONFIG_FILES, function(filename) {
+ that.log.debug.ln('try loading configuration from', filename);
+
+ return that.fs.loadAsObject(that.book.resolve(filename))
+ .then(function(_config) {
+ that.log.debug.ln('configuration loaded from', filename);
+
+ that.path = filename;
+ return that.replace(_config);
+ })
+ .fail(function(err) {
+ if (err.code != 'MODULE_NOT_FOUND') throw(err);
+ else return Promise(false);
+ });
+ })
+ .then(function() {
+ if (!isLanguageBook) {
+ if (!gitbook.satisfies(that.options.gitbook)) {
+ throw new Error('GitBook version doesn\'t satisfy version required by the book: '+that.options.gitbook);
+ }
+ if (that.options.gitbook != '*' && !semver.satisfies(semver.inc(gitbook.version, 'patch'), that.options.gitbook)) {
+ that.log.warn.ln('gitbook version specified in your book.json might be too strict for future patches, \''+(_.first(gitbook.version.split('.'))+'.x.x')+'\' is more adequate');
+ }
+
+ that.options.plugins = plugins.toList(that.options.plugins);
+ } else {
+ // Multilingual book should inherits the plugins list from parent
+ that.options.plugins = that.book.parent.config.get('plugins');
+ }
+
+ that.options.gitbook = gitbook.version;
+ });
+};
+
+// Replace the whole configuration
+Config.prototype.replace = function(options) {
+ var that = this;
+
+ // Extend base config
+ options = _.defaults(_.cloneDeep(options), this.baseConfig);
+
+ // Validate the config
+ this.options = validator.validate(options);
+
+ // options.input == book.root
+ Object.defineProperty(this.options, 'input', {
+ get: function () {
+ return that.book.root;
+ }
+ });
+
+ // options.originalInput == book.parent.root
+ Object.defineProperty(this.options, 'originalInput', {
+ get: function () {
+ return that.book.parent? that.book.parent.root : undefined;
+ }
+ });
+};
+
+// Return true if book has a configuration file
+Config.prototype.exists = function() {
+ return Boolean(this.path);
+};
+
+// Return path to a structure file
+// Strip the extension by default
+Config.prototype.getStructure = function(name, dontStripExt) {
+ var filename = this.options.structure[name];
+ if (dontStripExt) return filename;
+
+ filename = filename.split('.').slice(0, -1).join('.');
+ return filename;
+};
+
+// Return a configuration using a key and a default value
+Config.prototype.get = function(key, def) {
+ return _.get(this.options, key, def);
+};
+
+// Update a configuration
+Config.prototype.set = function(key, value) {
+ return _.set(this.options, key, value);
+};
+
+// Return a dump of the configuration
+Config.prototype.dump = function() {
+ return _.cloneDeep(this.options);
+};
+
+// Return templating context
+Config.prototype.getContext = function() {
+ return {
+ config: this.book.config.dump()
+ };
+};
+
+module.exports = Config;