diff --git a/src/Assets/AudioAsset.php b/src/Assets/AudioAsset.php index 2e2343c..2c2f845 100644 --- a/src/Assets/AudioAsset.php +++ b/src/Assets/AudioAsset.php @@ -22,6 +22,7 @@ public function __construct( public readonly ?string $file = null, ?string $mimeType = null, ?float $duration = null, + public readonly string|bool|null $crossorigin = null, ) { $this->mimeType = $mimeType ?? Helpers::guessMimeTypeFromExtension($file ?? $url); $this->lazyLoad(compact('duration'), function () { @@ -38,10 +39,11 @@ public function __toString(): string public function getImportElement(): Html { - return Html::el('audio', [ + return Html::el('audio', array_filter([ 'src' => $this->url, 'type' => $this->mimeType, - ]); + 'crossorigin' => $this->crossorigin, + ], fn($value) => $value !== null)); } @@ -52,6 +54,7 @@ public function getPreloadElement(): Html 'href' => $this->url, 'as' => 'audio', 'type' => $this->mimeType, + 'crossorigin' => $this->crossorigin, ], fn($value) => $value !== null)); } } diff --git a/src/Assets/GenericAsset.php b/src/Assets/GenericAsset.php index f301f01..e86f487 100644 --- a/src/Assets/GenericAsset.php +++ b/src/Assets/GenericAsset.php @@ -19,6 +19,7 @@ public function __construct( public readonly ?string $file = null, public readonly ?string $media = null, public readonly ?string $integrity = null, + public readonly string|bool|null $crossorigin = null, ) { $this->lazyLoad(compact('mimeType'), function () { $this->mimeType = $this->file ? (mime_content_type($this->file) ?: null) : null; diff --git a/src/Assets/VideoAsset.php b/src/Assets/VideoAsset.php index adc08ce..42249d5 100644 --- a/src/Assets/VideoAsset.php +++ b/src/Assets/VideoAsset.php @@ -21,6 +21,7 @@ public function __construct( /** Poster image URL */ public readonly ?string $poster = null, public readonly bool $autoPlay = false, + public readonly string|bool|null $crossorigin = null, ) { } @@ -40,6 +41,7 @@ public function getImportElement(): Html 'type' => $this->mimeType, 'poster' => $this->poster, 'autoplay' => $this->autoPlay ? true : null, + 'crossorigin' => $this->crossorigin, ], fn($value) => $value !== null)); } @@ -51,6 +53,7 @@ public function getPreloadElement(): Html 'href' => $this->url, 'as' => 'video', 'type' => $this->mimeType, + 'crossorigin' => $this->crossorigin, ], fn($value) => $value !== null)); } } diff --git a/tests/Assets/AudioAsset.phpt b/tests/Assets/AudioAsset.phpt index 86746f1..36d2c7e 100644 --- a/tests/Assets/AudioAsset.phpt +++ b/tests/Assets/AudioAsset.phpt @@ -31,22 +31,24 @@ test('Invalid MP3 file throws exception', function () { test('getImportElement()', function () { - $asset = new AudioAsset('/audio/sound.mp3', mimeType: 'audio/mpeg', duration: 120.5); + $asset = new AudioAsset('/audio/sound.mp3', mimeType: 'audio/mpeg', duration: 120.5, crossorigin: true); Assert::equal(Html::el('audio', [ 'src' => '/audio/sound.mp3', 'type' => 'audio/mpeg', + 'crossorigin' => true, ]), $asset->getImportElement()); }); test('getHtmlPreloadElement()', function () { - $asset = new AudioAsset('/audio/sound.mp3', mimeType: 'audio/mpeg'); + $asset = new AudioAsset('/audio/sound.mp3', mimeType: 'audio/mpeg', crossorigin: true); Assert::equal(Html::el('link', [ 'rel' => 'preload', 'href' => '/audio/sound.mp3', 'as' => 'audio', 'type' => 'audio/mpeg', + 'crossorigin' => true, ]), $asset->getPreloadElement()); }); diff --git a/tests/Assets/GenericAsset.phpt b/tests/Assets/GenericAsset.phpt index 028606f..70cbd75 100644 --- a/tests/Assets/GenericAsset.phpt +++ b/tests/Assets/GenericAsset.phpt @@ -15,3 +15,8 @@ test('MIME type is null without file', function () { $asset = new GenericAsset(''); Assert::null($asset->mimeType); }); + +test('crossorigin is stored', function () { + $asset = new GenericAsset('', crossorigin: true); + Assert::true($asset->crossorigin); +}); diff --git a/tests/Assets/VideoAsset.phpt b/tests/Assets/VideoAsset.phpt index 4cfcfce..95763c5 100644 --- a/tests/Assets/VideoAsset.phpt +++ b/tests/Assets/VideoAsset.phpt @@ -17,6 +17,7 @@ test('getImportElement()', function () { duration: 120.5, poster: '/img/poster.jpg', autoPlay: true, + crossorigin: true, ); Assert::equal(Html::el('video', [ @@ -26,17 +27,19 @@ test('getImportElement()', function () { 'type' => 'video/mp4', 'poster' => '/img/poster.jpg', 'autoplay' => true, + 'crossorigin' => true, ]), $asset->getImportElement()); }); test('getHtmlPreloadElement()', function () { - $asset = new VideoAsset('/video/movie.mp4', mimeType: 'video/mp4'); + $asset = new VideoAsset('/video/movie.mp4', mimeType: 'video/mp4', crossorigin: true); Assert::equal(Html::el('link', [ 'rel' => 'preload', 'href' => '/video/movie.mp4', 'as' => 'video', 'type' => 'video/mp4', + 'crossorigin' => true, ]), $asset->getPreloadElement()); }); diff --git a/tests/Assets/ViteMapper.phpt b/tests/Assets/ViteMapper.phpt index 835fc90..71d67c6 100644 --- a/tests/Assets/ViteMapper.phpt +++ b/tests/Assets/ViteMapper.phpt @@ -4,6 +4,7 @@ use Nette\Assets\EntryAsset; use Nette\Assets\FilesystemMapper; use Nette\Assets\ScriptAsset; use Nette\Assets\StyleAsset; +use Nette\Assets\VideoAsset; use Nette\Assets\ViteMapper; use Tester\Assert; @@ -36,6 +37,16 @@ test('Production mode - CSS entry point', function (): void { }); +test('Production mode - video entry point without dependencies', function (): void { + $mapper = new ViteMapper('https://example.com', __DIR__ . '/fixtures', __DIR__ . '/fixtures/manifest.json'); + $asset = $mapper->getAsset('src/video.mp4'); + + Assert::type(VideoAsset::class, $asset); + Assert::same('https://example.com/assets/video-3m4n5o6p.mp4', $asset->url); + Assert::true($asset->crossorigin); +}); + + test('Fallback to filesystem when asset not found in manifest', function (): void { $filesystemMapper = new FilesystemMapper('https://example.com', __DIR__ . '/fixtures'); $mapper = new ViteMapper('https://example.com', __DIR__ . '/fixtures', __DIR__ . '/fixtures/manifest.json', publicMapper: $filesystemMapper); diff --git a/tests/Assets/fixtures/manifest.json b/tests/Assets/fixtures/manifest.json index 7a62338..256baa2 100644 --- a/tests/Assets/fixtures/manifest.json +++ b/tests/Assets/fixtures/manifest.json @@ -18,5 +18,10 @@ "file": "assets/styles-9i0j1k2l.css", "src": "src/styles.css", "isEntry": true + }, + "src/video.mp4": { + "file": "assets/video-3m4n5o6p.mp4", + "src": "src/video.mp4", + "isEntry": true } } diff --git a/tests/types/assets-types.php b/tests/types/assets-types.php index ad725d2..f37981a 100644 --- a/tests/types/assets-types.php +++ b/tests/types/assets-types.php @@ -121,6 +121,7 @@ function testAudioAssetProperties(AudioAsset $asset): void assertType('string|null', $asset->file); assertType('float|null', $asset->duration); assertType('string|null', $asset->mimeType); + assertType('bool|string|null', $asset->crossorigin); } @@ -134,6 +135,7 @@ function testVideoAssetProperties(VideoAsset $asset): void assertType('float|null', $asset->duration); assertType('string|null', $asset->poster); assertType('bool', $asset->autoPlay); + assertType('bool|string|null', $asset->crossorigin); } @@ -154,6 +156,7 @@ function testGenericAssetProperties(GenericAsset $asset): void assertType('string|null', $asset->mimeType); assertType('string|null', $asset->media); assertType('string|null', $asset->integrity); + assertType('bool|string|null', $asset->crossorigin); }