cssnano
Version:
A modular CSS minifier, built on top of the PostCSS ecosystem.
81 lines (75 loc) • 2.42 kB
JavaScript
import cssnanoUtils from '#utils';
const { asciiLowerCase, isAnonymousLayer } = cssnanoUtils;
/**
* @param {import('postcss').AnyNode} nodeA
* @param {import('postcss').AnyNode} nodeB
* @return {boolean}
*/
function checkMatch(nodeA, nodeB) {
if (nodeA.type === 'atrule' && nodeB.type === 'atrule') {
const nameA = asciiLowerCase(nodeA.name);
const nameB = asciiLowerCase(nodeB.name);
if (nameA !== nameB) {
return false;
}
if (nameA === 'layer') {
const anonA = isAnonymousLayer(
/** @type {import('postcss').AtRule} */ (nodeA)
);
const anonB = isAnonymousLayer(
/** @type {import('postcss').AtRule} */ (nodeB)
);
if (anonA || anonB) {
return anonA && anonB && nodeA === nodeB;
}
}
return nodeA.params === nodeB.params;
}
if (nodeA.type === 'rule' && nodeB.type === 'rule') {
return (
nodeA === nodeB ||
/** @type {import('postcss').Rule} */ (nodeA).selector ===
/** @type {import('postcss').Rule} */ (nodeB).selector
);
}
return nodeA.type === nodeB.type;
}
/**
* True for `@keyframes` and its vendor-prefixed forms, whose selectors are
* cascaded by position.
*
* @param {import('postcss').Container | undefined} container
* @return {boolean}
*/
export function isKeyframes(container) {
return (
container?.type === 'atrule' &&
asciiLowerCase(
/** @type {import('postcss').AtRule} */ (container).name
).includes('keyframes')
);
}
/** @typedef {import('postcss').AnyNode & {parent?: Child}} Child */
/**
* True if two containers apply their content the same way: they are equal
* blocks, and so are their enclosing blocks up to the stylesheet. Either may
* be missing, for a node that is detached.
*
* @param {import('postcss').Container | undefined} containerA
* @param {import('postcss').Container | undefined} containerB
* @return {boolean}
*/
export function sameContainer(containerA, containerB) {
if (!containerA || !containerB) {
return !containerA && !containerB;
}
const a = /** @type {Child} */ (/** @type {unknown} */ (containerA));
const b = /** @type {Child} */ (/** @type {unknown} */ (containerB));
return (
checkMatch(a, b) &&
sameContainer(
/** @type {import('postcss').Container | undefined} */ (a.parent),
/** @type {import('postcss').Container | undefined} */ (b.parent)
)
);
}