postcss-calc
Version:
PostCSS plugin to reduce calc()
55 lines (50 loc) • 1.63 kB
JavaScript
/* §10.10 phase 2: merge convertible same-base unit buckets into the
first-encountered unit (px absorbs cm/in/pt/pc, deg absorbs
rad/grad/turn, …). Buckets with `base === null` (relative or unknown
units) keep their own slot.
*/
import { convert } from '../convertUnits.js';
/**
* @typedef {object} UnitBucket
* @property {string} unit
* @property {number} total
* @property {number} scale largest |term| accumulated into `total`, for noise detection
* @property {import('../convertUnits.js').BaseType | null} base
* @property {number} order
*/
/** Mutates `buckets` in place — totals of survivor buckets accumulate the
* converted values of merged neighbors. Caller must not reuse the input.
* @param {UnitBucket[]} buckets
* @return {UnitBucket[]}
*/
function mergeConvertibleBuckets(buckets) {
const ordered = [...buckets].sort((a, b) => a.order - b.order);
/** @type {Set<string>} */ const merged = new Set();
/** @type {UnitBucket[]} */ const out = [];
for (const b of ordered) {
const keyB = b.unit.toLowerCase();
if (merged.has(keyB)) {
continue;
}
merged.add(keyB);
if (b.base !== null) {
for (const other of ordered) {
const keyO = other.unit.toLowerCase();
if (merged.has(keyO)) {
continue;
}
if (other.base !== b.base) {
continue;
}
const converted = convert(other.total, other.unit, b.unit);
if (converted !== null) {
b.total += converted;
merged.add(keyO);
}
}
}
out.push(b);
}
return out;
}
export { mergeConvertibleBuckets };