Skip to content

Commit 4ebcb45

Browse files
authored
Update relative color parsing to latest spec (#465)
1 parent 0f064ab commit 4ebcb45

File tree

9 files changed

+423
-252
lines changed

9 files changed

+423
-252
lines changed

src/lib.rs

Lines changed: 115 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -17514,6 +17514,7 @@ mod tests {
1751417514
minify_test(".foo { color: hsl(100deg, 100%, 50%) }", ".foo{color:#5f0}");
1751517515
minify_test(".foo { color: hsl(100, 100%, 50%) }", ".foo{color:#5f0}");
1751617516
minify_test(".foo { color: hsl(100 100% 50%) }", ".foo{color:#5f0}");
17517+
minify_test(".foo { color: hsl(100 100 50) }", ".foo{color:#5f0}");
1751717518
minify_test(".foo { color: hsl(100, 100%, 50%, .8) }", ".foo{color:#5f0c}");
1751817519
minify_test(".foo { color: hsl(100 100% 50% / .8) }", ".foo{color:#5f0c}");
1751917520
minify_test(".foo { color: hsla(100, 100%, 50%, .8) }", ".foo{color:#5f0c}");
@@ -17525,12 +17526,21 @@ mod tests {
1752517526
minify_test(".foo { color: hwb(194 0% 0% / 50%) }", ".foo{color:#00c4ff80}");
1752617527
minify_test(".foo { color: hwb(194 0% 50%) }", ".foo{color:#006280}");
1752717528
minify_test(".foo { color: hwb(194 50% 0%) }", ".foo{color:#80e1ff}");
17529+
minify_test(".foo { color: hwb(194 50 0) }", ".foo{color:#80e1ff}");
1752817530
minify_test(".foo { color: hwb(194 50% 50%) }", ".foo{color:gray}");
1752917531
// minify_test(".foo { color: ActiveText }", ".foo{color:ActiveTet}");
1753017532
minify_test(
1753117533
".foo { color: lab(29.2345% 39.3825 20.0664); }",
1753217534
".foo{color:lab(29.2345% 39.3825 20.0664)}",
1753317535
);
17536+
minify_test(
17537+
".foo { color: lab(29.2345 39.3825 20.0664); }",
17538+
".foo{color:lab(29.2345% 39.3825 20.0664)}",
17539+
);
17540+
minify_test(
17541+
".foo { color: lab(29.2345% 39.3825% 20.0664%); }",
17542+
".foo{color:lab(29.2345% 49.2281 25.083)}",
17543+
);
1753417544
minify_test(
1753517545
".foo { color: lab(29.2345% 39.3825 20.0664 / 100%); }",
1753617546
".foo{color:lab(29.2345% 39.3825 20.0664)}",
@@ -17543,6 +17553,14 @@ mod tests {
1754317553
".foo { color: lch(29.2345% 44.2 27); }",
1754417554
".foo{color:lch(29.2345% 44.2 27)}",
1754517555
);
17556+
minify_test(
17557+
".foo { color: lch(29.2345 44.2 27); }",
17558+
".foo{color:lch(29.2345% 44.2 27)}",
17559+
);
17560+
minify_test(
17561+
".foo { color: lch(29.2345% 44.2% 27deg); }",
17562+
".foo{color:lch(29.2345% 66.3 27)}",
17563+
);
1754617564
minify_test(
1754717565
".foo { color: lch(29.2345% 44.2 45deg); }",
1754817566
".foo{color:lch(29.2345% 44.2 45)}",
@@ -17563,10 +17581,26 @@ mod tests {
1756317581
".foo { color: oklab(40.101% 0.1147 0.0453); }",
1756417582
".foo{color:oklab(40.101% .1147 .0453)}",
1756517583
);
17584+
minify_test(
17585+
".foo { color: oklab(.40101 0.1147 0.0453); }",
17586+
".foo{color:oklab(40.101% .1147 .0453)}",
17587+
);
17588+
minify_test(
17589+
".foo { color: oklab(40.101% 0.1147% 0.0453%); }",
17590+
".foo{color:oklab(40.101% .0004588 .0001812)}",
17591+
);
1756617592
minify_test(
1756717593
".foo { color: oklch(40.101% 0.12332 21.555); }",
1756817594
".foo{color:oklch(40.101% .12332 21.555)}",
1756917595
);
17596+
minify_test(
17597+
".foo { color: oklch(.40101 0.12332 21.555); }",
17598+
".foo{color:oklch(40.101% .12332 21.555)}",
17599+
);
17600+
minify_test(
17601+
".foo { color: oklch(40.101% 0.12332% 21.555); }",
17602+
".foo{color:oklch(40.101% .00049328 21.555)}",
17603+
);
1757017604
minify_test(
1757117605
".foo { color: oklch(40.101% 0.12332 .5turn); }",
1757217606
".foo{color:oklch(40.101% .12332 180)}",
@@ -18431,7 +18465,7 @@ mod tests {
1843118465
}
1843218466

1843318467
test("lab(from indianred calc(l * .8) a b)", "lab(43.1402% 45.7516 23.1557)");
18434-
test("lch(from indianred calc(l + 10%) c h)", "lch(63.9252% 51.2776 26.8448)");
18468+
test("lch(from indianred calc(l + 10) c h)", "lch(63.9252% 51.2776 26.8448)");
1843518469
test("lch(from indianred l calc(c - 50) h)", "lch(53.9252% 1.27763 26.8448)");
1843618470
test(
1843718471
"lch(from indianred l c calc(h + 180deg))",
@@ -18447,12 +18481,23 @@ mod tests {
1844718481
"rgba(205, 92, 92, .7)",
1844818482
);
1844918483
test(
18450-
"rgb(from rgba(205, 92, 92, .5) r g b / calc(alpha + 20%))",
18484+
"rgb(from rgba(205, 92, 92, .5) r g b / calc(alpha + .2))",
1845118485
"rgba(205, 92, 92, .7)",
1845218486
);
1845318487
test("lch(from indianred l sin(c) h)", "lch(53.9252% .84797 26.8448)");
1845418488
test("lch(from indianred l sqrt(c) h)", "lch(53.9252% 7.16084 26.8448)");
18455-
test("lch(from indianred l c sin(h))", "lch(53.9252% 51.2776 .990043)");
18489+
test("lch(from indianred l c sin(h))", "lch(53.9252% 51.2776 .451575)");
18490+
test("lch(from indianred calc(10% + 20%) c h)", "lch(30% 51.2776 26.8448)");
18491+
test("lch(from indianred calc(10 + 20) c h)", "lch(30% 51.2776 26.8448)");
18492+
test("lch(from indianred l c calc(10 + 20))", "lch(53.9252% 51.2776 30)");
18493+
test(
18494+
"lch(from indianred l c calc(10deg + 20deg))",
18495+
"lch(53.9252% 51.2776 30)",
18496+
);
18497+
test(
18498+
"lch(from indianred l c calc(10deg + 0.35rad))",
18499+
"lch(53.9252% 51.2776 30.0535)",
18500+
);
1845618501
minify_test(
1845718502
".foo{color:lch(from currentColor l c sin(h))}",
1845818503
".foo{color:lch(from currentColor l c sin(h))}",
@@ -18566,21 +18611,15 @@ mod tests {
1856618611

1856718612
// Testing permutation.
1856818613
test("rgb(from rebeccapurple g b r)", "rgb(51, 153, 102)");
18569-
test("rgb(from rebeccapurple b alpha r / g)", "rgba(153, 255, 102, 0.2)");
18570-
test("rgb(from rebeccapurple r r r / r)", "rgba(102, 102, 102, 0.4)");
18571-
test(
18572-
"rgb(from rebeccapurple alpha alpha alpha / alpha)",
18573-
"rgb(255, 255, 255)",
18574-
);
18614+
test("rgb(from rebeccapurple b alpha r / g)", "rgba(153, 1, 102, 1)");
18615+
test("rgb(from rebeccapurple r r r / r)", "rgba(102, 102, 102, 1)");
18616+
test("rgb(from rebeccapurple alpha alpha alpha / alpha)", "rgb(1, 1, 1)");
1857518617
test("rgb(from rgb(20%, 40%, 60%, 80%) g b r)", "rgb(102, 153, 51)");
18576-
test(
18577-
"rgb(from rgb(20%, 40%, 60%, 80%) b alpha r / g)",
18578-
"rgba(153, 204, 51, 0.4)",
18579-
);
18580-
test("rgb(from rgb(20%, 40%, 60%, 80%) r r r / r)", "rgba(51, 51, 51, 0.2)");
18618+
test("rgb(from rgb(20%, 40%, 60%, 80%) b alpha r / g)", "rgba(153, 1, 51, 1)");
18619+
test("rgb(from rgb(20%, 40%, 60%, 80%) r r r / r)", "rgba(51, 51, 51, 1)");
1858118620
test(
1858218621
"rgb(from rgb(20%, 40%, 60%, 80%) alpha alpha alpha / alpha)",
18583-
"rgba(204, 204, 204, 0.8)",
18622+
"rgba(1, 1, 1, 0.8)",
1858418623
);
1858518624

1858618625
// Testing mixes of number and percentage. (These would not be allowed in the non-relative syntax).
@@ -18704,17 +18743,29 @@ mod tests {
1870418743

1870518744
// Testing valid permutation (types match).
1870618745
test("hsl(from rebeccapurple h l s)", "rgb(128, 77, 179)");
18707-
test("hsl(from rebeccapurple h alpha l / s)", "rgba(102, 0, 204, 0.5)");
18708-
test("hsl(from rebeccapurple h l l / l)", "rgba(102, 61, 143, 0.4)");
18709-
test("hsl(from rebeccapurple h alpha alpha / alpha)", "rgb(255, 255, 255)");
18746+
test(
18747+
"hsl(from rebeccapurple h calc(alpha * 100) l / calc(s / 100))",
18748+
"rgba(102, 0, 204, 0.5)",
18749+
);
18750+
test(
18751+
"hsl(from rebeccapurple h l l / calc(l / 100))",
18752+
"rgba(102, 61, 143, 0.4)",
18753+
);
18754+
test(
18755+
"hsl(from rebeccapurple h calc(alpha * 100) calc(alpha * 100) / calc(alpha * 100))",
18756+
"rgb(255, 255, 255)",
18757+
);
1871018758
test("hsl(from rgb(20%, 40%, 60%, 80%) h l s)", "rgb(77, 128, 179)");
1871118759
test(
18712-
"hsl(from rgb(20%, 40%, 60%, 80%) h alpha l / s)",
18760+
"hsl(from rgb(20%, 40%, 60%, 80%) h calc(alpha * 100) l / calc(s / 100))",
1871318761
"rgba(20, 102, 184, 0.5)",
1871418762
);
18715-
test("hsl(from rgb(20%, 40%, 60%, 80%) h l l / l)", "rgba(61, 102, 143, 0.4)");
1871618763
test(
18717-
"hsl(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)",
18764+
"hsl(from rgb(20%, 40%, 60%, 80%) h l l / calc(l / 100))",
18765+
"rgba(61, 102, 143, 0.4)",
18766+
);
18767+
test(
18768+
"hsl(from rgb(20%, 40%, 60%, 80%) h calc(alpha * 100) calc(alpha * 100) / alpha)",
1871818769
"rgba(163, 204, 245, 0.8)",
1871918770
);
1872018771

@@ -18842,17 +18893,29 @@ mod tests {
1884218893

1884318894
// Testing valid permutation (types match).
1884418895
test("hwb(from rebeccapurple h b w)", "rgb(153, 102, 204)");
18845-
test("hwb(from rebeccapurple h alpha w / b)", "rgba(213, 213, 213, 0.4)");
18846-
test("hwb(from rebeccapurple h w w / w)", "rgba(128, 51, 204, 0.2)");
18847-
test("hwb(from rebeccapurple h alpha alpha / alpha)", "rgb(128, 128, 128)");
18896+
test(
18897+
"hwb(from rebeccapurple h calc(alpha * 100) w / calc(b / 100))",
18898+
"rgba(213, 213, 213, 0.4)",
18899+
);
18900+
test(
18901+
"hwb(from rebeccapurple h w w / calc(w / 100))",
18902+
"rgba(128, 51, 204, 0.2)",
18903+
);
18904+
test(
18905+
"hwb(from rebeccapurple h calc(alpha * 100) calc(alpha * 100) / alpha)",
18906+
"rgb(128, 128, 128)",
18907+
);
1884818908
test("hwb(from rgb(20%, 40%, 60%, 80%) h b w)", "rgb(102, 153, 204)");
1884918909
test(
18850-
"hwb(from rgb(20%, 40%, 60%, 80%) h alpha w / b)",
18910+
"hwb(from rgb(20%, 40%, 60%, 80%) h calc(alpha * 100) w / calc(b / 100))",
1885118911
"rgba(204, 204, 204, 0.4)",
1885218912
);
18853-
test("hwb(from rgb(20%, 40%, 60%, 80%) h w w / w)", "rgba(51, 128, 204, 0.2)");
1885418913
test(
18855-
"hwb(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)",
18914+
"hwb(from rgb(20%, 40%, 60%, 80%) h w w / calc(w / 100))",
18915+
"rgba(51, 128, 204, 0.2)",
18916+
);
18917+
test(
18918+
"hwb(from rgb(20%, 40%, 60%, 80%) h calc(alpha * 100) calc(alpha * 100) / alpha)",
1885618919
"rgba(128, 128, 128, 0.8)",
1885718920
);
1885818921

@@ -19305,23 +19368,31 @@ mod tests {
1930519368
// NOTE: 'c' is a valid hue, as hue is <angle>|<number>.
1930619369
test(
1930719370
&format!("{}(from {}(70% 45 30) alpha c h / l)", color_space, color_space),
19308-
&format!("{}(100% 45 30 / 0.7)", color_space),
19371+
&format!(
19372+
"{}(1 45 30 / {})",
19373+
color_space,
19374+
if *color_space == "lch" { "1" } else { ".7" }
19375+
),
1930919376
);
1931019377
test(
1931119378
&format!("{}(from {}(70% 45 30) l c c / alpha)", color_space, color_space),
1931219379
&format!("{}(70% 45 45)", color_space),
1931319380
);
1931419381
test(
1931519382
&format!("{}(from {}(70% 45 30) alpha c h / alpha)", color_space, color_space),
19316-
&format!("{}(100% 45 30)", color_space),
19383+
&format!("{}(1 45 30)", color_space),
1931719384
);
1931819385
test(
1931919386
&format!("{}(from {}(70% 45 30) alpha c c / alpha)", color_space, color_space),
19320-
&format!("{}(100% 45 45)", color_space),
19387+
&format!("{}(1 45 45)", color_space),
1932119388
);
1932219389
test(
1932319390
&format!("{}(from {}(70% 45 30 / 40%) alpha c h / l)", color_space, color_space),
19324-
&format!("{}(40% 45 30 / 0.7)", color_space),
19391+
&format!(
19392+
"{}(.4 45 30 / {})",
19393+
color_space,
19394+
if *color_space == "lch" { "1" } else { ".7" }
19395+
),
1932519396
);
1932619397
test(
1932719398
&format!("{}(from {}(70% 45 30 / 40%) l c c / alpha)", color_space, color_space),
@@ -19332,14 +19403,14 @@ mod tests {
1933219403
"{}(from {}(70% 45 30 / 40%) alpha c h / alpha)",
1933319404
color_space, color_space
1933419405
),
19335-
&format!("{}(40% 45 30 / 0.4)", color_space),
19406+
&format!("{}(.4 45 30 / 0.4)", color_space),
1933619407
);
1933719408
test(
1933819409
&format!(
1933919410
"{}(from {}(70% 45 30 / 40%) alpha c c / alpha)",
1934019411
color_space, color_space
1934119412
),
19342-
&format!("{}(40% 45 45 / 0.4)", color_space),
19413+
&format!("{}(.4 45 45 / 0.4)", color_space),
1934319414
);
1934419415

1934519416
// Testing with calc().
@@ -20201,13 +20272,10 @@ mod tests {
2020120272
".foo{color:hsl(from rebeccapurple s h l)}",
2020220273
".foo{color:hsl(from rebeccapurple s h l)}",
2020320274
);
20275+
minify_test(".foo{color:hsl(from rebeccapurple s s s / s)}", ".foo{color:#bfaa40}");
2020420276
minify_test(
20205-
".foo{color:hsl(from rebeccapurple s s s / s)}",
20206-
".foo{color:hsl(from rebeccapurple s s s/s)}",
20207-
);
20208-
minify_test(
20209-
".foo{color:hsl(from rebeccapurple alpha alpha alpha / alpha)}",
20210-
".foo{color:hsl(from rebeccapurple alpha alpha alpha/alpha)}",
20277+
".foo{color:hsl(from rebeccapurple calc(alpha * 100) calc(alpha * 100) calc(alpha * 100) / alpha)}",
20278+
".foo{color:#fff}",
2021120279
);
2021220280
}
2021320281
}
@@ -28761,10 +28829,14 @@ mod tests {
2876128829
let source_index = sm.add_source("input.css");
2876228830
sm.set_source_content(source_index as usize, source).unwrap();
2876328831

28764-
let mut stylesheet = StyleSheet::parse(&source, ParserOptions {
28765-
source_index,
28766-
..Default::default()
28767-
}).unwrap();
28832+
let mut stylesheet = StyleSheet::parse(
28833+
&source,
28834+
ParserOptions {
28835+
source_index,
28836+
..Default::default()
28837+
},
28838+
)
28839+
.unwrap();
2876828840
stylesheet.minify(MinifyOptions::default()).unwrap();
2876928841
stylesheet
2877028842
.to_css(PrinterOptions {

src/properties/custom.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::traits::{Parse, ParseWithOptions, ToCss};
1212
use crate::values::angle::Angle;
1313
use crate::values::color::{
1414
parse_hsl_hwb_components, parse_rgb_components, ColorFallbackKind, ComponentParser, CssColor, LightDarkColor,
15-
HSL, RGBA, SRGB,
15+
HSL, RGB, RGBA,
1616
};
1717
use crate::values::ident::{CustomIdent, DashedIdent, DashedIdentReference, Ident};
1818
use crate::values::length::{serialize_dimension, LengthValue};
@@ -1594,7 +1594,7 @@ impl<'i> UnresolvedColor<'i> {
15941594
match_ignore_ascii_case! { &*f,
15951595
"rgb" => {
15961596
input.parse_nested_block(|input| {
1597-
parser.parse_relative::<SRGB, _, _>(input, |input, parser| {
1597+
parser.parse_relative::<RGB, _, _>(input, |input, parser| {
15981598
let (r, g, b, is_legacy) = parse_rgb_components(input, parser)?;
15991599
if is_legacy {
16001600
return Err(input.new_custom_error(ParserError::InvalidValue))
@@ -1636,32 +1636,27 @@ impl<'i> UnresolvedColor<'i> {
16361636
where
16371637
W: std::fmt::Write,
16381638
{
1639-
#[inline]
1640-
fn c(c: &f32) -> i32 {
1641-
(c * 255.0).round().clamp(0.0, 255.0) as i32
1642-
}
1643-
16441639
match self {
16451640
UnresolvedColor::RGB { r, g, b, alpha } => {
16461641
if should_compile!(dest.targets.current, SpaceSeparatedColorNotation) {
16471642
dest.write_str("rgba(")?;
1648-
c(r).to_css(dest)?;
1643+
r.to_css(dest)?;
16491644
dest.delim(',', false)?;
1650-
c(g).to_css(dest)?;
1645+
g.to_css(dest)?;
16511646
dest.delim(',', false)?;
1652-
c(b).to_css(dest)?;
1647+
b.to_css(dest)?;
16531648
dest.delim(',', false)?;
16541649
alpha.to_css(dest, is_custom_property)?;
16551650
dest.write_char(')')?;
16561651
return Ok(());
16571652
}
16581653

16591654
dest.write_str("rgb(")?;
1660-
c(r).to_css(dest)?;
1655+
r.to_css(dest)?;
16611656
dest.write_char(' ')?;
1662-
c(g).to_css(dest)?;
1657+
g.to_css(dest)?;
16631658
dest.write_char(' ')?;
1664-
c(b).to_css(dest)?;
1659+
b.to_css(dest)?;
16651660
dest.delim('/', true)?;
16661661
alpha.to_css(dest, is_custom_property)?;
16671662
dest.write_char(')')
@@ -1671,9 +1666,9 @@ impl<'i> UnresolvedColor<'i> {
16711666
dest.write_str("hsla(")?;
16721667
h.to_css(dest)?;
16731668
dest.delim(',', false)?;
1674-
Percentage(*s).to_css(dest)?;
1669+
Percentage(*s / 100.0).to_css(dest)?;
16751670
dest.delim(',', false)?;
1676-
Percentage(*l).to_css(dest)?;
1671+
Percentage(*l / 100.0).to_css(dest)?;
16771672
dest.delim(',', false)?;
16781673
alpha.to_css(dest, is_custom_property)?;
16791674
dest.write_char(')')?;
@@ -1683,9 +1678,9 @@ impl<'i> UnresolvedColor<'i> {
16831678
dest.write_str("hsl(")?;
16841679
h.to_css(dest)?;
16851680
dest.write_char(' ')?;
1686-
Percentage(*s).to_css(dest)?;
1681+
Percentage(*s / 100.0).to_css(dest)?;
16871682
dest.write_char(' ')?;
1688-
Percentage(*l).to_css(dest)?;
1683+
Percentage(*l / 100.0).to_css(dest)?;
16891684
dest.delim('/', true)?;
16901685
alpha.to_css(dest, is_custom_property)?;
16911686
dest.write_char(')')

0 commit comments

Comments
 (0)