Skip to content

Commit b2bc080

Browse files
committed
feat: global/slotted selector support multiple values
1 parent 3ab4964 commit b2bc080

File tree

2 files changed

+84
-6
lines changed

2 files changed

+84
-6
lines changed

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

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,22 @@ describe('SFC scoped CSS', () => {
132132
.toMatchInlineSnapshot(`
133133
".foo[data-v-test-s] { color: red;
134134
}"
135-
`)
135+
`)
136+
expect(compileScoped(`:slotted(.foo) .bar { color: red; }`))
137+
.toMatchInlineSnapshot(`
138+
".foo[data-v-test-s] .bar { color: red;
139+
}"
140+
`)
141+
expect(compileScoped(`::v-slotted(.foo,.baz .bar) { color: red; }`))
142+
.toMatchInlineSnapshot(`
143+
".foo[data-v-test-s],.baz .bar[data-v-test-s] { color: red;
144+
}"
145+
`)
146+
expect(compileScoped(`::v-slotted(.foo,.baz) { color: red; }`))
147+
.toMatchInlineSnapshot(`
148+
".foo[data-v-test-s],.baz[data-v-test-s] { color: red;
149+
}"
150+
`)
136151
expect(compileScoped(`::v-slotted(.foo) { color: red; }`))
137152
.toMatchInlineSnapshot(`
138153
".foo[data-v-test-s] { color: red;
@@ -148,6 +163,16 @@ describe('SFC scoped CSS', () => {
148163
".baz .qux .foo .bar[data-v-test-s] { color: red;
149164
}"
150165
`)
166+
expect(compileScoped(`.baz .qux ::v-slotted(.foo,.bar) { color: red; }`))
167+
.toMatchInlineSnapshot(`
168+
".baz .qux .foo[data-v-test-s],.baz .qux .bar[data-v-test-s] { color: red;
169+
}"
170+
`)
171+
expect(compileScoped(`.baz .qux ::v-slotted(.foo,.bar) .m { color: red; }`))
172+
.toMatchInlineSnapshot(`
173+
".baz .qux .foo[data-v-test-s] .m,.baz .qux .bar[data-v-test-s] .m { color: red;
174+
}"
175+
`)
151176
})
152177

153178
test('::v-global', () => {
@@ -156,6 +181,11 @@ describe('SFC scoped CSS', () => {
156181
".foo { color: red;
157182
}"
158183
`)
184+
expect(compileScoped(`::v-global(.foo,.bar) { color: red; }`))
185+
.toMatchInlineSnapshot(`
186+
".foo,.bar { color: red;
187+
}"
188+
`)
159189
expect(compileScoped(`::v-global(.foo) { color: red; }`))
160190
.toMatchInlineSnapshot(`
161191
".foo { color: red;
@@ -172,6 +202,24 @@ describe('SFC scoped CSS', () => {
172202
".foo .bar { color: red;
173203
}"
174204
`)
205+
expect(
206+
compileScoped(`.baz .qux ::v-global(.foo .bar, .bar) { color: red; }`)
207+
).toMatchInlineSnapshot(`
208+
".foo .bar, .bar { color: red;
209+
}"
210+
`)
211+
// global ignores anything after it
212+
expect(compileScoped(`::v-global(.foo .bar) .baz { color: red; }`))
213+
.toMatchInlineSnapshot(`
214+
".foo .bar { color: red;
215+
}"
216+
`)
217+
expect(
218+
compileScoped(`.baz ::v-global(.foo .bar,.faa) .qux { color: red; }`)
219+
).toMatchInlineSnapshot(`
220+
".foo .bar,.faa { color: red;
221+
}"
222+
`)
175223
})
176224

177225
test('media query', () => {

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

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -194,11 +194,37 @@ function rewriteSelector(
194194
// instead.
195195
// ::v-slotted(.foo) -> .foo[xxxxxxx-s]
196196
if (value === ':slotted' || value === '::v-slotted') {
197-
rewriteSelector(id, n.nodes[0], selectorRoot, true /* slotted */)
198197
let last: selectorParser.Selector['nodes'][0] = n
199-
n.nodes[0].each(ss => {
200-
selector.insertAfter(last, ss)
201-
last = ss
198+
const nextNodes = [] as typeof selector.nodes
199+
n.nodes.forEach((ss, i) => {
200+
rewriteSelector(id, ss, selectorRoot, true /* slotted */)
201+
const index = selector.index(n)
202+
if (i > 0) {
203+
const prevList = selector.nodes.slice(0, index).concat(ss.nodes)
204+
if (nextNodes.length) {
205+
prevList.push(...nextNodes)
206+
nextNodes.forEach(s => {
207+
selector.removeChild(s)
208+
selector.insertAfter(last, s)
209+
last = s
210+
})
211+
}
212+
const newList = prevList.map(
213+
s => s.clone({}) as selectorParser.Selector['nodes'][0]
214+
)
215+
216+
newList.unshift(selectorParser.combinator({ value: ',' }))
217+
newList.forEach(s => {
218+
selector.insertAfter(last, s)
219+
last = s
220+
})
221+
} else {
222+
nextNodes.push(...selector.nodes.slice(index + 1))
223+
ss.each(s => {
224+
selector.insertAfter(last, s)
225+
last = s
226+
})
227+
}
202228
})
203229
// selector.insertAfter(n, n.nodes[0])
204230
selector.removeChild(n)
@@ -211,7 +237,11 @@ function rewriteSelector(
211237
// global: replace with inner selector and do not inject [id].
212238
// ::v-global(.foo) -> .foo
213239
if (value === ':global' || value === '::v-global') {
214-
selectorRoot.insertAfter(selector, n.nodes[0])
240+
let last = selector
241+
n.nodes.forEach(_node => {
242+
selectorRoot.insertAfter(last, _node)
243+
last = _node
244+
})
215245
selectorRoot.removeChild(selector)
216246
return false
217247
}

0 commit comments

Comments
 (0)