mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-12 05:48:57 +00:00
211 lines
6.3 KiB
JavaScript
211 lines
6.3 KiB
JavaScript
var _ = require('lodash');
|
|
var Q = require('q');
|
|
var path = require('path');
|
|
var semver = require('semver');
|
|
|
|
var pkg = require('../package.json');
|
|
var i18n = require('./utils/i18n');
|
|
var version = require('./version');
|
|
|
|
var DEFAULT_CONFIG = require('./config_default');
|
|
|
|
// Default plugins added to each books
|
|
var DEFAULT_PLUGINS = ['highlight', 'search', 'sharing', 'fontsettings'];
|
|
|
|
// Check if a plugin is a default plugin
|
|
// Plugin should be in the list
|
|
// And version from book.json specified for this plugin should be satisfied
|
|
function isDefaultPlugin(name, version) {
|
|
if (!_.contains(DEFAULT_PLUGINS, name)) return false;
|
|
|
|
try {
|
|
var pluginPkg = require('gitbook-plugin-'+name+'/package.json');
|
|
return semver.satisfies(pluginPkg.version, version || '*');
|
|
} catch(e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Normalize a list of plugins to use
|
|
function normalizePluginsList(plugins, addDefaults) {
|
|
// Normalize list to an array
|
|
plugins = _.isString(plugins) ? plugins.split(',') : (plugins || []);
|
|
|
|
// Remove empty parts
|
|
plugins = _.compact(plugins);
|
|
|
|
// Divide as {name, version} to handle format like 'myplugin@1.0.0'
|
|
plugins = _.map(plugins, function(plugin) {
|
|
if (plugin.name) return plugin;
|
|
|
|
var parts = plugin.split('@');
|
|
var name = parts[0];
|
|
var version = parts[1];
|
|
return {
|
|
'name': name,
|
|
'version': version, // optional
|
|
'isDefault': isDefaultPlugin(name, version)
|
|
};
|
|
});
|
|
|
|
// List plugins to remove
|
|
var toremove = _.chain(plugins)
|
|
.filter(function(plugin) {
|
|
return plugin.name.length > 0 && plugin.name[0] == '-';
|
|
})
|
|
.map(function(plugin) {
|
|
return plugin.name.slice(1);
|
|
})
|
|
.value();
|
|
|
|
// Merge with defaults
|
|
if (addDefaults !== false) {
|
|
_.each(DEFAULT_PLUGINS, function(plugin) {
|
|
if (_.find(plugins, { name: plugin })) {
|
|
return;
|
|
}
|
|
|
|
plugins.push({
|
|
'name': plugin,
|
|
'isDefault': true
|
|
});
|
|
});
|
|
}
|
|
|
|
// Remove plugin that start with '-'
|
|
plugins = _.filter(plugins, function(plugin) {
|
|
return !_.contains(toremove, plugin.name) && !(plugin.name.length > 0 && plugin.name[0] == '-');
|
|
});
|
|
|
|
// Remove duplicates
|
|
plugins = _.uniq(plugins, 'name');
|
|
|
|
return plugins;
|
|
}
|
|
|
|
var Configuration = function(book, options) {
|
|
this.book = book;
|
|
this.replace(options);
|
|
};
|
|
|
|
// Read and parse the configuration
|
|
Configuration.prototype.load = function() {
|
|
var that = this;
|
|
|
|
return Q()
|
|
.then(function() {
|
|
var configPath, _config;
|
|
|
|
try {
|
|
configPath = require.resolve(
|
|
that.book.resolve(that.options.configFile)
|
|
);
|
|
|
|
// Invalidate node.js cache for livreloading
|
|
delete require.cache[configPath];
|
|
|
|
_config = require(configPath);
|
|
that.options = _.merge(
|
|
that.options,
|
|
_.omit(_config, 'configFile', 'defaultsPlugins', 'generator', 'extension')
|
|
);
|
|
}
|
|
catch(err) {
|
|
if (err instanceof SyntaxError) return Q.reject(err);
|
|
return Q();
|
|
}
|
|
})
|
|
.then(function() {
|
|
if (!that.book.isSubBook()) {
|
|
if (!version.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(pkg.version, 'patch'), that.options.gitbook)) {
|
|
that.book.log.warn.ln('gitbook version specified in your book.json might be too strict for future patches, \''+(_.first(pkg.version.split('.'))+'.x.x')+'\' is more adequate');
|
|
}
|
|
}
|
|
|
|
that.options.output = path.resolve(that.options.output || that.book.resolve('_book'));
|
|
that.options.plugins = normalizePluginsList(that.options.plugins);
|
|
that.options.defaultsPlugins = normalizePluginsList(that.options.defaultsPlugins || '', false);
|
|
that.options.plugins = _.union(that.options.plugins, that.options.defaultsPlugins);
|
|
that.options.plugins = _.uniq(that.options.plugins, 'name');
|
|
|
|
// Default value for text direction (from language)
|
|
if (!that.options.direction) {
|
|
var lang = i18n.getCatalog(that.options.language);
|
|
if (lang) that.options.direction = lang.direction;
|
|
}
|
|
|
|
that.options.gitbook = pkg.version;
|
|
});
|
|
};
|
|
|
|
// Extend the configuration
|
|
Configuration.prototype.extend = function(options) {
|
|
_.extend(this.options, options);
|
|
};
|
|
|
|
// Replace the whole configuration
|
|
Configuration.prototype.replace = function(options) {
|
|
var that = this;
|
|
|
|
this.options = _.cloneDeep(DEFAULT_CONFIG);
|
|
this.options = _.merge(this.options, 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;
|
|
}
|
|
});
|
|
|
|
// options.originalOutput == book.parent.options.output
|
|
Object.defineProperty(this.options, 'originalOutput', {
|
|
get: function () {
|
|
return that.book.parent? that.book.parent.options.output : undefined;
|
|
}
|
|
});
|
|
};
|
|
|
|
// Dump configuration as json object
|
|
Configuration.prototype.dump = function() {
|
|
return _.cloneDeep(this.options);
|
|
};
|
|
|
|
// Get structure file
|
|
Configuration.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 normalized language
|
|
Configuration.prototype.normalizeLanguage = function() {
|
|
return i18n.normalizeLanguage(this.options.language);
|
|
};
|
|
|
|
// Return a configuration
|
|
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);
|
|
};
|
|
|
|
// Default configuration
|
|
Configuration.DEFAULT = DEFAULT_CONFIG;
|
|
|
|
module.exports= Configuration;
|