minification does not happen for gradients
Versions
Problem
Stylis does minification and it works great:
.foo { color: red; }
.bar {
color: blue;
background: orange;
}
/* ⬇️⬇️⬇️ */
.foo{color:red;}.bar{color:blue;background:orange;}
The problem happens with radial-gradient& repeating-linear-gradient:
.foo {
background: repeating-linear-gradient(
-45deg,
red,
red 5px,
blue 5px,
blue 10px
);
}
.bar {
color: blue;
background: orange;
}
.baz {
background-image:radial-gradient(
ellipse 50rem 50rem,
#8e91e6 0%,
#403f5a 25%,
transparent 46%
)
}
/* ⬇️⬇️⬇️ */
.foo{background:repeating-linear-gradient(
-45deg,
red,
red 5px,
blue 5px,
blue 10px
);}.bar{color:blue;background:orange;}.baz{background-image:radial-gradient(
ellipse 50rem 50rem,
#8e91e6 0%,
#403f5a 25%,
transparent 46%
);}
👆 notice that .foo & .baz are not minified.
Reproduction
https://codesandbox.io/s/awesome-rgb-wf0j3e
This does not only happen on gradients. Any style with Parentheses like var() calc() suffer from the same issue.
You can see this in test case, the parser ignores anything between parentheses
https://github.com/thysultan/stylis/blob/b8c0878307ce600c7ec5082f5f940febf663a722/test/Parser.js#L19-L27
You can workaround this by providing your own middleware.
import { compile, middleware, serialize, stringify } from 'stylis'
const parenthesesStartRegex = /\(\s+/g;
const parenthesesEndRegex = /\s+\)/g;
const commaSpaces = /,\s+/g;
const parenthesesRegex=/^[a-z-]+\(\s+/ig;
const minifyParentheses = element => {
if (
element.type === 'decl' &&
typeof element.props === 'string' &&
typeof element.children === 'string' &&
parenthesesRegex.test(element.children)
) {
element.return = `${element.props}:${element.children
.replaceAll(parenthesesStartRegex, '(')
.replaceAll(parenthesesEndRegex, ')')
.replaceAll(commaSpaces, ',')};`;
}
};
const css = `
.foo {
background: repeating-linear-gradient(
-45deg,
red,
red 5px,
blue 5px,
blue 10px
);
color: green;
}
.bar {
color: blue;
background: orange;
}
.baz {
background-image:radial-gradient(
ellipse 50rem 50rem,
#8e91e6 0%,
#403f5a 25%,
transparent 46%
)
}
`;
const processedCss = serialize(compile(css), middleware([minifyParentheses, stringify]));
console.log(processedCss)
output:
.foo{background:repeating-linear-gradient(-45deg,red,red 5px,blue 5px,blue 10px);color:green;}.bar{color:blue;background:orange;}.baz{background-image:radial-gradient(ellipse 50rem 50rem,#8e91e6 0%,#403f5a 25%,transparent 46%);}
Caveats
Note that this example doesn't consider nested ( ) or content in "". It may cause some issues if you just use this workaround.