public String render ( Node root , boolean processExtendRoots ) { OutputList output = new OutputList ( config . getMaxOutputSize ( ) ) ; for ( Node node : root . getChildren ( ) ) { lineNumber = node . getLineNumber ( ) ; position = node . getStartPosition ( ) ; String renderStr = node . getMaster ( ) . getImage ( ) ; if ( context . doesRenderStackContain ( renderStr ) ) { // This is a circular rendering. Stop rendering it here. addError ( new TemplateError ( ErrorType . WARNING , ErrorReason . EXCEPTION , ErrorItem . TAG , "Rendering cycle detected: '" + renderStr + "'" , null , getLineNumber ( ) , node . getStartPosition ( ) , null , BasicTemplateErrorCategory . IMPORT_CYCLE_DETECTED , ImmutableMap . of ( "string" , renderStr ) ) ) ; output . addNode ( new RenderedOutputNode ( renderStr ) ) ; } else { OutputNode out ; context . pushRenderStack ( renderStr ) ; try { out = node . render ( this ) ; } catch ( DeferredValueException e ) { out = new RenderedOutputNode ( node . getMaster ( ) . getImage ( ) ) ; } context . popRenderStack ( ) ; output . addNode ( out ) ; } } // render all extend parents, keeping the last as the root output if ( processExtendRoots ) { while ( ! extendParentRoots . isEmpty ( ) ) { context . getCurrentPathStack ( ) . push ( context . getExtendPathStack ( ) . peek ( ) . orElse ( "" ) , lineNumber , position ) ; Node parentRoot = extendParentRoots . removeFirst ( ) ; output = new OutputList ( config . getMaxOutputSize ( ) ) ; for ( Node node : parentRoot . getChildren ( ) ) { OutputNode out = node . render ( this ) ; output . addNode ( out ) ; } context . getExtendPathStack ( ) . pop ( ) ; context . getCurrentPathStack ( ) . pop ( ) ; } } resolveBlockStubs ( output ) ; return output . getValue ( ) ; }
Render the given root node using this interpreter s current context