Merge branch 'release/2.3.0'
This commit is contained in:
commit
46810c675e
@ -16,6 +16,7 @@ declare(strict_types=1);
|
|||||||
namespace Evoweb\EwBase\EventListener;
|
namespace Evoweb\EwBase\EventListener;
|
||||||
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Evoweb\EwBase\Services\Tailwindcss4Merger;
|
||||||
use TYPO3\CMS\Core\Core\RequestId;
|
use TYPO3\CMS\Core\Core\RequestId;
|
||||||
use TYPO3\CMS\Core\Page\AssetCollector;
|
use TYPO3\CMS\Core\Page\AssetCollector;
|
||||||
use TYPO3\CMS\Core\Page\Event\BeforeStylesheetsRenderingEvent;
|
use TYPO3\CMS\Core\Page\Event\BeforeStylesheetsRenderingEvent;
|
||||||
@ -26,7 +27,8 @@ use TYPO3\CMS\Core\Utility\PathUtility;
|
|||||||
readonly class CssMerger
|
readonly class CssMerger
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private RequestId $requestId
|
private RequestId $requestId,
|
||||||
|
protected Tailwindcss4Merger $tailwindcss4Merger
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,6 +36,9 @@ readonly class CssMerger
|
|||||||
{
|
{
|
||||||
if ($event->isInline() && $event->isPriority()) {
|
if ($event->isInline() && $event->isPriority()) {
|
||||||
$assetCollector = $event->getAssetCollector();
|
$assetCollector = $event->getAssetCollector();
|
||||||
|
if (empty($assetCollector->getStyleSheets()) && empty($assetCollector->getInlineStyleSheets())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$styles = [];
|
$styles = [];
|
||||||
$styles = $this->getStylesheetFileContent($assetCollector, $styles);
|
$styles = $this->getStylesheetFileContent($assetCollector, $styles);
|
||||||
@ -41,18 +46,9 @@ readonly class CssMerger
|
|||||||
|
|
||||||
$styles = array_unique($styles);
|
$styles = array_unique($styles);
|
||||||
$styles = trim(implode(LF, $styles));
|
$styles = trim(implode(LF, $styles));
|
||||||
if (empty($styles)) {
|
$styles = $this->tailwindcss4Merger->cssUnique($styles);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @var Site $site */
|
if ($this->assertStylesShouldBeAddedInline()) {
|
||||||
$site = $this->getRequest()->getAttribute('site');
|
|
||||||
if (
|
|
||||||
$site instanceof Site
|
|
||||||
&& ($siteSettings = $site->getSettings())
|
|
||||||
&& !$siteSettings->isEmpty()
|
|
||||||
&& $siteSettings->get('ew-base.inlineCssStyles')
|
|
||||||
) {
|
|
||||||
$assetCollector->addInlineStyleSheet('ew_base', $styles, [], ['priority' => true]);
|
$assetCollector->addInlineStyleSheet('ew_base', $styles, [], ['priority' => true]);
|
||||||
} else {
|
} else {
|
||||||
$temporaryFile = GeneralUtility::writeStyleSheetContentToTemporaryFile($styles);
|
$temporaryFile = GeneralUtility::writeStyleSheetContentToTemporaryFile($styles);
|
||||||
@ -87,16 +83,6 @@ readonly class CssMerger
|
|||||||
return $styles;
|
return $styles;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getStylesheetInlineContent(AssetCollector $assetCollector, array $styles): array
|
|
||||||
{
|
|
||||||
$styleSheetsInline = $assetCollector->getInlineStyleSheets(false);
|
|
||||||
foreach ($styleSheetsInline as $identifier => $asset) {
|
|
||||||
$styles[] = $asset['source'];
|
|
||||||
$assetCollector->removeInlineStyleSheet($identifier);
|
|
||||||
}
|
|
||||||
return $styles;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getFileContent(string $filePath): string
|
protected function getFileContent(string $filePath): string
|
||||||
{
|
{
|
||||||
$absoluteFilePath = GeneralUtility::getFileAbsFileName($filePath);
|
$absoluteFilePath = GeneralUtility::getFileAbsFileName($filePath);
|
||||||
@ -124,6 +110,24 @@ readonly class CssMerger
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getStylesheetInlineContent(AssetCollector $assetCollector, array $styles): array
|
||||||
|
{
|
||||||
|
$styleSheetsInline = $assetCollector->getInlineStyleSheets(false);
|
||||||
|
foreach ($styleSheetsInline as $identifier => $asset) {
|
||||||
|
$styles[] = $asset['source'];
|
||||||
|
$assetCollector->removeInlineStyleSheet($identifier);
|
||||||
|
}
|
||||||
|
return $styles;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function assertStylesShouldBeAddedInline(): bool
|
||||||
|
{
|
||||||
|
/** @var Site $site */
|
||||||
|
$site = $this->getRequest()->getAttribute('site');
|
||||||
|
return $site instanceof Site
|
||||||
|
&& $site->getSettings()?->get('ew-base.inlineCssStyles');
|
||||||
|
}
|
||||||
|
|
||||||
protected function getRequest(): ServerRequestInterface
|
protected function getRequest(): ServerRequestInterface
|
||||||
{
|
{
|
||||||
return $GLOBALS['TYPO3_REQUEST'];
|
return $GLOBALS['TYPO3_REQUEST'];
|
||||||
|
|||||||
147
Classes/Services/Tailwindcss4Merger.php
Normal file
147
Classes/Services/Tailwindcss4Merger.php
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<?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}";
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user