...

Text file src/github.com/noirbizarre/gonja/env/template.go.bak

Documentation: github.com/noirbizarre/gonja/env

     1package env
     2
     3import (
     4	"bytes"
     5	"io"
     6	"strings"
     7
     8	"github.com/pkg/errors"
     9
    10	// "github.com/noirbizarre/gonja/config"
    11	"github.com/noirbizarre/gonja/eval"
    12	"github.com/noirbizarre/gonja/nodes"
    13	"github.com/noirbizarre/gonja/parser"
    14	"github.com/noirbizarre/gonja/tokens"
    15)
    16
    17type TemplateGetter interface {
    18	GetTemplate(string) (*Template, error)
    19}
    20
    21// type TemplateWriter interface {
    22// 	io.Writer
    23// 	WriteString(string) (int, error)
    24// }
    25
    26// type templateWriter struct {
    27// 	w io.Writer
    28// }
    29
    30// func (tw *templateWriter) WriteString(s string) (int, error) {
    31// 	return tw.w.Write([]byte(s))
    32// }
    33
    34// func (tw *templateWriter) Write(b []byte) (int, error) {
    35// 	return tw.w.Write(b)
    36// }
    37
    38type Template struct {
    39	// set *TemplateSet
    40	Env *Environment
    41
    42	// Input
    43	// isTplString bool
    44	Name   string
    45	Reader io.Reader
    46	Source string
    47	// Config *config.Config
    48	// size        int
    49
    50	// Calculation
    51	// tokens []*Token
    52	Tokens *tokens.Stream
    53	Parser *parser.Parser
    54
    55	Root   *nodes.Template
    56	Parent *Template
    57	Blocks map[string]*nodes.Wrapper
    58	Macros eval.MacroSet
    59
    60	// first come, first serve (it's important to not override existing entries in here)
    61	// level          int
    62	// parent         *Template
    63	// child          *Template
    64	// blocks         map[string]*NodeWrapper
    65	// exportedMacros map[string]*MacroStmt
    66
    67	// // Output
    68	// root *nodeDocument
    69}
    70
    71// func newTemplateString(env *Environment, tpl []byte) (*Template, error) {
    72// 	return newTemplate(env, "<string>", true, tpl)
    73// }
    74
    75func NewTemplate(name string, source string, env *Environment) (*Template, error) {
    76	// source := string(tpl)
    77	// if cfg == nil {
    78	// 	cfg = config.DefaultConfig
    79	// }
    80
    81	// Create the template
    82	t := &Template{
    83		Env: env,
    84		// isTplString: isTplString,
    85		Name:   name,
    86		Source: source,
    87		Tokens: tokens.Lex(source),
    88		// Config: cfg,
    89		// size:           len(strTpl),
    90		// blocks:         make(map[string]*NodeWrapper),
    91		// exportedMacros: make(map[string]*MacroStmt),
    92	}
    93
    94	// // Tokenize it
    95	// tokens, err := lex(name, strTpl)
    96	// if err != nil {
    97	// 	return nil, err
    98	// }
    99	// t.tokens = tokens
   100
   101	// For debugging purposes, show all tokens:
   102	/*for i, t := range tokens {
   103		fmt.Printf("%3d. %s\n", i, t)
   104	}*/
   105
   106	// Parse it
   107	t.Parser = parser.NewParser(name, env.Config, t.Tokens)
   108	t.Parser.Statements = t.Env.Statements //.Parsers()
   109	root, err := t.Parser.Parse()
   110	if err != nil {
   111		return nil, err
   112	}
   113	t.Root = root
   114
   115	return t, nil
   116}
   117
   118func (tpl *Template) execute(ctx eval.Context, out io.StringWriter) error {
   119	// Determine the parent to be executed (for template inheritance)
   120	parent := tpl
   121	for parent.Parent != nil {
   122		parent = parent.Parent
   123	}
   124
   125	// Create context if none is given
   126	newCtx := eval.Context{}
   127	// newContext := make(Context)
   128	// newContext.Update(tpl.set.Globals)
   129
   130	if ctx != nil {
   131		newCtx.Update(ctx)
   132
   133		if len(newCtx) > 0 {
   134			// // Check for context name syntax
   135			// err := newCtx.checkForValidIdentifiers()
   136			// if err != nil {
   137			// 	return err
   138			// }
   139
   140			// Check for clashes with macro names
   141			for k := range newCtx {
   142				_, has := tpl.Macros[k]
   143				if has {
   144					return errors.Errorf("context key name '%s' clashes with macro '%s'", k, k)
   145				}
   146			}
   147		}
   148	}
   149
   150	// Create operational context
   151	exCtx := eval.NewExecutionContext(newCtx)
   152	exCtx.Globals.Update(tpl.Env.Globals)
   153	// exCtx := newExecutionContext(parent, newCtx)
   154
   155	var builder strings.Builder
   156	renderer := eval.NewRenderer(exCtx, &builder, tpl.Env.EvalConfig)
   157
   158	nodes.Walk(renderer, tpl.Root)
   159	// nodes.Inspect(tpl.Root, renderer.Render)
   160
   161	// // Run the selected document
   162	// if err := parent.Root.Execute(exCtx, writer); err != nil {
   163	// 	return err
   164	// }
   165	out.WriteString(builder.String())
   166
   167	return nil
   168}
   169
   170// func (tpl *Template) newTemplateWriterAndExecute(ctx *Context, writer io.Writer) error {
   171// 	return tpl.execute(ctx, &templateWriter{w: writer})
   172// }
   173
   174func (tpl *Template) newBufferAndExecute(ctx eval.Context) (*bytes.Buffer, error) {
   175	var buffer bytes.Buffer
   176	// Create output buffer
   177	// We assume that the rendered template will be 30% larger
   178	// buffer := bytes.NewBuffer(make([]byte, 0, int(float64(tpl.size)*1.3)))
   179	if err := tpl.execute(ctx, &buffer); err != nil {
   180		return nil, err
   181	}
   182	return &buffer, nil
   183}
   184
   185// // Executes the template with the given context and writes to writer (io.Writer)
   186// // on success. Context can be nil. Nothing is written on error; instead the error
   187// // is being returned.
   188// func (tpl *Template) ExecuteWriter(ctx *Context, writer io.Writer) error {
   189// 	buf, err := tpl.newBufferAndExecute(ctx)
   190// 	if err != nil {
   191// 		return err
   192// 	}
   193// 	_, err = buf.WriteTo(writer)
   194// 	if err != nil {
   195// 		return err
   196// 	}
   197// 	return nil
   198// }
   199
   200// // // Same as ExecuteWriter. The only difference between both functions is that
   201// // // this function might already have written parts of the generated template in the
   202// // // case of an execution error because there's no intermediate buffer involved for
   203// // // performance reasons. This is handy if you need high performance template
   204// // // generation or if you want to manage your own pool of buffers.
   205// // func (tpl *Template) ExecuteWriterUnbuffered(ctx *Context, writer io.Writer) error {
   206// // 	return tpl.newTemplateWriterAndExecute(ctx, writer)
   207// // }
   208
   209// Executes the template and returns the rendered template as a []byte
   210func (tpl *Template) ExecuteBytes(ctx map[string]interface{}) ([]byte, error) {
   211	// Execute template
   212	buffer, err := tpl.newBufferAndExecute(ctx)
   213	if err != nil {
   214		return nil, err
   215	}
   216	return buffer.Bytes(), nil
   217}
   218
   219// Executes the template and returns the rendered template as a string
   220func (tpl *Template) Execute(ctx map[string]interface{}) (string, error) {
   221	var b strings.Builder
   222	err := tpl.execute(ctx, &b)
   223	// Execute template
   224	// buffer, err := tpl.newBufferAndExecute(ctx)
   225	if err != nil {
   226		return "", err
   227	}
   228
   229	return b.String(), nil
   230
   231}

View as plain text