Extensions

Enclaves for Package Authors

Laravel packages that ship Blade views can use Forte enclaves to transform their templates without affecting the host application. Register a package enclave, scope its paths, add custom rewriters, and isolate it from application transformations.

For the full enclave API reference, see Enclaves.

#Why Package Enclaves

By default, Forte's app enclave targets only the application's resources/views directory and excludes views/vendor/**. This means any transformations registered by the application will not touch your package's views, and any transformations your package registers on the app enclave could leak into the application.

Package enclaves solve this by giving your package its own isolated scope. Rewriters registered on a package enclave only run against that package's views, both the source views shipped with the package and any published copies in the host application's views/vendor directory.

#Creating a Package Enclave

Use Forte::createForPackage in your service provider's boot method. The first argument is your package name (matching the vendor directory under views/vendor), and the optional second argument is the package's root path:

<?php
namespace Acme\Widgets;
use Forte\Facades\Forte;
use Illuminate\Support\ServiceProvider;
class WidgetsServiceProvider extends ServiceProvider
{
public function boot(): void
{
$this->loadViewsFrom(__DIR__.'/../resources/views', 'widgets');
Forte::createForPackage('widgets', __DIR__.'/..')
->elementForeachAttributes()
->elementConditionalAttributes();
}
}

This creates an enclave named vendor:widgets that includes two path patterns:

  • resource_path('views/vendor/widgets/**') for published views
  • {packagePath}/resources/views/** for the package's source views

Both the default rewriters (elementForeachAttributes, elementConditionalAttributes) and any custom rewriters you add will only apply to views matching those patterns.

#Adding Custom Rewriters

Package enclaves support the same rewriter registration methods as the app enclave. Use apply for rewrite passes and use for visitors:

<?php
use Forte\Enclaves\Enclave;
use Forte\Rewriting\Passes\Elements\AddClass;
use Forte\Rewriting\Passes\Elements\SetAttribute;
$enclave = new Enclave;
$enclave->apply(
new AddClass('table', 'min-w-full'),
new SetAttribute('img', 'loading', 'lazy'),
);
$enclave->hasRewriters(); // true
$enclave->rewriterCount(); // 2

The transform method accepts a callback that receives a NodePath for each node. Use it for a single transformation that does not need a dedicated visitor or pass:

<?php
use Forte\Enclaves\Enclave;
use Forte\Rewriting\NodePath;
$enclave = new Enclave;
$enclave->transform(function (NodePath $path) {
// Custom transformation logic
});
$enclave->hasRewriters(); // true

In a service provider, the complete setup looks like this:

<?php
namespace Acme\Widgets;
use Forte\Facades\Forte;
use Forte\Rewriting\Passes\Elements\AddClass;
use Illuminate\Support\ServiceProvider;
class WidgetsServiceProvider extends ServiceProvider
{
public function boot(): void
{
$this->loadViewsFrom(__DIR__.'/../resources/views', 'widgets');
$enclave = Forte::createForPackage('widgets', __DIR__.'/..');
$enclave->apply(
new AddClass('table', 'min-w-full divide-y divide-gray-200'),
new AddClass('th', 'px-6 py-3 text-left text-xs font-medium'),
new AddClass('td', 'px-6 py-4 whitespace-nowrap'),
);
}
}

#Rewriter Priority

When using use to register visitors, the second parameter controls priority. Higher-priority rewriters run first:

<?php
use Forte\Enclaves\Enclave;
use Forte\Rewriting\NodePath;
use Forte\Rewriting\Visitor;
class PkgHighPriorityVisitor extends Visitor
{
public function enter(NodePath $path): void {}
}
class PkgLowPriorityVisitor extends Visitor
{
public function enter(NodePath $path): void {}
}
$enclave = new Enclave;
$enclave->use(PkgHighPriorityVisitor::class, priority: 20);
$enclave->use(PkgLowPriorityVisitor::class, priority: 10);
$enclave->rewriterCount(); // 2

The PkgHighPriorityVisitor runs before PkgLowPriorityVisitor because it has the higher priority value.

#Application-Side Vendor Inclusion

If a package does not create its own enclave, application developers can still include that package's published views in the app enclave. Use includeVendorPackages on the facade:

<?php
namespace App\Providers;
use Forte\Facades\Forte;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot(): void
{
Forte::app()
->elementForeachAttributes();
Forte::includeVendorPackages('notifications', 'pagination');
}
}

This adds include patterns for the specified vendor directories, so the app enclave's rewriters also process those published views.

#Avoiding Conflicts

Package enclaves are fully isolated from the app enclave and from other packages. A few guidelines help keep things clean:

  • Use createForPackage rather than registering rewriters on the app enclave. This prevents your transformations from accidentally affecting application views
  • Do not call Forte::app() in package service providers. The app enclave belongs to the application, not to packages
  • Name your enclave consistently. The createForPackage method automatically names it vendor:{package}, which avoids collisions with other packages

#See Also

Continue with these related Forte guides:

  • Enclaves: Full enclave API reference including path patterns, management, and default rewriters
  • Rewrite Passes: Pre-built transformations for common tasks
  • Rewriters: Write custom rewriters for advanced transformations