consolidate implementation of rgb and rgba
This commit is contained in:
parent
7e793392a7
commit
97425665f9
@ -4,258 +4,152 @@ use num_traits::One;
|
|||||||
|
|
||||||
use super::Builtin;
|
use super::Builtin;
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
|
use crate::common::QuoteKind;
|
||||||
use crate::unit::Unit;
|
use crate::unit::Unit;
|
||||||
use crate::value::{Number, Value};
|
use crate::value::{Number, Value};
|
||||||
|
|
||||||
pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||||
f.insert(
|
let rgb = Builtin::new(|mut args, scope, super_selector| {
|
||||||
"rgb".to_owned(),
|
if args.is_empty() {
|
||||||
Builtin::new(|mut args, scope, super_selector| {
|
return Err("Missing argument $channels.".into());
|
||||||
if args.is_empty() {
|
}
|
||||||
return Err("Missing argument $channels.".into());
|
|
||||||
|
if args.len() == 1 {
|
||||||
|
let mut channels = match arg!(args, scope, super_selector, 0, "channels") {
|
||||||
|
Value::List(v, ..) => v,
|
||||||
|
_ => return Err("Missing argument $channels.".into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
if channels.len() > 3 {
|
||||||
|
return Err(format!(
|
||||||
|
"Only 3 elements allowed, but {} were passed.",
|
||||||
|
channels.len()
|
||||||
|
)
|
||||||
|
.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.len() == 1 {
|
let blue = match channels.pop() {
|
||||||
let mut channels = match arg!(args, scope, super_selector, 0, "channels") {
|
Some(Value::Dimension(n, Unit::None)) => n,
|
||||||
Value::List(v, ..) => v,
|
Some(Value::Dimension(n, Unit::Percent)) => {
|
||||||
_ => return Err("Missing argument $channels.".into()),
|
(n / Number::from(100)) * Number::from(255)
|
||||||
};
|
|
||||||
|
|
||||||
if channels.len() > 3 {
|
|
||||||
return Err(format!(
|
|
||||||
"Only 3 elements allowed, but {} were passed.",
|
|
||||||
channels.len()
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
Some(v) => return Err(format!("$blue: {} is not a number.", v).into()),
|
||||||
|
None => return Err("Missing element $blue.".into()),
|
||||||
|
};
|
||||||
|
|
||||||
let blue = match channels.pop() {
|
let green = match channels.pop() {
|
||||||
Some(Value::Dimension(n, Unit::None)) => n,
|
Some(Value::Dimension(n, Unit::None)) => n,
|
||||||
Some(Value::Dimension(n, Unit::Percent)) => {
|
Some(Value::Dimension(n, Unit::Percent)) => {
|
||||||
(n / Number::from(100)) * Number::from(255)
|
(n / Number::from(100)) * Number::from(255)
|
||||||
}
|
|
||||||
Some(v) => return Err(format!("$blue: {} is not a number.", v).into()),
|
|
||||||
None => return Err("Missing element $blue.".into()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let green = match channels.pop() {
|
|
||||||
Some(Value::Dimension(n, Unit::None)) => n,
|
|
||||||
Some(Value::Dimension(n, Unit::Percent)) => {
|
|
||||||
(n / Number::from(100)) * Number::from(255)
|
|
||||||
}
|
|
||||||
Some(v) => return Err(format!("$green: {} is not a number.", v).into()),
|
|
||||||
None => return Err("Missing element $green.".into()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let red = match channels.pop() {
|
|
||||||
Some(Value::Dimension(n, Unit::None)) => n,
|
|
||||||
Some(Value::Dimension(n, Unit::Percent)) => {
|
|
||||||
(n / Number::from(100)) * Number::from(255)
|
|
||||||
}
|
|
||||||
Some(v) => return Err(format!("$red: {} is not a number.", v).into()),
|
|
||||||
None => return Err("Missing element $red.".into()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let color = Color::from_rgba(red, green, blue, Number::one());
|
|
||||||
|
|
||||||
Ok(Value::Color(color))
|
|
||||||
} else if args.len() == 2 {
|
|
||||||
let color = match arg!(args, scope, super_selector, 0, "color") {
|
|
||||||
Value::Color(c) => c,
|
|
||||||
v => return Err(format!("$color: {} is not a color.", v).into()),
|
|
||||||
};
|
|
||||||
let alpha = match arg!(args, scope, super_selector, 1, "alpha") {
|
|
||||||
Value::Dimension(n, Unit::None) => n,
|
|
||||||
Value::Dimension(n, Unit::Percent) => n / Number::from(100),
|
|
||||||
v @ Value::Dimension(..) => {
|
|
||||||
return Err(
|
|
||||||
format!("$alpha: Expected {} to have no units or \"%\".", v).into()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
v => return Err(format!("$alpha: {} is not a number.", v).into()),
|
|
||||||
};
|
|
||||||
Ok(Value::Color(color.with_alpha(alpha)))
|
|
||||||
} else {
|
|
||||||
let red = match arg!(args, scope, super_selector, 0, "red") {
|
|
||||||
Value::Dimension(n, Unit::None) => n,
|
|
||||||
Value::Dimension(n, Unit::Percent) => {
|
|
||||||
(n / Number::from(100)) * Number::from(255)
|
|
||||||
}
|
|
||||||
v @ Value::Dimension(..) => {
|
|
||||||
return Err(
|
|
||||||
format!("$red: Expected {} to have no units or \"%\".", v).into()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
v => return Err(format!("$red: {} is not a number.", v).into()),
|
|
||||||
};
|
|
||||||
let green = match arg!(args, scope, super_selector, 1, "green") {
|
|
||||||
Value::Dimension(n, Unit::None) => n,
|
|
||||||
Value::Dimension(n, Unit::Percent) => {
|
|
||||||
(n / Number::from(100)) * Number::from(255)
|
|
||||||
}
|
|
||||||
v @ Value::Dimension(..) => {
|
|
||||||
return Err(
|
|
||||||
format!("$green: Expected {} to have no units or \"%\".", v).into()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
v => return Err(format!("$green: {} is not a number.", v).into()),
|
|
||||||
};
|
|
||||||
let blue = match arg!(args, scope, super_selector, 2, "blue") {
|
|
||||||
Value::Dimension(n, Unit::None) => n,
|
|
||||||
Value::Dimension(n, Unit::Percent) => {
|
|
||||||
(n / Number::from(100)) * Number::from(255)
|
|
||||||
}
|
|
||||||
v @ Value::Dimension(..) => {
|
|
||||||
return Err(
|
|
||||||
format!("$blue: Expected {} to have no units or \"%\".", v).into()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
v => return Err(format!("$blue: {} is not a number.", v).into()),
|
|
||||||
};
|
|
||||||
let alpha = match arg!(
|
|
||||||
args,
|
|
||||||
scope,
|
|
||||||
super_selector,
|
|
||||||
3,
|
|
||||||
"alpha" = Value::Dimension(Number::one(), Unit::None)
|
|
||||||
) {
|
|
||||||
Value::Dimension(n, Unit::None) => n,
|
|
||||||
Value::Dimension(n, Unit::Percent) => n / Number::from(100),
|
|
||||||
v @ Value::Dimension(..) => {
|
|
||||||
return Err(
|
|
||||||
format!("$alpha: Expected {} to have no units or \"%\".", v).into()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
v => return Err(format!("$alpha: {} is not a number.", v).into()),
|
|
||||||
};
|
|
||||||
Ok(Value::Color(Color::from_rgba(red, green, blue, alpha)))
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
f.insert(
|
|
||||||
"rgba".to_owned(),
|
|
||||||
Builtin::new(|mut args, scope, super_selector| {
|
|
||||||
if args.is_empty() {
|
|
||||||
return Err("Missing argument $channels.".into());
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.len() == 1 {
|
|
||||||
let mut channels = match arg!(args, scope, super_selector, 0, "channels") {
|
|
||||||
Value::List(v, ..) => v,
|
|
||||||
_ => return Err("Missing argument $channels.".into()),
|
|
||||||
};
|
|
||||||
|
|
||||||
if channels.len() > 3 {
|
|
||||||
return Err(format!(
|
|
||||||
"Only 3 elements allowed, but {} were passed.",
|
|
||||||
channels.len()
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
Some(v) => return Err(format!("$green: {} is not a number.", v).into()),
|
||||||
|
None => return Err("Missing element $green.".into()),
|
||||||
|
};
|
||||||
|
|
||||||
let blue = match channels.pop() {
|
let red = match channels.pop() {
|
||||||
Some(Value::Dimension(n, Unit::None)) => n,
|
Some(Value::Dimension(n, Unit::None)) => n,
|
||||||
Some(Value::Dimension(n, Unit::Percent)) => {
|
Some(Value::Dimension(n, Unit::Percent)) => {
|
||||||
(n / Number::from(100)) * Number::from(255)
|
(n / Number::from(100)) * Number::from(255)
|
||||||
}
|
}
|
||||||
Some(v) => return Err(format!("$blue: {} is not a number.", v).into()),
|
Some(v) => return Err(format!("$red: {} is not a number.", v).into()),
|
||||||
None => return Err("Missing element $blue.".into()),
|
None => return Err("Missing element $red.".into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let green = match channels.pop() {
|
let color = Color::from_rgba(red, green, blue, Number::one());
|
||||||
Some(Value::Dimension(n, Unit::None)) => n,
|
|
||||||
Some(Value::Dimension(n, Unit::Percent)) => {
|
|
||||||
(n / Number::from(100)) * Number::from(255)
|
|
||||||
}
|
|
||||||
Some(v) => return Err(format!("$green: {} is not a number.", v).into()),
|
|
||||||
None => return Err("Missing element $green.".into()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let red = match channels.pop() {
|
Ok(Value::Color(color))
|
||||||
Some(Value::Dimension(n, Unit::None)) => n,
|
} else if args.len() == 2 {
|
||||||
Some(Value::Dimension(n, Unit::Percent)) => {
|
let color = match arg!(args, scope, super_selector, 0, "color") {
|
||||||
(n / Number::from(100)) * Number::from(255)
|
Value::Color(c) => c,
|
||||||
|
v => return Err(format!("$color: {} is not a color.", v).into()),
|
||||||
|
};
|
||||||
|
let alpha = match arg!(args, scope, super_selector, 1, "alpha") {
|
||||||
|
Value::Dimension(n, Unit::None) => n,
|
||||||
|
Value::Dimension(n, Unit::Percent) => n / Number::from(100),
|
||||||
|
v @ Value::Dimension(..) => {
|
||||||
|
return Err(format!("$alpha: Expected {} to have no units or \"%\".", v).into())
|
||||||
|
}
|
||||||
|
v => return Err(format!("$alpha: {} is not a number.", v).into()),
|
||||||
|
};
|
||||||
|
Ok(Value::Color(color.with_alpha(alpha)))
|
||||||
|
} else {
|
||||||
|
let red = match arg!(args, scope, super_selector, 0, "red") {
|
||||||
|
Value::Dimension(n, Unit::None) => n,
|
||||||
|
Value::Dimension(n, Unit::Percent) => (n / Number::from(100)) * Number::from(255),
|
||||||
|
v @ Value::Dimension(..) => {
|
||||||
|
return Err(format!("$red: Expected {} to have no units or \"%\".", v).into())
|
||||||
|
}
|
||||||
|
v if v.is_special_function() => {
|
||||||
|
let green = arg!(args, scope, super_selector, 1, "green");
|
||||||
|
let blue = arg!(args, scope, super_selector, 2, "blue");
|
||||||
|
let mut string = format!("rgb({}, {}, {}", v, green, blue);
|
||||||
|
if !args.is_empty() {
|
||||||
|
string.push_str(", ");
|
||||||
|
string.push_str(&arg!(args, scope, super_selector, 3, "alpha").to_string());
|
||||||
}
|
}
|
||||||
Some(v) => return Err(format!("$red: {} is not a number.", v).into()),
|
string.push(')');
|
||||||
None => return Err("Missing element $red.".into()),
|
return Ok(Value::Ident(string, QuoteKind::None));
|
||||||
};
|
}
|
||||||
|
v => return Err(format!("$red: {} is not a number.", v).into()),
|
||||||
let color = Color::from_rgba(red, green, blue, Number::one());
|
};
|
||||||
|
let green = match arg!(args, scope, super_selector, 1, "green") {
|
||||||
Ok(Value::Color(color))
|
Value::Dimension(n, Unit::None) => n,
|
||||||
} else if args.len() == 2 {
|
Value::Dimension(n, Unit::Percent) => (n / Number::from(100)) * Number::from(255),
|
||||||
let color = match arg!(args, scope, super_selector, 0, "color") {
|
v @ Value::Dimension(..) => {
|
||||||
Value::Color(c) => c,
|
return Err(format!("$green: Expected {} to have no units or \"%\".", v).into())
|
||||||
v => return Err(format!("$color: {} is not a color.", v).into()),
|
}
|
||||||
};
|
v if v.is_special_function() => {
|
||||||
let alpha = match arg!(args, scope, super_selector, 1, "alpha") {
|
let blue = arg!(args, scope, super_selector, 2, "blue");
|
||||||
Value::Dimension(n, Unit::None) => n,
|
let mut string = format!("rgb({}, {}, {}", red, v, blue);
|
||||||
Value::Dimension(n, Unit::Percent) => n / Number::from(100),
|
if !args.is_empty() {
|
||||||
v @ Value::Dimension(..) => {
|
string.push_str(", ");
|
||||||
return Err(
|
string.push_str(&arg!(args, scope, super_selector, 3, "alpha").to_string());
|
||||||
format!("$alpha: Expected {} to have no units or \"%\".", v).into()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
v => return Err(format!("$alpha: {} is not a number.", v).into()),
|
string.push(')');
|
||||||
};
|
return Ok(Value::Ident(string, QuoteKind::None));
|
||||||
Ok(Value::Color(color.with_alpha(alpha)))
|
}
|
||||||
} else {
|
v => return Err(format!("$green: {} is not a number.", v).into()),
|
||||||
let red = match arg!(args, scope, super_selector, 0, "red") {
|
};
|
||||||
Value::Dimension(n, Unit::None) => n,
|
let blue = match arg!(args, scope, super_selector, 2, "blue") {
|
||||||
Value::Dimension(n, Unit::Percent) => {
|
Value::Dimension(n, Unit::None) => n,
|
||||||
(n / Number::from(100)) * Number::from(255)
|
Value::Dimension(n, Unit::Percent) => (n / Number::from(100)) * Number::from(255),
|
||||||
|
v @ Value::Dimension(..) => {
|
||||||
|
return Err(format!("$blue: Expected {} to have no units or \"%\".", v).into())
|
||||||
|
}
|
||||||
|
v if v.is_special_function() => {
|
||||||
|
let mut string = format!("rgb({}, {}, {}", red, green, v);
|
||||||
|
if !args.is_empty() {
|
||||||
|
string.push_str(", ");
|
||||||
|
string.push_str(&arg!(args, scope, super_selector, 3, "alpha").to_string());
|
||||||
}
|
}
|
||||||
v @ Value::Dimension(..) => {
|
string.push(')');
|
||||||
return Err(
|
return Ok(Value::Ident(string, QuoteKind::None));
|
||||||
format!("$red: Expected {} to have no units or \"%\".", v).into()
|
}
|
||||||
)
|
v => return Err(format!("$blue: {} is not a number.", v).into()),
|
||||||
}
|
};
|
||||||
v => return Err(format!("$red: {} is not a number.", v).into()),
|
let alpha = match arg!(
|
||||||
};
|
args,
|
||||||
let green = match arg!(args, scope, super_selector, 1, "green") {
|
scope,
|
||||||
Value::Dimension(n, Unit::None) => n,
|
super_selector,
|
||||||
Value::Dimension(n, Unit::Percent) => {
|
3,
|
||||||
(n / Number::from(100)) * Number::from(255)
|
"alpha" = Value::Dimension(Number::one(), Unit::None)
|
||||||
}
|
) {
|
||||||
v @ Value::Dimension(..) => {
|
Value::Dimension(n, Unit::None) => n,
|
||||||
return Err(
|
Value::Dimension(n, Unit::Percent) => n / Number::from(100),
|
||||||
format!("$green: Expected {} to have no units or \"%\".", v).into()
|
v @ Value::Dimension(..) => {
|
||||||
)
|
return Err(format!("$alpha: Expected {} to have no units or \"%\".", v).into())
|
||||||
}
|
}
|
||||||
v => return Err(format!("$green: {} is not a number.", v).into()),
|
v if v.is_special_function() => {
|
||||||
};
|
let string = format!("rgb({}, {}, {}, {})", red, green, blue, v);
|
||||||
let blue = match arg!(args, scope, super_selector, 2, "blue") {
|
return Ok(Value::Ident(string, QuoteKind::None));
|
||||||
Value::Dimension(n, Unit::None) => n,
|
}
|
||||||
Value::Dimension(n, Unit::Percent) => {
|
v => return Err(format!("$alpha: {} is not a number.", v).into()),
|
||||||
(n / Number::from(100)) * Number::from(255)
|
};
|
||||||
}
|
Ok(Value::Color(Color::from_rgba(red, green, blue, alpha)))
|
||||||
v @ Value::Dimension(..) => {
|
}
|
||||||
return Err(
|
});
|
||||||
format!("$blue: Expected {} to have no units or \"%\".", v).into()
|
f.insert("rgb".to_owned(), rgb.clone());
|
||||||
)
|
f.insert("rgba".to_owned(), rgb);
|
||||||
}
|
|
||||||
v => return Err(format!("$blue: {} is not a number.", v).into()),
|
|
||||||
};
|
|
||||||
let alpha = match arg!(
|
|
||||||
args,
|
|
||||||
scope,
|
|
||||||
super_selector,
|
|
||||||
3,
|
|
||||||
"alpha" = Value::Dimension(Number::one(), Unit::None)
|
|
||||||
) {
|
|
||||||
Value::Dimension(n, Unit::None) => n,
|
|
||||||
Value::Dimension(n, Unit::Percent) => n / Number::from(100),
|
|
||||||
v @ Value::Dimension(..) => {
|
|
||||||
return Err(
|
|
||||||
format!("$alpha: Expected {} to have no units or \"%\".", v).into()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
v => return Err(format!("$alpha: {} is not a number.", v).into()),
|
|
||||||
};
|
|
||||||
Ok(Value::Color(Color::from_rgba(red, green, blue, alpha)))
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
f.insert(
|
f.insert(
|
||||||
"red".to_owned(),
|
"red".to_owned(),
|
||||||
Builtin::new(|mut args, scope, super_selector| {
|
Builtin::new(|mut args, scope, super_selector| {
|
||||||
|
@ -46,7 +46,6 @@ pub(crate) fn eat_calc_args<I: Iterator<Item = Token>>(
|
|||||||
Ok(string)
|
Ok(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub(crate) fn is_special_function(s: &str) -> bool {
|
pub(crate) fn is_special_function(s: &str) -> bool {
|
||||||
s.starts_with("calc(")
|
s.starts_with("calc(")
|
||||||
|| s.starts_with("var(")
|
|| s.starts_with("var(")
|
||||||
|
@ -7,6 +7,7 @@ use crate::common::{Brackets, ListSeparator, Op, QuoteKind};
|
|||||||
use crate::error::SassResult;
|
use crate::error::SassResult;
|
||||||
use crate::unit::{Unit, UNIT_CONVERSION_TABLE};
|
use crate::unit::{Unit, UNIT_CONVERSION_TABLE};
|
||||||
|
|
||||||
|
use css_function::is_special_function;
|
||||||
pub(crate) use map::SassMap;
|
pub(crate) use map::SassMap;
|
||||||
pub(crate) use number::Number;
|
pub(crate) use number::Number;
|
||||||
pub(crate) use sass_function::SassFunction;
|
pub(crate) use sass_function::SassFunction;
|
||||||
@ -179,6 +180,13 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_special_function(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Ident(s, QuoteKind::None) => is_special_function(s),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bool(b: bool) -> Self {
|
pub fn bool(b: bool) -> Self {
|
||||||
if b {
|
if b {
|
||||||
Value::True
|
Value::True
|
||||||
|
Loading…
x
Reference in New Issue
Block a user