@@ -182,21 +182,109 @@ function localizeDeclValue(valueNode, context) {
182182 return newValueNode ;
183183}
184184
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 ) {
188264 var newValuesNode = Object . create ( valuesNode ) ;
189265 newValuesNode . nodes = valuesNode . nodes . map ( function ( valueNode ) {
190266 var subContext = {
191267 options : context . options ,
192268 global : context . global ,
193- localizeNextItem : localizeName && ! context . global
269+ localizeNextItem : localize && ! context . global
194270 } ;
195271 return localizeDeclValue ( valueNode , subContext ) ;
196272 } ) ;
197273 decl . value = Tokenizer . stringifyValues ( newValuesNode ) ;
198274}
199275
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+
200288module . exports = postcss . plugin ( 'postcss-modules-local-by-default' , function ( options ) {
201289 if ( typeof options !== 'object' ) {
202290 options = { } ; // If options is undefined or not an object the plugin fails
0 commit comments