giuseppeg / styled-jsx-postcss

Use PostCSS with styled-jsx 💥
MIT License
64 stars 11 forks source link

Not work with string interpolation. #8

Closed lixiaoyan closed 7 years ago

lixiaoyan commented 7 years ago

Something like this will throw errors and failed to compile.

<style jsx>{`
  p { color: ${color}; }
`}</style>
giuseppeg commented 7 years ago

yep need to upgrade the lib and try interpolation – this version was released before we introduced interpolation in styled-jsx

timsuchanek commented 7 years ago

@giuseppeg Can you guide me how to include the current styled-jsx with styled-jsx-postcss? Because I would really like the template strings together with styled-jsx-postcss. Do we just have to replace the transform calls in babel.js? Like here: https://github.com/zeit/styled-jsx/blob/master/src/babel.js#L313 Or is there other stuff to do?

giuseppeg commented 7 years ago

@timsuchanek when I wrote styled-jsx-postcss I added support for template strings, in this repo we should update the styled-jsx version in package.json to ^0.5.4.

The other day I tried that but I got a failure and I haven't had time to debug it yet. Not sure when I will be able to jump on it.

sbehrends commented 7 years ago

Found the same issue. First thought it was a styled-jsx issue but https://github.com/zeit/styled-jsx/issues/91 lead me here.

Any iterpolation was leading to "css.map is not a function"

giuseppeg commented 7 years ago

At this stage styled-jsx-postcss doesn't support interpolation... I don't have a lot of free time so I cannot tell when I will be able to look into it.

In the meantime if someone wants to give it a stab I can assist / answer questions

sarukuku commented 7 years ago

It would be really nice to get this fixed as postcss + interpolation is a very powerful combo. I'll see what I can do next week. Also, I think that this deserves a bug label. It seems a bit out of sync if styled-jsx supports interpolation but a plugin for styled-jsx doesn't. 🙂

alethes commented 7 years ago

After some investigation, I noticed that the temporary replacement of template literal expressions with CSS-friendly strings doesn't work properly. Specifically, e.getSource() returns a wrong string, making the replacement operation idempotent. Somehow, the reported node positions are messed up. For now, I couldn't find a good way of getting the expression source, other than reconstructing it from AST with babel-generator. It works well, although I'm sure there's a better solution.

There should be a way for getCss() to access just the source of the template/string literal with correct expression locations. Right now, exprPath.getSource().slice(1, -1) gets the entire source of the file.

Here's my fork.

giuseppeg commented 7 years ago

Thank you for looking into this @alethes!

Specifically, e.getSource() returns a wrong string, making the replacement operation idempotent. Somehow, the reported node positions are messed up.

Correct path.getSource() uses the original file content instead of the partially transpiled one. The problem is that I do the transformation on the ast transformed by styled-jsx but as I said the original file source is not up to date.

Probably it is possible to use babel generator to get the source like so generate(exprPath.node).code.

I've also started to think that the plugin should transform the original source code rather than the ast modified by styled-jsx.

alethes commented 7 years ago

Probably it is possible to use babel generator to get the source like so generate(exprPath.node).code.

I've used generate to reconstruct just the template literal expressions. I believe generate(exprPath.node).code would return the source of the styled-jsx-transformed expression, while requiring more parsing. Working directly with the source seems like a good idea. Another issue I've noticed while working on this is that postcss functions won't work with template literals. E.g. when I do color(${myColor} alpha(10%)), postcss receives the placeholder value instead of the color string stored in the variable, which causes an error. Ideally, the template literal expressions would be evaluated before the literal is passed to CSS. For now, I've created a pull request for my fix. I hope it will be useful.