postcss-ordered-values
Version:
Ensure values are ordered consistently in your CSS.
53 lines (48 loc) • 1.71 kB
JavaScript
import cssnanoUtils from 'cssnano-utils';
import vendorUnprefixed from './vendorUnprefixed.js';
import { parseMath } from './isTime.js';
import { isDimension, isFunction, isNumber, name } from './tokenize.js';
const { asciiLowerCase, lengthUnits, mathFunctions } = cssnanoUtils;
/**
* The lowercased CSS length unit of a single-token dimension, or null when
* the term is not a dimension with a length unit.
*
* @param {import('./tokenize.js').Term} term
* @return {string | null}
*/
export function lengthUnit(term) {
if (!isDimension(term)) return null;
const unit = /** @type {{unit: string}} */ (term.tokens[0][4])?.unit;
if (typeof unit !== 'string') return null;
const lowered = asciiLowerCase(unit);
return lengthUnits.has(lowered) ? lowered : null;
}
/**
* A syntactically sound <length> component: a dimension carrying a CSS
* length unit, or the unitless zero number.
*
* @param {import('./tokenize.js').Term} term
* @return {boolean}
*/
export function isLength(term) {
return (
lengthUnit(term) !== null ||
(isNumber(term) &&
/** @type {{value: number}} */ (term.tokens[0][4])?.value === 0)
);
}
/**
* Resolve a math function's dimension in a <length> context. Only expressions
* that resolve to a length match; number results, other dimensions, and
* malformed or vendor-prefixed arithmetic fail closed so invalid CSS is left
* byte-for-byte unchanged.
*
* @param {import('./tokenize.js').Term} node
* @return {'length' | null}
*/
export function classifyMathLength(node) {
if (!isFunction(node) || !mathFunctions.has(vendorUnprefixed(name(node)))) {
return null;
}
return parseMath(node.tokens) === 'length' ? 'length' : null;
}