Skip to content

Commit e37b665

Browse files
committed
Support applying classes that occur multiple times in a single selector
1 parent 6fe745b commit e37b665

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

__tests__/applyComplexClasses.test.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,38 @@ test('it matches classes that have multiple rules', () => {
247247
})
248248
})
249249

250+
test('applying a class that appears multiple times in one selector', () => {
251+
const input = `
252+
.a + .a > .a {
253+
color: red;
254+
}
255+
256+
.b {
257+
@apply a;
258+
}
259+
`
260+
261+
const output = `
262+
.a + .a > .a {
263+
color: red;
264+
}
265+
.b + .a > .a {
266+
color: red;
267+
}
268+
.a + .b > .a {
269+
color: red;
270+
}
271+
.a + .a > .b {
272+
color: red;
273+
}
274+
`
275+
276+
return run(input).then(result => {
277+
expect(result.css).toMatchCss(output)
278+
expect(result.warnings().length).toBe(0)
279+
})
280+
})
281+
250282
test('you can apply utility classes that do not actually exist as long as they would exist if utilities were being generated', () => {
251283
const input = `
252284
.foo { @apply mt-4; }

src/flagged/applyComplexClasses.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ function hasAtRule(css, atRule) {
2020
return foundAtRule
2121
}
2222

23-
function applyUtility(rule, className, replaceWith) {
23+
function applyUtility({ rule, utilityName: className, classPosition }, replaceWith) {
2424
const processedSelectors = rule.selectors.map(selector => {
2525
const processor = selectorParser(selectors => {
26+
let i = 0
2627
selectors.walkClasses(c => {
27-
if (c.value === className) {
28+
if (c.value === className && classPosition === i) {
2829
c.replaceWith(selectorParser.attribute({ attribute: '__TAILWIND-APPLY-PLACEHOLDER__' }))
2930
}
31+
i++
3032
})
3133
})
3234

@@ -78,14 +80,15 @@ function buildUtilityMap(css) {
7880
css.walkRules(rule => {
7981
const utilityNames = extractUtilityNames(rule.selector)
8082

81-
utilityNames.forEach(utilityName => {
83+
utilityNames.forEach((utilityName, i) => {
8284
if (utilityMap[utilityName] === undefined) {
8385
utilityMap[utilityName] = []
8486
}
8587

8688
utilityMap[utilityName].push({
8789
index,
8890
utilityName,
91+
classPosition: i,
8992
rule: rule.clone({ parent: rule.parent }),
9093
containsApply: hasAtRule(rule, 'apply'),
9194
})
@@ -205,7 +208,7 @@ function processApplyAtRules(css, lookupTree, config) {
205208
// Get new rules with the utility portion of the selector replaced with the new selector
206209
const rulesToInsert = [
207210
...injects.map(injectUtility => {
208-
return applyUtility(injectUtility.rule, injectUtility.utilityName, rule.selector)
211+
return applyUtility(injectUtility, rule.selector)
209212
}),
210213
afterRule,
211214
]

0 commit comments

Comments
 (0)