refactor parsing of special hsl/rgb fns

This commit is contained in:
Connor Skees 2021-07-30 06:15:22 -04:00
parent c6cb7c1d68
commit 1e2e32140b
3 changed files with 101 additions and 163 deletions

View File

@ -18,7 +18,9 @@ fn inner_hsl(name: &'static str, mut args: CallArgs, parser: &mut Parser) -> Sas
return Err(("Missing argument $channels.", args.span()).into());
}
if args.len() == 1 {
let len = args.len();
if len == 1 {
let mut channels = match args.get_err(0, "channels")? {
Value::List(v, ..) => v,
_ => return Err(("Missing argument $channels.", args.span()).into()),
@ -99,30 +101,42 @@ fn inner_hsl(name: &'static str, mut args: CallArgs, parser: &mut Parser) -> Sas
Number::one(),
))))
} else {
let hue = match args.get_err(0, "hue")? {
let hue = args.get_err(0, "hue")?;
let saturation = args.get_err(1, "saturation")?;
let lightness = args.get_err(2, "lightness")?;
let alpha = args.default_arg(
3,
"alpha",
Value::Dimension(Some(Number::one()), Unit::None, true),
)?;
if [&hue, &saturation, &lightness, &alpha]
.iter()
.copied()
.any(Value::is_special_function)
{
return Ok(Value::String(
format!(
"{}({})",
name,
Value::List(
if len == 4 {
vec![hue, saturation, lightness, alpha]
} else {
vec![hue, saturation, lightness]
},
ListSeparator::Comma,
Brackets::None
)
.to_css_string(args.span(), false)?
),
QuoteKind::None,
));
}
let hue = match hue {
Value::Dimension(Some(n), ..) => n,
Value::Dimension(None, ..) => todo!(),
v if v.is_special_function() => {
let saturation = args.get_err(1, "saturation")?;
let lightness = args.get_err(2, "lightness")?;
let mut string = format!(
"{}({}, {}, {}",
name,
v.to_css_string(args.span(), parser.options.is_compressed())?,
saturation.to_css_string(args.span(), parser.options.is_compressed())?,
lightness.to_css_string(args.span(), parser.options.is_compressed())?
);
if !args.is_empty() {
string.push_str(", ");
string.push_str(
&args
.get_err(3, "alpha")?
.to_css_string(args.span(), parser.options.is_compressed())?,
);
}
string.push(')');
return Ok(Value::String(string, QuoteKind::None));
}
v => {
return Err((
format!("$hue: {} is not a number.", v.inspect(args.span())?),
@ -131,29 +145,9 @@ fn inner_hsl(name: &'static str, mut args: CallArgs, parser: &mut Parser) -> Sas
.into())
}
};
let saturation = match args.get_err(1, "saturation")? {
let saturation = match saturation {
Value::Dimension(Some(n), ..) => n / Number::from(100),
Value::Dimension(None, ..) => todo!(),
v if v.is_special_function() => {
let lightness = args.get_err(2, "lightness")?;
let mut string = format!(
"{}({}, {}, {}",
name,
hue.to_string(parser.options.is_compressed()),
v.to_css_string(args.span(), parser.options.is_compressed())?,
lightness.to_css_string(args.span(), parser.options.is_compressed())?
);
if !args.is_empty() {
string.push_str(", ");
string.push_str(
&args
.get_err(3, "alpha")?
.to_css_string(args.span(), parser.options.is_compressed())?,
);
}
string.push(')');
return Ok(Value::String(string, QuoteKind::None));
}
v => {
return Err((
format!(
@ -165,28 +159,9 @@ fn inner_hsl(name: &'static str, mut args: CallArgs, parser: &mut Parser) -> Sas
.into())
}
};
let lightness = match args.get_err(2, "lightness")? {
let lightness = match lightness {
Value::Dimension(Some(n), ..) => n / Number::from(100),
Value::Dimension(None, ..) => todo!(),
v if v.is_special_function() => {
let mut string = format!(
"{}({}, {}, {}",
name,
hue.to_string(parser.options.is_compressed()),
saturation.to_string(parser.options.is_compressed()),
v.to_css_string(args.span(), parser.options.is_compressed())?
);
if !args.is_empty() {
string.push_str(", ");
string.push_str(
&args
.get_err(3, "alpha")?
.to_css_string(args.span(), parser.options.is_compressed())?,
);
}
string.push(')');
return Ok(Value::String(string, QuoteKind::None));
}
v => {
return Err((
format!(
@ -198,11 +173,7 @@ fn inner_hsl(name: &'static str, mut args: CallArgs, parser: &mut Parser) -> Sas
.into())
}
};
let alpha = match args.default_arg(
3,
"alpha",
Value::Dimension(Some(Number::one()), Unit::None, true),
)? {
let alpha = match alpha {
Value::Dimension(Some(n), Unit::None, _) => n,
Value::Dimension(Some(n), Unit::Percent, _) => n / Number::from(100),
Value::Dimension(None, ..) => todo!(),
@ -216,19 +187,6 @@ fn inner_hsl(name: &'static str, mut args: CallArgs, parser: &mut Parser) -> Sas
)
.into())
}
v if v.is_special_function() => {
return Ok(Value::String(
format!(
"{}({}, {}, {}, {})",
name,
hue.to_string(parser.options.is_compressed()),
saturation.to_string(parser.options.is_compressed()),
lightness.to_string(parser.options.is_compressed()),
v.to_css_string(args.span(), parser.options.is_compressed())?
),
QuoteKind::None,
));
}
v => {
return Err((
format!("$alpha: {} is not a number.", v.inspect(args.span())?),

View File

@ -20,7 +20,9 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser) -> Sas
return Err(("Missing argument $channels.", args.span()).into());
}
if args.len() == 1 {
let len = args.len();
if len == 1 {
let mut channels = match args.get_err(0, "channels")? {
Value::List(v, ..) => v,
_ => return Err(("Missing argument $channels.", args.span()).into()),
@ -150,7 +152,7 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser) -> Sas
let color = Color::from_rgba(red, green, blue, Number::one());
Ok(Value::Color(Box::new(color)))
} else if args.len() == 2 {
} else if len == 2 {
let color = match args.get_err(0, "color")? {
Value::Color(c) => c,
v if v.is_special_function() => {
@ -210,7 +212,40 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser) -> Sas
};
Ok(Value::Color(Box::new(color.with_alpha(alpha))))
} else {
let red = match args.get_err(0, "red")? {
let red = args.get_err(0, "red")?;
let green = args.get_err(1, "green")?;
let blue = args.get_err(2, "blue")?;
let alpha = args.default_arg(
3,
"alpha",
Value::Dimension(Some(Number::one()), Unit::None, true),
)?;
if [&red, &green, &blue, &alpha]
.iter()
.copied()
.any(Value::is_special_function)
{
return Ok(Value::String(
format!(
"{}({})",
name,
Value::List(
if len == 4 {
vec![red, green, blue, alpha]
} else {
vec![red, green, blue]
},
ListSeparator::Comma,
Brackets::None
)
.to_css_string(args.span(), false)?
),
QuoteKind::None,
));
}
let red = match red {
Value::Dimension(Some(n), Unit::None, _) => n,
Value::Dimension(Some(n), Unit::Percent, _) => {
(n / Number::from(100)) * Number::from(255)
@ -226,27 +261,6 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser) -> Sas
)
.into())
}
v if v.is_special_function() => {
let green = args.get_err(1, "green")?;
let blue = args.get_err(2, "blue")?;
let mut string = format!(
"{}({}, {}, {}",
name,
v.to_css_string(args.span(), parser.options.is_compressed())?,
green.to_css_string(args.span(), parser.options.is_compressed())?,
blue.to_css_string(args.span(), parser.options.is_compressed())?
);
if !args.is_empty() {
string.push_str(", ");
string.push_str(
&args
.get_err(3, "alpha")?
.to_css_string(args.span(), parser.options.is_compressed())?,
);
}
string.push(')');
return Ok(Value::String(string, QuoteKind::None));
}
v => {
return Err((
format!("$red: {} is not a number.", v.inspect(args.span())?),
@ -255,7 +269,7 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser) -> Sas
.into())
}
};
let green = match args.get_err(1, "green")? {
let green = match green {
Value::Dimension(Some(n), Unit::None, _) => n,
Value::Dimension(Some(n), Unit::Percent, _) => {
(n / Number::from(100)) * Number::from(255)
@ -271,26 +285,6 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser) -> Sas
)
.into())
}
v if v.is_special_function() => {
let blue = args.get_err(2, "blue")?;
let mut string = format!(
"{}({}, {}, {}",
name,
red.to_string(parser.options.is_compressed()),
v.to_css_string(args.span(), parser.options.is_compressed())?,
blue.to_css_string(args.span(), parser.options.is_compressed())?
);
if !args.is_empty() {
string.push_str(", ");
string.push_str(
&args
.get_err(3, "alpha")?
.to_css_string(args.span(), parser.options.is_compressed())?,
);
}
string.push(')');
return Ok(Value::String(string, QuoteKind::None));
}
v => {
return Err((
format!("$green: {} is not a number.", v.inspect(args.span())?),
@ -299,7 +293,7 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser) -> Sas
.into())
}
};
let blue = match args.get_err(2, "blue")? {
let blue = match blue {
Value::Dimension(Some(n), Unit::None, _) => n,
Value::Dimension(Some(n), Unit::Percent, _) => {
(n / Number::from(100)) * Number::from(255)
@ -315,25 +309,6 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser) -> Sas
)
.into())
}
v if v.is_special_function() => {
let mut string = format!(
"{}({}, {}, {}",
name,
red.to_string(parser.options.is_compressed()),
green.to_string(parser.options.is_compressed()),
v.to_css_string(args.span(), parser.options.is_compressed())?
);
if !args.is_empty() {
string.push_str(", ");
string.push_str(
&args
.get_err(3, "alpha")?
.to_css_string(args.span(), parser.options.is_compressed())?,
);
}
string.push(')');
return Ok(Value::String(string, QuoteKind::None));
}
v => {
return Err((
format!("$blue: {} is not a number.", v.inspect(args.span())?),
@ -342,11 +317,7 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser) -> Sas
.into())
}
};
let alpha = match args.default_arg(
3,
"alpha",
Value::Dimension(Some(Number::one()), Unit::None, true),
)? {
let alpha = match alpha {
Value::Dimension(Some(n), Unit::None, _) => n,
Value::Dimension(Some(n), Unit::Percent, _) => n / Number::from(100),
Value::Dimension(None, ..) => todo!(),
@ -360,17 +331,6 @@ fn inner_rgb(name: &'static str, mut args: CallArgs, parser: &mut Parser) -> Sas
)
.into())
}
v if v.is_special_function() => {
let string = format!(
"{}({}, {}, {}, {})",
name,
red.to_string(parser.options.is_compressed()),
green.to_string(parser.options.is_compressed()),
blue.to_string(parser.options.is_compressed()),
v.to_css_string(args.span(), parser.options.is_compressed())?
);
return Ok(Value::String(string, QuoteKind::None));
}
v => {
return Err((
format!("$alpha: {} is not a number.", v.inspect(args.span())?),

View File

@ -737,6 +737,26 @@ test!(
"a {\n color: rgba(1 2 max(3, 3));\n}\n",
"a {\n color: rgba(1, 2, max(3, 3));\n}\n"
);
test!(
rgb_special_fn_4_arg_maintains_units,
"a {\n color: rgb(1, 0.02, 3%, max(0.4));\n}\n",
"a {\n color: rgb(1, 0.02, 3%, max(0.4));\n}\n"
);
test!(
rgb_special_fn_3_arg_maintains_units,
"a {\n color: rgb(1, 0.02, max(0.4));\n}\n",
"a {\n color: rgb(1, 0.02, max(0.4));\n}\n"
);
test!(
hsl_special_fn_4_arg_maintains_units,
"a {\n color: hsl(1, 0.02, 3%, max(0.4));\n}\n",
"a {\n color: hsl(1, 0.02, 3%, max(0.4));\n}\n"
);
test!(
hsl_special_fn_3_arg_maintains_units,
"a {\n color: hsl(1, 0.02, max(0.4));\n}\n",
"a {\n color: hsl(1, 0.02, max(0.4));\n}\n"
);
test!(
#[ignore = "we do not check if interpolation occurred"]
interpolated_named_color_is_not_color,