Skip to content

Commit 2c23b8d

Browse files
committed
Eliminate irrelevant rules when applying variants (#12113)
* Eliminate irrelevant rules when applying variants * Update changelog
1 parent 17c7609 commit 2c23b8d

File tree

4 files changed

+62
-2
lines changed

4 files changed

+62
-2
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2222
- Skip over classes inside `:not(…)` when nested in an at-rule ([#12105](https://github.com/tailwindlabs/tailwindcss/pull/12105))
2323
- Update types to work with `Node16` module resolution ([#12097](https://github.com/tailwindlabs/tailwindcss/pull/12097))
2424
- Don’t crash when important and parent selectors are equal in `@apply` ([#12112](https://github.com/tailwindlabs/tailwindcss/pull/12112))
25+
- Eliminate irrelevant rules when applying variants ([#12113](https://github.com/tailwindlabs/tailwindcss/pull/12113))
2526

2627
## [3.3.3] - 2023-07-13
2728

src/lib/generateRules.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -820,10 +820,19 @@ function applyFinalFormat(match, { context, candidate }) {
820820
}
821821

822822
try {
823-
rule.selector = finalizeSelector(rule.selector, finalFormat, {
824-
candidate: original,
823+
let selector = finalizeSelector(rule.selector, finalFormat, {
824+
candidate,
825825
context,
826826
})
827+
828+
// Finalize Selector determined that this candidate is irrelevant
829+
// TODO: This elimination should happen earlier so this never happens
830+
if (selector === null) {
831+
rule.remove()
832+
return
833+
}
834+
835+
rule.selector = selector
827836
} catch {
828837
// If this selector is invalid we also want to skip it
829838
// But it's likely that being invalid here means there's a bug in a plugin rather than too loosely matching content

src/util/formatVariantSelector.js

+7
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,13 @@ export function finalizeSelector(current, formats, { context, candidate, base })
186186
// Remove extraneous selectors that do not include the base candidate
187187
selector.each((sel) => eliminateIrrelevantSelectors(sel, base))
188188

189+
// If ffter eliminating irrelevant selectors, we end up with nothing
190+
// Then the whole "rule" this is associated with does not need to exist
191+
// We use `null` as a marker value for that case
192+
if (selector.length === 0) {
193+
return null
194+
}
195+
189196
// If there are no formats that means there were no variants added to the candidate
190197
// so we can just return the selector as-is
191198
let formatAst = Array.isArray(formats)

tests/basic-usage.test.js

+43
Original file line numberDiff line numberDiff line change
@@ -1112,3 +1112,46 @@ crosscheck(({ stable, oxide, engine }) => {
11121112
expect(result.css).toMatchFormattedCss(css``)
11131113
})
11141114
})
1115+
1116+
test('Irrelevant rules are removed when applying variants', async () => {
1117+
let config = {
1118+
content: [
1119+
{
1120+
raw: html` <div class="md:w-full"></div> `,
1121+
},
1122+
],
1123+
corePlugins: { preflight: false },
1124+
plugins: [
1125+
function ({ addUtilities }) {
1126+
addUtilities({
1127+
'@supports (foo: bar)': {
1128+
// This doesn't contain `w-full` so it should not exist in the output
1129+
'.outer': { color: 'red' },
1130+
'.outer:is(.w-full)': { color: 'green' },
1131+
},
1132+
})
1133+
},
1134+
],
1135+
}
1136+
1137+
let input = css`
1138+
@tailwind utilities;
1139+
`
1140+
1141+
// We didn't find the hand class therefore
1142+
// nothing should be generated
1143+
let result = await run(input, config)
1144+
1145+
expect(result.css).toMatchFormattedCss(css`
1146+
@media (min-width: 768px) {
1147+
.md\:w-full {
1148+
width: 100%;
1149+
}
1150+
@supports (foo: bar) {
1151+
.outer.md\:w-full {
1152+
color: green;
1153+
}
1154+
}
1155+
}
1156+
`)
1157+
})

0 commit comments

Comments
 (0)