-
Notifications
You must be signed in to change notification settings - Fork 487
Open
Description
Description
The template engine's || handler in evalExpr (src/pipeline/template.ts:68-74) only evaluates the left side of the first ||. When the left side is falsy, the entire right side is returned as a literal string instead of being recursively evaluated.
Single || works:
phonetic: "${{ item.phonetic || 'N/A' }}"
# item.phonetic = '' → returns 'N/A' ✓Chained || breaks:
phonetic: "${{ item.phonetic || item.phonetics[0].text || '' }}"
# item.phonetic = '' → returns literal "item.phonetics[0].text || ''" ✗Root cause
// template.ts:68-74
const orMatch = expr.match(/^(.+?)\s*\|\|\s*(.+)$/);
if (orMatch) {
const left = evalExpr(orMatch[1].trim(), ctx); // ← recursively evaluated
if (left) return left;
const right = orMatch[2].trim();
return right.replace(/^['"]|['"]$/g, ''); // ← returned as literal string, NOT evaluated
}The right side should be recursively evaluated with evalExpr() when the left side is falsy, or the entire expression should fall through to evalJsExpr() which handles chained || correctly via new Function().
Impact
Any YAML adapter using chained || for fallback chains will silently output template text instead of actual values. The workaround is wrapping in an IIFE:
phonetic: "${{ (() => item.phonetic || item.phonetics?.[0]?.text || '')() }}"Suggested fix
Change line 73 from:
return right.replace(/^['"]|['"]$/g, '');to:
return evalExpr(right, ctx);This makes the right side recursively evaluate, correctly handling a || b || c chains.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels