diff --git a/.github/workflows/php-cs-fixer.yml b/.github/workflows/linting.yml similarity index 75% rename from .github/workflows/php-cs-fixer.yml rename to .github/workflows/linting.yml index fbec801..590fdba 100644 --- a/.github/workflows/php-cs-fixer.yml +++ b/.github/workflows/linting.yml @@ -13,9 +13,7 @@ jobs: ref: ${{ github.head_ref }} - name: Run PHP CS Fixer - uses: docker://oskarstark/php-cs-fixer-ga - with: - args: --config=.php_cs.dist.php --allow-risky=yes + uses: aglipanci/laravel-pint-action@2.3.0 - name: Commit changes uses: stefanzweifel/git-auto-commit-action@v5 diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 5101e1f..7d8d2e2 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -5,33 +5,24 @@ on: branches: - main pull_request: - branches: - - main jobs: test: - runs-on: ${{ matrix.os }} + runs-on: ubuntu-latest strategy: fail-fast: true matrix: - # os: [ubuntu-latest, windows-latest] - os: [ubuntu-latest] - php: [8.1, 8.2] - laravel: [10.*, 11.*] + php: [8.2, 8.3, 8.4] + laravel: [11.*, 12.*] stability: [prefer-lowest, prefer-stable] include: - - laravel: 10.* - testbench: 8.* - collision: ^6.0 - laravel: 11.* testbench: ^9.0 - collision: ^8.1 - exclude: - - laravel: 11.* - php: 8.1 + - laravel: 12.* + testbench: ^10.0 - name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }} + name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} steps: - name: Checkout code @@ -51,7 +42,7 @@ jobs: - name: Install dependencies run: | - composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" "nunomaduro/collision:${{ matrix.collision }}" "nesbot/carbon:^2.64.1" --no-interaction --no-update + composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update composer update --${{ matrix.stability }} --prefer-dist --no-interaction - name: Execute tests diff --git a/composer.json b/composer.json index 8122216..3b13f5f 100644 --- a/composer.json +++ b/composer.json @@ -15,14 +15,13 @@ } ], "require": { - "php": "^8.1", + "php": "^8.2", "spatie/laravel-package-tools": "^1.16", - "illuminate/contracts": "^10.0|^11.0" + "illuminate/contracts": "^11.0|^12.0" }, "require-dev": { - "nunomaduro/collision": "^6.0|^8.1", - "orchestra/testbench": "^8.0|^9.0", - "phpunit/phpunit": "^10.5" + "orchestra/testbench": "^9.0|^10.0", + "phpunit/phpunit": "^10.5|^11.0" }, "autoload": { "psr-4": { diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..0283c1f --- /dev/null +++ b/rector.php @@ -0,0 +1,22 @@ +withPaths([ + __DIR__.'/src', + __DIR__.'/tests', + ]) + ->withPreparedSets( + deadCode: true, + codeQuality: true, + typeDeclarations: true, + privatization: true, + earlyReturn: true, + ) + ->withAttributesSets() + ->withPhpSets() + ->withPhpVersion(PhpVersion::PHP_82); diff --git a/src/Actions/AppendTailwindTag.php b/src/Actions/AppendTailwindTag.php index 7cc5dee..fb865d7 100644 --- a/src/Actions/AppendTailwindTag.php +++ b/src/Actions/AppendTailwindTag.php @@ -4,7 +4,7 @@ class AppendTailwindTag { - public function __invoke(string $contents) + public function __invoke(string $contents): ?string { if (str_contains($contents, '{{ tailwindcss(')) { return $contents; @@ -12,7 +12,7 @@ public function __invoke(string $contents) return preg_replace( '/(\s*)(<\/head>)/', - PHP_EOL."\\1 ". + PHP_EOL.'\\1 '. "\\1 \\1\\2", $contents, ); diff --git a/src/Commands/BuildCommand.php b/src/Commands/BuildCommand.php index 79e6e21..145fa32 100644 --- a/src/Commands/BuildCommand.php +++ b/src/Commands/BuildCommand.php @@ -20,7 +20,7 @@ class BuildCommand extends Command protected $description = 'Generates a new build of Tailwind CSS for your project.'; - public function handle() + public function handle(): int { $binFile = config('tailwindcss.bin_path'); @@ -35,7 +35,7 @@ public function handle() $sourcePath = $this->fixFilePathForOs(config('tailwindcss.build.source_file_path')); $sourceRelativePath = str_replace(rtrim(resource_path(), DIRECTORY_SEPARATOR), '', $sourcePath); $destinationPath = $this->fixFilePathForOs(config('tailwindcss.build.destination_path')); - $destinationFileAbsolutePath = $destinationPath . DIRECTORY_SEPARATOR . trim($sourceRelativePath, DIRECTORY_SEPARATOR); + $destinationFileAbsolutePath = $destinationPath.DIRECTORY_SEPARATOR.trim($sourceRelativePath, DIRECTORY_SEPARATOR); $destinationFileRelativePath = str_replace(rtrim(public_path(), DIRECTORY_SEPARATOR), '', $destinationFileAbsolutePath); File::ensureDirectoryExists(dirname($destinationFileAbsolutePath)); @@ -57,7 +57,7 @@ public function handle() '-o', $destinationFileAbsolutePath, $this->option('watch') ? '--watch=always' : null, $this->shouldMinify() ? '-m' : null, - ]), function ($type, $output) { + ]), function ($type, $output): void { $this->output->write($output); }); @@ -106,11 +106,19 @@ private function fixOsFilePathToUriPath(string $path): string private function shouldVersion(): bool { - return $this->option('digest') || $this->option('prod'); + if ($this->option('digest')) { + return true; + } + + return (bool) $this->option('prod'); } private function shouldMinify(): bool { - return $this->option('minify') || $this->option('prod'); + if ($this->option('minify')) { + return true; + } + + return (bool) $this->option('prod'); } } diff --git a/src/Commands/DownloadCommand.php b/src/Commands/DownloadCommand.php index ea37638..f77df3b 100644 --- a/src/Commands/DownloadCommand.php +++ b/src/Commands/DownloadCommand.php @@ -16,7 +16,7 @@ class DownloadCommand extends Command protected $description = 'Downloads the Tailwind CSS binary for the version specified in your config/tailwindcss.php.'; - public function handle() + public function handle(): int { $os = php_uname('s'); $cpu = php_uname('m'); @@ -57,8 +57,10 @@ public function handle() return self::FAILURE; } - File::ensureDirectoryExists(dirname($targetPath)); - File::exists($targetPath) && File::delete($targetPath); + File::ensureDirectoryExists(dirname((string) $targetPath)); + if (File::exists($targetPath)) { + File::delete($targetPath); + } File::put($targetPath, $contents); File::chmod($targetPath, 0755); diff --git a/src/Commands/InstallCommand.php b/src/Commands/InstallCommand.php index aa15309..9bdf941 100644 --- a/src/Commands/InstallCommand.php +++ b/src/Commands/InstallCommand.php @@ -20,7 +20,7 @@ class InstallCommand extends Command protected $description = 'Installs the Tailwind CSS scaffolding for new Laravel applications.'; - public function handle() + public function handle(): int { $this->ensureTailwindConfigExists(); $this->ensureTailwindCliBinaryExists(); @@ -28,36 +28,35 @@ public function handle() $this->installMiddleware('\Tonysm\TailwindCss\Http\Middleware\AddLinkHeaderForPreloadedAssets::class'); $this->addIngoreLines(); $this->runFirstBuild(); - $this->removeUnusedFiles(); $this->newLine(); - $this->components->info('TailwindCSS Laravel was installed successfully.'); + $this->components->info('Tailwind CSS Laravel was installed successfully.'); return self::SUCCESS; } - protected function phpBinary() + protected function phpBinary(): string { - return (new PhpExecutableFinder())->find(false) ?: 'php'; + return (new PhpExecutableFinder)->find(false) ?: 'php'; } - private function ensureTailwindConfigExists() + private function ensureTailwindConfigExists(): void { $this->copyStubToApp( - stub: __DIR__ . '/../../stubs/postcss.config.js', + stub: __DIR__.'/../../stubs/postcss.config.js', to: base_path('postcss.config.js'), ); - if (! File::exists($appCssFilePath = resource_path('css/app.css')) || empty(trim(File::get($appCssFilePath))) || $this->mainCssIsDefault($appCssFilePath)) { + if (! File::exists($appCssFilePath = resource_path('css/app.css')) || in_array(trim(File::get($appCssFilePath)), ['', '0'], true) || $this->mainCssIsDefault($appCssFilePath)) { $this->copyStubToApp( - stub: __DIR__ . '/../../stubs/resources/css/app.css', + stub: __DIR__.'/../../stubs/resources/css/app.css', to: $appCssFilePath, ); } } - private function ensureTailwindCliBinaryExists() + private function ensureTailwindCliBinaryExists(): void { if (! File::exists(config('tailwindcss.bin_path')) || $this->option('download')) { Process::forever()->tty(SymfonyProcess::isTtySupported())->run([ @@ -66,7 +65,7 @@ private function ensureTailwindCliBinaryExists() 'tailwindcss:download', '--cli-version', $this->option('cli-version') ?: config('tailwindcss.version'), - ], function ($_type, $output) { + ], function ($_type, $output): void { $this->output->write($output); }); } @@ -81,12 +80,9 @@ private function copyStubToApp(string $stub, string $to): void /** * Install the middleware to a group in the application Http Kernel. * - * @param string $after - * @param string $name * @param string $group - * @return void */ - private function installMiddlewareAfter($after, $name, $group = 'web') + private function installMiddlewareAfter(string $after, string $name, $group = 'web'): void { $httpKernel = file_get_contents(app_path('Http/Kernel.php')); @@ -98,8 +94,8 @@ private function installMiddlewareAfter($after, $name, $group = 'web') } $modifiedMiddlewareGroup = str_replace( - $after . ',', - $after . ',' . PHP_EOL . ' ' . $name . ',', + $after.',', + $after.','.PHP_EOL.' '.$name.',', $middlewareGroup, ); @@ -110,12 +106,12 @@ private function installMiddlewareAfter($after, $name, $group = 'web') )); } - private function appendTailwindStylesToLayouts() + private function appendTailwindStylesToLayouts(): void { $this->existingLayoutFiles() ->each(fn ($file) => File::put( $file, - (new AppendTailwindTag())(File::get($file)), + (new AppendTailwindTag)(File::get($file)), )); } @@ -126,7 +122,7 @@ private function existingLayoutFiles() ->filter(fn ($file) => File::exists($file)); } - private function installMiddleware(string $middleware) + private function installMiddleware(string $middleware): void { if (file_exists(app_path('Http/Kernel.php'))) { $this->installMiddlewareAfter('SubstituteBindings::class', $middleware); @@ -135,7 +131,7 @@ private function installMiddleware(string $middleware) } } - private function installMiddlewareToBootstrap(string $middleware, string $group = 'web', string $modifier = 'append') + private function installMiddlewareToBootstrap(string $middleware, string $group = 'web', string $modifier = 'append'): void { $bootstrapApp = file_get_contents(base_path('bootstrap/app.php')); @@ -146,19 +142,19 @@ private function installMiddlewareToBootstrap(string $middleware, string $group $bootstrapApp = str_replace( '->withMiddleware(function (Middleware $middleware) {', '->withMiddleware(function (Middleware $middleware) {' - . PHP_EOL . " \$middleware->{$group}({$modifier}: [" - . PHP_EOL . " {$middleware}," - . PHP_EOL . ' ]);' - . PHP_EOL, + .PHP_EOL." \$middleware->{$group}({$modifier}: [" + .PHP_EOL." {$middleware}," + .PHP_EOL.' ]);' + .PHP_EOL, $bootstrapApp, ); file_put_contents(base_path('bootstrap/app.php'), $bootstrapApp); } - private function addIngoreLines() + private function addIngoreLines(): void { - $binary = basename(config('tailwindcss.bin_path')); + $binary = basename((string) config('tailwindcss.bin_path')); if (str_contains(File::get(base_path('.gitignore')), $binary)) { return; @@ -173,28 +169,17 @@ private function addIngoreLines() LINES); } - private function runFirstBuild() + private function runFirstBuild(): void { Process::forever()->tty(SymfonyProcess::isTtySupported())->run([ $this->phpBinary(), 'artisan', 'tailwindcss:build', - ], function ($_type, $output) { + ], function ($_type, $output): void { $this->output->write($output); }); } - private function removeUnusedFiles() - { - $files = [ - base_path('tailwind.config.js'), - ]; - - foreach ($files as $file) { - File::exists($file) && File::delete($file); - } - } - private function mainCssIsDefault($appCssFilePath): bool { return trim(File::get($appCssFilePath)) === trim(<<<'CSS' diff --git a/src/Http/Middleware/AddLinkHeaderForPreloadedAssets.php b/src/Http/Middleware/AddLinkHeaderForPreloadedAssets.php index 69ae176..b98c7ae 100644 --- a/src/Http/Middleware/AddLinkHeaderForPreloadedAssets.php +++ b/src/Http/Middleware/AddLinkHeaderForPreloadedAssets.php @@ -6,20 +6,18 @@ class AddLinkHeaderForPreloadedAssets { - public function __construct(private Manifest $manifest) - { - } + public function __construct(private readonly Manifest $manifest) {} public function handle($request, $next) { - return tap($next($request), function ($response) { - if (count($assets = $this->manifest->assetsForPreloading()) > 0) { + return tap($next($request), function ($response): void { + if (($assets = $this->manifest->assetsForPreloading()) !== []) { $response->header('Link', trim(implode(', ', array_filter(array_merge( [$response->headers->get('Link', null)], - collect($assets)->map(fn ($attributes, $asset) => implode('; ', array_merge( + collect($assets)->map(fn ($attributes, $asset): string => implode('; ', array_merge( ["<$asset>"], collect(array_merge(['rel' => 'preload', 'as' => 'style'], $attributes)) - ->map(fn ($value, $key) => "{$key}={$value}") + ->map(fn ($value, $key): string => "{$key}={$value}") ->all(), )))->all(), ))))); diff --git a/src/Manifest.php b/src/Manifest.php index a364bf6..b7d6c92 100644 --- a/src/Manifest.php +++ b/src/Manifest.php @@ -25,7 +25,7 @@ public static function path(): string return config('tailwindcss.build.manifest_file_path'); } - public function __invoke(string $path, $preload = true) + public function __invoke(string $path, $preload = true): string|\Illuminate\Support\HtmlString { static $manifests = []; @@ -52,9 +52,9 @@ public function __invoke(string $path, $preload = true) report($exception); return $path; - } else { - throw $exception; } + + throw $exception; } $asset = asset($manifest[$path]); diff --git a/src/TailwindCssServiceProvider.php b/src/TailwindCssServiceProvider.php index 9f11a74..421c12e 100644 --- a/src/TailwindCssServiceProvider.php +++ b/src/TailwindCssServiceProvider.php @@ -25,7 +25,7 @@ public function configurePackage(Package $package): void ]); } - public function packageRegistered() + public function packageRegistered(): void { $this->app->scoped(Manifest::class); } diff --git a/src/Testing/InteractsWithTailwind.php b/src/Testing/InteractsWithTailwind.php index 6cdd159..110b00e 100644 --- a/src/Testing/InteractsWithTailwind.php +++ b/src/Testing/InteractsWithTailwind.php @@ -12,9 +12,7 @@ trait InteractsWithTailwind */ protected function withoutTailwind(): static { - $this->swap(Manifest::class, function () { - return new HtmlString(''); - }); + $this->swap(Manifest::class, fn (): \Illuminate\Support\HtmlString => new HtmlString('')); return $this; } diff --git a/src/helpers.php b/src/helpers.php index ce701e0..36e9109 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -7,9 +7,7 @@ /** * Get the path to a versioned TailwindCSS file. * - * @param string $path - * @param bool|array $preload - * @return \Illuminate\Support\HtmlString|string + * @param bool|array $preload */ function tailwindcss(string $path, $preload = true): HtmlString|string { diff --git a/tests/AppendTailwindTagTest.php b/tests/AppendTailwindTagTest.php index 6ccc6a1..9a80acf 100644 --- a/tests/AppendTailwindTagTest.php +++ b/tests/AppendTailwindTagTest.php @@ -6,8 +6,8 @@ class AppendTailwindTagTest extends TestCase { - /** @test */ - public function append_tailwind_tag_before_closing_head_tag() + #[\PHPUnit\Framework\Attributes\Test] + public function append_tailwind_tag_before_closing_head_tag(): void { $contents = <<<'BLADE' @@ -40,6 +40,6 @@ public function append_tailwind_tag_before_closing_head_tag() BLADE; - $this->assertEquals($expected, (new AppendTailwindTag())($contents)); + $this->assertEquals($expected, (new AppendTailwindTag)($contents)); } } diff --git a/tests/PreloadingHeaderTest.php b/tests/PreloadingHeaderTest.php index 9c8edf9..cebce08 100644 --- a/tests/PreloadingHeaderTest.php +++ b/tests/PreloadingHeaderTest.php @@ -7,8 +7,8 @@ class PreloadingHeaderTest extends TestCase { - /** @test */ - public function no_link_header_when_not_preloading() + #[\PHPUnit\Framework\Attributes\Test] + public function no_link_header_when_not_preloading(): void { config()->set('tailwindcss.build.manifest_file_path', __DIR__.'/stubs/test-manifest.json'); @@ -24,8 +24,8 @@ public function no_link_header_when_not_preloading() $this->assertNull($response->headers->get('Link', null)); } - /** @test */ - public function adds_link_header_when_preloading() + #[\PHPUnit\Framework\Attributes\Test] + public function adds_link_header_when_preloading(): void { config()->set('tailwindcss.build.manifest_file_path', __DIR__.'/stubs/test-manifest.json'); @@ -41,8 +41,8 @@ public function adds_link_header_when_preloading() $this->assertEquals("<{$asset}>; rel=preload; as=style", $response->headers->get('Link', null)); } - /** @test */ - public function keeps_existing_preloading_link_header() + #[\PHPUnit\Framework\Attributes\Test] + public function keeps_existing_preloading_link_header(): void { config()->set('tailwindcss.build.manifest_file_path', __DIR__.'/stubs/test-manifest.json'); @@ -60,8 +60,8 @@ public function keeps_existing_preloading_link_header() $this->assertEquals("; rel=modulepreload, <{$asset}>; rel=preload; as=style", $response->headers->get('Link', null)); } - /** @test */ - public function adds_link_header_when_preloading_custom_attributes() + #[\PHPUnit\Framework\Attributes\Test] + public function adds_link_header_when_preloading_custom_attributes(): void { config()->set('tailwindcss.build.manifest_file_path', __DIR__.'/stubs/test-manifest.json'); diff --git a/tests/TestCase.php b/tests/TestCase.php index a0eb903..c9603bb 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -15,7 +15,7 @@ protected function setUp(): void parent::setUp(); Factory::guessFactoryNamesUsing( - fn (string $modelName) => 'Tonysm\\TailwindCss\\Database\\Factories\\'.class_basename($modelName).'Factory' + fn (string $modelName): string => 'Tonysm\\TailwindCss\\Database\\Factories\\'.class_basename($modelName).'Factory' ); if (File::exists($manifestFile = Manifest::path())) { @@ -30,7 +30,7 @@ protected function getPackageProviders($app) ]; } - public function getEnvironmentSetUp($app) + public function getEnvironmentSetUp($app): void { config()->set('database.default', 'testing'); config()->set('app.url', 'http://localhost'); diff --git a/tests/WorksWithoutCompiledManifestTest.php b/tests/WorksWithoutCompiledManifestTest.php index d7372c2..c055a19 100644 --- a/tests/WorksWithoutCompiledManifestTest.php +++ b/tests/WorksWithoutCompiledManifestTest.php @@ -15,13 +15,11 @@ protected function setUp(): void { parent::setUp(); - Route::get('_testing/missing-manifest', function () { - return View::file(__DIR__ . '/stubs/welcome.blade.php'); - }); + Route::get('_testing/missing-manifest', fn () => View::file(__DIR__.'/stubs/welcome.blade.php')); } - /** @test */ - public function throws_exception_when_missing_manifest() + #[\PHPUnit\Framework\Attributes\Test] + public function throws_exception_when_missing_manifest(): void { $this->expectException(Exception::class); $this->expectExceptionMessage('The Tailwind CSS manifest does not exist.'); @@ -32,8 +30,8 @@ public function throws_exception_when_missing_manifest() $this->fail('Expected an exception to be thrown, but it did not.'); } - /** @test */ - public function works_without_compiled_manifest_file() + #[\PHPUnit\Framework\Attributes\Test] + public function works_without_compiled_manifest_file(): void { $this->withoutTailwind() ->get('_testing/missing-manifest')