Skip to content

Commit

Permalink
fix(compiler-sfc): nested css supports atrule and comment (#11899)
Browse files Browse the repository at this point in the history
close #11896
  • Loading branch information
linzhe141 committed Sep 13, 2024
1 parent 706d4ac commit 0e7bc71
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 9 deletions.
32 changes: 32 additions & 0 deletions packages/compiler-sfc/__tests__/compileStyle.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,38 @@ describe('SFC scoped CSS', () => {
)
})

test('nesting selector with atrule and comment', () => {
expect(
compileScoped(
`h1 {
color: red;
/*background-color: pink;*/
@media only screen and (max-width: 800px) {
background-color: green;
.bar { color: white }
}
.foo { color: red; }
}`,
),
).toMatch(
`h1 {
&[data-v-test] {
color: red
/*background-color: pink;*/
}
@media only screen and (max-width: 800px) {
&[data-v-test] {
background-color: green
}
.bar[data-v-test] { color: white
}
}
.foo[data-v-test] { color: red;
}
}`,
)
})

test('multiple selectors', () => {
expect(compileScoped(`h1 .foo, .bar, .baz { color: red; }`)).toMatch(
`h1 .foo[data-v-test], .bar[data-v-test], .baz[data-v-test] { color: red;`,
Expand Down
31 changes: 22 additions & 9 deletions packages/compiler-sfc/src/style/pluginScoped.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,16 +233,12 @@ function rewriteSelector(

if (rule.nodes.some(node => node.type === 'rule')) {
const deep = (rule as any).__deep
const decls = rule.nodes.filter(node => node.type === 'decl')
if (!deep && decls.length) {
for (const decl of decls) {
rule.removeChild(decl)
if (!deep) {
extractAndWrapNodes(rule)
const atruleNodes = rule.nodes.filter(node => node.type === 'atrule')
for (const atnode of atruleNodes) {
extractAndWrapNodes(atnode)
}
const hostRule = new Rule({
nodes: decls,
selector: '&',
})
rule.prepend(hostRule)
}
shouldInject = deep
}
Expand Down Expand Up @@ -286,5 +282,22 @@ function isSpaceCombinator(node: selectorParser.Node) {
return node.type === 'combinator' && /^\s+$/.test(node.value)
}

function extractAndWrapNodes(parentNode: Rule | AtRule) {
if (!parentNode.nodes) return
const nodes = parentNode.nodes.filter(
node => node.type === 'decl' || node.type === 'comment',
)
if (nodes.length) {
for (const node of nodes) {
parentNode.removeChild(node)
}
const wrappedRule = new Rule({
nodes: nodes,
selector: '&',
})
parentNode.prepend(wrappedRule)
}
}

scopedPlugin.postcss = true
export default scopedPlugin

0 comments on commit 0e7bc71

Please sign in to comment.