Skip to content

Commit 38dcef8

Browse files
committed
fix: hsl and rgb with alpha channel parsed incorrectly
1 parent d1c9436 commit 38dcef8

File tree

4 files changed

+110
-2
lines changed

4 files changed

+110
-2
lines changed

src/Value/Color.php

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,15 @@ public static function parse(ParserState $oParserState, bool $bIgnoreCase = fals
7878
} else {
7979
$sColorTarget = $sColorMode;
8080
}
81+
8182
$iLength = $oParserState->strlen($sColorTarget);
8283
for ($i = 0; $i < $iLength; ++$i) {
8384
$oParserState->consumeWhiteSpace();
8485
if ($oParserState->comes('var')) {
8586
$aColor[$sColorTarget[$i]] = CSSFunction::parseIdentifierOrFunction($oParserState);
8687
$bContainsVarOrCalc = true;
8788
} elseif ($oParserState->comes('calc')) {
88-
$aColor[$sColorMode[$i]] = CalcFunction::parse($oParserState);
89+
$aColor[$sColorTarget[$i]] = CalcFunction::parse($oParserState);
8990
$bContainsVarOrCalc = true;
9091
} else {
9192
$aColor[$sColorTarget[$i]] = Size::parse($oParserState, true);
@@ -101,6 +102,33 @@ public static function parse(ParserState $oParserState, bool $bIgnoreCase = fals
101102
if ($oParserState->comes(',')) {
102103
$oParserState->consume(',');
103104
} elseif ($oParserState->comes('/')) {
105+
// According to https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/rgb
106+
// and https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl
107+
// '/' is used to separate the color from the alpha channel information
108+
// in rgb or hsl color functions (it is placed before the fourth argument).
109+
110+
if (in_array($sColorMode, ["hsl", "rgb"]) && count($aColor) !== 3) {
111+
throw new UnexpectedTokenException(
112+
'Unexpected token',
113+
'/',
114+
'custom',
115+
$oParserState->currentLine()
116+
);
117+
}
118+
119+
// If we have a hsl or rgb color function with an alpha channel,
120+
// we need to switch the color mode to rgba or hsla accordingly.
121+
switch ($sColorMode) {
122+
case "rgb":
123+
$sColorMode = "rgba";
124+
break;
125+
case "hsl":
126+
$sColorMode = "hsla";
127+
break;
128+
default:
129+
break;
130+
}
131+
104132
$oParserState->consume('/');
105133
} elseif ($oParserState->comes(')')) {
106134
// No alpha channel information

tests/ParserTest.php

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,15 @@ public function colorParsing(): void
169169
. '#css4-rgba {background-color: rgba(242,245,249,45%);background-color: #f2f5f9;}'
170170
. "\n"
171171
. '#calc {background-color: rgba(var(--some-rgb),calc(var(--some-alpha) * .1));'
172-
. 'background-color: hsla(var(--some-hsl),calc(var(--some-alpha) * .1));}',
172+
. 'background-color: hsla(var(--some-hsl),calc(var(--some-alpha) * .1));}'
173+
. "\n"
174+
. '#hsl-calc {background-color: hsla(0,0%,10%,calc(1 - var(--hover,0) * .25));}'
175+
. "\n"
176+
. "#hsl-alpha-numeric {background-color: hsla(0,0%,10%,.5);}"
177+
. "\n"
178+
. '#rgb-calc {background-color: rgba(0,0%,10%,calc(1 - var(--hover,0) * .25));}'
179+
. "\n"
180+
. "#rgb-alpha-numeric {background-color: rgba(0,0%,10%,.5);}",
173181
$oDoc->render()
174182
);
175183
}
@@ -862,6 +870,30 @@ public function invalidRulesInFile(): void
862870
self::assertSame($sExpected, $oDoc->render());
863871
}
864872

873+
/**
874+
* @test
875+
*/
876+
public function invalidHslOrRgbInFile(): void
877+
{
878+
$oDoc = self::parsedStructureForFile('invalid-hsl-rgb', Settings::create()->withMultibyteSupport(true));
879+
$sExpected = '#hsl-1 {}'
880+
. "\n"
881+
. '#hsl-2 {}'
882+
. "\n"
883+
. '#hsl-3 {}'
884+
. "\n"
885+
. '#hsl-4 {}'
886+
. "\n"
887+
. "#rgb-1 {}"
888+
. "\n"
889+
. '#rgb-2 {}'
890+
. "\n"
891+
. '#rgb-3 {}'
892+
. "\n"
893+
. '#rgb-4 {}';
894+
self::assertSame($sExpected, $oDoc->render());
895+
}
896+
865897
/**
866898
* @test
867899
*/

tests/fixtures/colortest.css

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,20 @@
3737
background-color: rgba(var(--some-rgb), calc(var(--some-alpha) * 0.1));
3838
background-color: hsla(var(--some-hsl), calc(var(--some-alpha) * 0.1));
3939
}
40+
41+
#hsl-calc {
42+
background-color: hsl(0 0% 10% / calc(1 - var(--hover, 0) * 0.25));
43+
}
44+
45+
#hsl-alpha-numeric {
46+
background-color: hsl(0 0% 10% / 0.5);
47+
}
48+
49+
#rgb-calc {
50+
background-color: rgb(0 0% 10% / calc(1 - var(--hover, 0) * 0.25));
51+
}
52+
53+
#rgb-alpha-numeric {
54+
background-color: rgb(0 0% 10% / 0.5);
55+
}
56+

tests/fixtures/invalid-hsl-rgb.css

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#hsl-1 {
2+
background-color: hsl(0 / 0% 10% 0.5);
3+
}
4+
5+
#hsl-2 {
6+
background-color: hsl(0 0% / 10% 0.5);
7+
}
8+
9+
#hsl-3 {
10+
background-color: hsl(0 0%/10% 0.5);
11+
}
12+
13+
#hsl-4 {
14+
background-color: hsl(0 / 0% 10% calc(1 - var(--hover, 0) * 0.25));
15+
}
16+
17+
#rgb-1 {
18+
background-color: rgb(0 / 0% 10% 0.5);
19+
}
20+
21+
#rgb-2 {
22+
background-color: rgb(0 0% / 10% 0.5);
23+
}
24+
25+
#rgb-3 {
26+
background-color: rgb(0 0%/10% 0.5);
27+
}
28+
29+
#rgb-4 {
30+
background-color: rgb(0 / 0% 10% calc(1 - var(--hover, 0) * 0.25));
31+
}

0 commit comments

Comments
 (0)