'background-position', 'size' => 'background-size', 'repeat' => 'background-repeat'] as $key => $prop) { $v = isset($value[$key]) && is_string($value[$key]) ? trim($value[$key]) : ''; if ($v !== '' && preg_match('/^[a-z0-9%.\s-]+$/i', $v)) { $out[] = $prop . ':' . $v; } } } return implode(';', $out); } /** Safe CSS colour (hex, rgb/hsl/color-mix functions, var(--x), named) or ''. */ public static function color($value): string { if (!is_string($value)) { return ''; } $value = trim($value); if ($value === '') { return ''; } if (preg_match('/^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i', $value) || preg_match('/^(rgba?|hsla?|color-mix)\([\w\s%.,\/#()-]+\)$/i', $value) || preg_match('/^var\(--[a-z0-9-]+\)$/i', $value) || preg_match('/^[a-z]+$/i', $value)) { return $value; } return ''; } /** @param array $g */ private static function gradient(array $g): string { $stops = []; $list = is_array($g['stops'] ?? null) ? array_values(array_filter($g['stops'], 'is_array')) : []; $valid = array_values(array_filter($list, static fn(array $s): bool => self::color($s['color'] ?? '') !== '')); $n = count($valid); if ($n < 2) { return ''; } foreach ($valid as $i => $s) { $pos = isset($s['position']) && is_numeric($s['position']) ? (float) $s['position'] + 0 : round(($i / ($n - 1)) * 100); $stops[] = self::color($s['color']) . ' ' . $pos . '%'; } if (($g['type'] ?? 'linear') === 'radial') { return 'radial-gradient(circle, ' . implode(', ', $stops) . ')'; } $angle = isset($g['angle']) && is_numeric($g['angle']) ? (float) $g['angle'] + 0 : 180; return 'linear-gradient(' . $angle . 'deg, ' . implode(', ', $stops) . ')'; } private static function url(string $url): string { $url = function_exists('esc_url_raw') ? (string) esc_url_raw($url) : $url; return str_replace(['\\', '"', "\r", "\n"], ['\\\\', '\\"', '', ''], $url); } }