Not 100% convinced this is a net positive change, but I regret not having done things this way at the beginning.
In 0.x, we pass the `separator` and `className` values already escaped, so `:` comes through as `\:` for example, and `w-1/2` comes through as `w-1\/2`.
At first this sounds fine, less work for the plugin author right? But CSS escaping rules are kind of complicated and you have to escape characters differently depending on whether or not they are at the start of an identifier.
For example, it's totally fine for a class to contain a zero (`0` ), but it can't _start_ with a zero. For a class to start with a zero, it needs to be escaped like this: `\30 `
This means that as a general rule, trying to escape the individual segments of a class separately is a bad idea — you should escape the class as a whole so only the necessary escaping is applied. We break this rule when we pre-escape the separator and className for plugin authors who use the `modifySelectors` function.
We already require users to manually escape class names when they are using `addUtilities` or `addComponents`, so to me it feels more consistent for things to work this way and it's how they should have worked from day one.
Basically this code:
```js
function({ addVariant }) {
addVariant('first-child', ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `.first-child${separator}${className}:first-child`
})
})
},
```
...would need to be re-written like this if I merge this change:
```js
function({ addVariant, e }) {
addVariant('first-child', ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `.${e(`first-child${separator}${className}`)}:first-child`
})
})
},
```
Although I think this is the right way for this to work, I hesitate because it's a breaking change that makes any variant plugins authored for 0.x incompatible with 1.x. It's an easy fix on the plugin author's part, but it's still annoying.
I'm leaning towards merging so I don't regret this even more later when the plugin ecosystem is a lot bigger. Anyone have any thoughts?
When you do something like container.before(someRoot), PostCSS actually *mutates* someRoot, leaving it empty and moving its contents before the container. container.before(arrayOfNodes) on the other hand does no weird mutation.
This PR makes sure generatedUtilities is an array of nodes instead of a PostCSS container to avoid this unexpected mutation. It makes it a bit more work to walk those nodes if they need to be transformed, but I think it's worth the trade-off. Can always write a helper function around that if the boilerplate starts to feel repetitive.
Allows you to write a plugin that registers a new variant but only
allows you to modify the selector (like what our built-in generators
do.)
Next steps are to support variants that wrap rules with at-rules
(like @supports for example), variants that can modify properties
(as opposed to just selectors), and to give variant plugin authors
control over how responsive variants interact with their own variants.
Just for now so that this feature can be introduced into the codebase
without forcing a BC break. The container classes will eventually be
moved to a built-in plugin that adds them as components.