diff --git a/config/hyde.php b/config/hyde.php index 08ffd8f946a..fb5c4b547a2 100644 --- a/config/hyde.php +++ b/config/hyde.php @@ -187,7 +187,21 @@ | Hyde ships with an app.css file containing compiled TailwindCSS styles | in the _media/ directory. If you want to load this file from the | HydeFront JsDelivr CDN, you can set this setting to true. + | */ 'load_app_styles_from_cdn' => false, + + /* + |-------------------------------------------------------------------------- + | Tailwind Play CDN + |-------------------------------------------------------------------------- + | + | The next setting enables a script for the TailwindCSS Play CDN which will + | compile CSS in the browser. While this is useful for local development + | it's not recommended for production use. To keep things consistent, + | your Tailwind configuration file will be injected into the HTML. + */ + + 'use_play_cdn' => false, ]; diff --git a/docs/creating-content/managing-assets.md b/docs/creating-content/managing-assets.md index cb339c366a6..687db384331 100644 --- a/docs/creating-content/managing-assets.md +++ b/docs/creating-content/managing-assets.md @@ -89,6 +89,14 @@ For the absolute majority of the cases, you don't need to mess with these files. #### Loading from CDN If you want to load the same pre-compiled file included with Hyde but from a CDN, you can set `load_app_styles_from_cdn` to `true` in the `config/hyde.php` file. While you lose the ability to customize it, your styles will be automatically updated when needed. +### Using the TailwindCSS Play CDN + +If you want to use the [TailwindCSS Play CDN](https://tailwindcss.com/docs/installation/play-cdn), you can set `use_play_cdn` to `true` in the `config/hyde.php` file. +This will in addition to loading the standard app.css file also add a script tag to load the TailwindCSS Play CDN. +What's even better is that Hyde will also inject the contents of the included `tailwind.config.js` file into the script tag, so the Play CDN styles match the ones created by Laravel Mix. +This also means you can tinker around with the TailwindCSS settings without having to compile anything. + +>warn Note that the Play CDN is not meant for production use, so enabling it will add a warning to the web console. ## Managing images As mentioned above, assets stored in the _media folder are automatically copied to the _site/media folder, diff --git a/packages/framework/config/hyde.php b/packages/framework/config/hyde.php index 08ffd8f946a..fb5c4b547a2 100644 --- a/packages/framework/config/hyde.php +++ b/packages/framework/config/hyde.php @@ -187,7 +187,21 @@ | Hyde ships with an app.css file containing compiled TailwindCSS styles | in the _media/ directory. If you want to load this file from the | HydeFront JsDelivr CDN, you can set this setting to true. + | */ 'load_app_styles_from_cdn' => false, + + /* + |-------------------------------------------------------------------------- + | Tailwind Play CDN + |-------------------------------------------------------------------------- + | + | The next setting enables a script for the TailwindCSS Play CDN which will + | compile CSS in the browser. While this is useful for local development + | it's not recommended for production use. To keep things consistent, + | your Tailwind configuration file will be injected into the HTML. + */ + + 'use_play_cdn' => false, ]; diff --git a/packages/framework/resources/views/layouts/styles.blade.php b/packages/framework/resources/views/layouts/styles.blade.php index 379c18af910..00a3135a895 100644 --- a/packages/framework/resources/views/layouts/styles.blade.php +++ b/packages/framework/resources/views/layouts/styles.blade.php @@ -8,5 +8,12 @@ @endif +{{-- Dynamic TailwindCSS Play CDN --}} +@if(config('hyde.use_play_cdn', false)) + + + +@endif + {{-- Add any extra styles to include after the others --}} -@stack('styles') \ No newline at end of file +@stack('styles') diff --git a/packages/framework/src/Facades/Asset.php b/packages/framework/src/Facades/Asset.php index 5a2e5b3028f..ab658c4a1a2 100644 --- a/packages/framework/src/Facades/Asset.php +++ b/packages/framework/src/Facades/Asset.php @@ -18,6 +18,7 @@ * @method static string cdnLink(string $file) * @method static string mediaLink(string $file) * @method static bool hasMediaFile(string $file) + * @method static string injectTailwindConfig() */ class Asset extends Facade { diff --git a/packages/framework/src/Framework/Services/AssetService.php b/packages/framework/src/Framework/Services/AssetService.php index b8e5ee4f92a..6a00d84b9a4 100644 --- a/packages/framework/src/Framework/Services/AssetService.php +++ b/packages/framework/src/Framework/Services/AssetService.php @@ -5,6 +5,8 @@ namespace Hyde\Framework\Services; use Hyde\Hyde; +use Illuminate\Support\Str; +use function str_contains; /** * Handles the retrieval of core asset files. Commonly used through the Asset facade. @@ -50,6 +52,19 @@ public function hasMediaFile(string $file): bool return file_exists(Hyde::path('_media').'/'.$file); } + public function injectTailwindConfig(): string + { + $config = Str::between(file_get_contents(Hyde::path('tailwind.config.js')), '{', '}'); + + if (str_contains($config, 'plugins: [')) { + $tokens = explode('plugins: [', $config, 2); + $tokens[1] = Str::after($tokens[1], ']'); + $config = implode('', $tokens); + } + + return preg_replace('/\s+/', ' ', "/* tailwind.config.js */ \n".rtrim($config, ",\n\r")); + } + protected function getCacheBustKey(string $file): string { if (! config('hyde.cache_busting', true)) { diff --git a/packages/framework/tests/Feature/AssetServiceTest.php b/packages/framework/tests/Feature/AssetServiceTest.php index 0250046c1ba..913facd0e6e 100644 --- a/packages/framework/tests/Feature/AssetServiceTest.php +++ b/packages/framework/tests/Feature/AssetServiceTest.php @@ -53,4 +53,15 @@ public function test_media_link_returns_media_path_without_cache_key_if_cache_bu $this->assertIsString($path = $service->mediaLink('app.css')); $this->assertEquals('media/app.css', $path); } + + public function test_inject_tailwind_config_returns_extracted_tailwind_config() + { + $service = new AssetService(); + $this->assertIsString($config = $service->injectTailwindConfig()); + $this->assertStringContainsString("darkMode: 'class'", $config); + $this->assertStringContainsString('theme: {', $config); + $this->assertStringContainsString('extend: {', $config); + $this->assertStringContainsString('typography: {', $config); + $this->assertStringNotContainsString('plugins', $config); + } } diff --git a/packages/framework/tests/Unit/Views/StylesComponentViewTest.php b/packages/framework/tests/Unit/Views/StylesComponentViewTest.php index 7d3db097891..ec69173943e 100644 --- a/packages/framework/tests/Unit/Views/StylesComponentViewTest.php +++ b/packages/framework/tests/Unit/Views/StylesComponentViewTest.php @@ -4,6 +4,7 @@ namespace Hyde\Framework\Testing\Unit\Views; +use function config; use Hyde\Facades\Asset; use Hyde\Hyde; use Hyde\Testing\TestCase; @@ -63,12 +64,18 @@ public function test_styles_can_be_pushed_to_the_component_styles_stack() @push("styles") foo bar @endpush - + @include("hyde::layouts.styles")' ) ); } + public function test_component_renders_tailwind_play_cdn_link_when_enabled_in_config() + { + config(['hyde.use_play_cdn' => true]); + $this->assertStringContainsString('', $this->renderTestView()); + } + public function test_component_renders_app_cdn_link_when_enabled_in_config() { config(['hyde.load_app_styles_from_cdn' => true]);