You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

80 lines
3.4 KiB

"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = collapseDuplicateDeclarations;
function collapseDuplicateDeclarations() {
return (root)=>{
root.walkRules((node)=>{
let seen = new Map();
let droppable = new Set([]);
let byProperty = new Map();
node.walkDecls((decl)=>{
// This could happen if we have nested selectors. In that case the
// parent will loop over all its declarations but also the declarations
// of nested rules. With this we ensure that we are shallowly checking
// declarations.
if (decl.parent !== node) {
return;
}
if (seen.has(decl.prop)) {
// Exact same value as what we have seen so far
if (seen.get(decl.prop).value === decl.value) {
// Keep the last one, drop the one we've seen so far
droppable.add(seen.get(decl.prop));
// Override the existing one with the new value. This is necessary
// so that if we happen to have more than one declaration with the
// same value, that we keep removing the previous one. Otherwise we
// will only remove the *first* one.
seen.set(decl.prop, decl);
return;
}
// Not the same value, so we need to check if we can merge it so
// let's collect it first.
if (!byProperty.has(decl.prop)) {
byProperty.set(decl.prop, new Set());
}
byProperty.get(decl.prop).add(seen.get(decl.prop));
byProperty.get(decl.prop).add(decl);
}
seen.set(decl.prop, decl);
});
// Drop all the duplicate declarations with the exact same value we've
// already seen so far.
for (let decl1 of droppable){
decl1.remove();
}
// Analyze the declarations based on its unit, drop all the declarations
// with the same unit but the last one in the list.
for (let declarations of byProperty.values()){
let byUnit = new Map();
for (let decl of declarations){
let unit = resolveUnit(decl.value);
if (unit === null) {
continue;
}
if (!byUnit.has(unit)) {
byUnit.set(unit, new Set());
}
byUnit.get(unit).add(decl);
}
for (let declarations1 of byUnit.values()){
// Get all but the last one
let removableDeclarations = Array.from(declarations1).slice(0, -1);
for (let decl of removableDeclarations){
decl.remove();
}
}
}
});
};
}
let UNITLESS_NUMBER = Symbol("unitless-number");
function resolveUnit(input) {
let result = /^-?\d*.?\d+([\w%]+)?$/g.exec(input);
if (result) {
var ref;
return (ref = result[1]) !== null && ref !== void 0 ? ref : UNITLESS_NUMBER;
}
return null;
}