mirror of
https://github.com/danog/liquid.git
synced 2024-12-03 12:37:46 +01:00
New top-level Context wrapper
This commit is contained in:
parent
e71bc95d5f
commit
d6bc456ee4
15
context.go
Normal file
15
context.go
Normal 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
|
||||||
|
}
|
@ -47,17 +47,17 @@ func (e engine) ParseTemplate(text []byte) (Template, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ParseAndRender is in the Engine interface.
|
// 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)
|
t, err := e.ParseTemplate(text)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return t.Render(bindings)
|
return t.Render(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseAndRenderString is in the Engine interface.
|
// ParseAndRenderString is in the Engine interface.
|
||||||
func (e engine) ParseAndRenderString(text string, bindings map[string]interface{}) (string, error) {
|
func (e engine) ParseAndRenderString(text string, c Context) (string, error) {
|
||||||
b, err := e.ParseAndRender([]byte(text), bindings)
|
b, err := e.ParseAndRender([]byte(text), c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
27
interface.go
27
interface.go
@ -28,15 +28,34 @@ type Engine interface {
|
|||||||
DefineTag(string, TagDefinition)
|
DefineTag(string, TagDefinition)
|
||||||
DefineStartTag(string, func(io.Writer, chunks.RenderContext) error)
|
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 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 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.
|
// 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 %}",
|
// TagDefinition is the type of a function that parses the argument string "args" from a tag "{% tagname args %}",
|
||||||
// and returns a renderer.
|
// and returns a renderer.
|
||||||
|
@ -16,19 +16,19 @@ var liquidTests = []struct{ in, expected string }{
|
|||||||
{`{{ "upper" | upcase }}`, "UPPER"},
|
{`{{ "upper" | upcase }}`, "UPPER"},
|
||||||
}
|
}
|
||||||
|
|
||||||
var liquidTestScope = map[string]interface{}{
|
var testContext = NewContext(map[string]interface{}{
|
||||||
"x": 123,
|
"x": 123,
|
||||||
"ar": []string{"first", "second", "third"},
|
"ar": []string{"first", "second", "third"},
|
||||||
"page": map[string]interface{}{
|
"page": map[string]interface{}{
|
||||||
"title": "Introduction",
|
"title": "Introduction",
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
|
|
||||||
func TestLiquid(t *testing.T) {
|
func TestLiquid(t *testing.T) {
|
||||||
engine := NewEngine()
|
engine := NewEngine()
|
||||||
for i, test := range liquidTests {
|
for i, test := range liquidTests {
|
||||||
t.Run(fmt.Sprint(i+1), func(t *testing.T) {
|
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.NoErrorf(t, err, test.in)
|
||||||
require.Equalf(t, test.expected, out, test.in)
|
require.Equalf(t, test.expected, out, test.in)
|
||||||
})
|
})
|
||||||
@ -43,7 +43,8 @@ func Example() {
|
|||||||
"title": "Introduction",
|
"title": "Introduction",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
out, err := engine.ParseAndRenderString(template, bindings)
|
context := NewContext(bindings)
|
||||||
|
out, err := engine.ParseAndRenderString(template, context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
18
template.go
18
template.go
@ -6,25 +6,15 @@ import (
|
|||||||
"github.com/osteele/liquid/chunks"
|
"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 {
|
type template struct {
|
||||||
ast chunks.ASTNode
|
ast chunks.ASTNode
|
||||||
settings chunks.Settings
|
settings chunks.Settings
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render executes the template within the bindings environment.
|
// 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)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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.
|
// RenderString is a convenience wrapper for Render, that has string input and output.
|
||||||
func (t *template) RenderString(bindings map[string]interface{}) (string, error) {
|
func (t *template) RenderString(c Context) (string, error) {
|
||||||
b, err := t.Render(bindings)
|
b, err := t.Render(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user