consolidate implementations of rgb and rgba

This commit is contained in:
ConnorSkees 2020-05-16 17:45:04 -04:00
parent 2d0a9abb13
commit b5a0931e45

View File

@ -12,7 +12,13 @@ use crate::selector::Selector;
use crate::unit::Unit;
use crate::value::{Number, Value};
fn rgb(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResult<Value> {
/// name: Either `rgb` or `rgba` depending on the caller
fn inner_rgb(
name: &'static str,
mut args: CallArgs,
scope: &Scope,
super_selector: &Selector,
) -> SassResult<Value> {
if args.is_empty() {
return Err(("Missing argument $channels.", args.span()).into());
}
@ -42,7 +48,8 @@ fn rgb(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResu
let red = channels.pop().unwrap();
return Ok(Value::Ident(
format!(
"rgb({}, {}, {})",
"{}({}, {}, {})",
name,
red.to_css_string(args.span())?,
green.to_css_string(args.span())?,
v.to_css_string(args.span())?
@ -66,12 +73,13 @@ fn rgb(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResu
Some(v) if v.is_special_function() => {
let string = match channels.pop() {
Some(red) => format!(
"rgb({}, {}, {})",
"{}({}, {}, {})",
name,
red.to_css_string(args.span())?,
v.to_css_string(args.span())?,
blue
),
None => format!("rgb({} {})", v.to_css_string(args.span())?, blue),
None => format!("{}({} {})", name, v.to_css_string(args.span())?, blue),
};
return Ok(Value::Ident(string, QuoteKind::None));
}
@ -91,7 +99,8 @@ fn rgb(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResu
Some(v) if v.is_special_function() => {
return Ok(Value::Ident(
format!(
"rgb({}, {}, {})",
"{}({}, {}, {})",
name,
v.to_css_string(args.span())?,
green,
blue
@ -119,7 +128,8 @@ fn rgb(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResu
let alpha = arg!(args, scope, super_selector, 1, "alpha");
return Ok(Value::Ident(
format!(
"rgb({}, {})",
"{}({}, {})",
name,
v.to_css_string(args.span())?,
alpha.to_css_string(args.span())?
),
@ -150,7 +160,8 @@ fn rgb(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResu
v if v.is_special_function() => {
return Ok(Value::Ident(
format!(
"rgb({}, {}, {}, {})",
"{}({}, {}, {}, {})",
name,
color.red(),
color.green(),
color.blue(),
@ -186,7 +197,8 @@ fn rgb(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResu
let green = arg!(args, scope, super_selector, 1, "green");
let blue = arg!(args, scope, super_selector, 2, "blue");
let mut string = format!(
"rgb({}, {}, {}",
"{}({}, {}, {}",
name,
v.to_css_string(args.span())?,
green.to_css_string(args.span())?,
blue.to_css_string(args.span())?
@ -225,7 +237,8 @@ fn rgb(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResu
v if v.is_special_function() => {
let blue = arg!(args, scope, super_selector, 2, "blue");
let mut string = format!(
"rgb({}, {}, {}",
"{}({}, {}, {}",
name,
red,
v.to_css_string(args.span())?,
blue.to_css_string(args.span())?
@ -262,8 +275,13 @@ fn rgb(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResu
.into())
}
v if v.is_special_function() => {
let mut string =
format!("rgb({}, {}, {}", red, green, v.to_css_string(args.span())?);
let mut string = format!(
"{}({}, {}, {}",
name,
red,
green,
v.to_css_string(args.span())?
);
if !args.is_empty() {
string.push_str(", ");
string.push_str(
@ -303,7 +321,8 @@ fn rgb(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResu
}
v if v.is_special_function() => {
let string = format!(
"rgb({}, {}, {}, {})",
"{}({}, {}, {}, {})",
name,
red,
green,
blue,
@ -325,317 +344,12 @@ fn rgb(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResu
}
}
fn rgba(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResult<Value> {
if args.is_empty() {
return Err(("Missing argument $channels.", args.span()).into());
}
fn rgb(args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResult<Value> {
inner_rgb("rgb", args, scope, super_selector)
}
if args.len() == 1 {
let mut channels = match arg!(args, scope, super_selector, 0, "channels") {
Value::List(v, ..) => v,
_ => return Err(("Missing argument $channels.", args.span()).into()),
};
if channels.len() > 3 {
return Err((
format!(
"Only 3 elements allowed, but {} were passed.",
channels.len()
),
args.span(),
)
.into());
}
let blue = 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) if v.is_special_function() => {
let green = channels.pop().unwrap();
let red = channels.pop().unwrap();
return Ok(Value::Ident(
format!(
"rgba({}, {}, {})",
red.to_css_string(args.span())?,
green.to_css_string(args.span())?,
v.to_css_string(args.span())?
),
QuoteKind::None,
));
}
Some(v) => {
return Err((
format!("$blue: {} is not a number.", v.to_css_string(args.span())?),
args.span(),
)
.into())
}
None => return Err(("Missing element $blue.", args.span()).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) if v.is_special_function() => {
let string = match channels.pop() {
Some(red) => format!(
"rgba({}, {}, {})",
red.to_css_string(args.span())?,
v.to_css_string(args.span())?,
blue
),
None => format!("rgba({} {})", v.to_css_string(args.span())?, blue),
};
return Ok(Value::Ident(string, QuoteKind::None));
}
Some(v) => {
return Err((
format!("$green: {} is not a number.", v.to_css_string(args.span())?),
args.span(),
)
.into())
}
None => return Err(("Missing element $green.", args.span()).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) if v.is_special_function() => {
return Ok(Value::Ident(
format!(
"rgba({}, {}, {})",
v.to_css_string(args.span())?,
green,
blue
),
QuoteKind::None,
));
}
Some(v) => {
return Err((
format!("$red: {} is not a number.", v.to_css_string(args.span())?),
args.span(),
)
.into())
}
None => return Err(("Missing element $red.", args.span()).into()),
};
let color = Color::from_rgba(red, green, blue, Number::one());
Ok(Value::Color(Box::new(color)))
} else if args.len() == 2 {
let color = match arg!(args, scope, super_selector, 0, "color") {
Value::Color(c) => c,
v if v.is_special_function() => {
let alpha = arg!(args, scope, super_selector, 1, "alpha");
return Ok(Value::Ident(
format!(
"rgba({}, {})",
v.to_css_string(args.span())?,
alpha.to_css_string(args.span())?
),
QuoteKind::None,
));
}
v => {
return Err((
format!("$color: {} is not a color.", v.to_css_string(args.span())?),
args.span(),
)
.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.to_css_string(args.span())?
),
args.span(),
)
.into())
}
v if v.is_special_function() => {
return Ok(Value::Ident(
format!(
"rgba({}, {}, {}, {})",
color.red(),
color.green(),
color.blue(),
v.to_css_string(args.span())?
),
QuoteKind::None,
));
}
v => {
return Err((
format!("$alpha: {} is not a number.", v.to_css_string(args.span())?),
args.span(),
)
.into())
}
};
Ok(Value::Color(Box::new(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.to_css_string(args.span())?
),
args.span(),
)
.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!(
"rgba({}, {}, {}",
v.to_css_string(args.span())?,
green.to_css_string(args.span())?,
blue.to_css_string(args.span())?
);
if !args.is_empty() {
string.push_str(", ");
string.push_str(
&arg!(args, scope, super_selector, 3, "alpha")
.to_css_string(args.span())?,
);
}
string.push(')');
return Ok(Value::Ident(string, QuoteKind::None));
}
v => {
return Err((
format!("$red: {} is not a number.", v.to_css_string(args.span())?),
args.span(),
)
.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.to_css_string(args.span())?
),
args.span(),
)
.into())
}
v if v.is_special_function() => {
let blue = arg!(args, scope, super_selector, 2, "blue");
let mut string = format!(
"rgba({}, {}, {}",
red,
v.to_css_string(args.span())?,
blue.to_css_string(args.span())?
);
if !args.is_empty() {
string.push_str(", ");
string.push_str(
&arg!(args, scope, super_selector, 3, "alpha")
.to_css_string(args.span())?,
);
}
string.push(')');
return Ok(Value::Ident(string, QuoteKind::None));
}
v => {
return Err((
format!("$green: {} is not a number.", v.to_css_string(args.span())?),
args.span(),
)
.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.to_css_string(args.span())?
),
args.span(),
)
.into())
}
v if v.is_special_function() => {
let mut string =
format!("rgba({}, {}, {}", red, green, v.to_css_string(args.span())?);
if !args.is_empty() {
string.push_str(", ");
string.push_str(
&arg!(args, scope, super_selector, 3, "alpha")
.to_css_string(args.span())?,
);
}
string.push(')');
return Ok(Value::Ident(string, QuoteKind::None));
}
v => {
return Err((
format!("$blue: {} is not a number.", v.to_css_string(args.span())?),
args.span(),
)
.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.to_css_string(args.span())?
),
args.span(),
)
.into())
}
v if v.is_special_function() => {
let string = format!(
"rgba({}, {}, {}, {})",
red,
green,
blue,
v.to_css_string(args.span())?
);
return Ok(Value::Ident(string, QuoteKind::None));
}
v => {
return Err((
format!("$alpha: {} is not a number.", v.to_css_string(args.span())?),
args.span(),
)
.into())
}
};
Ok(Value::Color(Box::new(Color::from_rgba(
red, green, blue, alpha,
))))
}
fn rgba(args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResult<Value> {
inner_rgb("rgba", args, scope, super_selector)
}
fn red(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResult<Value> {