Skip to content

Commit

Permalink
[BUGFIX] Don't render rgb colors with % values as hex (#803)
Browse files Browse the repository at this point in the history
The only percentage values that could be reliably converted to hex notation are
0%, 20%, 40%, etc.
It's beyond the scope of this library to do that.

Also add additional tests to confirm parsing of percentage values.
Some of these are commented out,
because the input data would result in rendering in an invalid format.
(The "legacy" syntax does not allow a mixture of `percentage`s and `number`s,
so it would be necessary to implement rendering in the "modern" syntax
to resolve those cases, which is beyond the scope of this PR.)

Co-authored-by: Jake Hotson <[email protected]>
  • Loading branch information
JakeQZ and JakeQZ authored Jan 25, 2025
1 parent 98c8bb8 commit 540b315
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Please also have a look at our

### Fixed

- Don't render `rgb` colors with percentage values using hex notation (#803)
- Parse `@font-face` `src` property as comma-delimited list (#790)
- Fix type errors in PHP strict mode (#664)
- Fix undefined local variable in `CalcFunction::parse()` (#593)
Expand Down
21 changes: 20 additions & 1 deletion src/Value/Color.php
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,11 @@ public function __toString(): string
public function render(OutputFormat $outputFormat): string
{
// Shorthand RGB color values
if ($outputFormat->getRGBHashNotation() && \implode('', \array_keys($this->aComponents)) === 'rgb') {
if (
$outputFormat->getRGBHashNotation()
&& \implode('', \array_keys($this->aComponents)) === 'rgb'
&& $this->allComponentsAreNumbers()
) {
$result = \sprintf(
'%02x%02x%02x',
$this->aComponents['r']->getSize(),
Expand All @@ -237,4 +241,19 @@ public function render(OutputFormat $outputFormat): string
}
return parent::render($outputFormat);
}

/**
* Test whether all color components are absolute numbers (CSS type `number`), not percentages or anything else.
* If any component is not an instance of `Size`, the method will also return `false`.
*/
private function allComponentsAreNumbers(): bool
{
foreach ($this->aComponents as $component) {
if (!$component instanceof Size || $component->getUnit() !== null) {
return false;
}
}

return true;
}
}
71 changes: 70 additions & 1 deletion tests/Unit/Value/ColorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ public static function provideValidColorAndExpectedRendering(): array
'rgb(0, 118, 0)',
'#007600',
],
'legacy rgb with percentage components' => [
'rgb(0%, 60%, 0%)',
'rgb(0%,60%,0%)',
],
'legacy rgba with fractional alpha' => [
'rgba(0, 119, 0, 0.5)',
'rgba(0,119,0,.5)',
Expand All @@ -62,6 +66,14 @@ public static function provideValidColorAndExpectedRendering(): array
'rgba(0, 119, 0, 50%)',
'rgba(0,119,0,50%)',
],
'legacy rgba with percentage components and fractional alpha' => [
'rgba(0%, 60%, 0%, 0.5)',
'rgba(0%,60%,0%,.5)',
],
'legacy rgba with percentage components and percentage alpha' => [
'rgba(0%, 60%, 0%, 50%)',
'rgba(0%,60%,0%,50%)',
],
'legacy rgb as rgba' => [
'rgba(0, 119, 0)',
'#070',
Expand All @@ -74,16 +86,73 @@ public static function provideValidColorAndExpectedRendering(): array
'rgb(0 119 0)',
'#070',
],
// The "legacy" syntax currently used for rendering does not allow a mixture of percentages and numbers.
/*
'modern rgb with percentage R' => [
'rgb(0% 119 0)',
'rgb(0% 119 0)',
],
'modern rgb with percentage G' => [
'rgb(0 60% 0)',
'rgb(0 60% 0)',
],
'modern rgb with percentage B' => [
'rgb(0 119 0%)',
'rgb(0 119 0%)',
],
'modern rgb with percentage R&G' => [
'rgb(0% 60% 0)',
'rgb(0% 60% 0)',
],
'modern rgb with percentage R&B' => [
'rgb(0% 119 0%)',
'rgb(0% 119 0%)',
],
'modern rgb with percentage G&B' => [
'rgb(0 60% 0%)',
'rgb(0 60% 0%)',
],
//*/
'modern rgb with percentage components' => [
'rgb(0% 60% 0%)',
'rgb(0%,60%,0%)',
],
/*
'modern rgb with none' => [
'rgb(none 119 0)',
'rgb(none 119 0)',
],
//*/
'modern rgba' => [
'modern rgba with fractional alpha' => [
'rgb(0 119 0 / 0.5)',
'rgba(0,119,0,.5)',
],
'modern rgba with percentage alpha' => [
'rgb(0 119 0 / 50%)',
'rgba(0,119,0,50%)',
],
/*
'modern rgba with percentage R' => [
'rgb(0% 119 0 / 0.5)',
'rgba(0% 119 0/.5)',
],
'modern rgba with percentage G' => [
'rgb(0 60% 0 / 0.5)',
'rgba(0 60% 0/.5)',
],
'modern rgba with percentage B' => [
'rgb(0 119 0% / 0.5)',
'rgba(0 119 0%/.5)',
],
//*/
'modern rgba with percentage RGB' => [
'rgb(0% 60% 0% / 0.5)',
'rgba(0%,60%,0%,.5)',
],
'modern rgba with percentage components' => [
'rgb(0% 60% 0% / 50%)',
'rgba(0%,60%,0%,50%)',
],
/*
'modern rgba with none as alpha' => [
'rgb(0 119 0 / none)',
Expand Down

0 comments on commit 540b315

Please sign in to comment.