diff --git a/src/args.rs b/src/args.rs index 4b89235..9df8016 100644 --- a/src/args.rs +++ b/src/args.rs @@ -32,6 +32,10 @@ impl CallArgs { pub fn get(&self, val: &str) -> Option<&Value> { self.0.get(val) } + + pub fn len(&self) -> usize { + self.0.len() + } } pub(crate) fn eat_func_args>( diff --git a/src/builtin/color.rs b/src/builtin/color.rs index ec93262..4ab295b 100644 --- a/src/builtin/color.rs +++ b/src/builtin/color.rs @@ -36,8 +36,49 @@ pub(crate) fn register(f: &mut BTreeMap) { } }); decl!(f "rgba", |args, _| { - let channels = args.get("channels").unwrap_or(&Value::Null); - if channels.is_null() { + + if args.len() == 1 { + let mut channels = match arg!(args, 0, "channels").eval() { + Value::List(v, _) => v, + _ => todo!("missing element $green") + }; + + assert_eq!(channels.len(), 3usize); + + let blue = match channels.pop() { + Some(Value::Dimension(n, Unit::None)) => n, + Some(Value::Dimension(n, Unit::Percent)) => n / Number::from(100), + _ => todo!("$blue: ___ is not a color") + }; + + let green = match channels.pop() { + Some(Value::Dimension(n, Unit::None)) => n, + Some(Value::Dimension(n, Unit::Percent)) => n / Number::from(100), + _ => todo!("$green: ___ is not a color") + }; + + let red = match channels.pop() { + Some(Value::Dimension(n, Unit::None)) => n, + Some(Value::Dimension(n, Unit::Percent)) => n / Number::from(100), + _ => todo!("$red: ___ is not a color") + }; + + let color = Color::from_rgba(red, green, blue, Number::from(1)); + + Some(Value::Color(color)) + + } else if args.len() == 2 { + let color = match arg!(args, 0, "color").eval() { + Value::Color(c) => c, + _ => todo!("expected color") + }; + let alpha = match arg!(args, 1, "alpha").eval() { + Value::Dimension(n, Unit::None) => n, + Value::Dimension(n, Unit::Percent) => n / Number::from(100), + _ => todo!("expected either unitless or % number for alpha"), + }; + Some(Value::Color(color.with_alpha(alpha))) + } else { let red = match arg!(args, 0, "red").eval() { Value::Dimension(n, Unit::None) => n, Value::Dimension(n, Unit::Percent) => (n / Number::from(100)) * Number::from(255), @@ -59,8 +100,6 @@ pub(crate) fn register(f: &mut BTreeMap) { _ => todo!("expected either unitless or % number for alpha"), }; Some(Value::Color(Color::from_rgba(red, green, blue, alpha))) - } else { - todo!("channels variable in `rgba`") } }); decl!(f "hsl", |args, _| { diff --git a/src/color/mod.rs b/src/color/mod.rs index 9c155e9..29dac18 100644 --- a/src/color/mod.rs +++ b/src/color/mod.rs @@ -171,6 +171,10 @@ impl Color { self.alpha.clone() } + pub fn with_alpha(self, alpha: Number) -> Self { + Color::from_rgba(self.red, self.green, self.blue, alpha) + } + /// Makes a color more opaque. /// Takes a color and a number between 0 and 1, /// and returns a color with the opacity increased by that amount. diff --git a/src/selector.rs b/src/selector.rs index 36d537e..04e704f 100644 --- a/src/selector.rs +++ b/src/selector.rs @@ -276,7 +276,9 @@ impl<'a> SelectorParser<'a> { } if let Some(Token { kind, .. }) = tokens.next() { match kind { - TokenKind::Ident(v) | TokenKind::Number(v) => self.selectors.push(SelectorKind::Element(v)), + TokenKind::Ident(v) | TokenKind::Number(v) => { + self.selectors.push(SelectorKind::Element(v)) + } TokenKind::Symbol(Symbol::Period) => self.selectors.push(SelectorKind::Class), TokenKind::Symbol(Symbol::Hash) => self.selectors.push(SelectorKind::Id), TokenKind::Symbol(Symbol::Colon) => self.consume_pseudo_selector(tokens), diff --git a/tests/color.rs b/tests/color.rs index 3c9dc14..3255070 100644 --- a/tests/color.rs +++ b/tests/color.rs @@ -81,6 +81,18 @@ test!( opacity_function_number_unit, "a {\n color: opacity(1px);\n}\n" ); +// blocked on better function-call argument parsing +// specifically, passing lists as values +// test!( +// rgba_one_arg, +// "a {\n color: rgba(1 2 3);;\n}\n", +// "a {\n color: #010203;\n}\n" +// ); +test!( + rgba_two_args, + "a {\n color: rgba(red, 0.5);\n}\n", + "a {\n color: rgba(255, 0, 0, 0.5);\n}\n" +); test!( rgba_opacity_over_1, "a {\n color: rgba(1, 2, 3, 3);\n}\n",