@@ -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