Andarist / stylis-plugin-extra-scope

Stylis plugin which adds extra scope to each produced CSS rule.
MIT License
23 stars 14 forks source link

Stylis V4 compatibility #11

Closed tpict closed 2 years ago

tpict commented 3 years ago

Adds compatibility for Stylis V4.

I've added an explicit check for @keyframes. Are there any other at-rules whose properties should be exempt from extra scoping?

Andarist commented 3 years ago

Thank you for the PR - I'll try to review this somewhat soon, but truth to be told this requires some focus and this is not on the top of my priority list so it might take me some time to get back to it.

tpict commented 3 years ago

This implementation causes weird issues with the & selector when used in conjunction with Emotion 11. After updating the scope of a node, child nodes that use & already have the new scope in their props, e.g. when traversing

.some-class {
  &.something-else {
   ...

the parent node is modified to #my-extra-scope .some-class, and when the child node is visited it's already been expanded to #my-extra-scope .some-class.something-else, so this code adds a duplicate #my-extra-scope selector.

I tried to remedy this by keeping track of modified parent nodes in a WeakSet and skipping their descendants, but not all selectors are expanded when they're visited, so they wind up without any extra scoping at all. Furthermore, the expansion doesn't seem to happen with Stylis alone, only when using Emotion, so I'm not even sure how to test for this.

Andarist commented 3 years ago

I would literally set up tests with Emotion here to test this. I'm not sure why Emotion would make it to affect children. Nodes are actually generated by Stylis and while some object references are shared within the "tree" the generated rules should not be affected like this. Maybe it's the compat plugin's fault? Nothing comes to my mind that would affect this for the case you have presented but it seems like the most likely culprit.

tpict commented 3 years ago

Thanks for the lead! Placing this plugin ahead of compat does fix the issue.

Looking at the Stylis source code, it appears that each node passes through each plugin before moving on to the next node. The compat plugin is combining the current selector onto its parent, which already has the extra scope, hence the duplication. I guess I need to implement the opposite of the logic in compat to skip nodes that have already been joined to their parent.

hasanavi commented 3 years ago

The latest version of @emotion/react doesn't work from the master branch - is this PR going to be merged soon?

luzannew commented 3 years ago

I can confirm this PR is working fine together with styled-components v5.2.1 which is using v4 of stylis.

Andarist commented 3 years ago

Styled Components v5 is not using Stylis v4 yet: https://github.com/styled-components/styled-components/blob/v5.2.1/packages/styled-components/package.json#L69

luzannew commented 3 years ago

Oh strange. looks like on the master branch they are using it: https://github.com/styled-components/styled-components/blob/master/packages/styled-components/package.json#L73

So I'm not sure from which branch they released v5.2.1

rr-justin-hanselman commented 3 years ago

Hello,

I was just wondering what the blockers are for this plugin fix? From the comments, the problems seem to be resolved?

Andarist commented 3 years ago

the main blocker is my lack of time to focus on this one

rr-justin-hanselman commented 3 years ago

Is there anything more external users (like myself) can do to help you? Or is just a matter of the repo owner finishing the PR vetting + release?

For now, I've just copied the potential changes and am using them in a local lib file, but I would love to seem them as part of the normal npm registry!

Andarist commented 3 years ago

If you could recheck the implementation - preferably with some notes on why it is written in a way that it is written - this would help a lot. I suspect that this version might not work properly with nested at rules but I have also not checked it.

In general, I'm not confident with merging this without understanding the thought process behind this implementation. I'm not saying that it's incorrect or wrong - it's just that Stylis plugins are quite tricky to get right.

Preparing PR that would merge master to this branch would also be helpful as this has some conflicts right now.

evantd commented 3 years ago

Re:

Nodes are actually generated by Stylis and while some object references are shared within the "tree" the generated rules should not be affected like this. Maybe it's the compat plugin's fault?

This comment in the compat plugin seems suspicious:

  // if this is an implicitly inserted rule (the one eagerly inserted at the each new nested level)
  // then the props has already been manipulated beforehand as they that array is shared between it and its "rule parent"
nelsondude commented 3 years ago

Is there any update on the status of this PR? Would be great to get this plugin updated.

iampava commented 3 years ago

Any updates on this?

tpict commented 2 years ago

Going to close this out in favour of #14