Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

minification does not happen for gradients #306

Open
layershifter opened this issue Oct 31, 2022 · 1 comment
Open

minification does not happen for gradients #306

layershifter opened this issue Oct 31, 2022 · 1 comment

Comments

@layershifter
Copy link

Versions

stylis@4.1.3

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

@Fonger
Copy link

Fonger commented Mar 16, 2024

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

stylis/test/Parser.js

Lines 19 to 27 in b8c0878

expect(
stylis(`
height:calc( 100vh - 1px );
height:calc(
100vh -
1px
);
`)
).to.equal(`.user{height:calc( 100vh - 1px );height:calc(\n 100vh -\n 1px\n );}`)

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants