@@ -53,12 +53,12 @@ function interpolateAmpInSelector(nodes, parent) {
53
53
*/
54
54
function mergeSelectors ( parent , child ) {
55
55
let merged = [ ]
56
- parent . selectors . forEach ( sel => {
56
+ for ( let sel of parent . selectors ) {
57
57
let parentNode = parse ( sel , parent )
58
58
59
- child . selectors . forEach ( selector => {
59
+ for ( let selector of child . selectors ) {
60
60
if ( ! selector ) {
61
- return
61
+ continue
62
62
}
63
63
let node = parse ( selector , child )
64
64
let replaced = interpolateAmpInSelector ( node , parentNode )
@@ -67,22 +67,43 @@ function mergeSelectors(parent, child) {
67
67
node . prepend ( parentNode . clone ( { } ) )
68
68
}
69
69
merged . push ( node . toString ( ) )
70
- } )
71
- } )
70
+ }
71
+ }
72
72
return merged
73
73
}
74
74
75
75
/**
76
- * Move a child and its preceeding comment(s) to after "after"
76
+ * Move a child and its preceding comment(s) to after "after"
77
+ * ! It is necessary to clarify the comment
77
78
*/
78
79
function breakOut ( child , after ) {
79
- let prev = child . prev ( )
80
- after . after ( child )
81
- while ( prev && prev . type === 'comment' ) {
82
- let nextPrev = prev . prev ( )
83
- after . after ( prev )
84
- prev = nextPrev
80
+ let changeParent = true
81
+
82
+ for ( let node of after . nodes ) {
83
+ if ( ! node . nodes ) continue
84
+
85
+ let prevNode = node . prev ( )
86
+ if ( prevNode ?. type !== 'comment' ) continue
87
+
88
+ let parentRule = after . toString ( )
89
+
90
+ /* Checking that the comment "describes" the rule following. Like this:
91
+ /* comment about the rule below /*
92
+ .rule {}
93
+ */
94
+ let regexp = new RegExp ( `${ prevNode . toString ( ) } *\n *${ node . toString ( ) } ` )
95
+
96
+ if ( parentRule . match ( regexp ) ) {
97
+ changeParent = false
98
+ after . after ( node ) . after ( prevNode )
99
+ }
100
+ }
101
+
102
+ // It is necessary if the above child has never been moved
103
+ if ( changeParent ) {
104
+ after . after ( child )
85
105
}
106
+
86
107
return child
87
108
}
88
109
@@ -104,14 +125,12 @@ function createFnAtruleChilds(bubble) {
104
125
children . push ( child )
105
126
}
106
127
} )
107
- if ( bubbling ) {
108
- if ( children . length ) {
109
- let clone = rule . clone ( { nodes : [ ] } )
110
- for ( let child of children ) {
111
- clone . append ( child )
112
- }
113
- atrule . prepend ( clone )
128
+ if ( bubbling && children . length ) {
129
+ let clone = rule . clone ( { nodes : [ ] } )
130
+ for ( let child of children ) {
131
+ clone . append ( child )
114
132
}
133
+ atrule . prepend ( clone )
115
134
}
116
135
}
117
136
}
@@ -125,16 +144,23 @@ function pickDeclarations(selector, declarations, after) {
125
144
after . after ( parent )
126
145
return parent
127
146
}
147
+ function pickAndClearDeclarations ( ruleSelector , declarations , after , clear = true ) {
148
+ if ( ! declarations . length ) return [ after , declarations ]
128
149
129
- function atruleNames ( defaults , custom ) {
130
- let list = { }
131
- for ( let name of defaults ) {
132
- list [ name ] = true
150
+ after = pickDeclarations ( ruleSelector , declarations , after )
151
+
152
+ if ( clear ) {
153
+ declarations = [ ]
133
154
}
134
- if ( custom ) {
135
- for ( let name of custom ) {
136
- list [ name . replace ( / ^ @ / , '' ) ] = true
137
- }
155
+
156
+ return [ after , declarations ]
157
+ }
158
+
159
+ function atruleNames ( defaults , custom = '' ) {
160
+ let names = defaults . concat ( custom )
161
+ let list = { }
162
+ for ( let name of names ) {
163
+ list [ name . replace ( / ^ @ / , '' ) ] = true
138
164
}
139
165
return list
140
166
}
@@ -297,10 +323,10 @@ module.exports = (opts = {}) => {
297
323
postcssPlugin : 'postcss-nested' ,
298
324
299
325
RootExit ( root ) {
300
- if ( root [ hasRootRule ] ) {
301
- root . walkAtRules ( rootRuleName , unwrapRootRule )
302
- root [ hasRootRule ] = false
303
- }
326
+ if ( ! root [ hasRootRule ] ) return
327
+
328
+ root . walkAtRules ( rootRuleName , unwrapRootRule )
329
+ root [ hasRootRule ] = false
304
330
} ,
305
331
306
332
Rule ( rule ) {
@@ -310,46 +336,48 @@ module.exports = (opts = {}) => {
310
336
let declarations = [ ]
311
337
312
338
rule . each ( child => {
313
- if ( child . type === 'rule' ) {
314
- if ( declarations . length ) {
315
- after = pickDeclarations ( rule . selector , declarations , after )
316
- declarations = [ ]
317
- }
318
-
319
- copyDeclarations = true
320
- unwrapped = true
321
- child . selectors = mergeSelectors ( rule , child )
322
- after = breakOut ( child , after )
323
- } else if ( child . type === 'atrule' ) {
324
- if ( declarations . length ) {
325
- after = pickDeclarations ( rule . selector , declarations , after )
326
- declarations = [ ]
327
- }
328
- if ( child . name === rootRuleName ) {
329
- unwrapped = true
330
- atruleChilds ( rule , child , true , child [ rootRuleMergeSel ] )
331
- after = breakOut ( child , after )
332
- } else if ( bubble [ child . name ] ) {
333
- copyDeclarations = true
334
- unwrapped = true
335
- atruleChilds ( rule , child , true )
336
- after = breakOut ( child , after )
337
- } else if ( unwrap [ child . name ] ) {
339
+ switch ( child . type ) {
340
+ case 'rule' :
341
+ [ after , declarations ] = pickAndClearDeclarations ( rule . selector , declarations , after )
342
+
338
343
copyDeclarations = true
339
344
unwrapped = true
340
- atruleChilds ( rule , child , false )
345
+ child . selectors = mergeSelectors ( rule , child )
341
346
after = breakOut ( child , after )
342
- } else if ( copyDeclarations ) {
343
- declarations . push ( child )
344
- }
345
- } else if ( child . type === 'decl' && copyDeclarations ) {
346
- declarations . push ( child )
347
+
348
+ break
349
+ case 'atrule' :
350
+ [ after , declarations ] = pickAndClearDeclarations ( rule . selector , declarations , after )
351
+
352
+ if ( child . name === rootRuleName ) {
353
+ unwrapped = true
354
+ atruleChilds ( rule , child , true , child [ rootRuleMergeSel ] )
355
+ after = breakOut ( child , after )
356
+ } else if ( bubble [ child . name ] ) {
357
+ copyDeclarations = true
358
+ unwrapped = true
359
+ atruleChilds ( rule , child , true )
360
+ after = breakOut ( child , after )
361
+ } else if ( unwrap [ child . name ] ) {
362
+ copyDeclarations = true
363
+ unwrapped = true
364
+ atruleChilds ( rule , child , false )
365
+ after = breakOut ( child , after )
366
+ } else if ( copyDeclarations ) {
367
+ declarations . push ( child )
368
+ }
369
+
370
+ break
371
+ case 'decl' :
372
+ if ( copyDeclarations ) {
373
+ declarations . push ( child )
374
+ }
375
+
376
+ break
347
377
}
348
378
} )
349
379
350
- if ( declarations . length ) {
351
- after = pickDeclarations ( rule . selector , declarations , after )
352
- }
380
+ pickAndClearDeclarations ( rule . selector , declarations , after , false )
353
381
354
382
if ( unwrapped && preserveEmpty !== true ) {
355
383
rule . raws . semicolon = true
0 commit comments