@stimulus-library/controllers
Version:
A library of useful controllers for Stimulus
59 lines (58 loc) • 2.63 kB
JavaScript
export function extractExpressions(expressionString) {
const andExpression = expressionString.includes("&&");
return expressionString.split(andExpression ? "&&" : "||");
}
export function extractPredicates(expressionString) {
expressionString = expressionString.trim();
const andExpression = expressionString.includes("&&");
const orExpression = expressionString.includes("||");
const groupings = expressionString.includes("(") || expressionString.includes(")");
if (andExpression && orExpression) {
throw new Error("Cannot have both && and || in the same expression.");
}
if (groupings) {
throw new Error("Cannot have logical groupings `(>3 && <= 9) || (>1 && <2)` in the expression. Only supports simple expressions like `>1 && <3`");
}
const expressions = extractExpressions(expressionString);
if (andExpression) {
return expressions.map(ex => _predicateForExpression(ex));
}
else if (orExpression) {
return expressions.map(ex => _predicateForExpression(ex));
}
else {
return [_predicateForExpression(expressionString)];
}
}
function _predicateForExpression(expression) {
const operators = [">=", "<=", "==", "!=", ">", "<"];
const operator = operators.find(part => expression.includes(part));
if (!operator) {
throw new Error(`Could not find operator in expression: ${expression}`);
}
let expressionValue = expression.split(operator)[1].trim();
const isNumber = /^-?\d*(\.\d+)?$/.test(expressionValue);
if (isNumber) {
expressionValue = parseFloat(expressionValue);
}
if (expressionValue === "") {
throw new Error(`Could not find a value in expression: ${expression}`);
}
const notEmpty = (signalValue) => signalValue !== "";
switch (operator) {
case ">":
return (signalValue) => isNumber && notEmpty(signalValue) && signalValue > expressionValue;
case "<":
return (signalValue) => isNumber && notEmpty(signalValue) && signalValue < expressionValue;
case ">=":
return (signalValue) => isNumber && notEmpty(signalValue) && signalValue >= expressionValue;
case "<=":
return (signalValue) => isNumber && notEmpty(signalValue) && signalValue <= expressionValue;
case "==":
return (signalValue) => notEmpty(signalValue) && signalValue == expressionValue;
case "!=":
return (signalValue) => notEmpty(signalValue) && signalValue != expressionValue;
default:
throw new Error(`Unknown operator ${operator}`);
}
}