fix(compiler-sfc): nested css supports atrule and comment (#11899)

close #11896
This commit is contained in:
linzhe 2024-09-13 16:53:49 +08:00 committed by GitHub
parent 706d4ac1d0
commit 0e7bc717e6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 54 additions and 9 deletions

View File

@ -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;`,

View File

@ -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
}
@ -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