mirror of
https://github.com/frappe/frappe_docker.git
synced 2026-06-21 15:25:09 +00:00
310 lines
No EOL
8.1 KiB
JavaScript
310 lines
No EOL
8.1 KiB
JavaScript
"use strict";
|
|
|
|
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
|
|
|
|
var isPlainObject = require("lodash.isplainobject");
|
|
|
|
/**
|
|
* Options Manager
|
|
*
|
|
* Input Options: Object
|
|
* Output: Array of plugins enabled with their options
|
|
*
|
|
* Handles multiple types of input option keys
|
|
*
|
|
* 1. boolean and object values
|
|
* { mangle: true } // should enable mangler
|
|
* { mangle: { blacklist: ["foo"] } } // should enabled mangler
|
|
* // and pass obj to mangle plugin
|
|
*
|
|
* 2. group
|
|
* { unsafe: true } // should enable all plugins under unsafe
|
|
* { unsafe: { flip: false } } // should disable flip-comparisons plugin
|
|
* // and other plugins should take their defaults
|
|
* { unsafe: { simplify: {multipass: true}}} // should pass obj to simplify
|
|
* // other plugins take defaults
|
|
*
|
|
* 3. same option passed on to multiple plugins
|
|
* { keepFnames: false } // should be passed on to mangle & dce
|
|
* // without disturbing their own options
|
|
*/
|
|
|
|
module.exports = {
|
|
option,
|
|
proxy,
|
|
group,
|
|
generate,
|
|
resolveOptions,
|
|
generateResult
|
|
};
|
|
|
|
/**
|
|
* Generate the plugin list from option tree and inputOpts
|
|
*/
|
|
function generate(optionTree, inputOpts) {
|
|
return generateResult(resolveOptions(optionTree, inputOpts));
|
|
}
|
|
|
|
/**
|
|
* Generate plugin list from the resolvedOptionTree
|
|
* where resolvedOptionTree = for every node, node.resolved = true;
|
|
*/
|
|
function generateResult(resolvedOpts) {
|
|
var options = resolvedOpts.children;
|
|
var result = [];
|
|
|
|
for (var i = 0; i < options.length; i++) {
|
|
var _option = options[i];
|
|
|
|
switch (_option.type) {
|
|
case "option":
|
|
if (_option.resolvedValue) {
|
|
result.push(_option.resolvedValue);
|
|
}
|
|
break;
|
|
case "group":
|
|
result.push.apply(result, _toConsumableArray(generateResult(_option)));
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Traverses input @param{optionTree} and adds resolvedValue
|
|
* calculated from @param{inputOpts} for each Node in the tree
|
|
*/
|
|
function resolveOptions(optionTree) {
|
|
var inputOpts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
|
|
var options = optionTree.children;
|
|
|
|
// a queue to resolve proxies at the end after all options groups are resolved
|
|
var proxiesToResolve = [];
|
|
|
|
for (var i = 0; i < options.length; i++) {
|
|
var _option2 = options[i];
|
|
switch (_option2.type) {
|
|
case "option":
|
|
resolveTypeOption(_option2, inputOpts);
|
|
break;
|
|
|
|
case "group":
|
|
resolveTypeGroup(_option2, inputOpts);
|
|
break;
|
|
|
|
case "proxy":
|
|
if (!hop(inputOpts, _option2.name)) {
|
|
break;
|
|
}
|
|
proxiesToResolve.push(_option2);
|
|
break;
|
|
|
|
default:
|
|
throw new TypeError("Option type not supported - " + _option2.type);
|
|
}
|
|
}
|
|
|
|
// resolve proxies
|
|
for (var _i = 0; _i < proxiesToResolve.length; _i++) {
|
|
var _proxy = proxiesToResolve[_i];
|
|
for (var j = 0; j < _proxy.to.length; j++) {
|
|
var _option3 = _proxy.to[j];
|
|
switch (_option3.type) {
|
|
case "option":
|
|
resolveTypeProxyToOption(_proxy, _option3, inputOpts);
|
|
break;
|
|
|
|
case "group":
|
|
case "proxy":
|
|
throw new Error(`proxy option cannot proxy to group/proxy. ${_proxy.name} proxied to ${_option3.name}`);
|
|
|
|
default:
|
|
throw new Error("Unsupported option type ${option.name}");
|
|
}
|
|
}
|
|
}
|
|
|
|
// return the same tree after modifications
|
|
return optionTree;
|
|
}
|
|
|
|
/**
|
|
* Resolve the type - simple option using the @param{inputOpts}
|
|
*/
|
|
function resolveTypeOption(option, inputOpts) {
|
|
option.resolved = true;
|
|
|
|
// option does NOT exist in inputOpts
|
|
if (!hop(inputOpts, option.name)) {
|
|
// default value
|
|
option.resolvedValue = option.defaultValue ? option.resolvingValue : null;
|
|
return;
|
|
}
|
|
|
|
// Object
|
|
// { mangle: { blacklist: ["foo", "bar"] } }
|
|
if (isPlainObject(inputOpts[option.name])) {
|
|
option.resolvedValue = [option.resolvingValue, inputOpts[option.name]];
|
|
return;
|
|
}
|
|
|
|
// any other truthy value, just enables the plugin
|
|
// { mangle: true }
|
|
if (inputOpts[option.name]) {
|
|
option.resolvedValue = option.resolvingValue;
|
|
return;
|
|
}
|
|
|
|
// disabled
|
|
option.resolvedValue = null;
|
|
}
|
|
|
|
/**
|
|
* Resolve the group using @param{inputOpts}
|
|
*/
|
|
function resolveTypeGroup(option, inputOpts) {
|
|
option.resolved = true;
|
|
|
|
// option does NOT exist in inputOpts
|
|
if (!hop(inputOpts, option.name)) {
|
|
var _newInputOpts = option.children.filter(function (opt) {
|
|
return opt.type !== "proxy";
|
|
}).reduce(function (acc, cur) {
|
|
var value = void 0;
|
|
switch (option.defaultValue) {
|
|
case "all":
|
|
value = true;break;
|
|
case "some":
|
|
value = cur.defaultValue;break;
|
|
case "none":
|
|
value = false;break;
|
|
default:
|
|
throw new Error(`Unsupported defaultValue - ${option.defaultValue} for option ${option.name}`);
|
|
}
|
|
return Object.assign({}, acc, {
|
|
[cur.name]: value
|
|
});
|
|
}, {});
|
|
|
|
// recurse
|
|
resolveOptions(option, _newInputOpts);
|
|
return;
|
|
}
|
|
|
|
// has individual options for items in group
|
|
// { unsafe: { flipComparisons: true } }
|
|
if (isPlainObject(inputOpts[option.name])) {
|
|
resolveOptions(option, inputOpts[option.name]);
|
|
return;
|
|
}
|
|
|
|
// else
|
|
// { unsafe: <true | false> }
|
|
var newInputOpts = option.children.filter(function (opt) {
|
|
return opt.type !== "proxy";
|
|
}).reduce(function (acc, cur) {
|
|
return Object.assign({}, acc, {
|
|
// if the input is truthy, enable all, else disable all
|
|
[cur.name]: !!inputOpts[option.name]
|
|
});
|
|
}, {});
|
|
resolveOptions(option, newInputOpts);
|
|
}
|
|
|
|
/**
|
|
* Resolve proxies and update the already resolved Options
|
|
*/
|
|
function resolveTypeProxyToOption(proxy, option, inputOpts) {
|
|
if (!option.resolved) {
|
|
throw new Error("Proxies cannot be applied before the original option is resolved");
|
|
}
|
|
|
|
// option is disabled
|
|
if (!option.resolvedValue) {
|
|
return;
|
|
}
|
|
|
|
// option doesn't contain any option on its own
|
|
if (option.resolvedValue === option.resolvingValue) {
|
|
option.resolvedValue = [option.resolvedValue, {
|
|
[proxy.name]: inputOpts[proxy.name]
|
|
}];
|
|
}
|
|
|
|
// option already has its own set of options to be passed to plugins
|
|
else if (Array.isArray(option.resolvedValue) && option.resolvedValue.length === 2) {
|
|
// proxies should not override
|
|
if (!hop(option.resolvedValue[1], proxy.name)) {
|
|
option.resolvedValue = [option.resolvingValue, Object.assign({}, option.resolvedValue[1], {
|
|
[proxy.name]: inputOpts[proxy.name]
|
|
})];
|
|
}
|
|
}
|
|
|
|
// plugin is invalid
|
|
else {
|
|
throw new Error(`Invalid resolved value for option ${option.name}`);
|
|
}
|
|
}
|
|
|
|
// create an option of type simple option
|
|
function option(name, resolvingValue) {
|
|
var defaultValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
|
|
|
assertName(name);
|
|
if (!resolvingValue) {
|
|
// as plugins are truthy values
|
|
throw new Error("Only truthy resolving values are supported");
|
|
}
|
|
return {
|
|
type: "option",
|
|
name,
|
|
resolvingValue,
|
|
defaultValue
|
|
};
|
|
}
|
|
|
|
// create an option of type proxy
|
|
function proxy(name, to) {
|
|
assertName(name);
|
|
assertArray(name, "to", to);
|
|
return {
|
|
type: "proxy",
|
|
name,
|
|
to
|
|
};
|
|
}
|
|
|
|
// create an option of type - group of options
|
|
function group(name, children) {
|
|
var defaultValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "some";
|
|
|
|
assertName(name);
|
|
assertArray(name, "children", children);
|
|
return {
|
|
type: "group",
|
|
name,
|
|
children: children.filter(function (x) {
|
|
return !!x;
|
|
}),
|
|
defaultValue
|
|
};
|
|
}
|
|
|
|
function hop(o, key) {
|
|
return Object.hasOwnProperty.call(o, key);
|
|
}
|
|
|
|
function assertArray(name, prop, arr) {
|
|
if (!Array.isArray(arr)) {
|
|
throw new Error(`Expected ${prop} to be an array in option ${name}`);
|
|
}
|
|
}
|
|
|
|
function assertName(name) {
|
|
if (!name) {
|
|
throw new Error("Invalid option name " + name);
|
|
}
|
|
} |