mirror of
https://github.com/resend/react-email.git
synced 2026-09-14 14:18:02 +08:00
fix(tailwind): pseudo selectors (#2963)
Co-authored-by: gabriel miranda <gabrielmfern@outlook.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@react-email/tailwind": patch
|
||||
---
|
||||
|
||||
fix mixed pseudo selectors not being split
|
||||
@@ -112,4 +112,35 @@ describe('extractRulesPerClass()', async () => {
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('treats rules with pseudo-selectors as fully non-inlinable', async () => {
|
||||
const tailwind = await setupTailwind({
|
||||
plugins: [
|
||||
{
|
||||
handler: (api) => {
|
||||
api.addUtilities({
|
||||
'.btn:hover': {
|
||||
color: 'red',
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const classes = ['btn'];
|
||||
tailwind.addUtilities(classes);
|
||||
|
||||
const stylesheet = tailwind.getStyleSheet();
|
||||
const { inlinable, nonInlinable } = extractRulesPerClass(
|
||||
stylesheet,
|
||||
classes,
|
||||
);
|
||||
|
||||
expect(convertToComparable(inlinable)).toMatchInlineSnapshot('{}');
|
||||
expect(convertToComparable(nonInlinable)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"btn": ".btn{&:hover{color:red}}",
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { type CssNode, clone, List, type Rule } from 'css-tree';
|
||||
import { type CssNode, clone, find, List, type Rule } from 'css-tree';
|
||||
import { isPartInlinable } from './is-part-inlinable';
|
||||
|
||||
/**
|
||||
@@ -12,6 +12,22 @@ export function splitMixedRule(rule: Rule): {
|
||||
inlinablePart: Rule | null;
|
||||
nonInlinablePart: Rule | null;
|
||||
} {
|
||||
// If the selector itself contains pseudo-selectors, every declaration in the
|
||||
// block only applies in that pseudo context — splitting would incorrectly
|
||||
// inline them as base styles. Return the whole rule as non-inlinable.
|
||||
const selectorHasPseudo =
|
||||
rule.prelude !== null &&
|
||||
find(
|
||||
rule.prelude,
|
||||
(node) =>
|
||||
node.type === 'PseudoClassSelector' ||
|
||||
node.type === 'PseudoElementSelector',
|
||||
) !== null;
|
||||
|
||||
if (selectorHasPseudo) {
|
||||
return { inlinablePart: null, nonInlinablePart: clone(rule) as Rule };
|
||||
}
|
||||
|
||||
const ruleCloneInlinable = clone(rule) as Rule;
|
||||
const ruleCloneNonInlinable = clone(rule) as Rule;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user