babel-plugin-styled-components icon indicating copy to clipboard operation
babel-plugin-styled-components copied to clipboard

[FEATURE] Let's add preprocessors and plugins support?

Open MaxmaxmaximusAWS opened this issue 3 years ago • 1 comments

Ince all css preprocessors are static, they do their job during compilation time, and in fact, if they are executed by babel BEFORE the data is passed to styled-components, then styled components won't know anything about it.

You already have a babel plugin babel-plugin-styled-components, let's add the plugins option there, and people can write plugins that can convert string literals BEFORE styled-components =). this way people can write, for example, a plugin babel-plugin-styled-components-postcss, and pass any preprocessor, compressor, optimizer, etc. to its settings. =)

while styled-components will not know anything about it at all, because at the output it will receive a normal valid css code =)

Furthermore, If we want to get the this construction for styled-components:

styled.div`
  color: red;

  &:hover {
    color: blue;
  }
`

then our preprocessors will not know about it, and will generate standard css code:

styled.div`
:host {
  color: red;
}

:host:hover {
  color: blue;
}
`

Implementation principle of the plugin system:

step 1

As for interpolation, many similar plugins solve this in a simple way, they replace all occurrences of interpolation with a label, like this: __INTERPOLATION_LABEL__id__

This is hypothetical code, which is supported by our hypothetical preprocessor, which allows you not to write colons, semicolons, and adds custom css properties. With indentation based blocks. I came up it just now =)

styled.div`
  gradient red blue

  &:hover-and-active ${ AdminPanel }
      gradient green yellow
`

Our postcss-babel-plugin will pass the above code to its child plugin, like this:

styled.div`
  gradient red blue

  &:hover-and-active __INTERPOLATION_LABEL__AdminPanel__
      gradient green yellow 
`

step 2

plugins will output something like this:

styled.div`
:host {
  background-image: linear-gradient(top, red, blue);
}

:host:hover __INTERPOLATION_LABEL__AdminPanel__ {
  background-image: linear-gradient(top, green, yellow);
}

:host:active __INTERPOLATION_LABEL__AdminPanel__ {
  background-image: linear-gradient(top, green, yellow);
}
`

step 3

Replace labels back to interpolation:

styled.div`
:host {
  background-image: linear-gradient(top, red, blue);
}

:host:hover ${ AdminPanel } {
  background-image: linear-gradient(top, green, yellow);
}

:host:active ${ AdminPanel } {
  background-image: linear-gradient(top, green, yellow);
}
`

step 4

Convert it to format that the current version runetime of styled-components understands. Replase subselectors by &, and unwrap :host blocks :

styled.div`
  background-image: linear-gradient(top, red, blue);

  &:hover ${ AdminPanel } {
    background-image: linear-gradient(top, green, yellow);
  }

  &:active ${ AdminPanel } {
    background-image: linear-gradient(top, green, yellow);
  }
`

and then pass this code to the standard pipeline webabel-plugin-styled-components

P.S. but it is best not to replace interpolation with labels, but just create a handy helper for that. Plugin creators should decide for themselves how to handle interpolation. maybe they will want to somehow change the javascript code in interpolation

MaxmaxmaximusAWS avatar Sep 01 '20 00:09 MaxmaxmaximusAWS

Discussion of a slightly more global concept of leaving runtime. https://github.com/styled-components/styled-components/issues/3249

MaxmaxmaximusAWS avatar Sep 01 '20 12:09 MaxmaxmaximusAWS