diff options
-rw-r--r-- | lib/book.js | 1 | ||||
-rw-r--r-- | lib/cli/index.js | 11 | ||||
-rw-r--r-- | lib/config/index.js | 20 | ||||
-rw-r--r-- | lib/config/plugins.js | 24 | ||||
-rw-r--r-- | lib/config/schema.js | 4 | ||||
-rw-r--r-- | lib/config/validator.js | 3 | ||||
-rw-r--r-- | lib/output/base.js | 8 | ||||
-rw-r--r-- | lib/plugins/index.js | 5 | ||||
-rw-r--r-- | test/config.js | 49 | ||||
-rw-r--r-- | test/glossary.js | 4 | ||||
-rw-r--r-- | test/langs.js | 2 | ||||
-rw-r--r-- | test/node_modules/gitbook-plugin-test-hooks/index.js | 16 | ||||
-rw-r--r-- | test/node_modules/gitbook-plugin-test-hooks/package.json | 7 | ||||
-rw-r--r-- | test/page.js | 6 | ||||
-rw-r--r-- | test/plugins.js | 16 | ||||
-rw-r--r-- | test/readme.js | 2 |
16 files changed, 129 insertions, 49 deletions
diff --git a/lib/book.js b/lib/book.js index d7834ee..400296e 100644 --- a/lib/book.js +++ b/lib/book.js @@ -180,6 +180,7 @@ Book.prototype.parse = function() { that.log.debug.ln('Preparing book for language', lang.id); var langBook = new Book(_.extend({}, that.opts, { parent: that, + config: that.config.dump(), root: that.resolve(lang.id) })); diff --git a/lib/cli/index.js b/lib/cli/index.js index 33df69f..58a0e1b 100644 --- a/lib/cli/index.js +++ b/lib/cli/index.js @@ -113,14 +113,19 @@ module.exports = { // Generate the book .then(function() { return Book.setup(helper.nodeFS, input, { - 'config': { - 'defaultsPlugins': ['livereload'] - }, 'logLevel': kwargs.log }) .then(function(book) { return book.parse() .then(function() { + // Add livereload plugin + book.config.set('plugins', + book.config.get('plugins') + .concat([ + { name: 'livereload' } + ]) + ); + var Out = helper.FORMATS[kwargs.format]; var output = new Out(book); diff --git a/lib/config/index.js b/lib/config/index.js index 272e92a..7f75733 100644 --- a/lib/config/index.js +++ b/lib/config/index.js @@ -22,13 +22,15 @@ function Config(book, baseConfig) { this.log = book.log; this.path = ''; - this.replace(baseConfig || {}); + 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) { @@ -47,19 +49,19 @@ Config.prototype.load = function() { }); }) .then(function() { - if (!that.book.isLanguageBook()) { + 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); - that.options.defaultsPlugins = plugins.toList(that.options.defaultsPlugins || '', false); - that.options.plugins = _.union(that.options.plugins, that.options.defaultsPlugins); - that.options.plugins = _.uniq(that.options.plugins, 'name'); + 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; }); @@ -69,6 +71,10 @@ Config.prototype.load = function() { 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 diff --git a/lib/config/plugins.js b/lib/config/plugins.js index c75cd55..5d98736 100644 --- a/lib/config/plugins.js +++ b/lib/config/plugins.js @@ -9,7 +9,7 @@ function isDefaultPlugin(name, version) { } // Normalize a list of plugins to use -function normalizePluginsList(plugins, addDefaults) { +function normalizePluginsList(plugins) { // Normalize list to an array plugins = _.isString(plugins) ? plugins.split(',') : (plugins || []); @@ -25,8 +25,7 @@ function normalizePluginsList(plugins, addDefaults) { var version = parts[1]; return { 'name': name, - 'version': version, // optional - 'isDefault': isDefaultPlugin(name, version) + 'version': version // optional }; }); @@ -41,19 +40,15 @@ function normalizePluginsList(plugins, addDefaults) { .value(); // Merge with defaults - if (addDefaults !== false) { - _.each(DEFAULT_PLUGINS, function(plugin) { - if (_.find(plugins, { name: plugin })) { - return; - } + _.each(DEFAULT_PLUGINS, function(plugin) { + if (_.find(plugins, { name: plugin })) { + return; + } - plugins.push({ - 'name': plugin, - 'isDefault': true - }); + plugins.push({ + 'name': plugin }); - } - + }); // Remove plugin that start with '-' plugins = _.filter(plugins, function(plugin) { return !_.contains(toremove, plugin.name) && !(plugin.name.length > 0 && plugin.name[0] == '-'); @@ -66,6 +61,7 @@ function normalizePluginsList(plugins, addDefaults) { } module.exports = { + isDefaultPlugin: isDefaultPlugin, toList: normalizePluginsList }; diff --git a/lib/config/schema.js b/lib/config/schema.js index ac7d05e..34a6c76 100644 --- a/lib/config/schema.js +++ b/lib/config/schema.js @@ -179,10 +179,6 @@ module.exports = { }, 'version': { 'type': 'string' - }, - 'isDefault': { - 'type': 'boolean', - 'default': false } }, 'additionalProperties': false, diff --git a/lib/config/validator.js b/lib/config/validator.js index 0ea278f..764b19a 100644 --- a/lib/config/validator.js +++ b/lib/config/validator.js @@ -1,4 +1,3 @@ -var _ = require('lodash'); var jsonschema = require('jsonschema'); var jsonSchemaDefaults = require('json-schema-defaults'); var mergeDefaults = require('merge-defaults'); @@ -9,8 +8,6 @@ var error = require('../utils/error'); // Validate a book.json content // And return a mix with the default value function validate(bookJson) { - bookJson = _.cloneDeep(bookJson); - var v = new jsonschema.Validator(); var result = v.validate(bookJson, schema, { propertyName: 'config' diff --git a/lib/output/base.js b/lib/output/base.js index 025e850..a1d8804 100644 --- a/lib/output/base.js +++ b/lib/output/base.js @@ -27,11 +27,7 @@ function Output(book, opts, parent) { this.log = this.book.log; // Create plugins manager - if (this.parent) { - this.plugins = this.parent.plugins; - } else { - this.plugins = new PluginsManager(this.book); - } + this.plugins = new PluginsManager(this.book); // Create template engine this.template = new TemplateEngine(this); @@ -52,7 +48,7 @@ Output.prototype.generate = function() { // Load all plugins .then(function() { - return Promise(that.parent? null: that.plugins.loadAll()) + return that.plugins.loadAll() .then(function() { that.template.addFilters(that.plugins.getFilters()); that.template.addBlocks(that.plugins.getBlocks()); diff --git a/lib/plugins/index.js b/lib/plugins/index.js index 2ebbcc8..8280542 100644 --- a/lib/plugins/index.js +++ b/lib/plugins/index.js @@ -5,6 +5,7 @@ var Promise = require('../utils/promise'); var fs = require('../utils/fs'); var BookPlugin = require('./plugin'); var registry = require('./registry'); +var pluginsConfig = require('../config/plugins'); /* PluginsManager is an interface to work with multiple plugins at once: @@ -82,8 +83,8 @@ PluginsManager.prototype._setup = function(plugin) { // Install all plugins for the book PluginsManager.prototype.install = function() { var that = this; - var plugins = _.filter(this.book.config.get('plugins'), { - isDefault: false + var plugins = _.filter(this.book.config.get('plugins'), function(plugin) { + return !pluginsConfig.isDefaultPlugin(plugin.name); }); if (plugins.length == 0) { diff --git a/test/config.js b/test/config.js index 7a96a5c..be28fc9 100644 --- a/test/config.js +++ b/test/config.js @@ -46,7 +46,7 @@ describe('Configuration', function() { return mock.setupDefaultBook() .then(function(_book) { book = _book; - return book.prepareConfig(); + return book.config.load(); }); }); @@ -64,7 +64,7 @@ describe('Configuration', function() { }) .then(function(_book) { book = _book; - return book.prepareConfig(); + return book.config.load(); }); }); @@ -82,7 +82,7 @@ describe('Configuration', function() { }) .then(function(_book) { book = _book; - return book.prepareConfig(); + return book.config.load(); }); }); @@ -90,5 +90,48 @@ describe('Configuration', function() { book.config.get('title', '').should.equal('Hello World'); }); }); + + describe('Multilingual', function() { + var book; + + before(function() { + return mock.setupDefaultBook({ + 'book.json': { + title: 'Hello World', + pluginsConfig: { + 'test': { + 'hello': true + } + } + }, + 'LANGS.md': '# Languages\n\n' + + '* [en](./en)\n' + + '* [fr](./fr)\n\n', + 'en/README.md': '# Hello', + 'fr/README.md': '# Bonjour', + 'en/book.json': { description: 'In english' }, + 'fr/book.json': { description: 'En francais' } + }) + .then(function(_book) { + book = _book; + return book.parse(); + }); + }); + + it('should correctly extend configuration', function() { + book.config.get('title', '').should.equal('Hello World'); + book.config.get('description', '').should.equal(''); + + var en = book.books[0]; + en.config.get('title', '').should.equal('Hello World'); + en.config.get('description', '').should.equal('In english'); + en.config.get('pluginsConfig.test.hello').should.equal(true); + + var fr = book.books[1]; + fr.config.get('title', '').should.equal('Hello World'); + fr.config.get('description', '').should.equal('En francais'); + fr.config.get('pluginsConfig.test.hello').should.equal(true); + }); + }); }); diff --git a/test/glossary.js b/test/glossary.js index e1ba82a..d6d1af6 100644 --- a/test/glossary.js +++ b/test/glossary.js @@ -7,7 +7,7 @@ describe('Glossary', function() { 'GLOSSARY.md': '' }) .then(function(book) { - return book.prepareConfig() + return book.config.load() .then(function() { return book.glossary.load(); @@ -27,7 +27,7 @@ describe('Glossary', function() { }) .then(function(_book) { book = _book; - return book.prepareConfig(); + return book.config.load(); }) .then(function() { return book.glossary.load(); diff --git a/test/langs.js b/test/langs.js index dbde992..91dbd5a 100644 --- a/test/langs.js +++ b/test/langs.js @@ -6,7 +6,7 @@ describe('Langs', function() { 'LANGS.md': '' }) .then(function(book) { - return book.prepareConfig() + return book.config.load() .then(function() { return book.langs.load(); diff --git a/test/node_modules/gitbook-plugin-test-hooks/index.js b/test/node_modules/gitbook-plugin-test-hooks/index.js new file mode 100644 index 0000000..c0666ca --- /dev/null +++ b/test/node_modules/gitbook-plugin-test-hooks/index.js @@ -0,0 +1,16 @@ +var should = require('should'); + +module.exports = { + hooks: { + 'init': function() { + global._hooks = []; + global._hooks.push('init'); + }, + 'finish': function() { + global._hooks.push('finish'); + }, + 'finish:before': function() { + global._hooks.push('finish:before'); + } + } +}; diff --git a/test/node_modules/gitbook-plugin-test-hooks/package.json b/test/node_modules/gitbook-plugin-test-hooks/package.json new file mode 100644 index 0000000..adb12a8 --- /dev/null +++ b/test/node_modules/gitbook-plugin-test-hooks/package.json @@ -0,0 +1,7 @@ +{ + "name": "gitbook-plugin-test-hooks", + "version": "1.0.0", + "engines": { + "gitbook": "*" + } +}
\ No newline at end of file diff --git a/test/page.js b/test/page.js index 37acc95..f11d55e 100644 --- a/test/page.js +++ b/test/page.js @@ -32,7 +32,7 @@ describe('Page', function() { 'variables/page/next.md': '{{ page.next.title }} {{ page.next.path }}', 'variables/page/dir/ltr.md': 'This is english: {{ page.dir }}', 'variables/page/dir/rtl.md': 'بسيطة {{ page.dir }}', - 'variables/book/title.md': '{{ book.title}}', + 'variables/config/title.md': '{{ config.title}}', 'GLOSSARY.md': '# Glossary\n\n\n## abracadabra\n\nthis is the description' }, [ @@ -318,8 +318,8 @@ describe('Page', function() { .should.be.fulfilledWith('<p>Test Variables variables/page/title.md</p>\n'); }); - it('should set book.title', function() { - var page = book.addPage('variables/book/title.md'); + it('should set config.title', function() { + var page = book.addPage('variables/config/title.md'); return page.toHTML(output) .should.be.fulfilledWith('<p>Hello World</p>\n'); }); diff --git a/test/plugins.js b/test/plugins.js index 172e00c..4d9cdf1 100644 --- a/test/plugins.js +++ b/test/plugins.js @@ -175,5 +175,21 @@ describe('Plugins', function() { blocks.testContext.process({ body: 'Hello' }); }); }); + + describe('Hooks', function() { + var plugin; + + before(function() { + plugin = new BookPlugin(book, 'test-hooks'); + return plugin.load(PLUGINS_ROOT); + }); + + it('can call a hook', function() { + return plugin.hook('init') + .then(function() { + global._hooks.should.deepEqual(['init']); + }); + }); + }); }); diff --git a/test/readme.js b/test/readme.js index 16aa81a..0cf66ff 100644 --- a/test/readme.js +++ b/test/readme.js @@ -6,7 +6,7 @@ describe('Readme', function() { 'README.md': '' }) .then(function(book) { - return book.prepareConfig() + return book.config.load() .then(function() { return book.readme.load(); |