summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/models/__tests__/plugin.js2
-rw-r--r--lib/models/__tests__/pluginDependency.js47
-rw-r--r--lib/models/config.js28
-rw-r--r--lib/models/plugin.js13
-rw-r--r--lib/models/pluginDependency.js115
-rw-r--r--lib/modifiers/config/addPlugin.js13
-rw-r--r--lib/modifiers/config/removePlugin.js12
-rw-r--r--lib/parse/parseConfig.js4
-rw-r--r--lib/plugins/__tests__/listAll.js53
-rw-r--r--lib/plugins/listAll.js43
-rw-r--r--lib/plugins/listForBook.js2
-rw-r--r--lib/utils/promise.js5
12 files changed, 245 insertions, 92 deletions
diff --git a/lib/models/__tests__/plugin.js b/lib/models/__tests__/plugin.js
index 81d9d51..b229664 100644
--- a/lib/models/__tests__/plugin.js
+++ b/lib/models/__tests__/plugin.js
@@ -1,5 +1,3 @@
-jest.autoMockOff();
-
describe('Plugin', function() {
var Plugin = require('../plugin');
diff --git a/lib/models/__tests__/pluginDependency.js b/lib/models/__tests__/pluginDependency.js
new file mode 100644
index 0000000..8aa55fb
--- /dev/null
+++ b/lib/models/__tests__/pluginDependency.js
@@ -0,0 +1,47 @@
+describe('PluginDependency', function() {
+ var PluginDependency = require('../pluginDependency');
+
+ describe('createFromString', function() {
+ it('must parse name', function() {
+ var plugin = PluginDependency.createFromString('hello');
+ expect(plugin.getName()).toBe('hello');
+ expect(plugin.getVersion()).toBe('*');
+ });
+
+ it('must parse state', function() {
+ var plugin = PluginDependency.createFromString('-hello');
+ expect(plugin.getName()).toBe('hello');
+ expect(plugin.isEnabled()).toBe(false);
+ });
+
+ describe('Version', function() {
+ it('must parse version', function() {
+ var plugin = PluginDependency.createFromString('hello@1.0.0');
+ expect(plugin.getName()).toBe('hello');
+ expect(plugin.getVersion()).toBe('1.0.0');
+ });
+
+ it('must parse semver', function() {
+ var plugin = PluginDependency.createFromString('hello@>=4.0.0');
+ expect(plugin.getName()).toBe('hello');
+ expect(plugin.getVersion()).toBe('>=4.0.0');
+ });
+ });
+
+ describe('GIT Version', function() {
+ it('must handle HTTPS urls', function() {
+ var plugin = PluginDependency.createFromString('hello@git+https://github.com/GitbookIO/plugin-ga.git');
+ expect(plugin.getName()).toBe('hello');
+ expect(plugin.getVersion()).toBe('git+https://github.com/GitbookIO/plugin-ga.git');
+ });
+
+ it('must handle SSH urls', function() {
+ var plugin = PluginDependency.createFromString('hello@git+ssh://samy@github.com/GitbookIO/plugin-ga.git');
+ expect(plugin.getName()).toBe('hello');
+ expect(plugin.getVersion()).toBe('git+ssh://samy@github.com/GitbookIO/plugin-ga.git');
+ });
+ });
+ });
+});
+
+
diff --git a/lib/models/config.js b/lib/models/config.js
index 6ee03e4..83dd6d4 100644
--- a/lib/models/config.js
+++ b/lib/models/config.js
@@ -2,6 +2,7 @@ var is = require('is');
var Immutable = require('immutable');
var File = require('./file');
+var PluginDependency = require('./pluginDependency');
var configDefault = require('../constants/configDefault');
var Config = Immutable.Record({
@@ -53,6 +54,33 @@ Config.prototype.setValue = function(keyPath, value) {
};
/**
+ Return a list of plugin dependencies
+
+ @return {List<PluginDependency>}
+*/
+Config.prototype.getPluginDependencies = function() {
+ var plugins = this.getValue('plugins');
+
+ if (is.string(plugins)) {
+ return PluginDependency.listFromString(plugins);
+ } else {
+ return PluginDependency.listFromArray(plugins);
+ }
+};
+
+/**
+ Update the list of plugins dependencies
+
+ @param {List<PluginDependency>}
+ @return {Config}
+*/
+Config.prototype.setPluginDependencies = function(deps) {
+ var plugins = PluginDependency.listToArray(deps);
+
+ return this.setValue('plugins', plugins);
+};
+
+/**
Create a new config for a file
@param {File} file
diff --git a/lib/models/plugin.js b/lib/models/plugin.js
index dd7bc90..23019aa 100644
--- a/lib/models/plugin.js
+++ b/lib/models/plugin.js
@@ -140,6 +140,19 @@ Plugin.createFromString = function(s) {
};
/**
+ Create a plugin from a dependency
+
+ @param {PluginDependency}
+ @return {Plugin}
+*/
+Plugin.createFromDep = function(dep) {
+ return new Plugin({
+ name: dep.getName(),
+ version: dep.getVersion()
+ });
+};
+
+/**
Return NPM id for a plugin name
@param {String}
diff --git a/lib/models/pluginDependency.js b/lib/models/pluginDependency.js
new file mode 100644
index 0000000..bb8e4b4
--- /dev/null
+++ b/lib/models/pluginDependency.js
@@ -0,0 +1,115 @@
+var is = require('is');
+var Immutable = require('immutable');
+
+var DEFAULT_VERSION = '*';
+
+/*
+ PluginDependency represents the informations about a plugin
+ stored in config.plugins
+*/
+var PluginDependency = Immutable.Record({
+ name: String(),
+
+ // Requirement version (ex: ">1.0.0")
+ version: String(DEFAULT_VERSION),
+
+ // Is this plugin enabled or disabled?
+ enabled: Boolean(true)
+}, 'PluginDependency');
+
+PluginDependency.prototype.getName = function() {
+ return this.get('name');
+};
+
+PluginDependency.prototype.getVersion = function() {
+ return this.get('version');
+};
+
+PluginDependency.prototype.isEnabled = function() {
+ return this.get('enabled');
+};
+
+/**
+ Create a plugin from a string
+
+ @param {String}
+ @return {Plugin|undefined}
+*/
+PluginDependency.createFromString = function(s) {
+ var parts = s.split('@');
+ var name = parts[0];
+ var version = parts.slice(1).join('@');
+ var enabled = true;
+
+ if (name[0] === '-') {
+ enabled = false;
+ name = name.slice(1);
+ }
+
+ return new PluginDependency({
+ name: name,
+ version: version || DEFAULT_VERSION,
+ enabled: enabled
+ });
+};
+
+/**
+ Create a PluginDependency from a string
+
+ @param {String}
+ @return {List<PluginDependency>}
+*/
+PluginDependency.listFromString = function(s) {
+ var parts = s.split(',');
+ return PluginDependency.listFromArray(parts);
+};
+
+/**
+ Create a PluginDependency from an array
+
+ @param {Array}
+ @return {List<PluginDependency>}
+*/
+PluginDependency.listFromArray = function(arr) {
+ return Immutable.List(arr)
+ .map(function(entry) {
+ if (is.string(entry)) {
+ return PluginDependency.createFromString(entry);
+ } else {
+ return PluginDependency({
+ name: entry.name,
+ version: entry.version
+ });
+ }
+ })
+ .filter(function(dep) {
+ return Boolean(dep.getName());
+ });
+};
+
+/**
+ Export plugin dependencies as an array
+
+ @param {List<PluginDependency>}
+ @return {Array<String>}
+*/
+PluginDependency.listToArray = function(arr) {
+ return arr
+ .map(function(dep) {
+ var result;
+
+ if (dep.isEnabled()) {
+ result += '-';
+ }
+
+ result += dep.getName();
+ if (dep.getVersion() !== DEFAULT_VERSION) {
+ result += '@' + dep.getVersion();
+ }
+
+ return result;
+ })
+ .toJS();
+};
+
+module.exports = PluginDependency;
diff --git a/lib/modifiers/config/addPlugin.js b/lib/modifiers/config/addPlugin.js
index 938b686..2a04a03 100644
--- a/lib/modifiers/config/addPlugin.js
+++ b/lib/modifiers/config/addPlugin.js
@@ -1,4 +1,4 @@
-
+var PluginDependency = require('../../models/pluginDependency');
/**
Add a plugin to a book's configuration
@@ -9,10 +9,15 @@
*/
function addPlugin(book, plugin, version) {
var config = book.getConfig();
- var plugins = config.getValue('plugins', []);
+ var deps = config.getPluginDependencies();
+
+ var dep = PluginDependency({
+ name: plugin,
+ version: version
+ });
- plugins = plugins.push('livereload');
- config = config.setValue('plugins', plugins);
+ deps = deps.push(dep);
+ config = config.setPluginDependencies(deps);
return book.setConfig(config);
}
diff --git a/lib/modifiers/config/removePlugin.js b/lib/modifiers/config/removePlugin.js
index 8c58f16..bc6bcc8 100644
--- a/lib/modifiers/config/removePlugin.js
+++ b/lib/modifiers/config/removePlugin.js
@@ -8,15 +8,13 @@
*/
function removePlugin(book, pluginName) {
var config = book.getConfig();
- var plugins = config.getValue('plugins', []);
+ var deps = config.getPluginDependencies();
- // Find index of this plugin
- var index = plugins.findIndex(function(plugin) {
- return plugin === pluginName;
- });
- plugins = plugins.delete(index);
- config = config.setValue('plugins', plugins);
+ deps = deps.filter(function(dep) {
+ return dep.getName() === pluginName;
+ });
+ config = config.setPluginDependencies(deps);
return book.setConfig(config);
}
diff --git a/lib/parse/parseConfig.js b/lib/parse/parseConfig.js
index 3ab64b7..a1e9d69 100644
--- a/lib/parse/parseConfig.js
+++ b/lib/parse/parseConfig.js
@@ -45,10 +45,6 @@ function parseConfig(book) {
values = validateConfig(values);
- if (is.string(values.plugins)) {
- values.plugins = values.plugins.split(',');
- }
-
var config = Config.create(file, values);
return book.set('config', config);
});
diff --git a/lib/plugins/__tests__/listAll.js b/lib/plugins/__tests__/listAll.js
index 71483a7..f9711a7 100644
--- a/lib/plugins/__tests__/listAll.js
+++ b/lib/plugins/__tests__/listAll.js
@@ -1,21 +1,10 @@
-jest.autoMockOff();
+var PluginDependency = require('../../models/pluginDependency');
+var listAll = require('../listAll');
describe('listAll', function() {
- var listAll = require('../listAll');
-
- it('must list from string', function() {
- var plugins = listAll('ga,great');
-
- expect(plugins.size).toBe(8);
-
- expect(plugins.has('ga')).toBe(true);
- expect(plugins.has('great')).toBe(true);
-
- expect(plugins.has('search')).toBe(true);
- });
-
- it('must list from array', function() {
- var plugins = listAll(['ga', 'great']);
+ it('must list default', function() {
+ var deps = PluginDependency.listFromString('ga,great');
+ var plugins = listAll(deps);
expect(plugins.size).toBe(8);
@@ -25,34 +14,9 @@ describe('listAll', function() {
expect(plugins.has('search')).toBe(true);
});
- it('must parse version (semver)', function() {
- var plugins = listAll(['ga@1.0.0', 'great@>=4.0.0']);
-
- expect(plugins.has('ga')).toBe(true);
- expect(plugins.has('great')).toBe(true);
-
- var ga = plugins.get('ga');
- expect(ga.getVersion()).toBe('1.0.0');
-
- var great = plugins.get('great');
- expect(great.getVersion()).toBe('>=4.0.0');
- });
-
- it('must parse version (git)', function() {
- var plugins = listAll(['ga@git+https://github.com/GitbookIO/plugin-ga.git', 'great@git+ssh://samy@github.com/GitbookIO/plugin-ga.git']);
-
- expect(plugins.has('ga')).toBe(true);
- expect(plugins.has('great')).toBe(true);
-
- var ga = plugins.get('ga');
- expect(ga.getVersion()).toBe('git+https://github.com/GitbookIO/plugin-ga.git');
-
- var great = plugins.get('great');
- expect(great.getVersion()).toBe('git+ssh://samy@github.com/GitbookIO/plugin-ga.git');
- });
-
it('must list from array with -', function() {
- var plugins = listAll(['ga', '-great']);
+ var deps = PluginDependency.listFromString('ga,-great');
+ var plugins = listAll(deps);
expect(plugins.size).toBe(7);
@@ -61,7 +25,8 @@ describe('listAll', function() {
});
it('must remove default plugins using -', function() {
- var plugins = listAll(['ga', '-search']);
+ var deps = PluginDependency.listFromString('ga,-search');
+ var plugins = listAll(deps);
expect(plugins.size).toBe(6);
diff --git a/lib/plugins/listAll.js b/lib/plugins/listAll.js
index d7ce5f3..9b2a96b 100644
--- a/lib/plugins/listAll.js
+++ b/lib/plugins/listAll.js
@@ -1,4 +1,3 @@
-var is = require('is');
var Immutable = require('immutable');
var Plugin = require('../models/plugin');
@@ -8,43 +7,27 @@ var DEFAULT_PLUGINS = require('../constants/defaultPlugins');
/**
List all plugins for a book
- @param {List<Plugin|String>}
+ @param {List<PluginDependency>} deps
@return {OrderedMap<Plugin>}
*/
-function listAll(plugins) {
- if (is.string(plugins)) {
- plugins = Immutable.List(plugins.split(','));
- }
-
- // Convert to an ordered map
- plugins = plugins.map(function(plugin) {
- if (is.string(plugin)) {
- plugin = Plugin.createFromString(plugin);
- } else {
- plugin = new Plugin(plugin);
- }
-
- return [plugin.getName(), plugin];
- });
- plugins = Immutable.OrderedMap(plugins);
-
+function listAll(deps) {
// Extract list of plugins to disable (starting with -)
- var toRemove = plugins.toList()
+ var toRemove = deps
.filter(function(plugin) {
- return plugin.getName()[0] === '-';
+ return !plugin.isEnabled();
})
.map(function(plugin) {
- return plugin.getName().slice(1);
+ return plugin.getName();
});
- // Remove the '-'
- plugins = plugins.mapKeys(function(name) {
- if (name[0] === '-') {
- return name.slice(1);
- } else {
- return name;
- }
- });
+ // 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);
// Append default plugins
DEFAULT_PLUGINS.forEach(function(pluginName) {
diff --git a/lib/plugins/listForBook.js b/lib/plugins/listForBook.js
index ce94678..5fb920f 100644
--- a/lib/plugins/listForBook.js
+++ b/lib/plugins/listForBook.js
@@ -10,7 +10,7 @@ var listAll = require('./listAll');
*/
function listForBook(book) {
var config = book.getConfig();
- var plugins = config.getValue('plugins');
+ var plugins = config.getPluginDependencies();
return listAll(plugins);
}
diff --git a/lib/utils/promise.js b/lib/utils/promise.js
index 19d7554..138546b 100644
--- a/lib/utils/promise.js
+++ b/lib/utils/promise.js
@@ -1,6 +1,11 @@
var Q = require('q');
var Immutable = require('immutable');
+// Debugging for long stack traces
+if (global.__DEV__ || process.env.DEBUG) {
+ Q.longStackSupport = true;
+}
+
/**
Reduce an array to a promise