@@ -182,21 +182,109 @@ function localizeDeclValue(valueNode, context) {
182
182
return newValueNode ;
183
183
}
184
184
185
- function localizeDecl ( decl , context ) {
186
- var valuesNode = Tokenizer . parseValues ( decl . value ) ;
187
- var localizeName = / a n i m a t i o n ( - n a m e ) ? $ / . test ( decl . prop ) ;
185
+ function localizeAnimationShorthandDeclValueNodes ( nodes , context ) {
186
+ var validIdent = validIdent = / ^ - ? [ _ a - z ] [ _ a - z 0 - 9 - ] * $ / i;
187
+
188
+ /*
189
+ The spec defines some keywords that you can use to describe properties such as the timing
190
+ function. These are still valid animation names, so as long as there is a property that accepts
191
+ a keyword, it is given priority. Only when all the properties that can take a keyword are
192
+ exhausted can the animation name be set to the keyword. I.e.
193
+
194
+ animation: infinite infinite;
195
+
196
+ The animation will repeat an infinite number of times from the first argument, and will have an
197
+ animation name of infinite from the second.
198
+ */
199
+ var animationKeywords = {
200
+ 'alternate' : 1 ,
201
+ 'alternate-reverse' : 1 ,
202
+ 'backwards' : 1 ,
203
+ 'both' : 1 ,
204
+ 'ease' : 1 ,
205
+ 'ease-in' : 1 ,
206
+ 'ease-in-out' : 1 ,
207
+ 'ease-out' : 1 ,
208
+ 'forwards' : 1 ,
209
+ 'infinite' : 1 ,
210
+ 'linear' : 1 ,
211
+ 'none' : Infinity , // No matter how many times you write none, it will never be an animation name
212
+ 'normal' : 1 ,
213
+ 'paused' : 1 ,
214
+ 'reverse' : 1 ,
215
+ 'running' : 1 ,
216
+ 'step-end' : 1 ,
217
+ 'step-start' : 1 ,
218
+ 'initial' : Infinity ,
219
+ 'inherit' : Infinity ,
220
+ 'unset' : Infinity ,
221
+ } ;
222
+
223
+ var didParseAnimationName = false ;
224
+ var parsedAnimationKeywords = { } ;
225
+ return nodes . map ( function ( valueNode ) {
226
+ var value = valueNode . type === 'item'
227
+ ? valueNode . name . toLowerCase ( )
228
+ : null ;
229
+
230
+ var shouldParseAnimationName = false ;
231
+
232
+ if ( ! didParseAnimationName && value && validIdent . test ( value ) ) {
233
+ if ( value in animationKeywords ) {
234
+ parsedAnimationKeywords [ value ] = ( value in parsedAnimationKeywords )
235
+ ? ( parsedAnimationKeywords [ value ] + 1 )
236
+ : 0 ;
237
+
238
+ shouldParseAnimationName = ( parsedAnimationKeywords [ value ] >= animationKeywords [ value ] ) ;
239
+ } else {
240
+ shouldParseAnimationName = true ;
241
+ }
242
+ }
243
+
244
+ var subContext = {
245
+ options : context . options ,
246
+ global : context . global ,
247
+ localizeNextItem : shouldParseAnimationName && ! context . global
248
+ } ;
249
+ return localizeDeclNode ( valueNode , subContext ) ;
250
+ } ) ;
251
+ }
252
+
253
+ function localizeAnimationShorthandDeclValues ( valuesNode , decl , context ) {
254
+ var newValuesNode = Object . create ( valuesNode ) ;
255
+ newValuesNode . nodes = valuesNode . nodes . map ( function ( valueNode , index ) {
256
+ var newValueNode = Object . create ( valueNode ) ;
257
+ newValueNode . nodes = localizeAnimationShorthandDeclValueNodes ( valueNode . nodes , context ) ;
258
+ return newValueNode ;
259
+ } ) ;
260
+ decl . value = Tokenizer . stringifyValues ( newValuesNode ) ;
261
+ }
262
+
263
+ function localizeDeclValues ( localize , valuesNode , decl , context ) {
188
264
var newValuesNode = Object . create ( valuesNode ) ;
189
265
newValuesNode . nodes = valuesNode . nodes . map ( function ( valueNode ) {
190
266
var subContext = {
191
267
options : context . options ,
192
268
global : context . global ,
193
- localizeNextItem : localizeName && ! context . global
269
+ localizeNextItem : localize && ! context . global
194
270
} ;
195
271
return localizeDeclValue ( valueNode , subContext ) ;
196
272
} ) ;
197
273
decl . value = Tokenizer . stringifyValues ( newValuesNode ) ;
198
274
}
199
275
276
+ function localizeDecl ( decl , context ) {
277
+ var valuesNode = Tokenizer . parseValues ( decl . value ) ;
278
+
279
+ var isAnimation = / a n i m a t i o n ? $ / . test ( decl . prop ) ;
280
+ if ( isAnimation ) return localizeAnimationShorthandDeclValues ( valuesNode , decl , context ) ;
281
+
282
+ var isAnimationName = / a n i m a t i o n ( - n a m e ) ? $ / . test ( decl . prop ) ;
283
+ if ( isAnimationName ) return localizeDeclValues ( true , valuesNode , decl , context ) ;
284
+
285
+ return localizeDeclValues ( false , valuesNode , decl , context ) ;
286
+ }
287
+
200
288
module . exports = postcss . plugin ( 'postcss-modules-local-by-default' , function ( options ) {
201
289
if ( typeof options !== 'object' ) {
202
290
options = { } ; // If options is undefined or not an object the plugin fails
0 commit comments