mirror of
https://github.com/danog/liquid.git
synced 2024-11-26 17:24:42 +01:00
Merge pull request #41 from heyvito/feat/cache
Add support to cached templates
This commit is contained in:
commit
26d973c198
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}
|
||||
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
|
||||
}
|
||||
|
@ -99,3 +99,19 @@ func BenchmarkEngine_Parse(b *testing.B) {
|
||||
require.NoError(b, err)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
parser.Config
|
||||
grammar
|
||||
Cache map[string][]byte
|
||||
}
|
||||
|
||||
type grammar struct {
|
||||
@ -21,5 +22,5 @@ func NewConfig() Config {
|
||||
tags: map[string]TagCompiler{},
|
||||
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"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"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) {
|
||||
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
|
||||
}
|
||||
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.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