@@ -15,6 +15,7 @@ use crate::traits::{Parse, ToCss};
1515use crate :: values:: color:: ColorFallbackKind ;
1616use crate :: values:: ident:: CustomIdent ;
1717use crate :: values:: percentage:: Percentage ;
18+ use crate :: values:: string:: CowArcStr ;
1819use crate :: vendor_prefix:: VendorPrefix ;
1920use cssparser:: * ;
2021
@@ -23,8 +24,9 @@ use cssparser::*;
2324#[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
2425pub struct KeyframesRule < ' i > {
2526 /// The animation name.
27+ /// <keyframes-name> = <custom-ident> | <string>
2628 #[ cfg_attr( feature = "serde" , serde( borrow) ) ]
27- pub name : CustomIdent < ' i > ,
29+ pub name : KeyframesName < ' i > ,
2830 /// A list of keyframes in the animation.
2931 pub keyframes : Vec < Keyframe < ' i > > ,
3032 /// A vendor prefix for the rule, e.g. `@-webkit-keyframes`.
@@ -33,6 +35,65 @@ pub struct KeyframesRule<'i> {
3335 pub loc : Location ,
3436}
3537
38+ /// KeyframesName
39+ #[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
40+ #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
41+ pub enum KeyframesName < ' i > {
42+ /// `<custom-ident>` of a `@keyframes` name.
43+ #[ cfg_attr( feature = "serde" , serde( borrow) ) ]
44+ Ident ( CustomIdent < ' i > ) ,
45+
46+ /// `<string>` of a `@keyframes` name.
47+ #[ cfg_attr( feature = "serde" , serde( borrow) ) ]
48+ Custom ( CowArcStr < ' i > ) ,
49+ }
50+
51+ impl < ' i > Parse < ' i > for KeyframesName < ' i > {
52+ fn parse < ' t > ( input : & mut Parser < ' i , ' t > ) -> Result < Self , ParseError < ' i , ParserError < ' i > > > {
53+ match input. next ( ) ?. clone ( ) {
54+ Token :: Ident ( ref s) => {
55+ // CSS-wide keywords without quotes throws an error.
56+ match_ignore_ascii_case ! { & * s,
57+ "none" | "initial" | "inherit" | "unset" | "default" | "revert" | "revert-layer" => {
58+ Err ( input. new_unexpected_token_error( Token :: Ident ( s. clone( ) ) ) )
59+ } ,
60+ _ => {
61+ Ok ( KeyframesName :: Ident ( CustomIdent ( s. into( ) ) ) )
62+ }
63+ }
64+ }
65+
66+ Token :: QuotedString ( ref s) => Ok ( KeyframesName :: Custom ( s. into ( ) ) ) ,
67+ t => return Err ( input. new_unexpected_token_error ( t. clone ( ) ) ) ,
68+ }
69+ }
70+ }
71+
72+ impl < ' i > ToCss for KeyframesName < ' i > {
73+ fn to_css < W > ( & self , dest : & mut Printer < W > ) -> Result < ( ) , PrinterError >
74+ where
75+ W : std:: fmt:: Write ,
76+ {
77+ match self {
78+ KeyframesName :: Ident ( ident) => {
79+ dest. write_ident ( ident. 0 . as_ref ( ) ) ?;
80+ }
81+ KeyframesName :: Custom ( s) => {
82+ // CSS-wide keywords and `none` cannot remove quotes.
83+ match_ignore_ascii_case ! { & * s,
84+ "none" | "initial" | "inherit" | "unset" | "default" | "revert" | "revert-layer" => {
85+ serialize_string( & s, dest) ?;
86+ } ,
87+ _ => {
88+ dest. write_ident( s. as_ref( ) ) ?;
89+ }
90+ }
91+ }
92+ }
93+ Ok ( ( ) )
94+ }
95+ }
96+
3697impl < ' i > KeyframesRule < ' i > {
3798 pub ( crate ) fn minify ( & mut self , context : & mut MinifyContext < ' _ , ' i > ) {
3899 context. handler_context . context = DeclarationContext :: Keyframes ;
0 commit comments