diff options
-rw-r--r-- | lib/models/plugin.js | 7 | ||||
-rw-r--r-- | lib/plugins/__tests__/listDependencies.js (renamed from lib/plugins/__tests__/listAll.js) | 10 | ||||
-rw-r--r-- | lib/plugins/__tests__/sortDependencies.js | 42 | ||||
-rw-r--r-- | lib/plugins/__tests__/sortPlugins.js | 45 | ||||
-rw-r--r-- | lib/plugins/findInstalled.js | 29 | ||||
-rw-r--r-- | lib/plugins/listAll.js | 44 | ||||
-rw-r--r-- | lib/plugins/listDependencies.js | 33 | ||||
-rw-r--r-- | lib/plugins/listDepsForBook.js | 18 | ||||
-rw-r--r-- | lib/plugins/listForBook.js | 18 | ||||
-rw-r--r-- | lib/plugins/loadForBook.js | 68 | ||||
-rw-r--r-- | lib/plugins/sortDependencies.js (renamed from lib/plugins/sortPlugins.js) | 16 |
11 files changed, 172 insertions, 158 deletions
diff --git a/lib/models/plugin.js b/lib/models/plugin.js index c8bb2f7..acabba9 100644 --- a/lib/models/plugin.js +++ b/lib/models/plugin.js @@ -18,6 +18,9 @@ var Plugin = Immutable.Record({ // Depth of this plugin in the dependency tree depth: Number(0), + // Parent depending on this plugin + parent: String(), + // Content of the "package.json" package: Immutable.Map(), @@ -49,6 +52,10 @@ Plugin.prototype.getDepth = function() { return this.get('depth'); }; +Plugin.prototype.getParent = function() { + return this.get('parent'); +}; + /** * Return the ID on NPM for this plugin * @return {String} diff --git a/lib/plugins/__tests__/listAll.js b/lib/plugins/__tests__/listDependencies.js index 6a08c84..940faba 100644 --- a/lib/plugins/__tests__/listAll.js +++ b/lib/plugins/__tests__/listDependencies.js @@ -1,11 +1,11 @@ var PluginDependency = require('../../models/pluginDependency'); -var listAll = require('../listAll'); +var listDependencies = require('../listDependencies'); var toNames = require('../toNames'); -describe('listAll', function() { +describe('listDependencies', function() { it('must list default', function() { var deps = PluginDependency.listFromString('ga,great'); - var plugins = listAll(deps); + var plugins = listDependencies(deps); var names = toNames(plugins); expect(names).toEqual([ @@ -16,7 +16,7 @@ describe('listAll', function() { it('must list from array with -', function() { var deps = PluginDependency.listFromString('ga,-great'); - var plugins = listAll(deps); + var plugins = listDependencies(deps); var names = toNames(plugins); expect(names).toEqual([ @@ -27,7 +27,7 @@ describe('listAll', function() { it('must remove default plugins using -', function() { var deps = PluginDependency.listFromString('ga,-search'); - var plugins = listAll(deps); + var plugins = listDependencies(deps); var names = toNames(plugins); expect(names).toEqual([ diff --git a/lib/plugins/__tests__/sortDependencies.js b/lib/plugins/__tests__/sortDependencies.js new file mode 100644 index 0000000..87df477 --- /dev/null +++ b/lib/plugins/__tests__/sortDependencies.js @@ -0,0 +1,42 @@ +var PluginDependency = require('../../models/pluginDependency'); +var sortDependencies = require('../sortDependencies'); +var toNames = require('../toNames'); + +describe('sortDependencies', function() { + it('must load themes after plugins', function() { + var allPlugins = PluginDependency.listFromArray([ + 'hello', + 'theme-test', + 'world' + ]); + + var sorted = sortDependencies(allPlugins); + var names = toNames(sorted); + + expect(names).toEqual([ + 'hello', + 'world', + 'theme-test' + ]); + }); + + it('must keep order of themes', function() { + var allPlugins = PluginDependency.listFromArray([ + 'theme-test', + 'theme-test1', + 'hello', + 'theme-test2', + 'world' + ]); + var sorted = sortDependencies(allPlugins); + var names = toNames(sorted); + + expect(names).toEqual([ + 'hello', + 'world', + 'theme-test', + 'theme-test1', + 'theme-test2' + ]); + }); +});
\ No newline at end of file diff --git a/lib/plugins/__tests__/sortPlugins.js b/lib/plugins/__tests__/sortPlugins.js deleted file mode 100644 index 4aa26a3..0000000 --- a/lib/plugins/__tests__/sortPlugins.js +++ /dev/null @@ -1,45 +0,0 @@ -var Immutable = require('immutable'); - -var Plugin = require('../../models/plugin'); -var sortPlugins = require('../sortPlugins'); -var toNames = require('../toNames'); - -describe('sortPlugins', function() { - it('must load themes after plugins', function() { - var allPlugins = Immutable.OrderedMap([ - ['hello', Plugin.createFromString('hello')], - ['theme-test', Plugin.createFromString('theme-test')], - ['world', Plugin.createFromString('world')] - ]); - - var sorted = sortPlugins(allPlugins); - var names = toNames(sorted); - - expect(names).toEqual([ - 'hello', - 'world', - 'theme-test' - ]); - }); - - it('must keep order of themes', function() { - var allPlugins = Immutable.OrderedMap([ - ['theme-test', Plugin.createFromString('theme-test')], - ['theme-test1', Plugin.createFromString('theme-test1')], - ['hello', Plugin.createFromString('hello')], - ['theme-test2', Plugin.createFromString('theme-test2')], - ['world', Plugin.createFromString('world')] - ]); - - var sorted = sortPlugins(allPlugins); - var names = toNames(sorted); - - expect(names).toEqual([ - 'hello', - 'world', - 'theme-test', - 'theme-test1', - 'theme-test2' - ]); - }); -});
\ No newline at end of file diff --git a/lib/plugins/findInstalled.js b/lib/plugins/findInstalled.js index dca3cbf..06cc6c4 100644 --- a/lib/plugins/findInstalled.js +++ b/lib/plugins/findInstalled.js @@ -8,21 +8,21 @@ var Plugin = require('../models/plugin'); var PREFIX = require('../constants/pluginPrefix'); /** - Validate if a package name is a GitBook plugin - - @return {Boolean} -*/ + * Validate if a package name is a GitBook plugin + * + * @return {Boolean} + */ function validateId(name) { return name && name.indexOf(PREFIX) === 0; } /** - List all packages installed inside a folder - - @param {String} folder - @return {OrderedMap<String:Plugin>} -*/ + * List all packages installed inside a folder + * + * @param {String} folder + * @return {OrderedMap<String:Plugin>} + */ function findInstalled(folder) { var options = { dev: false, @@ -31,7 +31,7 @@ function findInstalled(folder) { }; var results = Immutable.OrderedMap(); - function onPackage(pkg, isRoot) { + function onPackage(pkg, parent) { if (!pkg.name) return; var name = pkg.name; @@ -43,18 +43,19 @@ function findInstalled(folder) { var pluginName = name.slice(PREFIX.length); if (!validateId(name)){ - if (!isRoot) return; + if (parent) return; } else { results = results.set(pluginName, Plugin({ name: pluginName, version: version, path: pkgPath, - depth: depth + depth: depth, + parent: parent })); } Immutable.Map(dependencies).forEach(function(dep) { - onPackage(dep); + onPackage(dep, pluginName); }); } @@ -77,7 +78,7 @@ function findInstalled(folder) { var module_folder = path.join(node_modules, module); return Promise.nfcall(readInstalled, module_folder, options) .then(function(data) { - onPackage(data, true); + onPackage(data); }); }); }) diff --git a/lib/plugins/listAll.js b/lib/plugins/listAll.js deleted file mode 100644 index 70bf9cd..0000000 --- a/lib/plugins/listAll.js +++ /dev/null @@ -1,44 +0,0 @@ -var Immutable = require('immutable'); -var Plugin = require('../models/plugin'); - -var DEFAULT_PLUGINS = require('../constants/defaultPlugins'); -var sortPlugins = require('./sortPlugins'); - -/** - List all plugins for a book - - @param {List<PluginDependency>} deps - @return {OrderedMap<Plugin>} -*/ -function listAll(deps) { - // Extract list of plugins to disable (starting with -) - var toRemove = deps - .filter(function(plugin) { - return !plugin.isEnabled(); - }) - .map(function(plugin) { - return plugin.getName(); - }); - - // Concat with default plugins - deps = deps.concat(DEFAULT_PLUGINS); - - // Convert to an ordered map of Plugin - var plugins = deps - .map(function(dep) { - var plugin = Plugin.createFromDep(dep); - - return [dep.getName(), plugin]; - }); - plugins = Immutable.OrderedMap(plugins); - - // Remove plugins - plugins = plugins.filterNot(function(plugin, name) { - return toRemove.includes(name); - }); - - // Sort plugins - return sortPlugins(plugins); -} - -module.exports = listAll; diff --git a/lib/plugins/listDependencies.js b/lib/plugins/listDependencies.js new file mode 100644 index 0000000..d52eaa9 --- /dev/null +++ b/lib/plugins/listDependencies.js @@ -0,0 +1,33 @@ +var DEFAULT_PLUGINS = require('../constants/defaultPlugins'); +var sortDependencies = require('./sortDependencies'); + +/** + * List all dependencies for a book, including default plugins. + * It returns a concat with default plugins and remove disabled ones. + * + * @param {List<PluginDependency>} deps + * @return {List<PluginDependency>} + */ +function listDependencies(deps) { + // Extract list of plugins to disable (starting with -) + var toRemove = deps + .filter(function(plugin) { + return !plugin.isEnabled(); + }) + .map(function(plugin) { + return plugin.getName(); + }); + + // Concat with default plugins + deps = deps.concat(DEFAULT_PLUGINS); + + // Remove plugins + deps = deps.filterNot(function(plugin) { + return toRemove.includes(plugin.getName()); + }); + + // Sort + return sortDependencies(deps); +} + +module.exports = listDependencies; diff --git a/lib/plugins/listDepsForBook.js b/lib/plugins/listDepsForBook.js new file mode 100644 index 0000000..196e3aa --- /dev/null +++ b/lib/plugins/listDepsForBook.js @@ -0,0 +1,18 @@ +var listDependencies = require('./listDependencies'); + +/** + * List all plugin requirements for a book. + * It can be different from the final list of plugins, + * since plugins can have their own dependencies + * + * @param {Book} + * @return {List<PluginDependency>} + */ +function listDepsForBook(book) { + var config = book.getConfig(); + var plugins = config.getPluginDependencies(); + + return listDependencies(plugins); +} + +module.exports = listDepsForBook; diff --git a/lib/plugins/listForBook.js b/lib/plugins/listForBook.js deleted file mode 100644 index 5fb920f..0000000 --- a/lib/plugins/listForBook.js +++ /dev/null @@ -1,18 +0,0 @@ -var listAll = require('./listAll'); - -/** - List all plugin requirements for a book. - It can be different from the final list of plugins, - since plugins can have their own dependencies - - @param {Book} - @return {OrderedMap<Plugin>} -*/ -function listForBook(book) { - var config = book.getConfig(); - var plugins = config.getPluginDependencies(); - - return listAll(plugins); -} - -module.exports = listForBook; diff --git a/lib/plugins/loadForBook.js b/lib/plugins/loadForBook.js index 96a0cb5..757677e 100644 --- a/lib/plugins/loadForBook.js +++ b/lib/plugins/loadForBook.js @@ -1,47 +1,69 @@ -var Promise = require('../utils/promise'); +var Immutable = require('immutable'); -var listForBook = require('./listForBook'); +var Promise = require('../utils/promise'); +var listDepsForBook = require('./listDepsForBook'); var findForBook = require('./findForBook'); var loadPlugin = require('./loadPlugin'); /** - * Load a list of plugins in a book + * Load all plugins in a book + * * @param {Book} * @return {Promise<Map<String:Plugin>} */ function loadForBook(book) { var logger = book.getLogger(); - var requirements = listForBook(book); - var requirementsKeys = requirements.keySeq().toList(); + // List the dependencies + var requirements = listDepsForBook(book); + + // List all plugins installed in the book return findForBook(book) - .then(function(installed) { - // Filter out plugins not listed of first level - // (aka pre-installed plugins) - installed = installed.filter(function(plugin) { - return ( - plugin.getDepth() > 0 || - requirements.has(plugin.getName()) - ); - }); + .then(function(installedMap) { + var missing = []; + var plugins = requirements.reduce(function(result, dep) { + var name = dep.getName(); + var installed = installedMap.get(name); + + if (installed) { + var deps = installedMap + .filter(function(plugin) { + return plugin.getParent() === name; + }) + .toArray(); + + result = result.concat(deps); + result.push(installed); + } else { + missing.push(name); + } + + return result; + }, []); + + // Convert plugins list to a map + plugins = Immutable.List(plugins) + .map(function(plugin) { + return [ + plugin.getName(), + plugin + ]; + }); + plugins = Immutable.OrderedMap(plugins); // Log state - logger.info.ln(installed.size + ' plugins are installed'); - if (requirements.size != installed.size) { + logger.info.ln(installedMap.size + ' plugins are installed'); + if (requirements.size != installedMap.size) { logger.info.ln(requirements.size + ' explicitly listed'); } // Verify that all plugins are present - var notInstalled = requirementsKeys.filter(function(name) { - return !installed.has(name); - }); - - if (notInstalled.size > 0) { - throw new Error('Couldn\'t locate plugins "' + notInstalled.join(', ') + '", Run \'gitbook install\' to install plugins from registry.'); + if (missing.length > 0) { + throw new Error('Couldn\'t locate plugins "' + missing.join(', ') + '", Run \'gitbook install\' to install plugins from registry.'); } - return Promise.map(installed, function(plugin) { + return Promise.map(plugins, function(plugin) { return loadPlugin(book, plugin); }); }); diff --git a/lib/plugins/sortPlugins.js b/lib/plugins/sortDependencies.js index 155b691..7f10095 100644 --- a/lib/plugins/sortPlugins.js +++ b/lib/plugins/sortDependencies.js @@ -18,19 +18,17 @@ function pluginType(plugin) { /** - * Sort the list of installed plugins to match list in book.json + * Sort the list of dependencies to match list in book.json * The themes should always be loaded after the plugins * - * @param {<OrderedMap<String:Plugin>>} plugins - * @return {OrderedMap<String:Plugin>} + * @param {List<PluginDependency>} deps + * @return {List<PluginDependency>} */ -function sortPlugins(plugins) { +function sortDependencies(plugins) { var byTypes = plugins.groupBy(pluginType); - return byTypes.get(TYPE_PLUGIN, Immutable.OrderedMap()) - .merge( - byTypes.get(TYPE_THEME, Immutable.OrderedMap()) - ); + return byTypes.get(TYPE_PLUGIN, Immutable.List()) + .concat(byTypes.get(TYPE_THEME, Immutable.List())); } -module.exports = sortPlugins;
\ No newline at end of file +module.exports = sortDependencies;
\ No newline at end of file |