...

Source file src/github.com/noirbizarre/gonja/exec/template.go

Documentation: github.com/noirbizarre/gonja/exec

     1  package exec
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"strings"
     7  
     8  	"github.com/pkg/errors"
     9  
    10  	"github.com/noirbizarre/gonja/nodes"
    11  	"github.com/noirbizarre/gonja/parser"
    12  	"github.com/noirbizarre/gonja/tokens"
    13  )
    14  
    15  type TemplateLoader interface {
    16  	GetTemplate(string) (*Template, error)
    17  }
    18  
    19  type Template struct {
    20  	Name   string
    21  	Reader io.Reader
    22  	Source string
    23  
    24  	Env    *EvalConfig
    25  	Loader TemplateLoader
    26  
    27  	Tokens *tokens.Stream
    28  	Parser *parser.Parser
    29  
    30  	Root   *nodes.Template
    31  	Macros MacroSet
    32  }
    33  
    34  func NewTemplate(name string, source string, cfg *EvalConfig) (*Template, error) {
    35  	// Create the template
    36  	t := &Template{
    37  		Env:    cfg,
    38  		Name:   name,
    39  		Source: source,
    40  		Tokens: tokens.Lex(source),
    41  	}
    42  
    43  	// Parse it
    44  	t.Parser = parser.NewParser(name, cfg.Config, t.Tokens)
    45  	t.Parser.Statements = *t.Env.Statements
    46  	t.Parser.TemplateParser = t.Env.GetTemplate
    47  	root, err := t.Parser.Parse()
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	t.Root = root
    52  
    53  	return t, nil
    54  }
    55  
    56  func (tpl *Template) execute(ctx map[string]interface{}, out io.StringWriter) error {
    57  	exCtx := tpl.Env.Globals.Inherit()
    58  	exCtx.Update(ctx)
    59  
    60  	var builder strings.Builder
    61  	renderer := NewRenderer(exCtx, &builder, tpl.Env, tpl)
    62  
    63  	err := renderer.Execute()
    64  	if err != nil {
    65  		return errors.Wrap(err, `Unable to Execute template`)
    66  	}
    67  	out.WriteString(renderer.String())
    68  
    69  	return nil
    70  }
    71  
    72  func (tpl *Template) newBufferAndExecute(ctx map[string]interface{}) (*bytes.Buffer, error) {
    73  	var buffer bytes.Buffer
    74  	// Create output buffer
    75  	// We assume that the rendered template will be 30% larger
    76  	// buffer := bytes.NewBuffer(make([]byte, 0, int(float64(tpl.size)*1.3)))
    77  	if err := tpl.execute(ctx, &buffer); err != nil {
    78  		return nil, err
    79  	}
    80  	return &buffer, nil
    81  }
    82  
    83  // // Executes the template with the given context and writes to writer (io.Writer)
    84  // // on success. Context can be nil. Nothing is written on error; instead the error
    85  // // is being returned.
    86  // func (tpl *Template) ExecuteWriter(ctx *Context, writer io.Writer) error {
    87  // 	buf, err := tpl.newBufferAndExecute(ctx)
    88  // 	if err != nil {
    89  // 		return err
    90  // 	}
    91  // 	_, err = buf.WriteTo(writer)
    92  // 	if err != nil {
    93  // 		return err
    94  // 	}
    95  // 	return nil
    96  // }
    97  
    98  // // // Same as ExecuteWriter. The only difference between both functions is that
    99  // // // this function might already have written parts of the generated template in the
   100  // // // case of an execution error because there's no intermediate buffer involved for
   101  // // // performance reasons. This is handy if you need high performance template
   102  // // // generation or if you want to manage your own pool of buffers.
   103  // // func (tpl *Template) ExecuteWriterUnbuffered(ctx *Context, writer io.Writer) error {
   104  // // 	return tpl.newTemplateWriterAndExecute(ctx, writer)
   105  // // }
   106  
   107  // Executes the template and returns the rendered template as a []byte
   108  func (tpl *Template) ExecuteBytes(ctx map[string]interface{}) ([]byte, error) {
   109  	buffer, err := tpl.newBufferAndExecute(ctx)
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  	return buffer.Bytes(), nil
   114  }
   115  
   116  // Executes the template and returns the rendered template as a string
   117  func (tpl *Template) Execute(ctx map[string]interface{}) (string, error) {
   118  	var b strings.Builder
   119  	err := tpl.execute(ctx, &b)
   120  	if err != nil {
   121  		return "", err
   122  	}
   123  
   124  	return b.String(), nil
   125  }
   126  

View as plain text