2
2
3
3
const postcss = require ( 'postcss' ) ;
4
4
const Tokenizer = require ( 'css-selector-tokenizer' ) ;
5
+ const valueParser = require ( 'postcss-value-parser' ) ;
5
6
6
7
function normalizeNodeArray ( nodes ) {
7
8
const array = [ ] ;
@@ -162,45 +163,48 @@ function localizeNode(node, context) {
162
163
}
163
164
164
165
function localizeDeclNode ( node , context ) {
165
- let newNode ;
166
166
switch ( node . type ) {
167
- case 'item ' :
167
+ case 'word ' :
168
168
if ( context . localizeNextItem ) {
169
- newNode = Object . create ( node ) ;
170
- newNode . name = ':local(' + newNode . name + ')' ;
169
+ node . value = ':local(' + node . value + ')' ;
171
170
context . localizeNextItem = false ;
172
- return newNode ;
173
171
}
174
172
break ;
175
173
176
- case 'nested-item' :
177
- const newNodes = node . nodes . map ( function ( n ) {
178
- return localizeDeclValue ( n , context ) ;
179
- } ) ;
180
- node = Object . create ( node ) ;
181
- node . nodes = newNodes ;
182
- break ;
174
+ case 'function' :
175
+ if ( context . options && context . options . rewriteUrl && node . value . toLowerCase ( ) === 'url' ) {
176
+ node . nodes . map ( ( nestedNode ) => {
177
+ if ( nestedNode . type !== 'string' && nestedNode . type !== 'word' ) {
178
+ return ;
179
+ }
180
+
181
+ let newUrl = context . options . rewriteUrl ( context . global , nestedNode . value ) ;
182
+
183
+ switch ( nestedNode . type ) {
184
+ case 'string' :
185
+ if ( nestedNode . quote === '\'' ) {
186
+ newUrl = newUrl . replace ( / ( \\ ) / g, '\\$1' ) . replace ( / ' / g, '\\\'' )
187
+ }
188
+
189
+ if ( nestedNode . quote === '"' ) {
190
+ newUrl = newUrl . replace ( / ( \\ ) / g, '\\$1' ) . replace ( / " / g, '\\"' )
191
+ }
192
+
193
+ break ;
194
+ case 'word' :
195
+ newUrl = newUrl . replace ( / ( " | ' | \) | \\ ) / g, '\\$1' ) ;
196
+ break ;
197
+ }
183
198
184
- case 'url' :
185
- if ( context . options && context . options . rewriteUrl ) {
186
- newNode = Object . create ( node ) ;
187
- newNode . url = context . options . rewriteUrl ( context . global , node . url ) ;
188
- return newNode ;
199
+ nestedNode . value = newUrl ;
200
+ } ) ;
189
201
}
190
202
break ;
191
203
}
192
204
return node ;
193
205
}
194
206
195
- function localizeDeclValue ( valueNode , context ) {
196
- const newValueNode = Object . create ( valueNode ) ;
197
- newValueNode . nodes = valueNode . nodes . map ( function ( node ) {
198
- return localizeDeclNode ( node , context ) ;
199
- } ) ;
200
- return newValueNode ;
201
- }
202
-
203
- function localizeAnimationShorthandDeclValueNodes ( nodes , context ) {
207
+ function localizeAnimationShorthandDeclValues ( decl , context ) {
204
208
const validIdent = / ^ - ? [ _ a - z ] [ _ a - z 0 - 9 - ] * $ / i;
205
209
206
210
/*
@@ -240,9 +244,9 @@ function localizeAnimationShorthandDeclValueNodes(nodes, context) {
240
244
241
245
const didParseAnimationName = false ;
242
246
const parsedAnimationKeywords = { } ;
243
- return nodes . map ( function ( valueNode ) {
247
+ const valueNodes = valueParser ( decl . value ) . walk ( ( node ) => {
244
248
const value =
245
- valueNode . type === 'item ' ? valueNode . name . toLowerCase ( ) : null ;
249
+ node . type === 'word ' ? node . value . toLowerCase ( ) : null ;
246
250
247
251
let shouldParseAnimationName = false ;
248
252
@@ -266,52 +270,43 @@ function localizeAnimationShorthandDeclValueNodes(nodes, context) {
266
270
global : context . global ,
267
271
localizeNextItem : shouldParseAnimationName && ! context . global
268
272
} ;
269
- return localizeDeclNode ( valueNode , subContext ) ;
273
+ return localizeDeclNode ( node , subContext ) ;
270
274
} ) ;
271
- }
272
275
273
- function localizeAnimationShorthandDeclValues ( valuesNode , decl , context ) {
274
- const newValuesNode = Object . create ( valuesNode ) ;
275
- newValuesNode . nodes = valuesNode . nodes . map ( function ( valueNode , index ) {
276
- const newValueNode = Object . create ( valueNode ) ;
277
- newValueNode . nodes = localizeAnimationShorthandDeclValueNodes (
278
- valueNode . nodes ,
279
- context
280
- ) ;
281
- return newValueNode ;
282
- } ) ;
283
- decl . value = Tokenizer . stringifyValues ( newValuesNode ) ;
276
+ decl . value = valueNodes . toString ( ) ;
284
277
}
285
278
286
- function localizeDeclValues ( localize , valuesNode , decl , context ) {
287
- const newValuesNode = Object . create ( valuesNode ) ;
288
- newValuesNode . nodes = valuesNode . nodes . map ( function ( valueNode ) {
279
+ function localizeDeclValues ( localize , decl , context ) {
280
+ const valueNodes = valueParser ( decl . value ) ;
281
+ valueNodes . walk ( ( node , index , nodes ) => {
289
282
const subContext = {
290
283
options : context . options ,
291
284
global : context . global ,
292
285
localizeNextItem : localize && ! context . global
293
286
} ;
294
- return localizeDeclValue ( valueNode , subContext ) ;
287
+ nodes [ index ] = localizeDeclNode ( node , subContext ) ;
295
288
} ) ;
296
- decl . value = Tokenizer . stringifyValues ( newValuesNode ) ;
289
+ decl . value = valueNodes . toString ( ) ;
297
290
}
298
291
299
292
function localizeDecl ( decl , context ) {
300
- const valuesNode = Tokenizer . parseValues ( decl . value ) ;
301
-
302
- const isAnimation = / a n i m a t i o n ? $ / i. test ( decl . prop ) ;
293
+ const isAnimation = / a n i m a t i o n $ / i. test ( decl . prop ) ;
303
294
304
295
if ( isAnimation ) {
305
- return localizeAnimationShorthandDeclValues ( valuesNode , decl , context ) ;
296
+ return localizeAnimationShorthandDeclValues ( decl , context ) ;
306
297
}
307
298
308
299
const isAnimationName = / a n i m a t i o n ( - n a m e ) ? $ / i. test ( decl . prop ) ;
309
300
310
301
if ( isAnimationName ) {
311
- return localizeDeclValues ( true , valuesNode , decl , context ) ;
302
+ return localizeDeclValues ( true , decl , context ) ;
312
303
}
313
304
314
- return localizeDeclValues ( false , valuesNode , decl , context ) ;
305
+ const hasUrl = / u r l \( / i. test ( decl . value ) ;
306
+
307
+ if ( hasUrl ) {
308
+ return localizeDeclValues ( false , decl , context ) ;
309
+ }
315
310
}
316
311
317
312
module . exports = postcss . plugin ( 'postcss-modules-local-by-default' , function (
0 commit comments