From f0a661ac4680d5a4e8fa8180a78bab23d6274e19 Mon Sep 17 00:00:00 2001 From: Nicolas Lemoine Date: Thu, 15 Dec 2022 11:30:34 +0100 Subject: [PATCH] feat: add the ability to load selected entrypoints - Add the ability to load a selected entrypoints - Add BudEntrypointsLoader --- docs/loaders.md | 47 ++++++ src/Loader/AbstractWebpackLoader.php | 5 +- src/Loader/BudEntrypointsLoader.php | 29 ++++ src/Loader/EncoreEntrypointsLoader.php | 7 +- .../Unit/Loader/AbstractWebpackLoaderTest.php | 4 +- .../Unit/Loader/BudEntrypointsLoaderTest.php | 142 ++++++++++++++++++ .../Loader/EncoreEntrypointsLoaderTest.php | 43 ++++++ 7 files changed, 272 insertions(+), 5 deletions(-) create mode 100644 src/Loader/BudEntrypointsLoader.php create mode 100644 tests/phpunit/Unit/Loader/BudEntrypointsLoaderTest.php diff --git a/docs/loaders.md b/docs/loaders.md index dc238c6..4e128b4 100644 --- a/docs/loaders.md +++ b/docs/loaders.md @@ -92,6 +92,53 @@ $third->dependencies(); // handles from $asset[1] and $asset[2] ``` +Since your `entrypoints.json` file can contain multiple entries, you can choose to load only some of them. + +```json +{ + "entrypoints": { + "theme": { + "css": [ + "./theme.css", + "./theme1.css", + "./theme2.css", + ] + }, + "contact": { + "css": [ + "./contact.css", + ] + }, + "editor": { + "css": [ + "./editor.css", + ] + } + } +} +``` + +And loading this file: + +```php +load('entrypoints.json', ['theme', 'contact']); + +$second = $assets[1]; // theme1.css +$second->dependencies(); // handle from $asset[0] + +$third = $assets[2]; // theme2.css +$third->dependencies(); // handles from $asset[1] and $asset[2] +``` + +### `BudEntrypointsLoader` + +[Bud](https://bud.js.org/) also provides an `entrypoints.json` file and can be used with API as `EncoreEntrypointsLoader`. + ## `ArrayLoader` To create multiple Assets you can use following: diff --git a/src/Loader/AbstractWebpackLoader.php b/src/Loader/AbstractWebpackLoader.php index a8f9655..7ab26b2 100644 --- a/src/Loader/AbstractWebpackLoader.php +++ b/src/Loader/AbstractWebpackLoader.php @@ -52,13 +52,14 @@ abstract protected function parseData(array $data, string $resource): array; /** * @param mixed $resource + * @param array $entrypoints * * @return array * * phpcs:disable Inpsyde.CodeQuality.ArgumentTypeDeclaration * @psalm-suppress MixedArgument */ - public function load($resource): array + public function load($resource, array $entrypoints = []): array { if (!is_string($resource) || !is_readable($resource)) { throw new FileNotFoundException( @@ -79,7 +80,7 @@ public function load($resource): array ); } - return $this->parseData($data, $resource); + return $this->parseData($data, $resource, $entrypoints); } /** diff --git a/src/Loader/BudEntrypointsLoader.php b/src/Loader/BudEntrypointsLoader.php new file mode 100644 index 0000000..0ada133 --- /dev/null +++ b/src/Loader/BudEntrypointsLoader.php @@ -0,0 +1,29 @@ + $filesByExtension) { + $files = $filesByExtension['css'] ?? []; + $assets = array_merge($assets, $this->extractAssets($handle, $files, $directory)); + + $files = $filesByExtension['js'] ?? []; + $assets = array_merge($assets, $this->extractAssets($handle, $files, $directory)); + } + + return $assets; + } +} diff --git a/src/Loader/EncoreEntrypointsLoader.php b/src/Loader/EncoreEntrypointsLoader.php index f87f482..8961fe7 100644 --- a/src/Loader/EncoreEntrypointsLoader.php +++ b/src/Loader/EncoreEntrypointsLoader.php @@ -26,11 +26,16 @@ class EncoreEntrypointsLoader extends AbstractWebpackLoader implements LoaderInt /** * {@inheritDoc} */ - protected function parseData(array $data, string $resource): array + protected function parseData(array $data, string $resource, array $entrypoints = []): array { $directory = trailingslashit(dirname($resource)); /** @var array{entrypoints:array{css?:string[], js?:string[]}} $data */ $data = $data['entrypoints'] ?? []; + if(!empty($entrypoints)) { + $data = array_filter($data, static function (string $handle) use ($entrypoints) { + return in_array($handle, $entrypoints, true); + }, ARRAY_FILTER_USE_KEY); + } $assets = []; foreach ($data as $handle => $filesByExtension) { diff --git a/tests/phpunit/Unit/Loader/AbstractWebpackLoaderTest.php b/tests/phpunit/Unit/Loader/AbstractWebpackLoaderTest.php index 04db4be..dbec006 100644 --- a/tests/phpunit/Unit/Loader/AbstractWebpackLoaderTest.php +++ b/tests/phpunit/Unit/Loader/AbstractWebpackLoaderTest.php @@ -50,7 +50,7 @@ protected function parseData(array $data, string $resource): array return []; } - public function load($filePath): array + public function load($filePath, array $entrypoints = []): array { return parent::load($filePath); } @@ -77,7 +77,7 @@ protected function parseData(array $data, string $resource): array return []; } - public function load($filePath): array + public function load($filePath, array $entrypoints = []): array { return parent::load($filePath); } diff --git a/tests/phpunit/Unit/Loader/BudEntrypointsLoaderTest.php b/tests/phpunit/Unit/Loader/BudEntrypointsLoaderTest.php new file mode 100644 index 0000000..370a9c3 --- /dev/null +++ b/tests/phpunit/Unit/Loader/BudEntrypointsLoaderTest.php @@ -0,0 +1,142 @@ +root = vfsStream::setup('tmp'); + parent::setUp(); + } + + /** + * @test + */ + public function testLoad() + { + $testee = new BudEntrypointsLoader(); + + $file = $this->mockEntrypointsFile( + [ + "theme" => [ + "css" => [ + "./theme.css", + ], + "js" => [ + "./theme.js", + ], + ], + ] + ); + + $assets = $testee->load($file); + + static::assertCount(2, $assets); + static::assertInstanceOf(Style::class, $assets[0]); + static::assertInstanceOf(Script::class, $assets[1]); + } + + /** + * @test + */ + public function testLoadSelectedEntrypoints(): void + { + $testee = new BudEntrypointsLoader(); + + $file = $this->mockEntrypointsFile( + [ + "theme" => [ + "css" => [ + "./theme.css", + ], + "js" => [ + "./theme.js", + ], + ], + "contact" => [ + "css" => [ + "./contact.css", + ], + ], + "editor" => [ + "css" => [ + "./editor.css", + ], + "js" => [ + "./editor.js", + ], + ], + ] + ); + + $assets = $testee->load($file, ['theme', 'contact']); + + static::assertCount(3, $assets); + static::assertInstanceOf(Style::class, $assets[0]); + static::assertInstanceOf(Script::class, $assets[1]); + static::assertInstanceOf(Style::class, $assets[2]); + } + + /** + * @test + */ + public function testLoadWithDependencies() + { + $testee = new BudEntrypointsLoader(); + + $file = $this->mockEntrypointsFile( + [ + "theme" => [ + "css" => [ + "./theme.css", + "./theme1.css", + "./theme2.css", + ], + ], + ] + ); + + $assets = $testee->load($file); + static::assertCount(3, $assets); + + /** @var Asset $asset */ + $asset = $assets[1]; + static::assertSame(['theme'], $asset->dependencies()); + + $asset = $assets[2]; + static::assertSame(['theme', 'theme-1'], $asset->dependencies()); + } + + private function mockEntrypointsFile(array $json): string + { + return vfsStream::newFile('entrypoints.json') + ->withContent(json_encode($json)) + ->at($this->root) + ->url(); + } +} diff --git a/tests/phpunit/Unit/Loader/EncoreEntrypointsLoaderTest.php b/tests/phpunit/Unit/Loader/EncoreEntrypointsLoaderTest.php index f4b9aed..a3ed9c1 100644 --- a/tests/phpunit/Unit/Loader/EncoreEntrypointsLoaderTest.php +++ b/tests/phpunit/Unit/Loader/EncoreEntrypointsLoaderTest.php @@ -63,6 +63,49 @@ public function testLoad() static::assertInstanceOf(Script::class, $assets[1]); } + /** + * @test + */ + public function testLoadSelectedEntrypoints(): void + { + $testee = new EncoreEntrypointsLoader(); + + $file = $this->mockEntrypointsFile( + [ + "entrypoints" => [ + "theme" => [ + "css" => [ + "./theme.css", + ], + "js" => [ + "./theme.js", + ], + ], + "contact" => [ + "css" => [ + "./contact.css", + ], + ], + "editor" => [ + "css" => [ + "./editor.css", + ], + "js" => [ + "./editor.js", + ], + ], + ], + ] + ); + + $assets = $testee->load($file, ['theme', 'contact']); + + static::assertCount(3, $assets); + static::assertInstanceOf(Style::class, $assets[0]); + static::assertInstanceOf(Script::class, $assets[1]); + static::assertInstanceOf(Style::class, $assets[2]); + } + /** * @test */