@@ -10,6 +10,7 @@ use crate::properties::{Property, PropertyId, VendorPrefix};
1010use crate :: targets:: Browsers ;
1111use crate :: traits:: { Parse , PropertyHandler , Shorthand , ToCss , Zero } ;
1212use crate :: values:: number:: CSSNumber ;
13+ use crate :: values:: string:: CowArcStr ;
1314use crate :: values:: { easing:: EasingFunction , ident:: CustomIdent , time:: Time } ;
1415use cssparser:: * ;
1516use itertools:: izip;
@@ -28,6 +29,9 @@ pub enum AnimationName<'i> {
2829 /// An identifier of a `@keyframes` rule.
2930 #[ cfg_attr( feature = "serde" , serde( borrow) ) ]
3031 Ident ( CustomIdent < ' i > ) ,
32+ /// A `<string>` name of a `@keyframes` rule.
33+ #[ cfg_attr( feature = "serde" , serde( borrow) ) ]
34+ String ( CowArcStr < ' i > ) ,
3135}
3236
3337impl < ' i > Parse < ' i > for AnimationName < ' i > {
@@ -36,13 +40,12 @@ impl<'i> Parse<'i> for AnimationName<'i> {
3640 return Ok ( AnimationName :: None ) ;
3741 }
3842
39- let location = input. current_source_location ( ) ;
40- let name = match * input. next ( ) ? {
41- Token :: Ident ( ref s) => s. into ( ) ,
42- Token :: QuotedString ( ref s) => s. into ( ) ,
43- ref t => return Err ( location. new_unexpected_token_error ( t. clone ( ) ) ) ,
44- } ;
45- Ok ( AnimationName :: Ident ( CustomIdent ( name) ) )
43+ if let Ok ( s) = input. try_parse ( |input| input. expect_string_cloned ( ) ) {
44+ return Ok ( AnimationName :: String ( s. into ( ) ) ) ;
45+ }
46+
47+ let ident = CustomIdent :: parse ( input) ?;
48+ Ok ( AnimationName :: Ident ( ident) )
4649 }
4750}
4851
@@ -59,6 +62,22 @@ impl<'i> ToCss for AnimationName<'i> {
5962 }
6063 s. to_css ( dest)
6164 }
65+ AnimationName :: String ( s) => {
66+ if let Some ( css_module) = & mut dest. css_module {
67+ css_module. reference ( & s, dest. loc . source_index )
68+ }
69+
70+ // CSS-wide keywords and `none` cannot remove quotes.
71+ match_ignore_ascii_case ! { & * s,
72+ "none" | "initial" | "inherit" | "unset" | "default" | "revert" | "revert-layer" => {
73+ serialize_string( & s, dest) ?;
74+ Ok ( ( ) )
75+ } ,
76+ _ => {
77+ dest. write_ident( s. as_ref( ) )
78+ }
79+ }
80+ }
6281 }
6382 }
6483}
@@ -219,15 +238,15 @@ impl<'i> ToCss for Animation<'i> {
219238 self . name . to_css ( dest) ?;
220239 match & self . name {
221240 AnimationName :: None => return Ok ( ( ) ) ,
222- AnimationName :: Ident ( name) => {
241+ AnimationName :: Ident ( CustomIdent ( name ) ) | AnimationName :: String ( name) => {
223242 if !self . duration . is_zero ( ) || !self . delay . is_zero ( ) {
224243 dest. write_char ( ' ' ) ?;
225244 self . duration . to_css ( dest) ?;
226245 }
227246
228247 if ( self . timing_function != EasingFunction :: Ease
229248 && self . timing_function != EasingFunction :: CubicBezier ( 0.25 , 0.1 , 0.25 , 1.0 ) )
230- || EasingFunction :: is_ident ( & name. 0 )
249+ || EasingFunction :: is_ident ( & name)
231250 {
232251 dest. write_char ( ' ' ) ?;
233252 self . timing_function . to_css ( dest) ?;
@@ -238,22 +257,22 @@ impl<'i> ToCss for Animation<'i> {
238257 self . delay . to_css ( dest) ?;
239258 }
240259
241- if self . iteration_count != AnimationIterationCount :: Number ( 1.0 ) || name. 0 == "infinite" {
260+ if self . iteration_count != AnimationIterationCount :: Number ( 1.0 ) || name. as_ref ( ) == "infinite" {
242261 dest. write_char ( ' ' ) ?;
243262 self . iteration_count . to_css ( dest) ?;
244263 }
245264
246- if self . direction != AnimationDirection :: Normal || AnimationDirection :: parse_string ( & name. 0 ) . is_ok ( ) {
265+ if self . direction != AnimationDirection :: Normal || AnimationDirection :: parse_string ( & name) . is_ok ( ) {
247266 dest. write_char ( ' ' ) ?;
248267 self . direction . to_css ( dest) ?;
249268 }
250269
251- if self . fill_mode != AnimationFillMode :: None || AnimationFillMode :: parse_string ( & name. 0 ) . is_ok ( ) {
270+ if self . fill_mode != AnimationFillMode :: None || AnimationFillMode :: parse_string ( & name) . is_ok ( ) {
252271 dest. write_char ( ' ' ) ?;
253272 self . fill_mode . to_css ( dest) ?;
254273 }
255274
256- if self . play_state != AnimationPlayState :: Running || AnimationPlayState :: parse_string ( & name. 0 ) . is_ok ( ) {
275+ if self . play_state != AnimationPlayState :: Running || AnimationPlayState :: parse_string ( & name) . is_ok ( ) {
257276 dest. write_char ( ' ' ) ?;
258277 self . play_state . to_css ( dest) ?;
259278 }
0 commit comments