diff --git a/src/Compiler.php b/src/Compiler.php index d22d0a35..cb679f65 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -4888,6 +4888,89 @@ protected function hueToRGB($m1, $m2, $h) return $m1; } + protected function normalizeStringArgs($args) { + $normalizedArgs = []; + if (is_array($args[0][2] ?? null)) { + foreach ($args[0][2] as $part) { + if ($part instanceof Node\Number) { + $normalizedArgs[] = $part; + } + if (is_array($part)) { + $normalizedArgs[] = $part; + } + } + } + + return $normalizedArgs; + } + + /** + * Normalize color function arguments (handle space-separated syntax) + * + * @param array $args + * @param int $expectedCount + * @param bool $supportColor + * + * @return array + */ + protected function normalizeColorArgs($args, $expectedCount, $supportColor = false) + { + if (is_array($args[0] ?? null) && ($args[0][0] ?? null) === Type::T_STRING) { + // ['string', '', ['list', '', ['color', 123, 123, 123]], '', '/', '', Node\Number] + $args = $this->normalizeStringArgs($args); + } + + // Check if first arg is a list (space-separated syntax) + if (is_array($args[0] ?? null) && ($args[0][0] ?? null) === Type::T_LIST) { + $listItems = $args[0][2]; // Get the list items + + // Flatten the list items, handling slash-separated values + $normalizedItems = []; + + if (is_array($listItems[0] ?? null) && ($listItems[0][0] ?? null) === Type::T_LIST) { + // ['list', '', ['list', '', ['color', 123, 123, 123]]] + $normalizedItems = $this->normalizeColorArgs($listItems, $expectedCount, $supportColor); + } elseif (is_array($listItems[0] ?? null) && ($listItems[0][0] ?? null) === Type::T_COLOR) { + // ['color', 123, 123, 123] + $normalizedItems[] = $listItems[0]; + // Check list items + if (($listItems[1] ?? null) instanceof Node\Number) { + $normalizedItems[] = $listItems[1]; + } + // Proceed with opacity from normal args if not empty + if (($args[1] ?? null) instanceof Node\Number) { + $normalizedItems[] = $args[1]; + } + } else { + foreach ($listItems as $item) { + if (is_array($item) && ($item[0] ?? null) === Type::T_STRING && is_array($item[2] ?? null)) { + // This is a string like "48% / 50%" - extract just the numbers + $normalizedItem = $this->normalizeStringArgs($args); + foreach ($normalizedItem as $part) { + $normalizedItems[] = $part; + } + } else { + $normalizedItems[] = $item; + } + } + } + + // First arg is a color + if ($supportColor && $this->coerceColor($normalizedItems[0])) { + return $normalizedItems; + } + + // Pad with nulls if needed + while (count($normalizedItems) < $expectedCount) { + $normalizedItems[] = 0; + } + + return array_slice($normalizedItems, 0, $expectedCount); + } + + return $args; + } + /** * Convert HSL to RGB * @@ -5009,6 +5092,11 @@ protected function libIndex($args) protected static $libRgb = ['red', 'green', 'blue']; protected function libRgb($args) { + // Handle space-separated syntax: rgb(255 255 255) + $args = $this->normalizeColorArgs($args, 3); + if ($color = $this->coerceColor($args[0])) { + return $color; + } list($r, $g, $b) = $args; return [Type::T_COLOR, $r[1], $g[1], $b[1]]; @@ -5019,15 +5107,23 @@ protected function libRgb($args) 'green', 'blue', 'alpha']; protected function libRgba($args) { + // Handle space-separated syntax: rgba(255 255 255 50%) + $args = $this->normalizeColorArgs($args, 4, true); if ($color = $this->coerceColor($args[0])) { - $num = isset($args[3]) ? $args[3] : $args[1]; + $num = isset($args[3]) && is_array($args[3]) ? $args[3] : $args[1]; $alpha = $this->assertNumber($num); + if ($alpha > 1) { + $alpha = $alpha / 100; + } $color[4] = $alpha; return $color; } list($r, $g, $b, $a) = $args; + if (($a[1] ?? 0) > 1) { + $a[1] = $a[1] / 100; + } return [Type::T_COLOR, $r[1], $g[1], $b[1], $a[1]]; } @@ -5224,6 +5320,11 @@ protected function libMix($args) protected static $libHsl = ['hue', 'saturation', 'lightness']; protected function libHsl($args) { + // Handle space-separated syntax: hsl(180deg 50% 50%) + $args = $this->normalizeColorArgs($args, 3); + if ($color = $this->coerceColor($args[0])) { + return $color; + } list($h, $s, $l) = $args; return $this->toRGB($h[1], $s[1], $l[1]); @@ -5232,9 +5333,25 @@ protected function libHsl($args) protected static $libHsla = ['hue', 'saturation', 'lightness', 'alpha']; protected function libHsla($args) { + // Handle space-separated syntax: hsla(180deg 50% 58% / 50%) + $args = $this->normalizeColorArgs($args, 4, true); + if ($color = $this->coerceColor($args[0])) { + $num = is_array($args[3] ?? null) ? $args[3] : $args[1]; + $alpha = $this->assertNumber($num); + if ($alpha > 1) { + $alpha = $alpha / 100; + } + $color[4] = $alpha; + + return $color; + } + list($h, $s, $l, $a) = $args; $color = $this->toRGB($h[1], $s[1], $l[1]); + if (($a[1] ?? 0) > 1) { + $a[1] = $a[1] / 100; + } $color[4] = $a[1]; return $color;