Skip to content

Commit

Permalink
fix(transformer-directives): resolve selector group (#3485)
Browse files Browse the repository at this point in the history
  • Loading branch information
zoeyzhao19 committed Jan 25, 2024
1 parent cb0849a commit e5c1f9a
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 12 deletions.
28 changes: 16 additions & 12 deletions packages/transformer-directives/src/apply.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { StringifiedUtil } from '@unocss/core'
import { expandVariantGroup, notNull, regexScopePlaceholder } from '@unocss/core'
import type { CssNode, Rule, Selector, SelectorList } from 'css-tree'
import { clone, generate, parse } from 'css-tree'
import { List, clone, generate, parse } from 'css-tree'
import type { TransformerDirectivesContext } from '.'
import { transformDirectives } from '.'

Expand Down Expand Up @@ -63,24 +63,28 @@ export async function parseApply({ code, uno, offset, applyVariable }: Transform

for (const i of utils) {
const [, _selector, body, parent] = i
const selector = _selector?.replace(regexScopePlaceholder, ' ') || _selector
const selectorOrGroup = _selector?.replace(regexScopePlaceholder, ' ') || _selector

if (parent || (selector && selector !== '.\\-')) {
if (parent || (selectorOrGroup && selectorOrGroup !== '.\\-')) {
let newSelector = generate(node.prelude)
if (selector && selector !== '.\\-') {
const selectorAST = parse(selector, {
context: 'selector',
}) as Selector
if (selectorOrGroup && selectorOrGroup !== '.\\-') {
// use rule context since it could be a selector(.foo) or a selector group(.foo, .bar)
const ruleAST = parse(`${selectorOrGroup}{}`, {
context: 'rule',
}) as Rule

const prelude = clone(node.prelude) as SelectorList

prelude.children.forEach((child) => {
const parentSelectorAst = clone(selectorAST) as Selector
parentSelectorAst.children.forEach((i) => {
if (i.type === 'ClassSelector' && i.name === '\\-')
Object.assign(i, clone(child))
const selectorListAst = clone(ruleAST.prelude) as SelectorList
const classSelectors: List<CssNode> = new List()

selectorListAst.children.forEach((selectorAst) => {
classSelectors.appendList((selectorAst as Selector).children.filter(i => i.type === 'ClassSelector' && i.name === '\\-'))
})
Object.assign(child, parentSelectorAst)
classSelectors.forEach(i => Object.assign(i, clone(child)))

Object.assign(child, selectorListAst)
})
newSelector = generate(prelude)
}
Expand Down
30 changes: 30 additions & 0 deletions test/transformer-directives.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ describe('transformer-directives', () => {
xxl: '1536px',
},
},
variants: [
(matcher) => {
const prefix = 'sgroup:' // selector group

if (!matcher.startsWith(prefix))
return matcher

return {
matcher: matcher.slice(prefix.length),
selector: s => `${s}:hover, ${s}:focus`,
}
},
],
})

async function transform(code: string, _uno: UnoGenerator = uno) {
Expand Down Expand Up @@ -529,4 +542,21 @@ div {
"
`)
})

it('@apply selector group', async () => {
const result = await transform(
'.btn { @apply: sgroup:bg-orange }',
)
expect(result)
.toMatchInlineSnapshot(`
".btn {
}
.btn:hover,
.btn:focus {
--un-bg-opacity: 1;
background-color: rgb(251 146 60 / var(--un-bg-opacity));
}
"
`)
})
})

0 comments on commit e5c1f9a

Please sign in to comment.