editor.js/modules/tools.js
2017-02-10 16:00:01 +03:00

153 lines
4.1 KiB
JavaScript

/**
* Module working with plugins
*/
module.exports = (function () {
let editor = codex.editor;
/**
* Initialize plugins before using
* Ex. Load scripts or call some internal methods
* @return Promise
*/
function prepare() {
return new Promise(function (resolve_, reject_) {
Promise.resolve()
/**
* Compose a sequence of plugins that requires preparation
*/
.then(function () {
let pluginsRequiresPreparation = [],
allPlugins = editor.tools;
for ( let pluginName in allPlugins ) {
let plugin = allPlugins[pluginName];
if (plugin.prepare && typeof plugin.prepare != 'function' || !plugin.prepare) {
continue;
}
pluginsRequiresPreparation.push(plugin);
}
/**
* If no one passed plugins requires preparation, finish prepare() and go ahead
*/
if (!pluginsRequiresPreparation.length) {
resolve_();
}
return pluginsRequiresPreparation;
})
/** Wait plugins while they prepares */
.then(waitAllPluginsPreparation_)
.then(function () {
editor.core.log('Plugins loaded', 'info');
resolve_();
}).catch(function (error) {
reject_(error);
});
});
}
/**
* @param {array} plugins - list of tools that requires preparation
* @return {Promise} resolved while all plugins will be ready or failed
*/
function waitAllPluginsPreparation_(plugins) {
/**
* @calls allPluginsProcessed__ when all plugins prepared or failed
*/
return new Promise (function (allPluginsProcessed__) {
/**
* pluck each element from queue
* First, send resolved Promise as previous value
* Each plugins "prepare" method returns a Promise, that's why
* reduce current element will not be able to continue while can't get
* a resolved Promise
*
* If last plugin is "prepared" then go to the next stage of initialization
*/
plugins.reduce(function (previousValue, plugin, iteration) {
return previousValue.then(function () {
/**
* Wait till plugins prepared
* @calls pluginIsReady__ when plugin is ready or failed
*/
return new Promise ( function (pluginIsReady__) {
callPluginsPrepareMethod_( plugin )
.then( pluginIsReady__ )
.then( function () {
plugin.available = true;
})
.catch(function (error) {
editor.core.log(`Plugin «${plugin.type}» was not loaded. Preparation failed because %o`, 'warn', error);
plugin.available = false;
plugin.loadingMessage = error;
/** Go ahead even some plugin has problems */
pluginIsReady__();
})
.then(function () {
/** If last plugin has problems then just ignore and continue */
if (iteration == plugins.length - 1) {
allPluginsProcessed__();
}
});
});
});
}, Promise.resolve() );
});
}
var callPluginsPrepareMethod_ = function (plugin) {
return plugin.prepare( plugin.config || {} );
};
return {
prepare: prepare
};
}());