Skip to content

Commit

Permalink
Fix incorrect selectors when using @apply in selectors with combina…
Browse files Browse the repository at this point in the history
…tors and pseudos (#9722)

* sort tags, classes and pseudos per group (separated by combinators)

* use default behaviour of sort

* update changelog
  • Loading branch information
RobinMalfait committed Nov 3, 2022
1 parent c10ba4e commit d33b650
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix merging of arrays during config resolution ([#9706](https://github.com/tailwindlabs/tailwindcss/issues/9706))
- Ensure configured `font-feature-settings` are included in Preflight ([#9707](https://github.com/tailwindlabs/tailwindcss/pull/9707))
- Fix fractional values not being parsed properly inside arbitrary properties ([#9705](https://github.com/tailwindlabs/tailwindcss/pull/9705))
- Fix incorrect selectors when using `@apply` in selectors with combinators and pseudos ([#9722](https://github.com/tailwindlabs/tailwindcss/pull/9722))

## [3.2.1] - 2022-10-21

Expand Down
50 changes: 35 additions & 15 deletions src/lib/expandApplyAtRules.js
Expand Up @@ -346,22 +346,42 @@ function processApply(root, context, localCache) {
})
})

// Sort tag names before class names
// Sort tag names before class names (but only sort each group (separated by a combinator)
// separately and not in total)
// This happens when replacing `.bar` in `.foo.bar` with a tag like `section`
for (const sel of replaced) {
sel.sort((a, b) => {
if (a.type === 'tag' && b.type === 'class') {
return -1
} else if (a.type === 'class' && b.type === 'tag') {
return 1
} else if (a.type === 'class' && b.type === 'pseudo') {
return -1
} else if (a.type === 'pseudo' && b.type === 'class') {
return 1
for (let sel of replaced) {
let groups = [[]]
for (let node of sel.nodes) {
if (node.type === 'combinator') {
groups.push(node)
groups.push([])
} else {
let last = groups[groups.length - 1]
last.push(node)
}
}

return sel.index(a) - sel.index(b)
})
sel.nodes = []

for (let group of groups) {
if (Array.isArray(group)) {
group.sort((a, b) => {
if (a.type === 'tag' && b.type === 'class') {
return -1
} else if (a.type === 'class' && b.type === 'tag') {
return 1
} else if (a.type === 'class' && b.type === 'pseudo') {
return -1
} else if (a.type === 'pseudo' && b.type === 'class') {
return 1
}

return 0
})
}

sel.nodes = sel.nodes.concat(group)
}
}

sel.replaceWith(...replaced)
Expand All @@ -382,7 +402,7 @@ function processApply(root, context, localCache) {

if (apply.parent.type === 'atrule') {
if (apply.parent.name === 'screen') {
const screenType = apply.parent.params
let screenType = apply.parent.params

throw apply.error(
`@apply is not supported within nested at-rules like @screen. We suggest you write this as @apply ${applyCandidates
Expand Down Expand Up @@ -414,7 +434,7 @@ function processApply(root, context, localCache) {
}
}

for (const [parent, [candidates, atApplySource]] of perParentApplies) {
for (let [parent, [candidates, atApplySource]] of perParentApplies) {
let siblings = []

for (let [applyCandidate, important, rules] of candidates) {
Expand Down
50 changes: 50 additions & 0 deletions tests/apply.test.js
Expand Up @@ -1691,3 +1691,53 @@ it('should not replace multiple instances of the same class in a single selector
}
`)
})

it('should maintain the correct selector when applying other utilities', () => {
let config = {
content: [
{
raw: html`
<div>
<div class="check"></div>
</div>
`,
},
],
}

let input = css`
@tailwind utilities;
.foo:hover.bar .baz {
@apply bg-black;
color: red;
}
.foo:hover.bar > .baz {
@apply bg-black;
color: red;
}
`

return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
.foo.bar:hover .baz {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
}
.foo:hover.bar .baz {
color: red;
}
.foo.bar:hover > .baz {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
}
.foo:hover.bar > .baz {
color: red;
}
`)
})
})

0 comments on commit d33b650

Please sign in to comment.