mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Fix incorrect selectors when using @apply in selectors with combinators and pseudos (#9722)
* sort tags, classes and pseudos per group (separated by combinators) * use default behaviour of sort * update changelog
This commit is contained in:
parent
c10ba4e9ba
commit
d33b6503ea
@ -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
|
||||
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
return sel.index(a) - sel.index(b)
|
||||
})
|
||||
sel.nodes = sel.nodes.concat(group)
|
||||
}
|
||||
}
|
||||
|
||||
sel.replaceWith(...replaced)
|
||||
@ -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
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
`)
|
||||
})
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user