From ba25cbf38dd2272525ac8ffd7e192997b506e685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 2 Aug 2023 12:24:17 +0200 Subject: [PATCH] color: Expose named colors more directly. This will allow me to remove some duplicated version of this from Gecko. This changes the API of ascii_case_insensitive_phf_map, so needs to be a breaking bump. --- Cargo.toml | 2 +- src/color.rs | 338 ++++++++++++++++++++++++++------------------------ src/lib.rs | 7 +- src/macros.rs | 31 +++-- src/tests.rs | 4 +- 5 files changed, 203 insertions(+), 179 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f35bdc75..d322168c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cssparser" -version = "0.31.2" +version = "0.32.0" authors = [ "Simon Sapin " ] description = "Rust implementation of CSS Syntax Level 3" diff --git a/src/color.rs b/src/color.rs index 30a195e1..6c6ae8e1 100644 --- a/src/color.rs +++ b/src/color.rs @@ -999,6 +999,178 @@ impl FromParsedColor for Color { } } +ascii_case_insensitive_phf_map! { + named_colors -> (u8, u8, u8) = { + "black" => (0, 0, 0), + "silver" => (192, 192, 192), + "gray" => (128, 128, 128), + "white" => (255, 255, 255), + "maroon" => (128, 0, 0), + "red" => (255, 0, 0), + "purple" => (128, 0, 128), + "fuchsia" => (255, 0, 255), + "green" => (0, 128, 0), + "lime" => (0, 255, 0), + "olive" => (128, 128, 0), + "yellow" => (255, 255, 0), + "navy" => (0, 0, 128), + "blue" => (0, 0, 255), + "teal" => (0, 128, 128), + "aqua" => (0, 255, 255), + + "aliceblue" => (240, 248, 255), + "antiquewhite" => (250, 235, 215), + "aquamarine" => (127, 255, 212), + "azure" => (240, 255, 255), + "beige" => (245, 245, 220), + "bisque" => (255, 228, 196), + "blanchedalmond" => (255, 235, 205), + "blueviolet" => (138, 43, 226), + "brown" => (165, 42, 42), + "burlywood" => (222, 184, 135), + "cadetblue" => (95, 158, 160), + "chartreuse" => (127, 255, 0), + "chocolate" => (210, 105, 30), + "coral" => (255, 127, 80), + "cornflowerblue" => (100, 149, 237), + "cornsilk" => (255, 248, 220), + "crimson" => (220, 20, 60), + "cyan" => (0, 255, 255), + "darkblue" => (0, 0, 139), + "darkcyan" => (0, 139, 139), + "darkgoldenrod" => (184, 134, 11), + "darkgray" => (169, 169, 169), + "darkgreen" => (0, 100, 0), + "darkgrey" => (169, 169, 169), + "darkkhaki" => (189, 183, 107), + "darkmagenta" => (139, 0, 139), + "darkolivegreen" => (85, 107, 47), + "darkorange" => (255, 140, 0), + "darkorchid" => (153, 50, 204), + "darkred" => (139, 0, 0), + "darksalmon" => (233, 150, 122), + "darkseagreen" => (143, 188, 143), + "darkslateblue" => (72, 61, 139), + "darkslategray" => (47, 79, 79), + "darkslategrey" => (47, 79, 79), + "darkturquoise" => (0, 206, 209), + "darkviolet" => (148, 0, 211), + "deeppink" => (255, 20, 147), + "deepskyblue" => (0, 191, 255), + "dimgray" => (105, 105, 105), + "dimgrey" => (105, 105, 105), + "dodgerblue" => (30, 144, 255), + "firebrick" => (178, 34, 34), + "floralwhite" => (255, 250, 240), + "forestgreen" => (34, 139, 34), + "gainsboro" => (220, 220, 220), + "ghostwhite" => (248, 248, 255), + "gold" => (255, 215, 0), + "goldenrod" => (218, 165, 32), + "greenyellow" => (173, 255, 47), + "grey" => (128, 128, 128), + "honeydew" => (240, 255, 240), + "hotpink" => (255, 105, 180), + "indianred" => (205, 92, 92), + "indigo" => (75, 0, 130), + "ivory" => (255, 255, 240), + "khaki" => (240, 230, 140), + "lavender" => (230, 230, 250), + "lavenderblush" => (255, 240, 245), + "lawngreen" => (124, 252, 0), + "lemonchiffon" => (255, 250, 205), + "lightblue" => (173, 216, 230), + "lightcoral" => (240, 128, 128), + "lightcyan" => (224, 255, 255), + "lightgoldenrodyellow" => (250, 250, 210), + "lightgray" => (211, 211, 211), + "lightgreen" => (144, 238, 144), + "lightgrey" => (211, 211, 211), + "lightpink" => (255, 182, 193), + "lightsalmon" => (255, 160, 122), + "lightseagreen" => (32, 178, 170), + "lightskyblue" => (135, 206, 250), + "lightslategray" => (119, 136, 153), + "lightslategrey" => (119, 136, 153), + "lightsteelblue" => (176, 196, 222), + "lightyellow" => (255, 255, 224), + "limegreen" => (50, 205, 50), + "linen" => (250, 240, 230), + "magenta" => (255, 0, 255), + "mediumaquamarine" => (102, 205, 170), + "mediumblue" => (0, 0, 205), + "mediumorchid" => (186, 85, 211), + "mediumpurple" => (147, 112, 219), + "mediumseagreen" => (60, 179, 113), + "mediumslateblue" => (123, 104, 238), + "mediumspringgreen" => (0, 250, 154), + "mediumturquoise" => (72, 209, 204), + "mediumvioletred" => (199, 21, 133), + "midnightblue" => (25, 25, 112), + "mintcream" => (245, 255, 250), + "mistyrose" => (255, 228, 225), + "moccasin" => (255, 228, 181), + "navajowhite" => (255, 222, 173), + "oldlace" => (253, 245, 230), + "olivedrab" => (107, 142, 35), + "orange" => (255, 165, 0), + "orangered" => (255, 69, 0), + "orchid" => (218, 112, 214), + "palegoldenrod" => (238, 232, 170), + "palegreen" => (152, 251, 152), + "paleturquoise" => (175, 238, 238), + "palevioletred" => (219, 112, 147), + "papayawhip" => (255, 239, 213), + "peachpuff" => (255, 218, 185), + "peru" => (205, 133, 63), + "pink" => (255, 192, 203), + "plum" => (221, 160, 221), + "powderblue" => (176, 224, 230), + "rebeccapurple" => (102, 51, 153), + "rosybrown" => (188, 143, 143), + "royalblue" => (65, 105, 225), + "saddlebrown" => (139, 69, 19), + "salmon" => (250, 128, 114), + "sandybrown" => (244, 164, 96), + "seagreen" => (46, 139, 87), + "seashell" => (255, 245, 238), + "sienna" => (160, 82, 45), + "skyblue" => (135, 206, 235), + "slateblue" => (106, 90, 205), + "slategray" => (112, 128, 144), + "slategrey" => (112, 128, 144), + "snow" => (255, 250, 250), + "springgreen" => (0, 255, 127), + "steelblue" => (70, 130, 180), + "tan" => (210, 180, 140), + "thistle" => (216, 191, 216), + "tomato" => (255, 99, 71), + "turquoise" => (64, 224, 208), + "violet" => (238, 130, 238), + "wheat" => (245, 222, 179), + "whitesmoke" => (245, 245, 245), + "yellowgreen" => (154, 205, 50), + } +} + +/// Returns the named color with the given name. +/// +#[inline] +pub fn parse_named_color(ident: &str) -> Result +where + Output: FromParsedColor, +{ + let &(r, g, b) = named_colors::get(ident).ok_or(())?; + Ok(Output::from_rgba(r, g, b, 1.0)) +} + +/// Returns an iterator over all named CSS colors. +/// +#[inline] +pub fn all_named_colors() -> impl Iterator { + named_colors::entries().map(|(k, v)| (*k, *v)) +} + /// Return the named color with the given name. /// /// Matching is case-insensitive in the ASCII range. @@ -1009,167 +1181,11 @@ pub fn parse_color_keyword(ident: &str) -> Result where Output: FromParsedColor, { - ascii_case_insensitive_phf_map! { - keyword -> (u8, u8, u8) = { - "black" => (0, 0, 0), - "silver" => (192, 192, 192), - "gray" => (128, 128, 128), - "white" => (255, 255, 255), - "maroon" => (128, 0, 0), - "red" => (255, 0, 0), - "purple" => (128, 0, 128), - "fuchsia" => (255, 0, 255), - "green" => (0, 128, 0), - "lime" => (0, 255, 0), - "olive" => (128, 128, 0), - "yellow" => (255, 255, 0), - "navy" => (0, 0, 128), - "blue" => (0, 0, 255), - "teal" => (0, 128, 128), - "aqua" => (0, 255, 255), - - "aliceblue" => (240, 248, 255), - "antiquewhite" => (250, 235, 215), - "aquamarine" => (127, 255, 212), - "azure" => (240, 255, 255), - "beige" => (245, 245, 220), - "bisque" => (255, 228, 196), - "blanchedalmond" => (255, 235, 205), - "blueviolet" => (138, 43, 226), - "brown" => (165, 42, 42), - "burlywood" => (222, 184, 135), - "cadetblue" => (95, 158, 160), - "chartreuse" => (127, 255, 0), - "chocolate" => (210, 105, 30), - "coral" => (255, 127, 80), - "cornflowerblue" => (100, 149, 237), - "cornsilk" => (255, 248, 220), - "crimson" => (220, 20, 60), - "cyan" => (0, 255, 255), - "darkblue" => (0, 0, 139), - "darkcyan" => (0, 139, 139), - "darkgoldenrod" => (184, 134, 11), - "darkgray" => (169, 169, 169), - "darkgreen" => (0, 100, 0), - "darkgrey" => (169, 169, 169), - "darkkhaki" => (189, 183, 107), - "darkmagenta" => (139, 0, 139), - "darkolivegreen" => (85, 107, 47), - "darkorange" => (255, 140, 0), - "darkorchid" => (153, 50, 204), - "darkred" => (139, 0, 0), - "darksalmon" => (233, 150, 122), - "darkseagreen" => (143, 188, 143), - "darkslateblue" => (72, 61, 139), - "darkslategray" => (47, 79, 79), - "darkslategrey" => (47, 79, 79), - "darkturquoise" => (0, 206, 209), - "darkviolet" => (148, 0, 211), - "deeppink" => (255, 20, 147), - "deepskyblue" => (0, 191, 255), - "dimgray" => (105, 105, 105), - "dimgrey" => (105, 105, 105), - "dodgerblue" => (30, 144, 255), - "firebrick" => (178, 34, 34), - "floralwhite" => (255, 250, 240), - "forestgreen" => (34, 139, 34), - "gainsboro" => (220, 220, 220), - "ghostwhite" => (248, 248, 255), - "gold" => (255, 215, 0), - "goldenrod" => (218, 165, 32), - "greenyellow" => (173, 255, 47), - "grey" => (128, 128, 128), - "honeydew" => (240, 255, 240), - "hotpink" => (255, 105, 180), - "indianred" => (205, 92, 92), - "indigo" => (75, 0, 130), - "ivory" => (255, 255, 240), - "khaki" => (240, 230, 140), - "lavender" => (230, 230, 250), - "lavenderblush" => (255, 240, 245), - "lawngreen" => (124, 252, 0), - "lemonchiffon" => (255, 250, 205), - "lightblue" => (173, 216, 230), - "lightcoral" => (240, 128, 128), - "lightcyan" => (224, 255, 255), - "lightgoldenrodyellow" => (250, 250, 210), - "lightgray" => (211, 211, 211), - "lightgreen" => (144, 238, 144), - "lightgrey" => (211, 211, 211), - "lightpink" => (255, 182, 193), - "lightsalmon" => (255, 160, 122), - "lightseagreen" => (32, 178, 170), - "lightskyblue" => (135, 206, 250), - "lightslategray" => (119, 136, 153), - "lightslategrey" => (119, 136, 153), - "lightsteelblue" => (176, 196, 222), - "lightyellow" => (255, 255, 224), - "limegreen" => (50, 205, 50), - "linen" => (250, 240, 230), - "magenta" => (255, 0, 255), - "mediumaquamarine" => (102, 205, 170), - "mediumblue" => (0, 0, 205), - "mediumorchid" => (186, 85, 211), - "mediumpurple" => (147, 112, 219), - "mediumseagreen" => (60, 179, 113), - "mediumslateblue" => (123, 104, 238), - "mediumspringgreen" => (0, 250, 154), - "mediumturquoise" => (72, 209, 204), - "mediumvioletred" => (199, 21, 133), - "midnightblue" => (25, 25, 112), - "mintcream" => (245, 255, 250), - "mistyrose" => (255, 228, 225), - "moccasin" => (255, 228, 181), - "navajowhite" => (255, 222, 173), - "oldlace" => (253, 245, 230), - "olivedrab" => (107, 142, 35), - "orange" => (255, 165, 0), - "orangered" => (255, 69, 0), - "orchid" => (218, 112, 214), - "palegoldenrod" => (238, 232, 170), - "palegreen" => (152, 251, 152), - "paleturquoise" => (175, 238, 238), - "palevioletred" => (219, 112, 147), - "papayawhip" => (255, 239, 213), - "peachpuff" => (255, 218, 185), - "peru" => (205, 133, 63), - "pink" => (255, 192, 203), - "plum" => (221, 160, 221), - "powderblue" => (176, 224, 230), - "rebeccapurple" => (102, 51, 153), - "rosybrown" => (188, 143, 143), - "royalblue" => (65, 105, 225), - "saddlebrown" => (139, 69, 19), - "salmon" => (250, 128, 114), - "sandybrown" => (244, 164, 96), - "seagreen" => (46, 139, 87), - "seashell" => (255, 245, 238), - "sienna" => (160, 82, 45), - "skyblue" => (135, 206, 235), - "slateblue" => (106, 90, 205), - "slategray" => (112, 128, 144), - "slategrey" => (112, 128, 144), - "snow" => (255, 250, 250), - "springgreen" => (0, 255, 127), - "steelblue" => (70, 130, 180), - "tan" => (210, 180, 140), - "thistle" => (216, 191, 216), - "tomato" => (255, 99, 71), - "turquoise" => (64, 224, 208), - "violet" => (238, 130, 238), - "wheat" => (245, 222, 179), - "whitesmoke" => (245, 245, 245), - "yellowgreen" => (154, 205, 50), - } - } - - match_ignore_ascii_case! { ident , - "transparent" => Ok(Output::from_rgba(0, 0, 0, 0.0)), - "currentcolor" => Ok(Output::from_current_color()), - _ => keyword(ident) - .map(|&(r, g, b)| Output::from_rgba(r, g, b, 1.0)) - .ok_or(()), - } + Ok(match_ignore_ascii_case! { ident , + "transparent" => Output::from_rgba(0, 0, 0, 0.0), + "currentcolor" => Output::from_current_color(), + _ => return parse_named_color(ident), + }) } #[inline] diff --git a/src/lib.rs b/src/lib.rs index 74173cf6..143ec87b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,9 +68,10 @@ fn parse_border_spacing(_context: &ParserContext, input: &mut Parser) #![recursion_limit = "200"] // For color::parse_color_keyword pub use crate::color::{ - hsl_to_rgb, hwb_to_rgb, parse_color_keyword, parse_color_with, parse_hash_color, - serialize_color_alpha, AngleOrNumber, Color, ColorFunction, ColorParser, FromParsedColor, Hsl, - Hwb, Lab, Lch, NumberOrPercentage, Oklab, Oklch, PredefinedColorSpace, RgbaLegacy, + all_named_colors, hsl_to_rgb, hwb_to_rgb, parse_color_keyword, parse_color_with, + parse_hash_color, parse_named_color, serialize_color_alpha, AngleOrNumber, Color, + ColorFunction, ColorParser, FromParsedColor, Hsl, Hwb, Lab, Lch, NumberOrPercentage, Oklab, + Oklch, PredefinedColorSpace, RgbaLegacy, }; pub use crate::cow_rc_str::CowRcStr; pub use crate::from_bytes::{stylesheet_encoding, EncodingSupport}; diff --git a/src/macros.rs b/src/macros.rs index 981af010..04b385ca 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -76,36 +76,43 @@ macro_rules! match_ignore_ascii_case { /// /// fn color_rgb(input: &str) -> Option<(u8, u8, u8)> { /// cssparser::ascii_case_insensitive_phf_map! { -/// keyword -> (u8, u8, u8) = { +/// keywords -> (u8, u8, u8) = { /// "red" => (255, 0, 0), /// "green" => (0, 255, 0), /// "blue" => (0, 0, 255), /// } /// } -/// keyword(input).cloned() +/// keywords::get(input).cloned() /// } +/// ``` +/// +/// You can also iterate over the map entries by using `keywords::entries()`. #[macro_export] macro_rules! ascii_case_insensitive_phf_map { ($name: ident -> $ValueType: ty = { $( $key: tt => $value: expr ),+ }) => { ascii_case_insensitive_phf_map!($name -> $ValueType = { $( $key => $value, )+ }) }; ($name: ident -> $ValueType: ty = { $( $key: tt => $value: expr, )+ }) => { - pub fn $name(input: &str) -> Option<&'static $ValueType> { - // This dummy module works around a feature gate, - // see comment on the similar module in `match_ignore_ascii_case!` above. - mod _cssparser_internal { - $crate::_cssparser_internal_max_len! { - $( $key )+ - } - } + mod $name { use $crate::_cssparser_internal_phf as phf; + $crate::_cssparser_internal_max_len! { + $( $key )+ + } static MAP: phf::Map<&'static str, $ValueType> = phf::phf_map! { $( $key => $value, )* }; - $crate::_cssparser_internal_to_lowercase!(input, _cssparser_internal::MAX_LENGTH => lowercase); - lowercase.and_then(|s| MAP.get(s)) + + #[allow(dead_code)] + pub fn entries() -> impl Iterator { + MAP.entries() + } + + pub fn get(input: &str) -> Option<&'static $ValueType> { + $crate::_cssparser_internal_to_lowercase!(input, MAX_LENGTH => lowercase); + MAP.get(lowercase?) + } } } } diff --git a/src/tests.rs b/src/tests.rs index fac0b6be..658c4a3a 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1213,8 +1213,8 @@ fn procedural_masquerade_whitespace() { " \t\n" => () } } - assert_eq!(map(" \t\n"), Some(&())); - assert_eq!(map(" "), None); + assert_eq!(map::get(" \t\n"), Some(&())); + assert_eq!(map::get(" "), None); match_ignore_ascii_case! { " \t\n", " " => panic!("1"),