diff --git a/config/hyde.php b/config/hyde.php index 5bc3b78744d..df347ef4f49 100644 --- a/config/hyde.php +++ b/config/hyde.php @@ -354,7 +354,7 @@ | */ - 'cache_busting' => true, + 'enable_cache_busting' => true, /* |-------------------------------------------------------------------------- @@ -433,7 +433,7 @@ // Here you can specify HydeFront version and URL for when loading app.css from the CDN. // Only change these if you know what you're doing as some versions may incompatible with your Hyde version. - // 'hydefront_version' => '', - // 'hydefront_cdn_url' => '' + 'hydefront_version' => \Hyde\Framework\Services\AssetService::HYDEFRONT_VERSION, + 'hydefront_cdn_url' => \Hyde\Framework\Services\AssetService::HYDEFRONT_CDN_URL, ]; diff --git a/packages/framework/config/hyde.php b/packages/framework/config/hyde.php index 5bc3b78744d..df347ef4f49 100644 --- a/packages/framework/config/hyde.php +++ b/packages/framework/config/hyde.php @@ -354,7 +354,7 @@ | */ - 'cache_busting' => true, + 'enable_cache_busting' => true, /* |-------------------------------------------------------------------------- @@ -433,7 +433,7 @@ // Here you can specify HydeFront version and URL for when loading app.css from the CDN. // Only change these if you know what you're doing as some versions may incompatible with your Hyde version. - // 'hydefront_version' => '', - // 'hydefront_cdn_url' => '' + 'hydefront_version' => \Hyde\Framework\Services\AssetService::HYDEFRONT_VERSION, + 'hydefront_cdn_url' => \Hyde\Framework\Services\AssetService::HYDEFRONT_CDN_URL, ]; diff --git a/packages/framework/src/Framework/Services/AssetService.php b/packages/framework/src/Framework/Services/AssetService.php index ba95845ab62..8b95248a17a 100644 --- a/packages/framework/src/Framework/Services/AssetService.php +++ b/packages/framework/src/Framework/Services/AssetService.php @@ -5,6 +5,7 @@ namespace Hyde\Framework\Services; use Hyde\Hyde; +use Hyde\Facades\Config; use Illuminate\Support\Str; use function str_contains; @@ -13,28 +14,26 @@ * * This class is loaded into the service container, making it easy to access and modify. * + * The class also provides helper methods for interacting with versioned files, + * as well as the HydeFront CDN service and the media directories. + * * @see \Hyde\Facades\Asset */ class AssetService { - /** - * The default HydeFront version to load. - * - * @var string HydeFront SemVer Tag - */ - public string $version = 'v2.0'; + /** @var string The default HydeFront SemVer tag to load. This constant is set to match the styles used for the installed framework version. */ + public final const HYDEFRONT_VERSION = 'v2.0'; + + /** @var string The default HydeFront CDN path pattern. The Blade-style placeholders are replaced with the proper values. */ + public final const HYDEFRONT_CDN_URL = 'https://cdn.jsdelivr.net/npm/hydefront@{{ $version }}/dist/{{ $file }}'; - protected ?string $hydefrontUrl = null; + protected string $version = self::HYDEFRONT_VERSION; + protected string $cdnUrl = self::HYDEFRONT_CDN_URL; public function __construct() { - if (config('hyde.hydefront_version')) { - $this->version = config('hyde.hydefront_version'); - } - - if (config('hyde.hydefront_url')) { - $this->hydefrontUrl = config('hyde.hydefront_url'); - } + $this->version = Config::getString('hyde.hydefront_version', self::HYDEFRONT_VERSION); + $this->cdnUrl = Config::getString('hyde.hydefront_url', self::HYDEFRONT_CDN_URL); } public function version(): string @@ -49,18 +48,19 @@ public function cdnLink(string $file): string public function mediaLink(string $file): string { - return Hyde::mediaLink("$file").$this->getCacheBustKey($file); + return Hyde::mediaLink($file).$this->getCacheBustKey($file); } public function hasMediaFile(string $file): bool { - return file_exists(Hyde::mediaPath().'/'.$file); + return file_exists(Hyde::mediaPath($file)); } public function injectTailwindConfig(): string { $config = Str::between(file_get_contents(Hyde::path('tailwind.config.js')), '{', '}'); + // Remove the plugins array, as it is not used in the frontend. if (str_contains($config, 'plugins: [')) { $tokens = explode('plugins: [', $config, 2); $tokens[1] = Str::after($tokens[1], ']'); @@ -72,15 +72,16 @@ public function injectTailwindConfig(): string protected function constructCdnPath(string $file): string { - return $this->hydefrontUrl ?? 'https://cdn.jsdelivr.net/npm/hydefront@'.$this->version().'/dist/'.$file; + return str_replace( + ['{{ $version }}', '{{ $file }}'], [$this->version(), $file], + $this->cdnUrl + ); } protected function getCacheBustKey(string $file): string { - if (! config('hyde.cache_busting', true)) { - return ''; - } - - return '?v='.md5_file(Hyde::mediaPath("$file")); + return Config::getBool('hyde.enable_cache_busting', true) + ? '?v='.md5_file(Hyde::mediaPath("$file")) + : ''; } } diff --git a/packages/framework/tests/Feature/AssetServiceTest.php b/packages/framework/tests/Feature/AssetServiceTest.php index c83dfc840cf..0f36c294238 100644 --- a/packages/framework/tests/Feature/AssetServiceTest.php +++ b/packages/framework/tests/Feature/AssetServiceTest.php @@ -10,49 +10,11 @@ /** * @covers \Hyde\Framework\Services\AssetService + * + * @see \Hyde\Framework\Testing\Unit\AssetServiceUnitTest */ class AssetServiceTest extends TestCase { - public function test_has_version_string() - { - $service = new AssetService(); - $this->assertIsString($service->version); - } - - public function test_can_change_version() - { - $service = new AssetService(); - $service->version = '1.0.0'; - $this->assertEquals('1.0.0', $service->version); - } - - public function test_version_method_returns_version_property_when_config_override_is_not_set() - { - $service = new AssetService(); - $this->assertEquals($service->version, $service->version()); - } - - public function test_version_can_be_set_in_config() - { - config(['hyde.hydefront_version' => '1.0.0']); - $service = new AssetService(); - $this->assertEquals('1.0.0', $service->version()); - } - - public function test_cdn_path_constructor_returns_cdn_uri() - { - $service = new AssetService(); - $this->assertIsString($path = $service->cdnLink('styles.css')); - $this->assertStringContainsString('styles.css', $path); - } - - public function test_can_set_custom_cdn_uri_in_config() - { - config(['hyde.hydefront_url' => 'https://example.com']); - $service = new AssetService(); - $this->assertSame('https://example.com', $service->cdnLink('styles.css')); - } - public function test_media_link_returns_media_path_with_cache_key() { $service = new AssetService(); @@ -62,7 +24,7 @@ public function test_media_link_returns_media_path_with_cache_key() public function test_media_link_returns_media_path_without_cache_key_if_cache_busting_is_disabled() { - config(['hyde.cache_busting' => false]); + config(['hyde.enable_cache_busting' => false]); $service = new AssetService(); $this->assertIsString($path = $service->mediaLink('app.css')); $this->assertEquals('media/app.css', $path); @@ -78,15 +40,4 @@ public function test_media_link_supports_custom_media_directories() $this->assertIsString($path = $service->mediaLink('app.css')); $this->assertEquals('assets/app.css?v='.md5_file(Hyde::path('_assets/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/Feature/MetadataViewTest.php b/packages/framework/tests/Feature/MetadataViewTest.php index 6a1f28ecb65..ebebb5cc425 100644 --- a/packages/framework/tests/Feature/MetadataViewTest.php +++ b/packages/framework/tests/Feature/MetadataViewTest.php @@ -26,7 +26,7 @@ protected function setUp(): void parent::setUp(); config(['hyde.url' => 'http://localhost']); - config(['hyde.cache_busting' => false]); + config(['hyde.enable_cache_busting' => false]); } protected function build(?string $page = null): void diff --git a/packages/framework/tests/Unit/AssetServiceUnitTest.php b/packages/framework/tests/Unit/AssetServiceUnitTest.php new file mode 100644 index 00000000000..4ab275e48dc --- /dev/null +++ b/packages/framework/tests/Unit/AssetServiceUnitTest.php @@ -0,0 +1,110 @@ +assertSame('v2.0', AssetService::HYDEFRONT_VERSION); + } + + public function testServiceHasVersionString() + { + $this->assertIsString((new AssetService())->version()); + } + + public function testVersionStringDefaultsToConstant() + { + $this->assertSame(AssetService::HYDEFRONT_VERSION, (new AssetService())->version()); + } + + public function testVersionCanBeSetInConfig() + { + self::mockConfig(['hyde.hydefront_version' => '1.0.0']); + $this->assertSame('1.0.0', (new AssetService())->version()); + } + + public function testCdnPatternConstant() + { + $this->assertSame('https://cdn.jsdelivr.net/npm/hydefront@{{ $version }}/dist/{{ $file }}', AssetService::HYDEFRONT_CDN_URL); + } + + public function testCanSetCustomCdnUrlInConfig() + { + self::mockConfig(['hyde.hydefront_url' => 'https://example.com']); + $this->assertSame('https://example.com', (new AssetService())->cdnLink('')); + } + + public function testCanUseCustomCdnUrlWithVersion() + { + self::mockConfig(['hyde.hydefront_url' => '{{ $version }}']); + $this->assertSame('v2.0', (new AssetService())->cdnLink('')); + } + + public function testCanUseCustomCdnUrlWithFile() + { + self::mockConfig(['hyde.hydefront_url' => '{{ $file }}']); + $this->assertSame('styles.css', (new AssetService())->cdnLink('styles.css')); + } + + public function testCanUseCustomCdnUrlWithVersionAndFile() + { + self::mockConfig(['hyde.hydefront_url' => '{{ $version }}/{{ $file }}']); + $this->assertSame('v2.0/styles.css', (new AssetService())->cdnLink('styles.css')); + } + + public function testCanUseCustomCdnUrlWithCustomVersion() + { + self::mockConfig([ + 'hyde.hydefront_url' => '{{ $version }}', + 'hyde.hydefront_version' => '1.0.0', + ]); + $this->assertSame('1.0.0', (new AssetService())->cdnLink('')); + } + + public function testCdnLinkHelper() + { + $this->assertSame( + 'https://cdn.jsdelivr.net/npm/hydefront@v2.0/dist/styles.css', + (new AssetService())->cdnLink('styles.css') + ); + } + + public function testHasMediaFileHelper() + { + $this->assertFalse((new AssetService())->hasMediaFile('styles.css')); + } + + public function testHasMediaFileHelperReturnsTrueForExistingFile() + { + $this->assertTrue((new AssetService())->hasMediaFile('app.css')); + } + + public function testInjectTailwindConfigReturnsExtractedTailwindConfig() + { + $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/RelativeLinksAcrossPagesRetainsIntegrityTest.php b/packages/framework/tests/Unit/RelativeLinksAcrossPagesRetainsIntegrityTest.php index a6781f68d92..926444e5e33 100644 --- a/packages/framework/tests/Unit/RelativeLinksAcrossPagesRetainsIntegrityTest.php +++ b/packages/framework/tests/Unit/RelativeLinksAcrossPagesRetainsIntegrityTest.php @@ -25,7 +25,7 @@ protected function setUp(): void { parent::setUp(); - config(['hyde.cache_busting' => false]); + config(['hyde.enable_cache_busting' => false]); config(['hyde.navigation.subdirectories' => 'flat']); $this->needsDirectory('_pages/nested'); diff --git a/packages/framework/tests/Unit/Views/ScriptsComponentViewTest.php b/packages/framework/tests/Unit/Views/ScriptsComponentViewTest.php index 619dff9ffa4..cc40046fd21 100644 --- a/packages/framework/tests/Unit/Views/ScriptsComponentViewTest.php +++ b/packages/framework/tests/Unit/Views/ScriptsComponentViewTest.php @@ -18,7 +18,7 @@ class ScriptsComponentViewTest extends TestCase protected function renderTestView(): string { - config(['hyde.cache_busting' => false]); + config(['hyde.enable_cache_busting' => false]); $this->mockCurrentPage($this->mockCurrentPage ?? ''); return Blade::render(file_get_contents( diff --git a/packages/framework/tests/Unit/Views/StylesComponentViewTest.php b/packages/framework/tests/Unit/Views/StylesComponentViewTest.php index 91b1f073258..bde50cca974 100644 --- a/packages/framework/tests/Unit/Views/StylesComponentViewTest.php +++ b/packages/framework/tests/Unit/Views/StylesComponentViewTest.php @@ -21,7 +21,7 @@ class StylesComponentViewTest extends TestCase protected function renderTestView(): string { - config(['hyde.cache_busting' => false]); + config(['hyde.enable_cache_busting' => false]); $this->mockCurrentPage($this->mockCurrentPage ?? ''); return Blade::render(file_get_contents(