function convertValue(args, type, value) { if (type === undefined || type === null || type == "raw") { // nop: type == "raw" } else if (type == "value") { value = args.value; } else if (type == "json") { value = JSON.parse(value); } else { throw `Unknown value type: ${type}`; } return value === undefined ? null : value; } function getValue(args, condition, options, lhs, getValueArray) { for (var name of getValueArray) { // descending order by length if (lhs ? condition.startsWith(name) : condition.endsWith(name)) { return [name, convertValue(args, options[`input_data_type:${name}`], args[name])]; } } throw `Invalid condition: ${condition}`; } function makeOptions(option_names) { var options = {}; for (var name of argToList(option_names ? option_names : "")) { name = name.trim(); var seppos = name.lastIndexOf("="); var value = true; if (seppos >= 0){ value = name.substr(seppos+1); name = name.substr(0, seppos); } if (!name) { throw "Found an empty name in options."; } options[name] = value; } return options; } function getOperator(lhs_name, rhs_name, condition) { var operator = condition.substr( lhs_name.length, condition.length - lhs_name.length - rhs_name.length); const specials = [" ", "!", "=", "~", "<", ">"]; if (specials.indexOf(operator.slice(0, 1)) < 0 || specials.indexOf(operator.slice(-1)) < 0 ){ throw `Invalid condition: ${condition}`; } return operator.trim(); } function lowerIfPossible(lhs, rhs, case_insensitive) { if (case_insensitive && typeof lhs == "string" && typeof rhs == "string") { return [lhs.toLowerCase(), rhs.toLowerCase()]; } else { return [lhs, rhs]; } } function evaluate(operator, lhs, rhs, options) { switch (operator) { case "===": { [lhs, rhs] = lowerIfPossible(lhs, rhs, options.case_insensitive); return lhs === rhs; } case "!==": { [lhs, rhs] = lowerIfPossible(lhs, rhs, options.case_insensitive); return lhs !== rhs; } case "==": { [lhs, rhs] = lowerIfPossible(lhs, rhs, options.case_insensitive); return (lhs === null ? "" : lhs) == (rhs === null ? "" : rhs); } case "!=": { [lhs, rhs] = lowerIfPossible(lhs, rhs, options.case_insensitive); return (lhs === null ? "" : lhs) != (rhs === null ? "" : rhs); } case ">": { [lhs, rhs] = lowerIfPossible(lhs, rhs, options.case_insensitive); return lhs > rhs; } case ">=": { [lhs, rhs] = lowerIfPossible(lhs, rhs, options.case_insensitive); return lhs >= rhs; } case "<": { [lhs, rhs] = lowerIfPossible(lhs, rhs, options.case_insensitive); return lhs < rhs; } case "<=": { [lhs, rhs] = lowerIfPossible(lhs, rhs, options.case_insensitive); return lhs <= rhs; } case "=~": { var xopts = ""; if (options.regex_dot_all) { xopts += "s"; } if (options.regex_multiline) { xopts += "m"; } if (options.case_insensitive) { xopts += "i"; } var regex = new RegExp(String(rhs), xopts); var str = String(lhs); var res = str.match(regex); return res !== null && (!options.regex_full_match || res[0].length == str.length); } case "in list": { lhs = String(lhs); lhs = options.case_insensitive ? lhs.toLowerCase() : lhs; rhs = options.case_insensitive ? rhs.toLowerCase() : rhs; return argToList(rhs).indexOf(lhs) >= 0; } case "not in list": { return !evaluate("in list", lhs, rhs, options); } default: { throw `Unknown operator: ${operator}`; } } } if ((args.condition && args.condition.indexOf("equals") >= 0 || (args.conditionB && args.conditionB.indexOf("equals") >= 0))) { throw "Legacy parameter (equals) is not supported for `condition`, please use lhs and rhs or leave it blank"; } const condition = args.condition ? args.condition.trim() : 'value==equals'; const conditionB = args.conditionB ? args.conditionB.trim() : 'value==equals'; const conditionInBetween = args.conditionInBetween ? args.conditionInBetween.trim() : 'and'; const options = makeOptions(args.options); const optionsB = makeOptions(args.optionsB); const getValueArrayA = ["equals", "value", "lhs", "rhs"]; const [lhs_name, lhs] = getValue(args, condition, options, true, getValueArrayA); const [rhs_name, rhs] = getValue(args, condition, options, false, getValueArrayA); const operator = getOperator(lhs_name, rhs_name, condition); const getValueArrayB = ["equals", "value","lhsB", "rhsB"]; const [lhsB_name, lhsB] = getValue(args, conditionB, optionsB, true, getValueArrayB); const [rhsB_name, rhsB] = getValue(args, conditionB, optionsB, false, getValueArrayB); const operator2 = getOperator(lhsB_name, rhsB_name, conditionB); var resultA = evaluate(operator, lhs, rhs, options); var ret; if (lhsB && (args.lhsB !== undefined || args.rhsB !== undefined || args.conditionB !== undefined || args.conditionInBetween !== undefined || args.optionsB !== undefined)) { var resultB = evaluate(operator2, lhsB, rhsB, optionsB); if (conditionInBetween == 'and' && (resultA && resultB)) { ret = convertValue(args, options["input_data_type:then"], args.then); } else if (conditionInBetween == 'or' && (resultA || resultB)) { ret = convertValue(args, options["input_data_type:then"], args.then); } else { ret = convertValue(args, options["input_data_type:else"], args.else); } } else { if (resultA) { ret = convertValue(args, options["input_data_type:then"], args.then); } else { ret = convertValue(args, options["input_data_type:else"], args.else); } } return ret === null ? "" : ret;