UNPKG

postcss-calc

Version:
58 lines (53 loc) 1.46 kB
import { num, dim, call } from '../node.js'; import { foldConstArgs } from './fold.js'; /** @typedef {import('../node.js').Node} Node */ /** * @param {'mod' | 'rem'} name * @param {Node[]} args * @return {Node} */ function simplifyModRem(name, args) { if (args.length !== 2) { return call(name, args); } const fold = foldConstArgs(args); if (fold === null) { return call(name, args); } const [a, b] = /** @type {[number, number]} */ (fold.values); const result = applyModRem(name, a, b); // NaN results drop the unit (`mod(5px, 0px)` → `calc(NaN)`, not // `calc(NaN * 1px)`). §10.12 unit-preserving form is a known divergence. if (Number.isNaN(result)) { return num(Number.NaN); } return fold.unit === '' ? num(result) : dim(result, fold.unit); } /** * @param {'mod' | 'rem'} name * @param {number} a * @param {number} b * @return {number} */ function applyModRem(name, a, b) { if (b === 0) { return Number.NaN; } if (!Number.isFinite(a)) { return Number.NaN; } if (!Number.isFinite(b)) { // mod: result is NaN when A has opposite sign to B; otherwise A. // rem: result is A regardless of signs. if (name === 'mod' && a !== 0 && Math.sign(a) !== Math.sign(b)) { return Number.NaN; } return a; } if (name === 'rem') { return a % b; // sign follows dividend } // sign follows divisor return a - b * Math.floor(a / b); } export { simplifyModRem };