UNPKG

postcss-calc

Version:
95 lines (82 loc) 3.43 kB
// Pre-simplify args once, route by name. Leaf folds receive simplified // args so they don't need to recurse into `simplify` themselves. import { simplifyMinMax } from './min-max.js'; import { simplifyClamp } from './clamp.js'; import { simplifyAbs } from './abs.js'; import { simplifySign } from './sign.js'; import { simplifyModRem } from './mod-rem.js'; import { simplifyRound } from './round.js'; import { simplifyTrig } from './trig.js'; import { simplifyInverseTrig } from './inverse-trig.js'; import { simplifyAtan2 } from './atan2.js'; import { simplifyPow } from './pow.js'; import { simplifySqrt } from './sqrt.js'; import { simplifyExp } from './exp.js'; import { simplifyLog } from './log.js'; import { simplifyHypot } from './hypot.js'; import { call } from '../node.js'; /** @typedef {import('../node.js').Node} Node */ /** @typedef {import('../simplify.js').SimplifyFn} SimplifyFn */ /** @typedef {(name: string, args: Node[]) => Node} MathSimplifier */ // Bare CSS math functions with implemented simplification semantics, keyed // by lowercase name. calc() and its vendor-prefixed forms are handled // separately as wrappers in simplifyCall. This map is the single source of // truth for both dispatch and `isSupportedMathFunction`. /** @type {Map<string, MathSimplifier>} */ const MATH_SIMPLIFIERS = new Map([ ['min', simplifyMinMax], ['max', simplifyMinMax], ['clamp', (_name, args) => simplifyClamp(args)], ['abs', (_name, args) => simplifyAbs(args)], ['sign', (_name, args) => simplifySign(args)], ['mod', (_name, args) => simplifyModRem('mod', args)], ['rem', (_name, args) => simplifyModRem('rem', args)], ['round', (_name, args) => simplifyRound(args)], ['sin', (_name, args) => simplifyTrig('sin', args)], ['cos', (_name, args) => simplifyTrig('cos', args)], ['tan', (_name, args) => simplifyTrig('tan', args)], ['asin', (_name, args) => simplifyInverseTrig('asin', args)], ['acos', (_name, args) => simplifyInverseTrig('acos', args)], ['atan', (_name, args) => simplifyInverseTrig('atan', args)], ['atan2', (_name, args) => simplifyAtan2(args)], ['pow', (_name, args) => simplifyPow(args)], ['sqrt', (_name, args) => simplifySqrt(args)], ['hypot', (_name, args) => simplifyHypot(args)], ['log', (_name, args) => simplifyLog(args)], ['exp', (_name, args) => simplifyExp(args)], ]); /** * Whether a bare CSS math function has an implemented simplifier. * * @param {string} name * @return {boolean} */ function isSupportedMathFunction(name) { return MATH_SIMPLIFIERS.has(name.toLowerCase()); } /** * @param {Extract<Node, { type: 'Call' }>} node * @param {SimplifyFn} simplify * @return {Node} */ function simplifyCall(node, simplify) { const name = node.name.toLowerCase(); if (name === 'calc' || name === '-webkit-calc' || name === '-moz-calc') { if (node.args.length !== 1) { throw new Error(`${node.name}() takes exactly one argument`); } return simplify(node.args[0]); } const args = node.args.map((a) => simplify(a)); const simplifier = MATH_SIMPLIFIERS.get(name); if (simplifier) { // min/max preserve the call's original casing in their opaque-args // fallback; the rest normalize to lowercase internally. return simplifier( name === 'min' || name === 'max' ? node.name : name, args ); } return call(node.name, args); } export { isSupportedMathFunction, simplifyCall };