148 lines
5.1 KiB
PHP
148 lines
5.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/*
|
|
* This file is developed by evoWeb.
|
|
*
|
|
* It is free software; you can redistribute it and/or modify it under
|
|
* the terms of the GNU General Public License, either version 2
|
|
* of the License, or any later version.
|
|
*
|
|
* For the full copyright and license information, please read the
|
|
* LICENSE.txt file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Evoweb\EwBase\Services;
|
|
|
|
class Tailwindcss4Merger
|
|
{
|
|
public function cssUnique(string $styles): string
|
|
{
|
|
$atLayerOrder = $this->getLayerOrder($styles);
|
|
$atLayerBase = $this->getLayerBase($styles);
|
|
$atLayerTheme = $this->getLayerTheme($styles);
|
|
$atLayerUtilities = $this->getLayerUtilities($styles);
|
|
$atLayerComponents = $this->getLayerComponents($styles);
|
|
$atProperty = $this->getProperties($styles);
|
|
$atLayerProperties = $this->getLayerProperties($styles);
|
|
return implode(chr(10), [
|
|
$atLayerOrder,
|
|
$atLayerBase,
|
|
$atLayerTheme,
|
|
$atLayerUtilities,
|
|
$atLayerComponents,
|
|
$atProperty,
|
|
$atLayerProperties,
|
|
]);
|
|
}
|
|
|
|
protected function getLayerOrder(string $styles): string
|
|
{
|
|
preg_match_all('/(?<layer>@layer[^;{]+;)/i', $styles, $matches);
|
|
return implode(chr(10), array_unique($matches['layer'] ?? []));
|
|
}
|
|
|
|
protected function getLayerBase(string $styles): string
|
|
{
|
|
$matches = $this->getLayerByName($styles, 'base');
|
|
$base = [];
|
|
foreach ($matches as $match) {
|
|
$match = $this->unwrapLayer($match, 'base');
|
|
$match = preg_replace('/}\n *\./', "}\n||.", $match);
|
|
$match = preg_replace('/}\n\W*@/', "}\n||@", $match);
|
|
$parts = explode('||', $match);
|
|
$base = array_merge($base, $parts);
|
|
}
|
|
return $this->wrapLayer('base', array_unique($base));
|
|
}
|
|
|
|
protected function getLayerTheme(string $styles): string
|
|
{
|
|
$matches = $this->getLayerByName($styles, 'theme');
|
|
$themes = [];
|
|
foreach ($matches as $match) {
|
|
preg_match_all('/(?<theme>--[^;]+;)/i', $match, $subMatches);
|
|
$themes = array_merge($themes, $subMatches['theme'] ?? []);
|
|
}
|
|
return '@layer theme {
|
|
:root, :host {'
|
|
. chr(10)
|
|
. implode(chr(10), array_unique($themes))
|
|
. chr(10)
|
|
. ' }
|
|
}';
|
|
}
|
|
|
|
protected function getLayerUtilities(string $styles): string
|
|
{
|
|
$matches = $this->getLayerByName($styles, 'utilities');
|
|
$utilities = [];
|
|
foreach ($matches as $match) {
|
|
$match = $this->unwrapLayer($match, 'utilities');
|
|
$match = preg_replace('/}\n *\./', "}\n||.", $match);
|
|
$parts = explode('||', $match);
|
|
$utilities = array_merge($utilities, $parts);
|
|
}
|
|
return $this->wrapLayer('utilities', array_unique($utilities));
|
|
}
|
|
|
|
protected function getLayerComponents(string $styles): string
|
|
{
|
|
$matches = $this->getLayerByName($styles, 'components');
|
|
$components = [];
|
|
foreach ($matches as $match) {
|
|
$match = $this->unwrapLayer($match, 'components');
|
|
$match = preg_replace('/}\n *\./', "}\n||.", $match);
|
|
$parts = explode('||', $match);
|
|
$components = array_merge($components, $parts);
|
|
}
|
|
return $this->wrapLayer('components', array_unique($components));
|
|
}
|
|
|
|
protected function getLayerByName(string $styles, string $name): array
|
|
{
|
|
preg_match_all('/@layer[^{;]+\{.+?(?=\n})\n}/s', $styles, $matches);
|
|
$layer = [];
|
|
foreach ($matches['0'] as $match) {
|
|
if (str_starts_with($match, '@layer ' . $name) !== false) {
|
|
$layer[] = $match;
|
|
}
|
|
}
|
|
return $layer;
|
|
}
|
|
|
|
protected function getProperties(string $styles): string
|
|
{
|
|
preg_match_all('/(?<property>@property[^{]+\{[^}]+})/i', $styles, $matches);
|
|
return implode(chr(10), array_unique($matches['property'] ?? []));
|
|
}
|
|
|
|
protected function getLayerProperties(string $styles): string
|
|
{
|
|
$matches = $this->getLayerByName($styles, 'properties');
|
|
$properties = [
|
|
' @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
|
|
*, ::before, ::after, ::backdrop {'
|
|
];
|
|
foreach ($matches as $match) {
|
|
preg_match_all('/(?<properties>--tw[^ ]+: [^;]+;)/i', $match, $subMatches);
|
|
$properties = array_merge($properties, $subMatches['properties']);
|
|
}
|
|
$properties = array_unique($properties);
|
|
$properties[] = ' }
|
|
}';
|
|
return $this->wrapLayer('properties', $properties);
|
|
}
|
|
|
|
protected function unwrapLayer(string $styles, string $name): string
|
|
{
|
|
return trim(str_replace('@layer ' . $name . ' {', '', substr($styles, 0, -1)));
|
|
}
|
|
|
|
protected function wrapLayer(string $name, array $styles): string
|
|
{
|
|
return '@layer ' . $name . " {\n" . implode("\n", $styles) . "\n}";
|
|
}
|
|
}
|