1
0
mirror of https://github.com/danog/liquid.git synced 2024-11-30 10:48:59 +01:00
liquid/chunks/render_context.go
2017-06-30 14:51:21 -04:00

91 lines
2.5 KiB
Go

package chunks
import (
"bytes"
"fmt"
"io"
"github.com/osteele/liquid/expressions"
)
// RenderContext provides the rendering context for a tag renderer.
type RenderContext interface {
Get(name string) interface{}
Set(name string, value interface{})
GetVariableMap() map[string]interface{}
Evaluate(expr expressions.Expression) (interface{}, error)
EvaluateString(source string) (interface{}, error)
EvaluateStatement(tag, source string) (interface{}, error)
RenderBranch(io.Writer, *ASTControlTag) error
RenderChildren(io.Writer) error
InnerString() (string, error)
}
type renderContext struct {
ctx Context
node *ASTFunctional
cn *ASTControlTag
}
// Evaluate evaluates an expression within the template context.
func (c renderContext) Evaluate(expr expressions.Expression) (out interface{}, err error) {
return c.ctx.Evaluate(expr)
}
// EvaluateString evaluates an expression within the template context.
func (c renderContext) EvaluateString(source string) (out interface{}, err error) {
defer func() {
if r := recover(); r != nil {
switch e := r.(type) {
case expressions.InterpreterError:
err = e
default:
// fmt.Println(string(debug.Stack()))
panic(fmt.Errorf("%s during evaluation of %s", e, source))
}
}
}()
return expressions.EvaluateString(source, expressions.NewContext(c.ctx.vars))
}
func (c renderContext) EvaluateStatement(tag, source string) (interface{}, error) {
return c.EvaluateString(fmt.Sprintf("%%%s %s", tag, source))
}
// GetVariableMap returns the variable map. This is required by some tangled code
// in Jekyll includes, that should hopefully get better.
func (c renderContext) GetVariableMap() map[string]interface{} {
return c.ctx.vars
}
// Get gets a variable value within an evaluation context.
func (c renderContext) Get(name string) interface{} {
return c.ctx.vars[name]
}
// Set sets a variable value from an evaluation context.
func (c renderContext) Set(name string, value interface{}) {
c.ctx.vars[name] = value
}
// RenderChildren renders the current node's children.
func (c renderContext) RenderChildren(w io.Writer) error {
if c.cn == nil {
return nil
}
return c.ctx.RenderASTSequence(w, c.cn.Body)
}
func (c renderContext) RenderBranch(w io.Writer, b *ASTControlTag) error {
return c.ctx.RenderASTSequence(w, b.Body)
}
// InnerString renders the children to a string.
func (c renderContext) InnerString() (string, error) {
buf := new(bytes.Buffer)
if err := c.RenderChildren(buf); err != nil {
return "", err
}
return buf.String(), nil
}