Format CSS in template literals with expressions#2102
Conversation
FYI, styled-jsx doesn't support dynamic expressions like this, only styled-components do ;) |
| function wrapCssTemplate(quasisDoc, expressionDocs) { | ||
| const allReplaced = replacePlaceholders(quasisDoc, expressionDocs); | ||
| if (!allReplaced) { | ||
| throw new Error("Couldn't insert all the expressions"); |
There was a problem hiding this comment.
Could you use createError with the right location, this way if it fires people won't be as confused.
There was a problem hiding this comment.
Ok, but this won't be shown to users, it's there just in case a placeholder was parsed in an odd way and we couldn't find it. Throwing the error aborts the formatting of the template literal but the rest of the file should be formatted normally.
Maybe it should be an assert.
There was a problem hiding this comment.
You are right, let's just leave it like this. If it becomes an issue, people will report it and we'll figure out a solution.
src/multiparser.js
Outdated
| ) { | ||
| // If placeholder is splitted, join it | ||
| const [at, placeholder, ...rest] = doc.parts; | ||
| doc.parts = [at + placeholder, ...rest]; |
There was a problem hiding this comment.
Could you re-create a doc tree while you are iterating instead of doing mutations? It's going to bite us in the future I'm sure :(
There was a problem hiding this comment.
I'm having problems trying to find a clean way to re-create the doc. Is the mutation during the iteration what you don't like? If so, I can postpone the mutations until the traverse finishes.
src/multiparser.js
Outdated
| const text = rawQuasis.join("@prettier-placeholder"); | ||
|
|
||
| return { | ||
| parser: "postcss", |
There was a problem hiding this comment.
We should make all the CSS go through the same codepath instead of duplicating this non trivial logic.
|
This is so exciting! Thanks for building it <3 If you can build a new doc tree instead of mutating it and merging the CSS codepaths, I'll merge it. I'm so excited :) |
|
Thanks, I'll try to fix it later today. Do you know why Node v4 does not like the PR? For the styled-jsx test cases, I'm using what @giuseppeg recommended in this issue |
|
Probably crashes on destructuring for node 4. You can use nvm to install node 4 and try it yourself. Good to know about styled-jsx that supports expressions, I thought it didn't. |
We do support expressions (constants) but we don't allow the usage of @pomber you may want to update the fixture, I added more use cases. |
|
Can you use mapDoc to rebuild it? |
3a6fcba to
6050530
Compare
| animation: 3s | ||
| ease-in | ||
| 1s | ||
| \${foo => foo.getIterations()} |
|
This is so exciting! Is there a chance that someone will type |
|
Mmm, it won't break, but the template won't be formatted. So you could use |
src/multiparser.js
Outdated
| (/^[A-Z]/.test(parent.tag.object.name) && | ||
| parent.tag.property.name === "extend")); | ||
|
|
||
| if (isStyledJsx || isStyledComponents) { |
There was a problem hiding this comment.
nit: isStyledComponents and isStyledJsx could be functions that get the current path as input.
Then you can make an helper function isCss:
export const isCss = path => [isStyledJsx, isStyledCompoents].some(test => test(path))This way you can add tests for other libraries easily.
|
Just FYI there's probably going to be merge conflicts with #2109. |
fd060c7 to
577d189
Compare
|
Done with the merge, thanks @azz :p |
|
<3 <3 <3 <3 |
This adds support for formatting CSS inside template literals with expressions (#1948). For example:
Currently is only working for styled-jsx, but if you like the approach, I can add styled-components too, it should be easy.
It works like this:
@prettier-placeholderIf it fails to find or replace any of the placeholders it throws an error and abort the formatting of the template literal.