Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- The views also answer to the canonical `laranail/confetti` namespace
(`view('laranail/confetti::components.scripts')`), registered by
package-tools over the same paths as `laranail-confetti`, published overrides
included. A naming test asserts both forms against the live view finder.

### Changed

- The package renders through `laranail/confetti::` (`ConfettiTags::VIEW`).
`laranail-confetti::` still resolves the same files.
- Requires `laranail/package-tools ^0.1.3`, the first release that registers
both namespace forms.
- `laranail::confetti.install` now extends laranail/package-tools'
`InstallCommand` and takes laranail/console's display API and run lifecycle
from its `InteractsWithConsoleServices` and `InteractsWithConsoleWriter`
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"illuminate/view": "^13.0",
"laranail/console": "^0.1",
"laranail/enumerator": "^0.1",
"laranail/package-tools": "^0.1"
"laranail/package-tools": "^0.1.3"
},
"require-dev": {
"filament/filament": "^4.0 || ^5.0",
Expand Down
8 changes: 7 additions & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,17 @@ Everything this package registers is prefixed, and none of it is called just
| Surface | Name | Used as |
|---|---|---|
| Blade component | `laranail-confetti` | `<x-laranail-confetti::scripts />` |
| View namespace | `laranail-confetti` | `view('laranail-confetti::components.scripts')` |
| View namespace | `laranail/confetti` (canonical), `laranail-confetti` (alias) | `view('laranail/confetti::components.scripts')` |
| Route middleware | `laranail-confetti` | `->middleware('laranail-confetti')` |
| Artisan commands | `laranail::confetti.` | `php artisan laranail::confetti.doctor` |
| Alpine component | `laranailConfetti` | `<div x-data="laranailConfetti">` |

The view namespace answers to both spellings over the same paths. `laranail/confetti`
is canonical, because it is the composer package name, and the package renders
through it. `laranail-confetti` is kept, not deprecated: it is the spelling a
Blade tag needs, and overrides published to
`resources/views/vendor/laranail-confetti` keep winning under either name.

Laravel keeps view namespaces, component prefixes and middleware aliases in flat
maps keyed by that name. Two packages claiming the same key do not collide
loudly; the second silently replaces the first, and it surfaces much later as a
Expand Down
4 changes: 4 additions & 0 deletions src/Providers/ConfettiServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ public function configurePackage(Package $package): void
$package
->name('laranail/confetti')
->hasConfigFile()
// Declared under the hyphen form so overrides already published to
// resources/views/vendor/laranail-confetti keep winning; package-tools
// registers the canonical `laranail/confetti` namespace over the same
// paths, and the package renders through that one.
->hasViews('laranail-confetti')
->hasAssets()
->hasBladeComponentNamespace(
Expand Down
6 changes: 5 additions & 1 deletion src/View/ConfettiTags.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@
*/
final readonly class ConfettiTags
{
public const string VIEW = 'laranail-confetti::components.scripts';
/**
* The view, under the canonical `laranail/confetti` namespace. The `laranail-confetti` namespace
* still resolves the same file, including an override published under it.
*/
public const string VIEW = 'laranail/confetti::components.scripts';

public function __construct(
private ConfettiConfig $config,
Expand Down
2 changes: 1 addition & 1 deletion tests/Feature/FilamentPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ function renderPanelHook(Panel $panel, string $hook): string

ConfettiPlugin::make()->register($panel);

$expected = view('laranail-confetti::components.scripts', [
$expected = view('laranail/confetti::components.scripts', [
'enabled' => true,
'bootJson' => app(BootConfig::class)->toJson(),
'scriptTag' => app(ScriptTagBuilder::class)->render(),
Expand Down
2 changes: 1 addition & 1 deletion tests/Feature/InjectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

// A page that already carries the component.
Route::get('/explicit', fn (): string => '<html><body>'
. view('laranail-confetti::components.scripts', [
. view('laranail/confetti::components.scripts', [
'enabled' => true,
'bootJson' => app(BootConfig::class)->toJson(),
'scriptTag' => app(ScriptTagBuilder::class)->render(),
Expand Down
21 changes: 21 additions & 0 deletions tests/Feature/NamingConventionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Blade;
use Simtabi\Laranail\Confetti\View\ConfettiTags;
use Simtabi\Laranail\Package\Tools\Testing\NamingScope;
use Simtabi\Laranail\Package\Tools\Testing\AssertsRegisteredNames;

uses(AssertsRegisteredNames::class);

/**
* Every public name this package claims is prefixed with the org and the slug.
Expand All @@ -29,6 +34,22 @@
expect($hints)->not->toHaveKey('confetti');
});

it('registers both view namespace forms over the same paths, and renders through the canonical one', function (): void {
// basePath is resources/: package-tools v0.1.3 defaults ownership to the
// package root, which also claims vendor/ and tests/ registrations (fixed in v0.1.4).
$scope = NamingScope::for('laranail/confetti', 'Simtabi\\Laranail\\Confetti\\', basePath: dirname(__DIR__, 2) . '/resources');

expect($this->assertViewNamespacesScoped($scope, atLeast: 2))
->toContain('laranail/confetti', PREFIX);

$hints = View::getFinder()->getHints();

expect($hints['laranail/confetti'])->toBe($hints[PREFIX]);
expect(ConfettiTags::VIEW)->toStartWith('laranail/confetti::');
expect(view('laranail-confetti::components.scripts')->getPath())
->toBe(view(ConfettiTags::VIEW)->getPath());
});

it('registers its Blade components under the org-scoped prefix', function (): void {
$namespaces = new ReflectionProperty(Blade::getFacadeRoot(), 'classComponentNamespaces')
->getValue(Blade::getFacadeRoot());
Expand Down
2 changes: 1 addition & 1 deletion tests/Feature/SessionTransportTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
return redirect('/page');
});

Route::middleware('web')->get('/page', fn (): Factory|View => view('laranail-confetti::components.scripts', [
Route::middleware('web')->get('/page', fn (): Factory|View => view('laranail/confetti::components.scripts', [
'enabled' => true,
'bootJson' => app(BootConfig::class)->toJson(),
'scriptTag' => app(ScriptTagBuilder::class)->render(),
Expand Down
Loading