1- import type { AtRule , PluginCreator , Rule } from 'postcss'
1+ import {
2+ type AtRule ,
3+ type Container ,
4+ type Document ,
5+ type PluginCreator ,
6+ Rule ,
7+ } from 'postcss'
28import selectorParser from 'postcss-selector-parser'
39import { warn } from '../warn'
410
@@ -71,21 +77,32 @@ function processRule(id: string, rule: Rule) {
7177 return
7278 }
7379 processedRules . add ( rule )
80+ let deep = false
81+ let parent : Document | Container | undefined = rule . parent
82+ while ( parent && parent . type !== 'root' ) {
83+ if ( ( parent as any ) . __deep ) {
84+ deep = true
85+ break
86+ }
87+ parent = parent . parent
88+ }
7489 rule . selector = selectorParser ( selectorRoot => {
7590 selectorRoot . each ( selector => {
76- rewriteSelector ( id , selector , selectorRoot )
91+ rewriteSelector ( id , rule , selector , selectorRoot , deep )
7792 } )
7893 } ) . processSync ( rule . selector )
7994}
8095
8196function rewriteSelector (
8297 id : string ,
98+ rule : Rule ,
8399 selector : selectorParser . Selector ,
84100 selectorRoot : selectorParser . Root ,
101+ deep : boolean ,
85102 slotted = false ,
86103) {
87104 let node : selectorParser . Node | null = null
88- let shouldInject = true
105+ let shouldInject = ! deep
89106 // find the last child node to insert attribute selector
90107 selector . each ( n => {
91108 // DEPRECATED ">>>" and "/deep/" combinator
@@ -107,6 +124,7 @@ function rewriteSelector(
107124 // deep: inject [id] attribute at the node before the ::v-deep
108125 // combinator.
109126 if ( value === ':deep' || value === '::v-deep' ) {
127+ ; ( rule as any ) . __deep = true
110128 if ( n . nodes . length ) {
111129 // .foo ::v-deep(.bar) -> .foo[xxxxxxx] .bar
112130 // replace the current node with ::v-deep's inner selector
@@ -147,7 +165,14 @@ function rewriteSelector(
147165 // instead.
148166 // ::v-slotted(.foo) -> .foo[xxxxxxx-s]
149167 if ( value === ':slotted' || value === '::v-slotted' ) {
150- rewriteSelector ( id , n . nodes [ 0 ] , selectorRoot , true /* slotted */ )
168+ rewriteSelector (
169+ id ,
170+ rule ,
171+ n . nodes [ 0 ] ,
172+ selectorRoot ,
173+ deep ,
174+ true /* slotted */ ,
175+ )
151176 let last : selectorParser . Selector [ 'nodes' ] [ 0 ] = n
152177 n . nodes [ 0 ] . each ( ss => {
153178 selector . insertAfter ( last , ss )
@@ -206,11 +231,27 @@ function rewriteSelector(
206231 }
207232 } )
208233
234+ if ( rule . nodes . some ( node => node . type === 'rule' ) ) {
235+ const deep = ( rule as any ) . __deep
236+ const decls = rule . nodes . filter ( node => node . type === 'decl' )
237+ if ( ! deep && decls . length ) {
238+ for ( const decl of decls ) {
239+ rule . removeChild ( decl )
240+ }
241+ const hostRule = new Rule ( {
242+ nodes : decls ,
243+ selector : '&' ,
244+ } )
245+ rule . prepend ( hostRule )
246+ }
247+ shouldInject = deep
248+ }
249+
209250 if ( node ) {
210251 const { type, value } = node as selectorParser . Node
211252 if ( type === 'pseudo' && ( value === ':is' || value === ':where' ) ) {
212253 ; ( node as selectorParser . Pseudo ) . nodes . forEach ( value =>
213- rewriteSelector ( id , value , selectorRoot , slotted ) ,
254+ rewriteSelector ( id , rule , value , selectorRoot , deep , slotted ) ,
214255 )
215256 shouldInject = false
216257 }
0 commit comments