From 35325a45e48ae58cd305df447e6e054419377681 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 15 Aug 2022 11:50:32 -0400 Subject: [PATCH] Sort tag names before class names when rewriting selectors --- src/lib/expandApplyAtRules.js | 14 +++++++++ tests/apply.test.js | 56 +++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/lib/expandApplyAtRules.js b/src/lib/expandApplyAtRules.js index 97f97a98d3e0..dd6aee28db63 100644 --- a/src/lib/expandApplyAtRules.js +++ b/src/lib/expandApplyAtRules.js @@ -332,6 +332,20 @@ function processApply(root, context, localCache) { }) }) + // Sort tag names before class names + // 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 + } + + return sel.index(a) - sel.index(b) + }) + } + sel.replaceWith(...replaced) }) diff --git a/tests/apply.test.js b/tests/apply.test.js index ee7d567bb659..3108806f8e80 100644 --- a/tests/apply.test.js +++ b/tests/apply.test.js @@ -1585,6 +1585,62 @@ it('can apply user utilities that start with a dash', async () => { `) }) +it('can apply joined classes when using elements', async () => { + let config = { + content: [{ raw: html`
` }], + plugins: [], + } + + let input = css` + .foo.bar { + color: red; + } + .bar.foo { + color: green; + } + header { + @apply foo; + } + main { + @apply foo bar; + } + footer { + @apply bar; + } + ` + + let result = await run(input, config) + + expect(result.css).toMatchFormattedCss(css` + .foo.bar { + color: red; + } + .bar.foo { + color: green; + } + header.bar { + color: red; + color: green; + } + main.bar { + color: red; + } + main.foo { + color: red; + } + main.bar { + color: green; + } + main.foo { + color: green; + } + footer.foo { + color: red; + color: green; + } + `) +}) + it('can produce selectors that replace multiple instances of the same class', async () => { let config = { content: [{ raw: html`
` }],