-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Description
What version of Tailwind CSS are you using?
3.0.16
What build tool (or framework if it abstracts the build tool) are you using?
postcss-cli 9.1.0
What version of Node.js are you using?
17.x
Reproduction URL
See the reproduction in 43081j/postcss-lit#26
postcss recently introduced the concept of a "document". This allows custom syntaxes to be written for it which represent their arbitrary AST as the document, containing one or more Root nodes which are the actual CSS from said document.
For example, CSS in JS solutions would result in a Document representing the JS file, and one or more Root representing the contained stylesheets.
When combined with tailwind, this works like so:
- postcss executes the custom syntax against the file, resolving to a postcss-compatible AST
- postcss executes tailwind on this AST (
Document { nodes: [Root, Root] }at this point)
Tailwind then executes code like this to replace the at-rules:
tailwindcss/src/lib/expandTailwindAtRules.js
Lines 206 to 209 in 490c9dc
| if (layerNodes.base) { | |
| layerNodes.base.before(cloneNodes([...baseNodes, ...defaultNodes], layerNodes.base.source)) | |
| layerNodes.base.remove() | |
| } |
This works because layerNode.base.parent is one of the child Root nodes. So by calling before, we're prepending child nodes to the Root, not the Document (GOOD).
However, we can then reach this:
tailwindcss/src/lib/expandTailwindAtRules.js
Lines 239 to 241 in 490c9dc
| } else if (variantNodes.length > 0) { | |
| root.append(cloneNodes(variantNodes, root.source)) | |
| } |
Which, as you see, will append explicitly to root: the Document in this case.
This will result in an AST like so:
Document {
nodes: [
Root,
Root,
Rule, // BAD NODE!
]
}When a custom syntax then attempts to stringify the AST back to the original non-css document, this misplaced Rule will be thrown on the end... causing a syntax error in the output.
Solution?
I don't know tailwind's source well enough to suggest a solution here. Possibly, if any layerNodes.* exists, use its parent as the root. If none exist, fall back to what it does now?
Or is there maybe an existing way to explicitly mark where those rules should exist? wherever layerNodes.variants comes from. Can we simply put some at-rule like @tailwindvariants?
Until this is fixed, custom postcss syntaxes can't really work with "variant rules".