diff --git a/CHANGELOG.md b/CHANGELOG.md index a1f9a7e98..d37045864 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ Please also have a look at our ### Added +- Partial support for CSS Color Module Level 4 syntax: + - `rgb` and `rgba`, and `hsl` and `hsla` are now aliases (#797} - Add official support for PHP 8.4 (#657) - Support arithmetic operators in CSS function arguments (#607) - Add support for inserting an item in a CSS list (#545) diff --git a/src/Value/Color.php b/src/Value/Color.php index 07ec5b135..f62bda3cc 100644 --- a/src/Value/Color.php +++ b/src/Value/Color.php @@ -72,23 +72,51 @@ public static function parse(ParserState $oParserState, bool $bIgnoreCase = fals $oParserState->consumeWhiteSpace(); $oParserState->consume('('); + // CSS Color Module Level 4 says that `rgb` and `rgba` are now aliases; likewise `hsl` and `hsla`. + // So, attempt to parse with the `a`, and allow for it not being there. + switch ($sColorMode) { + case 'rgb': + $colorModeForParsing = 'rgba'; + $mayHaveOptionalAlpha = true; + break; + case 'hsl': + $colorModeForParsing = 'hsla'; + $mayHaveOptionalAlpha = true; + break; + case 'rgba': + // This is handled identically to the following case. + case 'hsla': + $colorModeForParsing = $sColorMode; + $mayHaveOptionalAlpha = true; + break; + default: + $colorModeForParsing = $sColorMode; + $mayHaveOptionalAlpha = false; + } + $bContainsVar = false; - $iLength = $oParserState->strlen($sColorMode); + $iLength = $oParserState->strlen($colorModeForParsing); for ($i = 0; $i < $iLength; ++$i) { $oParserState->consumeWhiteSpace(); if ($oParserState->comes('var')) { - $aColor[$sColorMode[$i]] = CSSFunction::parseIdentifierOrFunction($oParserState); + $aColor[$colorModeForParsing[$i]] = CSSFunction::parseIdentifierOrFunction($oParserState); $bContainsVar = true; } else { - $aColor[$sColorMode[$i]] = Size::parse($oParserState, true); + $aColor[$colorModeForParsing[$i]] = Size::parse($oParserState, true); } - if ($bContainsVar && $oParserState->comes(')')) { - // With a var argument the function can have fewer arguments + // This must be done first, to consume comments as well, so that the `comes` test will work. + $oParserState->consumeWhiteSpace(); + + // With a `var` argument, the function can have fewer arguments. + // And as of CSS Color Module Level 4, the alpha argument is optional. + $canCloseNow = + $bContainsVar || + ($mayHaveOptionalAlpha && $i >= $iLength - 2); + if ($canCloseNow && $oParserState->comes(')')) { break; } - $oParserState->consumeWhiteSpace(); if ($i < ($iLength - 1)) { $oParserState->consume(','); } diff --git a/tests/Unit/Value/ColorTest.php b/tests/Unit/Value/ColorTest.php index 08df85732..b4799aa87 100644 --- a/tests/Unit/Value/ColorTest.php +++ b/tests/Unit/Value/ColorTest.php @@ -62,15 +62,15 @@ public static function provideValidColorAndExpectedRendering(): array 'rgba(0, 119, 0, 50%)', 'rgba(0,119,0,50%)', ], - /* 'legacy rgb as rgba' => [ 'rgba(0, 119, 0)', - 'rgb(0,119,0)', + '#070', ], 'legacy rgba as rgb' => [ 'rgb(0, 119, 0, 0.5)', 'rgba(0,119,0,.5)', ], + /* 'modern rgb' => [ 'rgb(0 119 0)', 'rgb(0,119,0)', @@ -112,16 +112,14 @@ public static function provideValidColorAndExpectedRendering(): array 'hsla(120, 100%, 25%, 50%)', 'hsla(120,100%,25%,50%)', ], - /* 'legacy hsl as hsla' => [ 'hsla(120, 100%, 25%)', 'hsl(120,100%,25%)', ], 'legacy hsla as hsl' => [ 'hsl(120, 100%, 25%, 0.5)', - 'hsla(120,100%,25%,0.5)', + 'hsla(120,100%,25%,.5)', ], - //*/ ]; }