Skip to content

Commit

Permalink
Merge PR #135: Update color format
Browse files Browse the repository at this point in the history
  • Loading branch information
kaj authored Mar 23, 2022
2 parents 8c4ba69 + 2e7b356 commit 039ff98
Show file tree
Hide file tree
Showing 50 changed files with 2,753 additions and 2,545 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ project adheres to
paths (PR #132).
* Detect `@import` loops.
* Report undefined variable / module errors better.
* Update color formatting. Sass-spec changed how it decides what
format to show a color in (PR #135).
* Enable clippy in CI and fix some things it complained about (PR #128).
* Update sass-spec test suite to 2022-03-09.
* Update sass-spec test suite to 2022-03-17.


## Release 0.23.4
Expand Down
31 changes: 17 additions & 14 deletions src/parser/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,23 +377,26 @@ pub fn variable(input: Span) -> PResult<Value> {
}

fn hex_color(input: Span) -> PResult<Value> {
let (rest, rgba) = delimited(
let (rest, (r, g, b, a)) = delimited(
tag("#"),
map(
alt((
tuple((hexchar2, hexchar2, hexchar2, opt(hexchar2))),
tuple((hexchar1, hexchar1, hexchar1, opt(hexchar1))),
)),
|(r, g, b, a): (u8, u8, u8, Option<u8>)| {
Rgba::from_rgba(r, g, b, a.unwrap_or(255))
},
),
alt((
tuple((hexchar2, hexchar2, hexchar2, opt(hexchar2))),
tuple((hexchar1, hexchar1, hexchar1, opt(hexchar1))),
)),
peek(map(not(alphanumeric1), |_| ())),
)(input)?;
let length = input.fragment().len() - rest.fragment().len();
// Unwrap should be ok as only ascii is matched.
let raw = from_utf8(&input.fragment()[0..length]).unwrap().to_string();
Ok((rest, Value::Color(rgba, Some(raw))))

if let Some(a) = a {
let rgba = Rgba::from_rgba(r, g, b, a);
Ok((rest, Value::Color(rgba, None)))
} else {
let rgba = Rgba::from_rgb(r, g, b);
let length = input.fragment().len() - rest.fragment().len();
// Unwrap should be ok as only ascii is matched.
let raw =
from_utf8(&input.fragment()[0..length]).unwrap().to_string();
Ok((rest, Value::Color(rgba, Some(raw))))
}
}

pub fn unary_op(input: Span) -> PResult<Value> {
Expand Down
67 changes: 41 additions & 26 deletions src/sass/functions/color/hsl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,9 @@ pub fn register(f: &mut Scope) {
});
def!(f, grayscale(color), |args| match args.get(&name!(color))? {
Value::Color(col, _) => {
let hsla = col.to_hsla();
Ok(
Hsla::new(hsla.hue(), zero(), hsla.lum(), hsla.alpha())
.into(),
)
let col = col.to_hsla();
Ok(Hsla::new(col.hue(), zero(), col.lum(), col.alpha(), false)
.into())
}
v @ Value::Numeric(..) => Ok(make_call("grayscale", vec![v])),
v => Err(is_not(&v, "a color")).named(name!(color)),
Expand Down Expand Up @@ -66,17 +64,15 @@ pub fn expose(m: &Scope, global: &mut FunctionMap) {
});
def!(f, darken(color, amount), |s| {
let col = get_color(s, "color")?;
let hsla = col.to_hsla();
let lum =
hsla.lum() - get_checked(s, name!(amount), check_pct_range)?;
Ok(Hsla::new(hsla.hue(), hsla.sat(), lum, hsla.alpha()).into())
let col = col.to_hsla();
let lum = col.lum() - get_checked(s, name!(amount), check_pct_range)?;
Ok(Hsla::new(col.hue(), col.sat(), lum, col.alpha(), false).into())
});
def!(f, desaturate(color, amount), |s| {
let col = get_color(s, "color")?;
let hsla = col.to_hsla();
let sat =
hsla.sat() - get_checked(s, name!(amount), check_pct_range)?;
Ok(Hsla::new(hsla.hue(), sat, hsla.lum(), hsla.alpha()).into())
let col = col.to_hsla();
let sat = col.sat() - get_checked(s, name!(amount), check_pct_range)?;
Ok(Hsla::new(col.hue(), sat, col.lum(), col.alpha(), false).into())
});
def_va!(f, saturate(kwargs), |s| {
let a1 = FormalArgs::new(vec![one_arg!(color), one_arg!(amount)]);
Expand All @@ -86,9 +82,9 @@ pub fn expose(m: &Scope, global: &mut FunctionMap) {
Ok(s) => {
let col = get_color(&s, "color")?;
let sat = get_checked(&s, name!(amount), check_pct_range)?;
let hsla = col.to_hsla();
let sat = hsla.sat() + sat;
Ok(Hsla::new(hsla.hue(), sat, hsla.lum(), hsla.alpha())
let col = col.to_hsla();
let sat = col.sat() + sat;
Ok(Hsla::new(col.hue(), sat, col.lum(), col.alpha(), false)
.into())
}
Err(ArgsError::Missing(_)) => {
Expand All @@ -104,10 +100,9 @@ pub fn expose(m: &Scope, global: &mut FunctionMap) {
});
def!(f, lighten(color, amount), |s| {
let col = get_color(s, "color")?;
let hsla = col.to_hsla();
let lum =
hsla.lum() + get_checked(s, name!(amount), check_pct_range)?;
Ok(Hsla::new(hsla.hue(), hsla.sat(), lum, hsla.alpha()).into())
let col = col.to_hsla();
let lum = col.lum() + get_checked(s, name!(amount), check_pct_range)?;
Ok(Hsla::new(col.hue(), col.sat(), lum, col.alpha(), false).into())
});
for (gname, lname) in &[
(name!(adjust_hue), name!(adjust_hue)),
Expand Down Expand Up @@ -180,6 +175,7 @@ fn hsla_from_values(
check_pct_opt(s).named(name!(saturation))?,
check_pct_opt(l).named(name!(lightness))?,
check_alpha(a).named(name!(alpha))?,
true, // ??
)
.into())
}
Expand All @@ -206,27 +202,46 @@ fn check_pct_opt(v: Value) -> Result<Rational, String> {

#[test]
fn test_hsl_black() {
assert_eq!("black", do_evaluate(&[], b"hsl(17, 32%, 0%);"))
assert_eq!(
do_evaluate(&[], b"hsl(17, 32%, 0%);"),
"hsl(17deg, 32%, 0%)"
)
}
#[test]
fn test_hsl_white() {
assert_eq!("white", do_evaluate(&[], b"hsl(300, 82%, 100%);"))
assert_eq!(
do_evaluate(&[], b"hsl(300, 82%, 100%);"),
"hsl(300deg, 82%, 100%)"
)
}
#[test]
fn test_hsl_gray() {
assert_eq!("gray", do_evaluate(&[], b"hsl(300, 0%, 50%);"))
assert_eq!(
do_evaluate(&[], b"hsl(300, 0%, 50%);"),
"hsl(300deg, 0%, 50%)"
)
}
#[test]
fn test_hsl_red() {
assert_eq!("#f7c9c9", do_evaluate(&[], b"hsl(0, 75%, 88%);"))
assert_eq!(
do_evaluate(&[], b"hsl(0, 75%, 88%);"),
"hsl(0deg, 75%, 88%)"
)
}
#[test]
fn test_hsl_yellow() {
assert_eq!("#ffff42", do_evaluate(&[], b"hsl(60, 100%, 63%);"))
assert_eq!(
do_evaluate(&[], b"hsl(60, 100%, 63%);"),
"hsl(60deg, 100%, 63%)"
)
}

#[test]
fn test_hsl_blue_magenta() {
assert_eq!("#6118aa", do_evaluate(&[], b"hsl(270, 75%, 38%);"))
assert_eq!(
do_evaluate(&[], b"hsl(270, 75%, 38%);"),
"hsl(270deg, 75%, 38%)"
)
}

#[cfg(test)]
Expand Down
8 changes: 7 additions & 1 deletion src/sass/functions/color/other.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use super::{
FunctionMap, Name,
};
use crate::css::{CallArgs, Value};
use crate::value::{Hsla, Hwba, Rational, Rgba};
use crate::value::{Hsla, Hwba, Rational, RgbFormat, Rgba};
use crate::Scope;
use num_traits::{one, zero, Signed};

Expand Down Expand Up @@ -44,6 +44,7 @@ pub fn register(f: &mut Scope) {
opt_add(rgba.green(), gre),
opt_add(rgba.blue(), blu),
opt_add(rgba.alpha(), a_adj),
rgba.source(),
)
.into())
} else if bla.is_some() || whi.is_some() {
Expand All @@ -63,6 +64,7 @@ pub fn register(f: &mut Scope) {
opt_add(hsla.sat(), sat),
opt_add(hsla.lum(), lig),
opt_add(hsla.alpha(), a_adj),
hsla.hsla_format,
)
.into())
}
Expand Down Expand Up @@ -107,6 +109,7 @@ pub fn register(f: &mut Scope) {
cmb(rgba.green(), gre, ff),
cmb(rgba.blue(), blu, ff),
cmb(rgba.alpha(), a_adj, one),
RgbFormat::Name,
)
.into())
} else if bla.is_none() && whi.is_none() {
Expand All @@ -116,6 +119,7 @@ pub fn register(f: &mut Scope) {
cmb(hsla.sat(), sat, one),
cmb(hsla.lum(), lig, one),
cmb(hsla.alpha(), a_adj, one),
hsla.hsla_format,
)
.into())
} else {
Expand Down Expand Up @@ -173,6 +177,7 @@ pub fn register(f: &mut Scope) {
gre.unwrap_or_else(|| rgba.green()),
blu.unwrap_or_else(|| rgba.blue()),
alp.unwrap_or_else(|| rgba.alpha()),
rgba.source(),
)
.into())
} else if bla.is_none() && whi.is_none() {
Expand All @@ -182,6 +187,7 @@ pub fn register(f: &mut Scope) {
sat.unwrap_or_else(|| hsla.sat()),
lig.unwrap_or_else(|| hsla.lum()),
alp.unwrap_or_else(|| hsla.alpha()),
false, // hsla.hsla_format,
)
.into())
} else {
Expand Down
22 changes: 14 additions & 8 deletions src/sass/functions/color/rgb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use super::{
};
use crate::css::{CallArgs, Value};
use crate::sass::{ArgsError, FormalArgs, Name};
use crate::value::{Rational, Rgba};
use crate::value::{Rational, RgbFormat, Rgba};
use crate::{Scope, ScopeRef};
use num_traits::{one, Zero};
use std::convert::TryFrom;
Expand Down Expand Up @@ -52,6 +52,7 @@ pub fn register(f: &mut Scope) {
m_c(a.green(), b.green()),
m_c(a.blue(), b.blue()),
a.alpha() * w + b.alpha() * (one - w),
RgbFormat::Name,
)
.into())
});
Expand All @@ -66,6 +67,7 @@ pub fn register(f: &mut Scope) {
inv(rgba.green()),
inv(rgba.blue()),
rgba.alpha(),
rgba.source(),
)
.into())
}
Expand Down Expand Up @@ -150,6 +152,7 @@ fn do_rgba(fn_name: &Name, s: &ScopeRef) -> Result<Value, Error> {
} else {
let mut c = check_color(c).named(name!(color))?;
c.set_alpha(check_alpha(a).named(name!(alpha))?);
c.reset_source();
Ok(c.into())
}
}
Expand Down Expand Up @@ -185,6 +188,7 @@ fn rgba_from_values(
check_channel(g).named(name!(green))?,
check_channel(b).named(name!(blue))?,
check_alpha(a).named(name!(alpha))?,
RgbFormat::Rgb,
)
.into())
}
Expand All @@ -196,19 +200,21 @@ mod test {

#[test]
fn test_high() {
assert_eq!("white", do_evaluate(&[], b"rgb(150%, 300, 256);"));
assert_eq!(
do_evaluate(&[], b"rgb(150%, 300, 256);"),
"rgb(255, 255, 255)"
);
}

#[test]
fn test_low() {
assert_eq!("black", do_evaluate(&[], b"rgb(-3, -2%, 0);"));
assert_eq!(do_evaluate(&[], b"rgb(-3, -2%, 0);"), "rgb(0, 0, 0)");
}
#[test]
fn test_mid() {
assert_eq!("gray", do_evaluate(&[], b"rgb(50%, 255/2, 25% + 25);"));
}
#[test]
fn test_named() {
assert_eq!("gray", do_evaluate(&[], b"rgb(50%, 255/2, 25% + 25);"));
assert_eq!(
do_evaluate(&[], b"rgb(50%, 255/2, 25% + 25);"),
"rgb(128, 128, 128)"
);
}
}
9 changes: 5 additions & 4 deletions src/value/colors/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ impl From<&Hsla> for Rgba {
let lum = hsla.lum();
if sat.is_zero() {
let gray = lum * 255;
Rgba::new(gray, gray, gray, hsla.alpha())
Rgba::new(gray, gray, gray, hsla.alpha(), RgbFormat::Name)
} else {
fn hue2rgb(p: Rational, q: Rational, t: Rational) -> Rational {
let t = (t - t.floor()) * 6;
Expand All @@ -30,6 +30,7 @@ impl From<&Hsla> for Rgba {
hue2rgb(p, q, hue) * 255,
hue2rgb(p, q, hue - Rational::new(1, 3)) * 255,
hsla.alpha(),
RgbFormat::Name,
)
}
}
Expand All @@ -51,7 +52,7 @@ impl From<&Hwba> for Hsla {
} else {
(Rational::one() - b - l) / std::cmp::min(l, Rational::one() - l)
};
Hsla::new(hwba.hue(), s, l, hwba.alpha())
Hsla::new(hwba.hue(), s, l, hwba.alpha(), false)
}
}

Expand All @@ -62,7 +63,7 @@ impl From<&Rgba> for Hsla {
let (max, min, largest) = max_min_largest(red, green, blue);

if max == min {
Hsla::new(zero(), zero(), max, rgba.alpha())
Hsla::new(zero(), zero(), max, rgba.alpha(), false)
} else {
let d = max - min;
let hue = match largest {
Expand All @@ -72,7 +73,7 @@ impl From<&Rgba> for Hsla {
} * (360 / 6);
let mm = max + min;
let sat = d / if mm > one() { -mm + 2 } else { mm };
Hsla::new(hue, sat, mm / 2, rgba.alpha())
Hsla::new(hue, sat, mm / 2, rgba.alpha(), false)
}
}
}
Expand Down
Loading

0 comments on commit 039ff98

Please sign in to comment.