1
0
mirror of https://github.com/danog/liquid.git synced 2024-11-30 05:58:59 +01:00

New top-level Context wrapper

This commit is contained in:
Oliver Steele 2017-07-01 23:52:38 -04:00
parent e71bc95d5f
commit d6bc456ee4
5 changed files with 51 additions and 26 deletions

15
context.go Normal file
View File

@ -0,0 +1,15 @@
package liquid
type context struct {
bindings map[string]interface{}
}
// NewContext creates a new context from a variable binding map.
func NewContext(bindings map[string]interface{}) Context {
return &context{bindings}
}
// Bindings is in the Render interface.
func (c *context) Bindings() map[string]interface{} {
return c.bindings
}

View File

@ -47,17 +47,17 @@ func (e engine) ParseTemplate(text []byte) (Template, error) {
}
// ParseAndRender is in the Engine interface.
func (e engine) ParseAndRender(text []byte, bindings map[string]interface{}) ([]byte, error) {
func (e engine) ParseAndRender(text []byte, c Context) ([]byte, error) {
t, err := e.ParseTemplate(text)
if err != nil {
return nil, err
}
return t.Render(bindings)
return t.Render(c)
}
// ParseAndRenderString is in the Engine interface.
func (e engine) ParseAndRenderString(text string, bindings map[string]interface{}) (string, error) {
b, err := e.ParseAndRender([]byte(text), bindings)
func (e engine) ParseAndRenderString(text string, c Context) (string, error) {
b, err := e.ParseAndRender([]byte(text), c)
if err != nil {
return "", err
}

View File

@ -28,15 +28,34 @@ type Engine interface {
DefineTag(string, TagDefinition)
DefineStartTag(string, func(io.Writer, chunks.RenderContext) error)
ParseTemplate(b []byte) (Template, error)
ParseTemplate([]byte) (Template, error)
// ParseAndRender parses and then renders the template.
ParseAndRender(b []byte, bindings map[string]interface{}) ([]byte, error)
ParseAndRender([]byte, Context) ([]byte, error)
// ParseAndRenderString is a convenience wrapper for ParseAndRender, that has string input and output.
ParseAndRenderString(s string, bindings map[string]interface{}) (string, error)
ParseAndRenderString(string, Context) (string, error)
}
// Template renders a template according to scope.
//
// Bindings is a map of liquid variable names to objects.
type Template interface {
// Render executes the template with the specified bindings.
Render(Context) ([]byte, error)
// RenderString is a convenience wrapper for Render, that has string input and output.
RenderString(Context) (string, error)
}
// Context supplies variable bindings and other information to a
// Render.
//
// In the future, it will hold methods to get and set the current
// filename.
type Context interface {
Bindings() map[string]interface{}
}
// Renderer is the type of a function that is evaluated within a context and writes to output.
type Renderer func(io.Writer, chunks.Context) error
// type Renderer func(io.Writer, chunks.Context) error
// TagDefinition is the type of a function that parses the argument string "args" from a tag "{% tagname args %}",
// and returns a renderer.

View File

@ -16,19 +16,19 @@ var liquidTests = []struct{ in, expected string }{
{`{{ "upper" | upcase }}`, "UPPER"},
}
var liquidTestScope = map[string]interface{}{
var testContext = NewContext(map[string]interface{}{
"x": 123,
"ar": []string{"first", "second", "third"},
"page": map[string]interface{}{
"title": "Introduction",
},
}
})
func TestLiquid(t *testing.T) {
engine := NewEngine()
for i, test := range liquidTests {
t.Run(fmt.Sprint(i+1), func(t *testing.T) {
out, err := engine.ParseAndRenderString(test.in, liquidTestScope)
out, err := engine.ParseAndRenderString(test.in, testContext)
require.NoErrorf(t, err, test.in)
require.Equalf(t, test.expected, out, test.in)
})
@ -43,7 +43,8 @@ func Example() {
"title": "Introduction",
},
}
out, err := engine.ParseAndRenderString(template, bindings)
context := NewContext(bindings)
out, err := engine.ParseAndRenderString(template, context)
if err != nil {
log.Fatalln(err)
}

View File

@ -6,25 +6,15 @@ import (
"github.com/osteele/liquid/chunks"
)
// Template renders a template according to scope.
//
// Bindings is a map of liquid variable names to objects.
type Template interface {
// Render executes the template with the specified bindings.
Render(bindings map[string]interface{}) ([]byte, error)
// RenderString is a convenience wrapper for Render, that has string input and output.
RenderString(bindings map[string]interface{}) (string, error)
}
type template struct {
ast chunks.ASTNode
settings chunks.Settings
}
// Render executes the template within the bindings environment.
func (t *template) Render(bindings map[string]interface{}) ([]byte, error) {
func (t *template) Render(c Context) ([]byte, error) {
buf := new(bytes.Buffer)
err := t.ast.Render(buf, chunks.NewContext(bindings, t.settings))
err := t.ast.Render(buf, chunks.NewContext(c.Bindings(), t.settings))
if err != nil {
return nil, err
}
@ -32,8 +22,8 @@ func (t *template) Render(bindings map[string]interface{}) ([]byte, error) {
}
// RenderString is a convenience wrapper for Render, that has string input and output.
func (t *template) RenderString(bindings map[string]interface{}) (string, error) {
b, err := t.Render(bindings)
func (t *template) RenderString(c Context) (string, error) {
b, err := t.Render(c)
if err != nil {
return "", err
}