@@ -712,7 +712,7 @@ impl Rgb {
712712 } ) ?;
713713
714714 if let SimpleToken :: Function ( name) = function_token {
715- if name != "rgb" {
715+ if name. to_lowercase ( ) != "rgb" {
716716 return Err ( CssParseError :: ParseError {
717717 message : format ! ( "Expected 'rgb' function, got '{}'" , name) ,
718718 } ) ;
@@ -723,6 +723,11 @@ impl Rgb {
723723 } ) ;
724724 }
725725
726+ // Skip optional whitespace before first value
727+ while let Ok ( Some ( SimpleToken :: Whitespace ) ) = tokens. peek ( ) {
728+ tokens. consume_next_token ( ) ?;
729+ }
730+
726731 // Parse r value
727732 let r = Self :: parse_rgb_number_token ( tokens) ?;
728733
@@ -738,6 +743,11 @@ impl Rgb {
738743 // Parse b value
739744 let b = Self :: parse_rgb_number_token ( tokens) ?;
740745
746+ // Skip optional whitespace before closing paren
747+ while let Ok ( Some ( SimpleToken :: Whitespace ) ) = tokens. peek ( ) {
748+ tokens. consume_next_token ( ) ?;
749+ }
750+
741751 // Expect closing paren
742752 let close_token = tokens
743753 . consume_next_token ( ) ?
@@ -769,7 +779,7 @@ impl Rgb {
769779 } ) ?;
770780
771781 if let SimpleToken :: Function ( name) = function_token {
772- if name != "rgb" {
782+ if name. to_lowercase ( ) != "rgb" {
773783 return Err ( CssParseError :: ParseError {
774784 message : format ! ( "Expected 'rgb' function, got '{}'" , name) ,
775785 } ) ;
@@ -885,7 +895,7 @@ impl Rgb {
885895
886896impl Display for Rgb {
887897 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
888- write ! ( f, "rgb({},{},{})" , self . r, self . g, self . b)
898+ write ! ( f, "rgb({}, {}, {})" , self . r, self . g, self . b)
889899 }
890900}
891901
@@ -919,7 +929,7 @@ impl Rgba {
919929 } ) ?;
920930
921931 if let SimpleToken :: Function ( name) = function_token {
922- if name != "rgba" {
932+ if name. to_lowercase ( ) != "rgba" {
923933 return Err ( CssParseError :: ParseError {
924934 message : format ! ( "Expected 'rgba' function, got '{}'" , name) ,
925935 } ) ;
@@ -930,6 +940,11 @@ impl Rgba {
930940 } ) ;
931941 }
932942
943+ // Skip optional whitespace before first value
944+ while let Ok ( Some ( SimpleToken :: Whitespace ) ) = tokens. peek ( ) {
945+ tokens. consume_next_token ( ) ?;
946+ }
947+
933948 // Parse r value
934949 let r = Self :: parse_rgba_number_token ( tokens) ?;
935950
@@ -951,6 +966,11 @@ impl Rgba {
951966 // Parse alpha value
952967 let a = Self :: parse_alpha_value_token ( tokens) ?;
953968
969+ // Skip optional whitespace before closing paren
970+ while let Ok ( Some ( SimpleToken :: Whitespace ) ) = tokens. peek ( ) {
971+ tokens. consume_next_token ( ) ?;
972+ }
973+
954974 // Expect closing paren
955975 let close_token = tokens
956976 . consume_next_token ( ) ?
@@ -970,21 +990,21 @@ impl Rgba {
970990 )
971991 }
972992
973- /// Parse space-separated RGBA with slash: rgb(255 0 0 / 0.5)
993+ /// Parse space-separated RGBA with slash: rgb(255 0 0 / 0.5) or rgba(255 0 0 / 0.5)
974994 fn space_slash_parser ( ) -> TokenParser < Rgba > {
975995 TokenParser :: new (
976996 |tokens| {
977- // Expect Function("rgb") - note: uses rgb, not rgba!
997+ // Expect Function("rgb" or " rgba")
978998 let function_token = tokens
979999 . consume_next_token ( ) ?
9801000 . ok_or ( CssParseError :: ParseError {
981- message : "Expected RGB function" . to_string ( ) ,
1001+ message : "Expected RGB/RGBA function" . to_string ( ) ,
9821002 } ) ?;
9831003
9841004 if let SimpleToken :: Function ( name) = function_token {
985- if name != "rgb" {
1005+ if name. to_lowercase ( ) != "rgb" && name . to_lowercase ( ) != "rgba " {
9861006 return Err ( CssParseError :: ParseError {
987- message : format ! ( "Expected 'rgb' function, got '{}'" , name) ,
1007+ message : format ! ( "Expected 'rgb' or 'rgba' function, got '{}'" , name) ,
9881008 } ) ;
9891009 }
9901010 } else {
@@ -1164,7 +1184,7 @@ impl Rgba {
11641184
11651185impl Display for Rgba {
11661186 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1167- write ! ( f, "rgba({},{},{},{})" , self . r, self . g, self . b, self . a)
1187+ write ! ( f, "rgba({}, {}, {}, {})" , self . r, self . g, self . b, self . a)
11681188 }
11691189}
11701190
@@ -1207,7 +1227,7 @@ impl Hsl {
12071227 } ) ?;
12081228
12091229 if let SimpleToken :: Function ( name) = function_token {
1210- if name != "hsl" {
1230+ if name. to_lowercase ( ) != "hsl" {
12111231 return Err ( CssParseError :: ParseError {
12121232 message : format ! ( "Expected 'hsl' function, got '{}'" , name) ,
12131233 } ) ;
@@ -1218,6 +1238,11 @@ impl Hsl {
12181238 } ) ;
12191239 }
12201240
1241+ // Skip optional whitespace before first value
1242+ while let Ok ( Some ( SimpleToken :: Whitespace ) ) = tokens. peek ( ) {
1243+ tokens. consume_next_token ( ) ?;
1244+ }
1245+
12211246 // Parse hue value (angle or number)
12221247 let h = Self :: parse_hsl_hue_token ( tokens) ?;
12231248
@@ -1233,6 +1258,11 @@ impl Hsl {
12331258 // Parse lightness percentage
12341259 let l = Self :: parse_hsl_percentage_token ( tokens) ?;
12351260
1261+ // Skip optional whitespace before closing paren
1262+ while let Ok ( Some ( SimpleToken :: Whitespace ) ) = tokens. peek ( ) {
1263+ tokens. consume_next_token ( ) ?;
1264+ }
1265+
12361266 // Expect closing paren
12371267 let close_token = tokens
12381268 . consume_next_token ( ) ?
@@ -1264,7 +1294,7 @@ impl Hsl {
12641294 } ) ?;
12651295
12661296 if let SimpleToken :: Function ( name) = function_token {
1267- if name != "hsl" {
1297+ if name. to_lowercase ( ) != "hsl" {
12681298 return Err ( CssParseError :: ParseError {
12691299 message : format ! ( "Expected 'hsl' function, got '{}'" , name) ,
12701300 } ) ;
@@ -1408,8 +1438,7 @@ impl Hsl {
14081438
14091439impl Display for Hsl {
14101440 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1411- let h_value = self . h . value ; // Extract the numeric value without unit
1412- write ! ( f, "hsl({},{},{})" , h_value, self . s, self . l)
1441+ write ! ( f, "hsl({}, {}, {})" , self . h, self . s, self . l)
14131442 }
14141443}
14151444
@@ -1454,7 +1483,7 @@ impl Hsla {
14541483 } ) ?;
14551484
14561485 if let SimpleToken :: Function ( name) = function_token {
1457- if name != "hsla" {
1486+ if name. to_lowercase ( ) != "hsla" {
14581487 return Err ( CssParseError :: ParseError {
14591488 message : format ! ( "Expected 'hsla' function, got '{}'" , name) ,
14601489 } ) ;
@@ -1517,7 +1546,7 @@ impl Hsla {
15171546 } ) ?;
15181547
15191548 if let SimpleToken :: Function ( name) = function_token {
1520- if name != "hsl" {
1549+ if name. to_lowercase ( ) != "hsl" {
15211550 return Err ( CssParseError :: ParseError {
15221551 message : format ! ( "Expected 'hsl' function, got '{}'" , name) ,
15231552 } ) ;
@@ -1726,8 +1755,7 @@ impl Hsla {
17261755
17271756impl Display for Hsla {
17281757 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1729- let h_value = self . h . value ; // Extract the numeric value without unit
1730- write ! ( f, "hsla({},{},{},{})" , h_value, self . s, self . l, self . a)
1758+ write ! ( f, "hsla({}, {}, {}, {})" , self . h, self . s, self . l, self . a)
17311759 }
17321760}
17331761
@@ -1790,7 +1818,7 @@ impl Lch {
17901818 } ) ?;
17911819
17921820 if let SimpleToken :: Function ( name) = function_token {
1793- if name != "lch" {
1821+ if name. to_lowercase ( ) != "lch" {
17941822 return Err ( CssParseError :: ParseError {
17951823 message : format ! ( "Expected 'lch' function, got '{}'" , name) ,
17961824 } ) ;
@@ -1998,7 +2026,7 @@ impl Oklch {
19982026 move |input| {
19992027 // Parse 'oklch(' function start
20002028 match input. consume_next_token ( ) ? {
2001- Some ( SimpleToken :: Function ( fn_name) ) if fn_name == "oklch" => { }
2029+ Some ( SimpleToken :: Function ( fn_name) ) if fn_name. to_lowercase ( ) == "oklch" => { }
20022030 _ => {
20032031 return Err ( CssParseError :: ParseError {
20042032 message : "Expected oklch() function" . to_string ( ) ,
@@ -2065,7 +2093,7 @@ impl Oklch {
20652093 }
20662094 }
20672095
2068- /// Parse OKLCH hue: angle | number (number * 360 -> angle conversion)
2096+ /// Parse OKLCH hue: angle | number (interpreted as degrees) | 'none'
20692097 fn parse_oklch_hue ( input : & mut crate :: token_types:: TokenList ) -> Result < Angle , CssParseError > {
20702098 match input. consume_next_token ( ) ? {
20712099 Some ( SimpleToken :: Dimension { value, unit } ) => {
@@ -2078,9 +2106,12 @@ impl Oklch {
20782106 } )
20792107 }
20802108 }
2081- Some ( SimpleToken :: Number ( n) ) => Ok ( Angle :: new ( ( n as f32 ) * 360.0 , "deg" . to_string ( ) ) ) ,
2109+ Some ( SimpleToken :: Number ( n) ) => Ok ( Angle :: new ( n as f32 , "deg" . to_string ( ) ) ) ,
2110+ Some ( SimpleToken :: Ident ( keyword) ) if keyword == "none" => {
2111+ Ok ( Angle :: new ( 0.0 , "deg" . to_string ( ) ) )
2112+ }
20822113 _ => Err ( CssParseError :: ParseError {
2083- message : "Expected hue: angle or number " . to_string ( ) ,
2114+ message : "Expected hue: angle, number, or 'none' " . to_string ( ) ,
20842115 } ) ,
20852116 }
20862117 }
@@ -2153,7 +2184,7 @@ impl Oklab {
21532184 move |input| {
21542185 // Parse 'oklab(' function start
21552186 match input. consume_next_token ( ) ? {
2156- Some ( SimpleToken :: Function ( fn_name) ) if fn_name == "oklab" => { }
2187+ Some ( SimpleToken :: Function ( fn_name) ) if fn_name. to_lowercase ( ) == "oklab" => { }
21572188 _ => {
21582189 return Err ( CssParseError :: ParseError {
21592190 message : "Expected oklab() function" . to_string ( ) ,
@@ -2337,25 +2368,25 @@ mod tests {
23372368 #[ test]
23382369 fn test_rgb_color_display ( ) {
23392370 let color = Rgb :: new ( 255 , 0 , 0 ) ;
2340- assert_eq ! ( color. to_string( ) , "rgb(255,0, 0)" ) ;
2371+ assert_eq ! ( color. to_string( ) , "rgb(255, 0, 0)" ) ;
23412372 }
23422373
23432374 #[ test]
23442375 fn test_rgba_color_display ( ) {
23452376 let color = Rgba :: new ( 255 , 0 , 0 , 0.5 ) ;
2346- assert_eq ! ( color. to_string( ) , "rgba(255,0,0, 0.5)" ) ;
2377+ assert_eq ! ( color. to_string( ) , "rgba(255, 0, 0, 0.5)" ) ;
23472378 }
23482379
23492380 #[ test]
23502381 fn test_hsl_color_display ( ) {
23512382 let color = Hsl :: from_primitives ( 360.0 , 100.0 , 50.0 ) ;
2352- assert_eq ! ( color. to_string( ) , "hsl(360, 100%,50%)" ) ;
2383+ assert_eq ! ( color. to_string( ) , "hsl(360deg, 100%, 50%)" ) ;
23532384 }
23542385
23552386 #[ test]
23562387 fn test_hsla_color_display ( ) {
23572388 let color = Hsla :: from_primitives ( 360.0 , 100.0 , 50.0 , 0.8 ) ;
2358- assert_eq ! ( color. to_string( ) , "hsla(360, 100%,50%,0.8)" ) ;
2389+ assert_eq ! ( color. to_string( ) , "hsla(360deg, 100%, 50%, 0.8)" ) ;
23592390 }
23602391
23612392 #[ test]
@@ -2367,7 +2398,7 @@ mod tests {
23672398 assert_eq ! ( hash. to_string( ) , "#FF0000" ) ;
23682399
23692400 let rgb = Color :: Rgb ( Rgb :: new ( 255 , 0 , 0 ) ) ;
2370- assert_eq ! ( rgb. to_string( ) , "rgb(255,0, 0)" ) ;
2401+ assert_eq ! ( rgb. to_string( ) , "rgb(255, 0, 0)" ) ;
23712402 }
23722403
23732404 #[ test]
0 commit comments