| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- "use strict";
- /**
- * Returns the given plugins as an array, rather than an object map.
- * All other methods in this module expect an array of plugins rather than an object map.
- *
- * @param {object} plugins - A map of plugin objects
- * @return {object[]}
- */
- exports.all = function (plugins) {
- return Object.keys(plugins)
- .filter((key) => {
- return typeof plugins[key] === "object";
- })
- .map((key) => {
- plugins[key].name = key;
- return plugins[key];
- });
- };
- /**
- * Filters the given plugins, returning only the ones return `true` for the given method.
- *
- * @param {object[]} plugins - An array of plugin objects
- * @param {string} method - The name of the filter method to invoke for each plugin
- * @param {object} file - A file info object, which will be passed to each method
- * @return {object[]}
- */
- exports.filter = function (plugins, method, file) {
- return plugins
- .filter((plugin) => {
- return !!getResult(plugin, method, file);
- });
- };
- /**
- * Sorts the given plugins, in place, by their `order` property.
- *
- * @param {object[]} plugins - An array of plugin objects
- * @returns {object[]}
- */
- exports.sort = function (plugins) {
- for (let plugin of plugins) {
- plugin.order = plugin.order || Number.MAX_SAFE_INTEGER;
- }
- return plugins.sort((a, b) => { return a.order - b.order; });
- };
- /**
- * Runs the specified method of the given plugins, in order, until one of them returns a successful result.
- * Each method can return a synchronous value, a Promise, or call an error-first callback.
- * If the promise resolves successfully, or the callback is called without an error, then the result
- * is immediately returned and no further plugins are called.
- * If the promise rejects, or the callback is called with an error, then the next plugin is called.
- * If ALL plugins fail, then the last error is thrown.
- *
- * @param {object[]} plugins - An array of plugin objects
- * @param {string} method - The name of the method to invoke for each plugin
- * @param {object} file - A file info object, which will be passed to each method
- * @returns {Promise}
- */
- exports.run = function (plugins, method, file, $refs) {
- let plugin, lastError, index = 0;
- return new Promise(((resolve, reject) => {
- runNextPlugin();
- function runNextPlugin () {
- plugin = plugins[index++];
- if (!plugin) {
- // There are no more functions, so re-throw the last error
- return reject(lastError);
- }
- try {
- // console.log(' %s', plugin.name);
- let result = getResult(plugin, method, file, callback, $refs);
- if (result && typeof result.then === "function") {
- // A promise was returned
- result.then(onSuccess, onError);
- }
- else if (result !== undefined) {
- // A synchronous result was returned
- onSuccess(result);
- }
- else if (index === plugins.length) {
- throw new Error("No promise has been returned or callback has been called.");
- }
- }
- catch (e) {
- onError(e);
- }
- }
- function callback (err, result) {
- if (err) {
- onError(err);
- }
- else {
- onSuccess(result);
- }
- }
- function onSuccess (result) {
- // console.log(' success');
- resolve({
- plugin,
- result
- });
- }
- function onError (error) {
- // console.log(' %s', err.message || err);
- lastError = {
- plugin,
- error,
- };
- runNextPlugin();
- }
- }));
- };
- /**
- * Returns the value of the given property.
- * If the property is a function, then the result of the function is returned.
- * If the value is a RegExp, then it will be tested against the file URL.
- * If the value is an aray, then it will be compared against the file extension.
- *
- * @param {object} obj - The object whose property/method is called
- * @param {string} prop - The name of the property/method to invoke
- * @param {object} file - A file info object, which will be passed to the method
- * @param {function} [callback] - A callback function, which will be passed to the method
- * @returns {*}
- */
- function getResult (obj, prop, file, callback, $refs) {
- let value = obj[prop];
- if (typeof value === "function") {
- return value.apply(obj, [file, callback, $refs]);
- }
- if (!callback) {
- // The synchronous plugin functions (canParse and canRead)
- // allow a "shorthand" syntax, where the user can match
- // files by RegExp or by file extension.
- if (value instanceof RegExp) {
- return value.test(file.url);
- }
- else if (typeof value === "string") {
- return value === file.extension;
- }
- else if (Array.isArray(value)) {
- return value.indexOf(file.extension) !== -1;
- }
- }
- return value;
- }
|