@smidswater/postcss-conditionals
Version:
PostCSS plugin that enables @if statements in your CSS
216 lines (165 loc) • 5.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _cssColorConverter = _interopRequireDefault(require("css-color-converter"));
var _parser = require("./parser");
var _convert3 = _interopRequireDefault(require("./convert"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _slicedToArray(arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return _sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }
function evaluate(ast) {
switch (ast.type) {
case 'LogicalExpression':
return evaluateLogicalExpression(ast);
case 'BinaryExpression':
return evaluateBinaryExpression(ast);
case 'MathematicalExpression':
return evaluateMathematicalExpression(ast);
case 'UnaryExpression':
return evaluateUnaryExpression(ast);
default:
return ast;
}
}
function evaluateLogicalExpression(ast) {
var left = evaluate(ast.left);
var right = evaluate(ast.right);
if (left.type !== 'BooleanValue') throw new Error('Unexpected node type');
if (right.type !== 'BooleanValue') throw new Error('Unexpected node type');
var value = ast.operator === 'AND' ? left.value && right.value : left.value || right.value;
return {
type: 'BooleanValue',
value: value
};
}
function compare(val1, val2) {
return val1 === val2 ? 0 : val1 > val2 ? 1 : -1;
}
function evaluateBinaryExpression(ast) {
var _convert = (0, _convert3.default)(evaluate(ast.left), evaluate(ast.right)),
left = _convert.left,
right = _convert.right;
var operator = ast.operator;
var cmp = function cmp() {
var comparison = compare(left.value, right.value);
switch (operator) {
case '==':
if (left.type !== right.type) return false;
return comparison === 0;
case '!=':
if (left.type !== right.type) return true;
return comparison !== 0;
case '>=':
if (left.type !== right.type) throw new Error('Node type mismatch');
return comparison >= 0;
case '>':
if (left.type !== right.type) throw new Error('Node type mismatch');
return comparison > 0;
case '<=':
if (left.type !== right.type) throw new Error('Node type mismatch');
return comparison <= 0;
case '<':
if (left.type !== right.type) throw new Error('Node type mismatch');
return comparison < 0;
}
};
return {
type: 'BooleanValue',
value: cmp()
};
}
function evaluateMathematicalExpression(ast) {
var _convert2 = (0, _convert3.default)(evaluate(ast.left), evaluate(ast.right)),
left = _convert2.left,
right = _convert2.right;
var operator = ast.operator;
if (left.type !== right.type) {
throw new Error('Node type mismatch');
}
if (left.type === 'ColorValue') return evaluateColorMath(left, right, operator);
switch (operator) {
case '+':
left.value = left.value + right.value;
break;
case '-':
left.value = left.value - right.value;
break;
case '*':
left.value = left.value * right.value;
break;
case '/':
left.value = left.value / right.value;
break;
}
return left;
}
function evaluateColorMath(left, right, op) {
var val1 = (0, _cssColorConverter.default)(left.value).toRgbaArray();
var val2 = (0, _cssColorConverter.default)(right.value).toRgbaArray();
if (val1[3] !== val2[3]) {
throw new Error('Alpha channels must be equal');
}
var _val = _slicedToArray(val1, 3),
r = _val[0],
g = _val[1],
b = _val[2];
var a = val1[3];
switch (op) {
case '+':
r = Math.min(r + val2[0], 255);
g = Math.min(g + val2[1], 255);
b = Math.min(b + val2[2], 255);
break;
case '-':
r = Math.max(r - val2[0], 0);
g = Math.max(g - val2[1], 0);
b = Math.max(b - val2[2], 0);
break;
case '*':
r = Math.min(r * val2[0], 255);
g = Math.min(g * val2[1], 255);
b = Math.min(b * val2[2], 255);
break;
case '/':
r = Math.max(r / val2[0], 0);
g = Math.max(g / val2[1], 0);
b = Math.max(b / val2[2], 0);
break;
}
return {
type: 'ColorValue',
value: (0, _cssColorConverter.default)().fromRgba([r, g, b, a]).toHexString()
};
}
function evaluateUnaryExpression(ast) {
var node = evaluate(ast.argument);
if (node.type !== 'BooleanValue') {
throw new Error('Node type mismatch');
}
return {
type: 'BooleanValue',
value: !node.value
};
}
var _default = function _default(expr) {
var ast = null;
try {
ast = _parser.parser.parse(expr);
} catch (e) {
throw new Error('Failed to parse expression');
}
var result = evaluate(ast);
switch (result.type) {
case 'LogicalExpression':
case 'BinaryExpression':
case 'MathematicalExpression':
case 'UnaryExpression':
throw new Error('Could not evaluate expression');
default:
return Boolean(result.value);
}
};
exports.default = _default;
module.exports = exports.default;