-
Notifications
You must be signed in to change notification settings - Fork 65
fix: handle nesting in comma separated selectors #207
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
6799698 to
058744f
Compare
📊 Bundle size reportUnchanged fixtures
|
058744f to
27c7266
Compare
| expect( | ||
| compileCSS({ | ||
| ...defaultOptions, | ||
| pseudo: ':global(body) &', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original selector is invalid, replaced it with a proper test case.
| // Issues are reported: | ||
| // https://github.com/thysultan/stylis.js/issues/253 | ||
| // https://github.com/thysultan/stylis.js/issues/252 | ||
| if (selector.indexOf(':global(') === 0) { | ||
| // 👇 :global(GROUP_1)GROUP_2 | ||
| const GLOBAL_PSEUDO_REGEX = /global\((.+)\)(.+)?/; | ||
| const result = GLOBAL_PSEUDO_REGEX.exec(selector)!; | ||
|
|
||
| let rtlClassNameSelector: string | null = null; | ||
| let rtlCSSDeclaration: string | null = null; | ||
| globalSelector = result[1] + ' '; | ||
| const restPseudo = result[2] || ''; | ||
|
|
||
| if (rtlProperty && rtlClassName) { | ||
| rtlClassNameSelector = `.${rtlClassName}`; | ||
| rtlCSSDeclaration = Array.isArray(rtlValue) | ||
| ? `{ ${rtlValue.map(v => `${hyphenateProperty(rtlProperty)}: ${v}`).join(';')}; }` | ||
| : `{ ${hyphenateProperty(rtlProperty)}: ${rtlValue}; }`; | ||
| } | ||
| // should be normalized to handle ":global(SELECTOR) &" | ||
| const normalizedPseudoSelector = normalizePseudoSelector(restPseudo); | ||
|
|
||
| let cssRule = ''; | ||
| if (normalizedPseudoSelector === '') { | ||
| return acc; | ||
| } | ||
|
|
||
| // Should be handled by namespace plugin of Stylis, is buggy now | ||
| // Issues are reported: | ||
| // https://github.com/thysultan/stylis.js/issues/253 | ||
| // https://github.com/thysultan/stylis.js/issues/252 | ||
| if (pseudo.indexOf(':global(') === 0) { | ||
| // 👇 :global(GROUP_1)GROUP_2 | ||
| const GLOBAL_PSEUDO_REGEX = /global\((.+)\)(.+)?/; | ||
| const [, globalSelector, restPseudo = ''] = GLOBAL_PSEUDO_REGEX.exec(pseudo)!; | ||
| return `${normalizedPseudoSelector} { ${acc} }`; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved the hack with small changes, will replace it with a Stylis plugin in a follow up PR.
| expect(getStyleBucketName([], '', '', '')).toBe('d'); | ||
| expect(getStyleBucketName(['.foo'], '', '', '')).toBe('d'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New test cases.
| if (selectors.length > 0) { | ||
| const normalizedPseudo = selectors[0].trim(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We take into account only the first pseudo selector, so it's find to use the first element.
| expect( | ||
| resolveStyleRules({ | ||
| ':hover,:focus-within': { | ||
| '::before': { | ||
| color: 'orange', | ||
| }, | ||
| }, | ||
| }), | ||
| ).toMatchInlineSnapshot(` | ||
| .fij4gri:hover::before, | ||
| .fij4gri:focus-within::before { | ||
| color: orange; | ||
| } | ||
| `); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test case from #204.
| it('handles :global selector', () => { | ||
| expect( | ||
| resolveStyleRules({ | ||
| ':global(body) &': { color: 'green' }, | ||
| }), | ||
| ).toMatchInlineSnapshot(` | ||
| body .fm1e7ra { | ||
| color: green; | ||
| } | ||
| `); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again a test that does not have any sense.
| `); | ||
| expect( | ||
| resolveStyleRules({ | ||
| ':global(body):focus': { color: 'pink' }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now spaces are handled (#206).
| it('supports :global as a nested selector', () => { | ||
| expect( | ||
| resolveStyleRules({ | ||
| ':focus': { ':global(body)': { color: 'green' } }, | ||
| }), | ||
| ).toMatchInlineSnapshot(` | ||
| body .fz7er5p:focus { | ||
| color: green; | ||
| } | ||
| `); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As now we have scopes this test surprisingly works 🐱
27c7266 to
737a2a6
Compare
737a2a6 to
280d7fb
Compare
| // https://github.com/thysultan/stylis.js/issues/252 | ||
| if (selector.indexOf(':global(') === 0) { | ||
| // 👇 :global(GROUP_1)GROUP_2 | ||
| const GLOBAL_PSEUDO_REGEX = /global\((.+)\)(.+)?/; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe hoist the regex so it doesn't get created on every iteration ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, but in a followup I will get it of this part anyway (I will replace this part with a stylis plugin).
| className: string; | ||
|
|
||
| pseudo: string; | ||
| selectors: string[]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would the length of selectors ever exceed 2 ? It seems that the only case we are handling here is pseudo selector + element. It shouldn't be possible to go further since it would be invalid css ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please provide an example?

Fixes #204.
Fixes #206.
Changes in selectors handling
In
resolveStyleRules()&compileCSS()I renamedpseudotoselectorsand changed their type to bestring[]:To reflect what it contains as
selectorscan contain not only pseudo selectors.To handle selectors properly as it was a problem without a solution:
Before we were concatenating inputs with selectors and getting
":hover,:focus-within::before"that will be compiled by Stylis to:And without proper wrapping with curly braces we cannot handle it. With selectors as an array with can send as input
:hover,:focus-within { ::before { } }that will be handled properly.Changes in
:global()handlingBecause before we didn't know scopes of selectors we were doing
.trim()and were losing" "in rules (#206):griffel/packages/core/src/runtime/compileCSS.ts
Lines 92 to 93 in 0e358cb
Currently I kept existing hack with
:global()in place to avoid more changes in this PR, but in a follow up - I will replace it with a Stylis plugin.