also looking at this
fix(loops): an @empty(expr) conditional in a @forelse row is not the separator
#2104
2 files
+24
-2
| @@ -48,7 +48,7 @@ import type { StxOptions } from './types' | ||
| 48 | 48 | import { processConditionals } from './conditionals' |
| 49 | 49 | import { ErrorCodes, inlineError } from './error-handling' |
| 50 | 50 | import { processExpressions } from './expressions' |
| 51 | import { findDirectiveBlocks, findMatchingDelimiter } from './parser' | |
| 51 | import { findDirectiveBlocks, findMatchingDelimiter, findMatchingEndTag } from './parser' | |
| 52 | 52 | import { createSafeFunction, freeIdentifiers, isExpressionSafe, isForExpressionSafe, SANITIZE_CACHE, sanitizeExpression, safeEvaluate, safeEvaluateObject } from './safe-evaluator' |
| 53 | 53 | |
| 54 | 54 | // Default loop configuration |
| @@ -577,7 +577,9 @@ else if (remaining.startsWith('@endforelse')) { | ||
| 577 | 577 | searchI = atPos + '@endforelse'.length |
| 578 | 578 | } |
| 579 | 579 | else if (nestedDepth === 0 && remaining.startsWith('@empty')) { |
| 580 | if (fullContent.length <= atPos + 6 || !/[a-z]/i.test(fullContent[atPos + 6])) { | |
| 580 | // ... in a row is the conditional, not this separator | |
| 581 | const isConditional = /^@empty[ \t]*\(/.test(remaining) && findMatchingEndTag(fullContent, 'empty', 'endempty', atPos + 6) !== -1 | |
| 582 | if ((fullContent.length <= atPos + 6 || !/[a-z]/i.test(fullContent[atPos + 6])) && !isConditional) { | |
| 581 | 583 | emptyPos = atPos |
| 582 | 584 | break |
| 583 | 585 | } |
| @@ -575,6 +575,26 @@ describe('Loops Comprehensive', () => { | ||
| 575 | 575 | expect(result).toContain('x') |
| 576 | 576 | expect(result).not.toContain('empty') |
| 577 | 577 | }) |
| 578 | it('should not take an @empty(expr) conditional in a row for the @empty separator', () => { | |
| 579 | const template = '@forelse(items as item)<p>@empty(item.name)missing | |