mirror of
https://github.com/danog/liquid.git
synced 2024-11-30 08:39:01 +01:00
Add support to cached templates
This commit is contained in:
parent
e0ae1590bf
commit
481fd9c7a3
16
engine.go
16
engine.go
@ -110,3 +110,19 @@ func (e *Engine) Delims(objectLeft, objectRight, tagLeft, tagRight string) *Engi
|
|||||||
e.cfg.Delims = []string{objectLeft, objectRight, tagLeft, tagRight}
|
e.cfg.Delims = []string{objectLeft, objectRight, tagLeft, tagRight}
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseTemplateAndCache is the same as ParseTemplateLocation, except that the
|
||||||
|
// source location is used for error reporting and for the {% include %} tag.
|
||||||
|
// If parsing is successful, provided source is then cached, and can be retrieved
|
||||||
|
// by {% include %} tags, as long as there is not a real file in the provided path.
|
||||||
|
//
|
||||||
|
// The path and line number are used for error reporting.
|
||||||
|
// The path is also the reference for relative pathnames in the {% include %} tag.
|
||||||
|
func (e *Engine) ParseTemplateAndCache(source []byte, path string, line int) (*Template, SourceError) {
|
||||||
|
t, err := e.ParseTemplateLocation(source, path, line)
|
||||||
|
if err != nil {
|
||||||
|
return t, err
|
||||||
|
}
|
||||||
|
e.cfg.Cache[path] = source
|
||||||
|
return t, err
|
||||||
|
}
|
||||||
|
@ -92,3 +92,19 @@ func BenchmarkEngine_Parse(b *testing.B) {
|
|||||||
engine.ParseTemplate(s)
|
engine.ParseTemplate(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEngine_ParseTemplateAndCache(t *testing.T) {
|
||||||
|
// Given two templates...
|
||||||
|
templateA := []byte("Foo")
|
||||||
|
templateB := []byte(`{% include "template_a.html" %}, Bar`)
|
||||||
|
|
||||||
|
// Cache the first
|
||||||
|
eng := NewEngine()
|
||||||
|
_, err := eng.ParseTemplateAndCache(templateA, "template_a.html", 1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// ...and execute the second.
|
||||||
|
result, err := eng.ParseAndRender(templateB, Bindings{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, string(result), "Foo, Bar")
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
parser.Config
|
parser.Config
|
||||||
grammar
|
grammar
|
||||||
|
Cache map[string][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type grammar struct {
|
type grammar struct {
|
||||||
@ -21,5 +22,5 @@ func NewConfig() Config {
|
|||||||
tags: map[string]TagCompiler{},
|
tags: map[string]TagCompiler{},
|
||||||
blockDefs: map[string]*blockSyntax{},
|
blockDefs: map[string]*blockSyntax{},
|
||||||
}
|
}
|
||||||
return Config{parser.NewConfig(g), g}
|
return Config{Config: parser.NewConfig(g), grammar: g, Cache: map[string][]byte{}}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/osteele/liquid/expressions"
|
"github.com/osteele/liquid/expressions"
|
||||||
@ -111,7 +112,14 @@ func (c rendererContext) RenderChildren(w io.Writer) Error {
|
|||||||
|
|
||||||
func (c rendererContext) RenderFile(filename string, b map[string]interface{}) (string, error) {
|
func (c rendererContext) RenderFile(filename string, b map[string]interface{}) (string, error) {
|
||||||
source, err := ioutil.ReadFile(filename)
|
source, err := ioutil.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil && os.IsNotExist(err) {
|
||||||
|
// Is it cached?
|
||||||
|
if cval, ok := c.ctx.config.Cache[filename]; ok {
|
||||||
|
source = cval
|
||||||
|
} else {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
} else if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
root, err := c.ctx.config.Compile(string(source), c.node.SourceLoc)
|
root, err := c.ctx.config.Compile(string(source), c.node.SourceLoc)
|
||||||
|
@ -58,3 +58,18 @@ func TestIncludeTag_file_not_found_error(t *testing.T) {
|
|||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.True(t, os.IsNotExist(err.Cause()))
|
require.True(t, os.IsNotExist(err.Cause()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIncludeTag_cached_value_handling(t *testing.T) {
|
||||||
|
config := render.NewConfig()
|
||||||
|
// foo.html does not exist on testdata.
|
||||||
|
config.Cache["testdata/foo.html"] = []byte("bar")
|
||||||
|
loc := parser.SourceLoc{Pathname: "testdata/include_source.html", LineNo: 1}
|
||||||
|
AddStandardTags(config)
|
||||||
|
|
||||||
|
root, err := config.Compile(`{% include "foo.html" %}`, loc)
|
||||||
|
require.NoError(t, err)
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
err = render.Render(root, buf, includeTestBindings, config)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "bar", strings.TrimSpace(buf.String()))
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user