Skip to content

Commit

Permalink
ensure apply of rule inside atrule works
Browse files Browse the repository at this point in the history
If that atrule happens to contain another rule that is technically
unrelated.

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
  • Loading branch information
RobinMalfait and thecrypticace committed Dec 17, 2021
1 parent 9e03a68 commit 9f4be07
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 0 deletions.
36 changes: 36 additions & 0 deletions src/lib/expandApplyAtRules.js
Expand Up @@ -266,6 +266,42 @@ function processApply(root, context) {

if (canRewriteSelector) {
root.walkRules((rule) => {
// Let's imagine you have the following structure:
//
// .foo {
// @apply bar;
// }
//
// @supports (a: b) {
// .bar {
// color: blue
// }
//
// .something-unrelated {}
// }
//
// In this case we want to apply `.bar` but it happens to be in
// an atrule node. We clone that node instead of the nested one
// because we still want that @supports rule to be there once we
// applied everything.
//
// However it happens to be that the `.something-unrelated` is
// also in that same shared @supports atrule. This is not good,
// and this should not be there. The good part is that this is
// a clone already and it can be safely removed. The question is
// how do we know we can remove it. Basically what we can do is
// match it agaisnt the applyCandidate that you want to apply. If
// it doesn't match the we can safely delete it.
//
// If we didn't do this, then the `replaceSelector` function
// would have replaced this with something that didn't exist and
// therefore it removed the selector altogether. In this specific
// case it would result in `{}` instead of `.something-unrelated {}`
if (!extractClasses(rule).some((thing) => thing === applyCandidate)) {
rule.remove()
return
}

rule.selector = replaceSelector(parent.selector, rule.selector, applyCandidate)

rule.walkDecls((d) => {
Expand Down
62 changes: 62 additions & 0 deletions tests/apply.test.js
Expand Up @@ -712,3 +712,65 @@ it('should not be possible to apply user css with variants', () => {
)
})
})

it('should not apply unrelated siblings when applying something from within atrules', () => {
let config = {
content: [{ raw: html`<div class="foo bar something-unrelated"></div>` }],
plugins: [],
}

let input = css`
@tailwind components;
@tailwind utilities;
@layer components {
.foo {
font-weight: bold;
@apply bar;
}
.bar {
color: green;
}
@supports (a: b) {
.bar {
color: blue;
}
.something-unrelated {
color: red;
}
}
}
`

return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
.foo {
font-weight: bold;
color: green;
}
@supports (a: b) {
.foo {
color: blue;
}
}
.bar {
color: green;
}
@supports (a: b) {
.bar {
color: blue;
}
.something-unrelated {
color: red;
}
}
`)
})
})

0 comments on commit 9f4be07

Please sign in to comment.