@@ -158,6 +158,9 @@ export default class Runtime {
158158 return true ; // Indicate that the file was changed
159159 }
160160
161+ /**
162+ * Evaluate all tags in the AST and return the final text.
163+ */
161164 async evaluateAll ( customCtx : Record < string , any > = { } ) : Promise < string > {
162165 if ( this . state . running ) {
163166 // Should I return an error here?
@@ -190,6 +193,10 @@ export default class Runtime {
190193 return text ;
191194 }
192195
196+ /**
197+ * Evaluate a specific tag and its children.
198+ * This is a lower-level method, use `evaluateAll` for the whole AST.
199+ */
193200 async evaluateTag ( tag : T . ParseToken , customCtx : Record < string , any > = { } ) : Promise < void > {
194201 if ( ! tag . name ) {
195202 return ; // Raw text or invalid tag
@@ -260,6 +267,9 @@ export default class Runtime {
260267 const children = new AST ( this . config ) . parse ( result ) ;
261268 if ( children . length ) {
262269 tag . children = children ;
270+ // Sync indexes and paths after parsing children
271+ this . ast . syncIndexes ( ) ;
272+ AST . addPaths ( this . ast . nodes ) ;
263273 }
264274 }
265275 }
@@ -286,7 +296,8 @@ export default class Runtime {
286296 // a separate variable scope for the children
287297 // At this point, the parent props are interpolated
288298 if ( evalChildren ) {
289- const childrenCtx = deepClone ( customCtx ) ;
299+ // The children scope is also saved in the parent tag
300+ ( tag as T . DoubleTag ) . childCtx = deepClone ( customCtx ) ;
290301 for ( const c of tag . children ) {
291302 if ( c . name && ( c . single || c . double ) ) {
292303 c . parent = { name : tag . name , index : tag . index , params : tag . params , rawText : '' } ;
@@ -302,7 +313,7 @@ export default class Runtime {
302313 }
303314 }
304315
305- await this . evaluateTag ( c , childrenCtx ) ;
316+ await this . evaluateTag ( c , ( tag as T . DoubleTag ) . childCtx ) ;
306317 }
307318 }
308319 }
0 commit comments