Problem
An ... conditional inside a @forelse row was taken as the @forelse's @empty separator, so the row was cut at the conditional. With items [{ name: 'Ann' }, { name: '' }]:
@forelse(items as item)<p>missing</p>@empty<p>No items</p>@endforelserendered <p><p>, and an empty list printed the leftover @empty / @endempty text. The same row in @foreach renders <p>Ann</p><p>missing</p>.
Fix
While looking for the separator, an @empty( (spaces or tabs allowed before the parenthesis) whose @endempty is inside the same @forelse is the conditional and is skipped. Without a matching @endempty it is still the separator, so separator text such as @empty (none) keeps working.
One case changes: a separator whose text starts with parentheses (@empty (none)) together with a literal, unescaped @endempty later in the same @forelse is now read as a conditional, and the @forelse is not rendered. @@endempty renders it correctly, the same escape the other block directives need for their end tags in text.
Tests
Two cases in test/directives/loops.test.ts under @forelse. The first fails on main:
Expected to contain: "<p>Ann</p>"
Received: "<p><p>"The second, separator text that starts with parentheses, passes on main and with the change. bun run build, bun run smoke:install, bun run typecheck, bun run lint and bun run format:check pass, and bun test packages examples --max-concurrency=1 has no new failures compared with main (the tests failing on both need a browser or other parts of the environment I don't have).