Skip to content

Commit ed61821

Browse files
authored
Properly optimize universal defaults for legacy pseudo-element syntax (#5594)
1 parent 991a598 commit ed61821

File tree

2 files changed

+87
-1
lines changed

2 files changed

+87
-1
lines changed

src/lib/resolveDefaultsAtRules.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,25 @@ import postcss from 'postcss'
22
import selectorParser from 'postcss-selector-parser'
33
import { flagEnabled } from '../featureFlags'
44

5+
function isPseudoElement(n) {
6+
if (n.type !== 'pseudo') {
7+
return false
8+
}
9+
10+
return (
11+
n.value.startsWith('::') ||
12+
[':before', ':after', ':first-line', ':first-letter'].includes(n.value)
13+
)
14+
}
15+
516
function minimumImpactSelector(nodes) {
617
let rest = nodes
718
// Keep all pseudo & combinator types (:not([hidden]) ~ :not([hidden]))
819
.filter((n) => n.type === 'pseudo' || n.type === 'combinator')
920
// Remove leading pseudo's (:hover, :focus, ...)
1021
.filter((n, idx, all) => {
1122
// Keep pseudo elements
12-
if (n.type === 'pseudo' && n.value.startsWith('::')) return true
23+
if (isPseudoElement(n)) return true
1324

1425
if (idx === 0 && n.type === 'pseudo') return false
1526
if (idx > 0 && n.type === 'pseudo' && all[idx - 1].type === 'pseudo') return false

tests/resolve-defaults-at-rules.test.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,81 @@ test('with apply', async () => {
391391
})
392392
})
393393

394+
test('legacy pseudo-element syntax is supported', async () => {
395+
let config = {
396+
experimental: { optimizeUniversalDefaults: true },
397+
content: [{ raw: html`<div class="foo"></div>` }],
398+
corePlugins: ['transform', 'scale', 'rotate', 'skew'],
399+
}
400+
401+
let input = css`
402+
@tailwind base;
403+
/* --- */
404+
@tailwind utilities;
405+
406+
.a:before {
407+
content: '';
408+
@apply rotate-45;
409+
}
410+
411+
.b:after {
412+
content: '';
413+
@apply rotate-3;
414+
}
415+
416+
.c:first-line {
417+
content: '';
418+
@apply rotate-1;
419+
}
420+
421+
.d:first-letter {
422+
content: '';
423+
@apply rotate-6;
424+
}
425+
`
426+
427+
return run(input, config).then((result) => {
428+
expect(result.css).toMatchFormattedCss(css`
429+
.a:before,
430+
.b:after,
431+
.c:first-line,
432+
.d:first-letter {
433+
--tw-translate-x: 0;
434+
--tw-translate-y: 0;
435+
--tw-rotate: 0;
436+
--tw-skew-x: 0;
437+
--tw-skew-y: 0;
438+
--tw-scale-x: 1;
439+
--tw-scale-y: 1;
440+
--tw-transform: translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y))
441+
rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
442+
scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
443+
}
444+
/* --- */
445+
.a:before {
446+
content: '';
447+
--tw-rotate: 45deg;
448+
transform: var(--tw-transform);
449+
}
450+
.b:after {
451+
content: '';
452+
--tw-rotate: 3deg;
453+
transform: var(--tw-transform);
454+
}
455+
.c:first-line {
456+
content: '';
457+
--tw-rotate: 1deg;
458+
transform: var(--tw-transform);
459+
}
460+
.d:first-letter {
461+
content: '';
462+
--tw-rotate: 6deg;
463+
transform: var(--tw-transform);
464+
}
465+
`)
466+
})
467+
})
468+
394469
test('with borders', async () => {
395470
let config = {
396471
content: [{ raw: html`<div class="border border-red-500 md:border-2"></div>` }],

0 commit comments

Comments
 (0)