@@ -77,11 +77,9 @@ function AtImport(options) {
77
77
* @param {Object } options
78
78
*/
79
79
function parseStyles ( styles , options , cb , importedFiles , ignoredAtRules , media ) {
80
- styles . eachAtRule ( function checkAtRule ( atRule ) {
81
- if ( atRule . name !== "import" ) {
82
- return
83
- }
84
-
80
+ var imports = [ ]
81
+ styles . eachAtRule ( "import" , function checkAtRule ( atRule ) { imports . push ( atRule ) } )
82
+ imports . forEach ( function ( atRule ) {
85
83
helpers . try ( function transformAtImport ( ) {
86
84
readAtImport ( atRule , options , cb , importedFiles , ignoredAtRules , media )
87
85
} , atRule . source )
@@ -102,14 +100,16 @@ function addIgnoredAtRulesOnTop(styles, ignoredAtRules) {
102
100
while ( i -- ) {
103
101
var ignoredAtRule = ignoredAtRules [ i ] [ 0 ]
104
102
ignoredAtRule . params = ignoredAtRules [ i ] [ 1 ] . fullUri + ( ignoredAtRules [ i ] [ 1 ] . media ? " " + ignoredAtRules [ i ] [ 1 ] . media : "" )
105
- ignoredAtRule . before = "\n"
106
- ignoredAtRule . after = ""
103
+
104
+ // keep ast ref
105
+ ignoredAtRule . parent = styles
107
106
108
107
// don't use prepend() to avoid weird behavior of normalize()
109
108
styles . nodes . unshift ( ignoredAtRule )
110
109
}
111
110
112
- if ( first && first . before !== undefined ) {
111
+ // separate remote import a little with others rules if no newlines already
112
+ if ( first && first . before . indexOf ( "\n" ) === - 1 ) {
113
113
first . before = "\n\n" + first . before
114
114
}
115
115
}
@@ -126,33 +126,38 @@ function readAtImport(atRule, options, cb, importedFiles, ignoredAtRules, media)
126
126
// @todo extract what can be interesting from this one
127
127
var parsedAtImport = parseImport ( atRule . params , atRule . source )
128
128
129
-
130
-
131
129
// adjust media according to current scope
132
130
media = parsedAtImport . media ? ( media ? media + " and " : "" ) + parsedAtImport . media : ( media ? media : null )
133
131
134
132
// just update protocol base uri (protocol://url) or protocol-relative (//url) if media needed
135
133
if ( parsedAtImport . uri . match ( / ^ (?: [ a - z ] + : ) ? \/ \/ / i) ) {
136
134
parsedAtImport . media = media
137
- var atRuleCloned = atRule . clone ( )
138
- atRuleCloned . parent = atRule . parent . clone ( )
139
- ignoredAtRules . push ( [ atRuleCloned , parsedAtImport ] )
140
- atRule . removeSelf ( )
135
+
136
+ // save
137
+ ignoredAtRules . push ( [ atRule , parsedAtImport ] )
138
+
139
+ // detach
140
+ detach ( atRule )
141
+
141
142
return
142
143
}
143
144
144
145
addInputToPath ( options )
145
146
var resolvedFilename = resolveFilename ( parsedAtImport . uri , options . root , options . path , atRule . source )
146
147
148
+ // skip files already imported at the same scope
147
149
if ( importedFiles [ resolvedFilename ] && importedFiles [ resolvedFilename ] [ media ] ) {
148
- atRule . removeSelf ( )
150
+ detach ( atRule )
149
151
return
150
152
}
153
+
154
+ // save imported files to skip them next time
151
155
if ( ! importedFiles [ resolvedFilename ] ) {
152
156
importedFiles [ resolvedFilename ] = { }
153
157
}
154
158
importedFiles [ resolvedFilename ] [ media ] = true
155
159
160
+
156
161
readImportedContent ( atRule , parsedAtImport , clone ( options ) , resolvedFilename , cb , importedFiles , ignoredAtRules )
157
162
}
158
163
@@ -179,7 +184,7 @@ function readImportedContent(atRule, parsedAtImport, options, resolvedFilename,
179
184
180
185
if ( fileContent . trim ( ) === "" ) {
181
186
console . log ( helpers . message ( resolvedFilename + " is empty" , atRule . source ) )
182
- atRule . removeSelf ( )
187
+ detach ( atRule )
183
188
return
184
189
}
185
190
@@ -199,29 +204,41 @@ function readImportedContent(atRule, parsedAtImport, options, resolvedFilename,
199
204
* @param {Object } newStyles
200
205
*/
201
206
function insertRules ( atRule , parsedAtImport , newStyles ) {
207
+ var newNodes = newStyles . nodes
208
+
202
209
// wrap rules if the @import have a media query
203
210
if ( parsedAtImport . media && parsedAtImport . media . length ) {
211
+ // better output
212
+ if ( newStyles . nodes && newStyles . nodes . length ) {
213
+ newStyles . nodes [ 0 ] . before = newStyles . nodes [ 0 ] . before || "\n"
214
+ // newStyles.nodes[newStyles.nodes.length - 1].after = (newStyles.nodes[newStyles.nodes.length - 1].after || "") + "\n"
215
+ }
216
+
204
217
// wrap new rules with media (media query)
205
218
var wrapper = postcss . atRule ( {
206
219
name : "media" ,
207
220
params : parsedAtImport . media
208
221
} )
209
- wrapper . append ( newStyles )
210
- newStyles = wrapper
211
222
212
- // better output
213
- newStyles . before = atRule . before
214
- if ( newStyles . nodes && newStyles . nodes . length ) {
215
- newStyles . nodes [ 0 ] . before = newStyles . nodes [ 0 ] . before || "\n"
216
- }
217
- newStyles . after = atRule . after || "\n"
223
+ // keep ast clean
224
+ newNodes . forEach ( function ( node ) { node . parent = wrapper } )
225
+ wrapper . source = atRule . source
226
+
227
+ // copy code style
228
+ wrapper . before = atRule . before
229
+ wrapper . after = atRule . after
230
+
231
+ // move nodes
232
+ wrapper . nodes = newNodes
233
+ newNodes = [ wrapper ]
218
234
}
219
- else if ( newStyles . nodes && newStyles . nodes . length ) {
220
- newStyles . nodes [ 0 ] . before = atRule . before
235
+ else if ( newNodes && newNodes . length ) {
236
+ newNodes [ 0 ] . before = atRule . before
221
237
}
222
-
223
- atRule . parent . insertBefore ( atRule , newStyles )
224
- atRule . removeSelf ( )
238
+ // replace atRule by imported nodes
239
+ var nodes = atRule . parent . nodes
240
+ nodes . splice . apply ( nodes , [ nodes . indexOf ( atRule ) , 0 ] . concat ( newNodes ) )
241
+ detach ( atRule )
225
242
}
226
243
227
244
/**
@@ -317,3 +334,7 @@ function addInputToPath(options) {
317
334
}
318
335
}
319
336
}
337
+
338
+ function detach ( node ) {
339
+ node . parent . nodes . splice ( node . parent . nodes . indexOf ( node ) , 1 )
340
+ }
0 commit comments