From 1fdcad00f9f2d06af661f84e3f1113c3ee4a44a2 Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Wed, 17 Apr 2024 17:56:09 +0200 Subject: [PATCH] New: Make Tailwind.merge configurable --- Classes/EelHelper/TailwindHelper.php | 18 ++-- Classes/Package.php | 30 ++++++ Classes/Service/TailwindMergeService.php | 121 +++++++++++++++++++++++ Configuration/Caches.yaml | 3 + Configuration/Settings.Carbon.yaml | 3 + README.md | 53 +++++++++- composer.json | 2 +- 7 files changed, 217 insertions(+), 13 deletions(-) create mode 100644 Classes/Package.php create mode 100644 Classes/Service/TailwindMergeService.php create mode 100644 Configuration/Caches.yaml create mode 100644 Configuration/Settings.Carbon.yaml diff --git a/Classes/EelHelper/TailwindHelper.php b/Classes/EelHelper/TailwindHelper.php index f975e4a..7aaabb9 100644 --- a/Classes/EelHelper/TailwindHelper.php +++ b/Classes/EelHelper/TailwindHelper.php @@ -3,15 +3,17 @@ namespace Carbon\Eel\EelHelper; use Carbon\Eel\Service\MergeClassesService; +use Carbon\Eel\Service\TailwindMergeService; use Neos\Eel\ProtectedContextAwareInterface; use Neos\Flow\Annotations as Flow; -use YieldStudio\TailwindMerge\TailwindMerge; -/** - * @Flow\Proxy(false) - */ class TailwindHelper implements ProtectedContextAwareInterface { + /** + * @var TailwindMergeService + * @Flow\Inject + */ + protected $mergeService; /** * Merge multiple Tailwind CSS classes and automatically resolves conflicts between them without headaches. @@ -22,13 +24,7 @@ class TailwindHelper implements ProtectedContextAwareInterface public function merge(...$arguments): ?string { $mergedString = MergeClassesService::merge(...$arguments); - - if ($mergedString) { - $twMerge = TailwindMerge::instance(); - return $twMerge->merge($mergedString); - } - - return null; + return $mergedString ? $this->mergeService->merge($mergedString) : null; } diff --git a/Classes/Package.php b/Classes/Package.php new file mode 100644 index 0000000..edd7ca6 --- /dev/null +++ b/Classes/Package.php @@ -0,0 +1,30 @@ +getSignalSlotDispatcher(); + + $flushTailwindCache = function () use ($bootstrap) { + $cacheManager = $bootstrap->getEarlyInstance(CacheManager::class); + $cacheManager->getCache('Carbon_Eel_Tailwind')->flush(); + }; + + $dispatcher->connect(FileMonitor::class, 'filesHaveChanged', function ($fileMonitorIdentifier, array $changedFiles) use ($flushTailwindCache) { + if ($fileMonitorIdentifier == 'Flow_ConfigurationFiles') { + $flushTailwindCache(); + } + }); + } +} diff --git a/Classes/Service/TailwindMergeService.php b/Classes/Service/TailwindMergeService.php new file mode 100644 index 0000000..78708f6 --- /dev/null +++ b/Classes/Service/TailwindMergeService.php @@ -0,0 +1,121 @@ +flowCacheManager = $flowCacheManager; + } + + protected $instance; + + /** + * Merge the given classes + * + * @param iterable|mixed $arguments Optional variable list of arrays / values + * @return string|null The merged classes + */ + public function merge(...$arguments): ?string + { + if (!$this->instance) { + $this->instance = $this->createInstance(); + } + + return $this->instance->merge(...$arguments); + } + + /** + * Create a new TailwindMerge instance + * + * @return TailwindMerge + */ + protected function createInstance(): TailwindMerge { + $cache = $this->flowCacheManager->getSimpleCache('Carbon_Eel_Tailwind'); + if (isset($this->mergeConfig) && is_array($this->mergeConfig)) { + return TailwindMerge::factory()->withConfiguration($this->parseConfig($this->mergeConfig))->withCache($cache)->make(); + } + + return TailwindMerge::factory()->withCache($cache)->make(); + } + + /** + * Merge the configuration and replace the constants with the actual validators + * + * @param iterable|mixed $config The configuration + * @return mixed + */ + protected function parseConfig($config) { + if (is_array($config)) { + $parsedConfig = []; + foreach ($config as $key => $value) { + $parsedConfig[$key] = $this->parseConfig($value); + } + return $parsedConfig; + } + + switch ($config) { + case 'ANY_VALUE_VALIDATOR': + return AnyValueValidator::validate(...); + case 'ARBITRARY_IMAGE_VALIDATOR': + return ArbitraryImageValidator::validate(...); + case 'ARBITRARY_LENGTH_VALIDATOR': + return ArbitraryLengthValidator::validate(...); + case 'ARBITRARY_NUMBER_VALIDATOR': + return ArbitraryNumberValidator::validate(...); + case 'ARBITRARY_POSITION_VALIDATOR': + return ArbitraryPositionValidator::validate(...); + case 'ARBITRARY_SHADOW_VALIDATOR': + return ArbitraryShadowValidator::validate(...); + case 'ARBITRARY_SIZE_VALIDATOR': + return ArbitrarySizeValidator::validate(...); + case 'ARBITRARY_VALUE_VALIDATOR': + return ArbitraryValueValidator::validate(...); + case 'INTEGER_VALIDATOR': + return IntegerValidator::validate(...); + case 'LENGTH_VALIDATOR': + return LengthValidator::validate(...); + case 'NUMBER_VALIDATOR': + return NumberValidator::validate(...); + case 'PERCENT_VALIDATOR': + return PercentValidator::validate(...); + case 'TSHIRT_SIZE_VALIDATOR': + return TshirtSizeValidator::validate(...); + } + + return $config; + } +} diff --git a/Configuration/Caches.yaml b/Configuration/Caches.yaml new file mode 100644 index 0000000..830c194 --- /dev/null +++ b/Configuration/Caches.yaml @@ -0,0 +1,3 @@ +Carbon_Eel_Tailwind: + frontend: Neos\Cache\Frontend\StringFrontend + backend: Neos\Cache\Backend\FileBackend diff --git a/Configuration/Settings.Carbon.yaml b/Configuration/Settings.Carbon.yaml new file mode 100644 index 0000000..421616f --- /dev/null +++ b/Configuration/Settings.Carbon.yaml @@ -0,0 +1,3 @@ +Carbon: + Eel: + tailwindMergeConfig: null diff --git a/README.md b/README.md index c7ea0fa..9d4cbd1 100755 --- a/README.md +++ b/README.md @@ -284,6 +284,55 @@ Examples: **Return** The merged string +#### Configuration + +If you are using Tailwind CSS without any extra config, you can use the Eel helper right away. And stop reading here. + +If you're using a custom Tailwind config, you may need to configure the Eel helper as well to merge classes properly. + +By default it is configured in a way that you can still use it if all the following apply to your Tailwind config: + +- Only using color names which don't clash with other Tailwind class names +- Only deviating by number values from number-based Tailwind classes +- Only using font-family classes which don't clash with default font-weight classes +- Sticking to default Tailwind config for everything else + +If some of these points don't apply to you, you need to customize the configuration. + +This is an example to add a custom font size of `very-large`: + +```yaml +Carbon: + Eel: + tailwindMergeConfig: + classGroups: + 'font-size': + - text: ['very-large'] +``` + +You can also enable different [validators], to make everything easier. For instance, if you use the +[Tailwind OKLCH Plugin], you can set it like that: + +```yaml +Carbon: + Eel: + tailwindMergeConfig: + classGroups: + 'fill-lightness': + - 'fill-lightness-offset': ['INTEGER_VALIDATOR', 'ARBITRARY_NUMBER_VALIDATOR'] + 'border-lightness': + - 'border-lightness-offset': ['INTEGER_VALIDATOR', 'ARBITRARY_NUMBER_VALIDATOR'] + 'text-lightness': + - 'text-lightness-offset': ['INTEGER_VALIDATOR', 'ARBITRARY_NUMBER_VALIDATOR'] + 'bg-lightness': + - 'bg-lightness-offset': ['INTEGER_VALIDATOR', 'ARBITRARY_NUMBER_VALIDATOR'] +``` + +If you want to use a certain validator, just change it to constant case and add it as a string. +So, for examle, if you want to use the `TshirtSizeValidator`, just add `TSHIRT_SIZE_VALIDATOR` to the list. + +> The merge service uses a its own cache `Carbon_Eel_Tailwind`. Make sure to clear the cache when you are making changes to the configuration. + ## AlpineJS Helper ### `AlpineJS.object(arg1, arg2, ..argN)` @@ -682,4 +731,6 @@ Some of the Eel helpers were inspired and or copied from [punkt.de] [`dateinterval` format]: https://www.php.net/manual/en/dateinterval.format.php [`dateinterval`]: https://www.php.net/manual/de/class.dateinterval.php [Tailwind CSS]: https://tailwindcss.com -[tailwind-merge-php]: https://github.com/YieldStudio/tailwind-merge-php +[tailwind-merge-php]: https://github.com/gehrisandro/tailwind-merge-php +[validators]: https://github.com/gehrisandro/tailwind-merge-php/tree/main/src/Validators +[tailwind oklch plugin]: https://github.com/MartijnCuppens/tailwindcss-oklch diff --git a/composer.json b/composer.json index 4252e9a..f216d49 100755 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "php": "^8.1", "neos/flow": "^7.0 || ^8.0 || ^9.0", "behat/transliterator": "^1.2", - "yieldstudio/tailwind-merge-php": "^0.0.3", + "gehrisandro/tailwind-merge-php": "^1.0", "matthiasmullie/minify": "^1.3" }, "authors": [