Skip to content

Fix @theme directive collision in health check view#60340

Merged
taylorotwell merged 1 commit into
laravel:13.xfrom
cathrinevaage:patch-1
Jun 1, 2026
Merged

Fix @theme directive collision in health check view#60340
taylorotwell merged 1 commit into
laravel:13.xfrom
cathrinevaage:patch-1

Conversation

@cathrinevaage
Copy link
Copy Markdown
Contributor

Problem

Any application that registers a custom @theme Blade directive has that directive invoked while the framework compiles its own health check view (/up). health-up.blade.php is compiled by Blade.
Since #58344 switched it to Tailwind v4, the file contains:

<style type="text/tailwindcss">
  @theme {
      --font-sans: ...;
  }
</style>

@theme here is meant as Tailwind v4 CSS, read at runtime by @tailwindcss/browser@4. But Blade compiles the template first, and theme is a valid custom-directive name. A directive's arguments are optional, so @theme { matches as that directive with an empty expression — and if an app has registered one (a documented feature), Blade replaces the token while compiling the framework's own view.

Reproduction

Register a minimal @theme directive in a service provider:

Blade::directive('theme', fn ($expression) => '/* blade */');

Clear compiled views and open /up:

php artisan view:clear

The <style type="text/tailwindcss"> block renders as:

/* blade */ {
    --font-sans: 'Figtree', ...

instead of:

@theme {
    --font-sans: 'Figtree', ...

Blade matched the Tailwind @theme { at-rule as the directive and replaced it.

Impact

This no-op directive just breaks the emitted CSS. Directives that build PHP from $expression (e.g. @theme($name, ...)) produce invalid PHP for the empty match and return a 500 on /up.

Fix

Escape the at-rule as @@theme. Blade emits a literal @theme and no longer matches it as a directive; Tailwind receives the same CSS as before. No change to default installations.

Notes

  • Affects 12.x as well (where Update tailwind version #58344 merged); same line is present on 13.x.
  • No test added: the change is a static template escape with no unit-test surface.

Escape the Tailwind @theme at-rule as @@theme in the health check Blade template so custom @theme Blade directives in consuming applications are not invoked when the view is compiled.
No change to rendered HTML for default installations.
@taylorotwell taylorotwell merged commit b26aae6 into laravel:13.x Jun 1, 2026
54 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants