Skip to content

Commit 9f4be07

Browse files
ensure apply of rule inside atrule works
If that atrule happens to contain another rule that is technically unrelated. Co-authored-by: Jordan Pittman <[email protected]>
1 parent 9e03a68 commit 9f4be07

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

src/lib/expandApplyAtRules.js

+36
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,42 @@ function processApply(root, context) {
266266

267267
if (canRewriteSelector) {
268268
root.walkRules((rule) => {
269+
// Let's imagine you have the following structure:
270+
//
271+
// .foo {
272+
// @apply bar;
273+
// }
274+
//
275+
// @supports (a: b) {
276+
// .bar {
277+
// color: blue
278+
// }
279+
//
280+
// .something-unrelated {}
281+
// }
282+
//
283+
// In this case we want to apply `.bar` but it happens to be in
284+
// an atrule node. We clone that node instead of the nested one
285+
// because we still want that @supports rule to be there once we
286+
// applied everything.
287+
//
288+
// However it happens to be that the `.something-unrelated` is
289+
// also in that same shared @supports atrule. This is not good,
290+
// and this should not be there. The good part is that this is
291+
// a clone already and it can be safely removed. The question is
292+
// how do we know we can remove it. Basically what we can do is
293+
// match it agaisnt the applyCandidate that you want to apply. If
294+
// it doesn't match the we can safely delete it.
295+
//
296+
// If we didn't do this, then the `replaceSelector` function
297+
// would have replaced this with something that didn't exist and
298+
// therefore it removed the selector altogether. In this specific
299+
// case it would result in `{}` instead of `.something-unrelated {}`
300+
if (!extractClasses(rule).some((thing) => thing === applyCandidate)) {
301+
rule.remove()
302+
return
303+
}
304+
269305
rule.selector = replaceSelector(parent.selector, rule.selector, applyCandidate)
270306

271307
rule.walkDecls((d) => {

tests/apply.test.js

+62
Original file line numberDiff line numberDiff line change
@@ -712,3 +712,65 @@ it('should not be possible to apply user css with variants', () => {
712712
)
713713
})
714714
})
715+
716+
it('should not apply unrelated siblings when applying something from within atrules', () => {
717+
let config = {
718+
content: [{ raw: html`<div class="foo bar something-unrelated"></div>` }],
719+
plugins: [],
720+
}
721+
722+
let input = css`
723+
@tailwind components;
724+
@tailwind utilities;
725+
726+
@layer components {
727+
.foo {
728+
font-weight: bold;
729+
@apply bar;
730+
}
731+
732+
.bar {
733+
color: green;
734+
}
735+
736+
@supports (a: b) {
737+
.bar {
738+
color: blue;
739+
}
740+
741+
.something-unrelated {
742+
color: red;
743+
}
744+
}
745+
}
746+
`
747+
748+
return run(input, config).then((result) => {
749+
expect(result.css).toMatchFormattedCss(css`
750+
.foo {
751+
font-weight: bold;
752+
color: green;
753+
}
754+
755+
@supports (a: b) {
756+
.foo {
757+
color: blue;
758+
}
759+
}
760+
761+
.bar {
762+
color: green;
763+
}
764+
765+
@supports (a: b) {
766+
.bar {
767+
color: blue;
768+
}
769+
770+
.something-unrelated {
771+
color: red;
772+
}
773+
}
774+
`)
775+
})
776+
})

0 commit comments

Comments
 (0)