Skip to content

Commit 436415a

Browse files
fix(compiler-sfc): support global selector nesting
1 parent 6eb29d3 commit 436415a

File tree

2 files changed

+45
-6
lines changed

2 files changed

+45
-6
lines changed

packages/compiler-sfc/__tests__/compileStyle.spec.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,40 @@ color: red
181181
".foo .bar { color: red;
182182
}"
183183
`)
184-
// global ignores anything before it
184+
185185
expect(compileScoped(`.baz .qux ::v-global(.foo .bar) { color: red; }`))
186186
.toMatchInlineSnapshot(`
187-
".foo .bar { color: red;
187+
".baz .qux[data-v-test] .foo .bar { color: red;
188+
}"
189+
`)
190+
191+
expect(compileScoped(`::v-global(body) h1 { color: red; }`))
192+
.toMatchInlineSnapshot(`
193+
"body h1[data-v-test] { color: red;
194+
}"
195+
`)
196+
197+
expect(compileScoped(`::v-global(body h1) { color: red; }`))
198+
.toMatchInlineSnapshot(`
199+
"body h1 { color: red;
200+
}"
201+
`)
202+
203+
expect(compileScoped(`html ::v-global(body) h1 { color: red; }`))
204+
.toMatchInlineSnapshot(`
205+
"html body h1[data-v-test] { color: red;
188206
}"
189207
`)
208+
209+
expect(compileScoped(`::v-global(body){ color: red; h1 { color: blue; } }`))
210+
.toMatchInlineSnapshot(`
211+
"body{
212+
&{ color: red;
213+
}
214+
h1[data-v-test] { color: blue;
215+
}
216+
}"
217+
`)
190218
})
191219

192220
test(':is() and :where() with multiple selectors', () => {

packages/compiler-sfc/src/style/pluginScoped.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,14 @@ function rewriteSelector(
103103
) {
104104
let node: selectorParser.Node | null = null
105105
let shouldInject = !deep
106+
let wrappedGlobal = false
106107
// find the last child node to insert attribute selector
107108
selector.each(n => {
109+
if ((rule as any).__global) {
110+
shouldInject = false
111+
return false
112+
}
113+
108114
// DEPRECATED ">>>" and "/deep/" combinator
109115
if (
110116
n.type === 'combinator' &&
@@ -189,8 +195,12 @@ function rewriteSelector(
189195
// global: replace with inner selector and do not inject [id].
190196
// ::v-global(.foo) -> .foo
191197
if (value === ':global' || value === '::v-global') {
192-
selector.replaceWith(n.nodes[0])
193-
return false
198+
n.replaceWith(...n.nodes)
199+
if (selector.nodes.length === 1) {
200+
shouldInject = false
201+
wrappedGlobal = true
202+
return false
203+
}
194204
}
195205
}
196206

@@ -233,7 +243,7 @@ function rewriteSelector(
233243
if (rule.nodes.some(node => node.type === 'rule')) {
234244
const deep = (rule as any).__deep
235245
if (!deep) {
236-
extractAndWrapNodes(rule)
246+
extractAndWrapNodes(rule, wrappedGlobal)
237247
const atruleNodes = rule.nodes.filter(node => node.type === 'atrule')
238248
for (const atnode of atruleNodes) {
239249
extractAndWrapNodes(atnode)
@@ -281,7 +291,7 @@ function isSpaceCombinator(node: selectorParser.Node) {
281291
return node.type === 'combinator' && /^\s+$/.test(node.value)
282292
}
283293

284-
function extractAndWrapNodes(parentNode: Rule | AtRule) {
294+
function extractAndWrapNodes(parentNode: Rule | AtRule, wrappedGlobal = false) {
285295
if (!parentNode.nodes) return
286296
const nodes = parentNode.nodes.filter(
287297
node => node.type === 'decl' || node.type === 'comment',
@@ -294,6 +304,7 @@ function extractAndWrapNodes(parentNode: Rule | AtRule) {
294304
nodes: nodes,
295305
selector: '&',
296306
})
307+
;(wrappedRule as any).__global = wrappedGlobal
297308
parentNode.prepend(wrappedRule)
298309
}
299310
}

0 commit comments

Comments
 (0)