Repository navigation
Add %empty branch to %loop and harden loop directives - #91
Merged
Merged
Conversation
A bare %empty between %loop and %endloop renders its content when the iterable is empty, like Blade's @forelse / @empty. %empty($x) with parentheses remains the conditional helper. A pre-scan in Compiler::compile records which loops own a branch so each directive compiles correctly line by line; nested loops get their own flag and a %loop without %empty still compiles to a plain foreach. Also fix the greedy condition in %stop(...) and %jump(...), which swallowed any later parentheses on the same line, and add unit tests covering every loop directive, the pre-scan, and the stack runner.
Document key/value and single-line %loop forms, note that %jump and %stop compile to continue and break and work in every loop kind, give %for and %while real examples, and fix the %else and %endnotempty typos in the conditional helpers section. Table of contents now matches section order.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an
%emptybranch to%loop, equivalent to Blade's@forelse/@empty, fixes a greedy-regex bug in%stop(...)/%jump(...), and brings the loop directives under unit tests.What changed
%emptyloop branch (src/Lexique/CompileLoop.php,src/Compiler.php)%empty(no parentheses) between%loopand%endlooprenders its content when the iterable is empty.%empty($x)with parentheses remains the existing conditional helper, even inside a loop. A bare%emptypreviously compiled toif (empty()), which is invalid PHP, so no working template changes meaning.%loopcannot see whether an%emptyfollows. A pre-scan inCompiler::compile()walks%loop/%empty/%endlooptokens with a stack after comments and verbatim blocks are stripped, and records which loops own a branch and at what depth. The three loop compilers consume those queues.%loopwithout%emptycompiles exactly as before, so existing templates and cached output are unchanged.%forand%whilehave no empty branch.Fix: greedy
%stop(...)/%jump(...)condition.+for the condition, so%stop($b) ... ($y)on one line extended the condition to the last)and produced broken PHP. It now uses the same balanced-paren matcher as the loop heads. Same class of bug as thecondition_patternfix already in the changelog.Tests (
tests/CompileLoopTest.php, 15 → 36 tests)%stop(previously untested),%jump, the bare%emptycompiler, the pre-scan (nesting, helper and stray tokens ignored, state reset), and the stack runner.%loopkey/value,%while,%forwith%jump/%stop, and%emptywith nested loops and after%stop.Docs (
docs/en.md,docs/fr.md,CHANGELOG.md)%emptysection, key/value and single-line%loopexamples, real%for/%whileexamples, note that%jump/%stopwork in all loops, table of contents reordered to match,%esle→%elseand%notendempty→%endnotemptytypo fixes.Verification
vendor/bin/phpunit: 124 tests, 302 assertions, all passing.phpcs --standard=psr12clean on the changed source files.Tintin::render()with both populated and empty data.