ReviewOS

also looking at this

stacks/stx

fix(loops): an @empty(expr) conditional in a @forelse row is not the separator

#2104
Open mkantautas wants to merge fix/forelse-empty-conditional into main
2 files +24 -2
packages/stx/src/loops.tsmodified+4-2
Changes to packages/stx/src/loops.ts
@@ -48,7 +48,7 @@ import type { StxOptions } from './types'
4848import { processConditionals } from './conditionals'
4949import { ErrorCodes, inlineError } from './error-handling'
5050import { processExpressions } from './expressions'
51import { findDirectiveBlocks, findMatchingDelimiter } from './parser'
51import { findDirectiveBlocks, findMatchingDelimiter, findMatchingEndTag } from './parser'
5252import { createSafeFunction, freeIdentifiers, isExpressionSafe, isForExpressionSafe, SANITIZE_CACHE, sanitizeExpression, safeEvaluate, safeEvaluateObject } from './safe-evaluator'
5353
5454// Default loop configuration
@@ -577,7 +577,9 @@ else if (remaining.startsWith('@endforelse')) {
577577 searchI = atPos + '@endforelse'.length
578578 }
579579else 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) {
581583 emptyPos = atPos
582584 break
583585 }
packages/stx/test/directives/loops.test.tsmodified+20-0
Changes to packages/stx/test/directives/loops.test.ts
@@ -575,6 +575,26 @@ describe('Loops Comprehensive', () => {
575575 expect(result).toContain('x')
576576 expect(result).not.toContain('empty')
577577 })
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