Skip to content

Commit 7924e7b

Browse files
committed
Don’t replace all instances of the same class
This isn’t 100% correct either so we’re backing out this change
1 parent ef74fd3 commit 7924e7b

File tree

3 files changed

+25
-5
lines changed

3 files changed

+25
-5
lines changed

CHANGELOG.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717

1818
- Use absolute paths when resolving changed files for resilience against working directory changes ([#9032](https://github.com/tailwindlabs/tailwindcss/pull/9032))
1919
- Fix ring color utility generation when using `respectDefaultRingColorOpacity` ([#9070](https://github.com/tailwindlabs/tailwindcss/pull/9070))
20-
- Replace all occurrences of a class in a selector when using `@apply` ([#9107](https://github.com/tailwindlabs/tailwindcss/pull/9107))
2120
- Sort tags before classes when `@applying` a selector with joined classes ([#9107](https://github.com/tailwindlabs/tailwindcss/pull/9107))
2221

2322
## [3.1.8] - 2022-08-05

src/lib/expandApplyAtRules.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,20 +315,36 @@ function processApply(root, context, localCache) {
315315
let replaced = new Set()
316316

317317
utilitySelectorsList.each((utilitySelector) => {
318+
let hasReplaced = false
318319
utilitySelector = utilitySelector.clone()
319320

320321
utilitySelector.walkClasses((node) => {
321322
if (node.value !== candidateClass.value) {
322323
return
323324
}
324325

326+
// Don't replace multiple instances of the same class
327+
// This is theoretically correct but only partially
328+
// We'd need to generate every possible permutation of the replacement
329+
// For example with `.foo + .foo { … }` and `section { @apply foo; }`
330+
// We'd need to generate all of these:
331+
// - `.foo + .foo`
332+
// - `.foo + section`
333+
// - `section + .foo`
334+
// - `section + section`
335+
if (hasReplaced) {
336+
return
337+
}
338+
325339
// Since you can only `@apply` class names this is sufficient
326340
// We want to replace the matched class name with the selector the user is using
327341
// Ex: Replace `.text-blue-500` with `.foo.bar:is(.something-cool)`
328342
node.replaceWith(...sel.nodes.map((node) => node.clone()))
329343

330344
// Record that we did something and we want to use this new selector
331345
replaced.add(utilitySelector)
346+
347+
hasReplaced = true
332348
})
333349
})
334350

tests/apply.test.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,7 +1641,10 @@ it('can apply joined classes when using elements', async () => {
16411641
`)
16421642
})
16431643

1644-
it('can produce selectors that replace multiple instances of the same class', async () => {
1644+
it('should not replace multiple instances of the same class in a single selector', async () => {
1645+
// NOTE: This test is non-normative and is not part of the spec of how `@apply` works per-se
1646+
// It describes how it currently works because the "correct" way produces a combinatorial explosion
1647+
// of selectors that is not easily doable
16451648
let config = {
16461649
content: [{ raw: html`<div class="foo-1 -foo-1 new-class"></div>` }],
16471650
plugins: [],
@@ -1674,14 +1677,16 @@ it('can produce selectors that replace multiple instances of the same class', as
16741677
.bar + .bar {
16751678
color: fuchsia;
16761679
}
1677-
header + header {
1680+
header + .foo {
16781681
color: blue;
16791682
}
1680-
main + main {
1683+
main + .foo {
16811684
color: blue;
1685+
}
1686+
main + .bar {
16821687
color: fuchsia;
16831688
}
1684-
footer + footer {
1689+
footer + .bar {
16851690
color: fuchsia;
16861691
}
16871692
`)

0 commit comments

Comments
 (0)