Add parent built-in function (#27)
This commit is contained in:
parent
e8500f5e35
commit
a2f5b4b91d
36
example_parent_test.go
Normal file
36
example_parent_test.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
package stick_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/tyler-sommer/stick"
|
||||
)
|
||||
|
||||
// An example of macro definition and usage.
|
||||
//
|
||||
// This example uses a macro to list the values, also showing two
|
||||
// ways to import macros. Check the templates in the testdata folder
|
||||
// for more information.
|
||||
func ExampleEnv_Execute_parent() {
|
||||
d, _ := os.Getwd()
|
||||
env := stick.New(stick.NewFilesystemLoader(filepath.Join(d, "testdata")))
|
||||
|
||||
err := env.Execute("parent.txt.twig", os.Stdout, nil)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
// Output:
|
||||
// This is a document.
|
||||
//
|
||||
// Not A title
|
||||
//
|
||||
// Testing parent()
|
||||
//
|
||||
// This is a test
|
||||
//
|
||||
// Another section
|
||||
//
|
||||
// Some extra information.
|
||||
}
|
35
exec.go
35
exec.go
|
@ -23,6 +23,7 @@ type state struct {
|
|||
name string // The name of the template.
|
||||
meta *metadata // Additional template metadata.
|
||||
|
||||
current *parse.BlockNode // Current block, may be nil.
|
||||
blocks []map[string]*parse.BlockNode // Block scopes.
|
||||
macros map[string]*parse.MacroNode // Imported macros.
|
||||
|
||||
|
@ -183,6 +184,19 @@ func (s *state) getBlock(name string) *parse.BlockNode {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *state) getParentBlock(name string) *parse.BlockNode {
|
||||
rootFound := false
|
||||
for _, blocks := range s.blocks {
|
||||
if block, ok := blocks[name]; ok {
|
||||
if rootFound {
|
||||
return block
|
||||
}
|
||||
rootFound = true
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Method walk is the main entry-point into template execution.
|
||||
func (s *state) walk(node parse.Node) error {
|
||||
switch node := node.(type) {
|
||||
|
@ -235,6 +249,11 @@ func (s *state) walk(node parse.Node) error {
|
|||
}(s.name)
|
||||
s.name = block.Origin
|
||||
}
|
||||
prev := s.current
|
||||
s.current = block
|
||||
defer func() {
|
||||
s.current = prev
|
||||
}()
|
||||
return s.walk(block.Body)
|
||||
}
|
||||
// TODO: It seems this should never occur.
|
||||
|
@ -691,6 +710,22 @@ func (s *state) evalExpr(exp parse.Expr) (v Value, e error) {
|
|||
func (s *state) evalFunction(exp *parse.FuncExpr) (Value, error) {
|
||||
fnName := exp.Name
|
||||
switch fnName {
|
||||
case "parent":
|
||||
if s.current == nil {
|
||||
return nil, errors.New("not inside a block!")
|
||||
}
|
||||
name := s.current.Name
|
||||
if blk := s.getParentBlock(name); blk != nil {
|
||||
pout := s.out
|
||||
buf := &bytes.Buffer{}
|
||||
s.out = buf
|
||||
if err := s.walk(blk.Body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.out = pout
|
||||
return buf.String(), nil
|
||||
}
|
||||
return nil, errors.New("Unable to locate block \"" + name + "\"")
|
||||
case "block":
|
||||
eargs := exp.Args
|
||||
if len(eargs) != 1 {
|
||||
|
|
17
testdata/parent.txt.twig
vendored
Normal file
17
testdata/parent.txt.twig
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
{% extends 'base.txt.twig' %}
|
||||
|
||||
{% use 'parts.txt.twig' %}
|
||||
|
||||
{% block title %}Not {{ parent() }}{% endblock %}
|
||||
|
||||
{% block intro %}Testing parent(){% endblock %}
|
||||
|
||||
{% block body %}This is a test{% endblock %}
|
||||
|
||||
{% block secondary_title %}{{ parent() }}{% endblock %}
|
||||
|
||||
{% block secondary_body %}{{ parent() }}{% endblock %}
|
||||
|
||||
{% block conclusion %}{% endblock %}
|
||||
|
||||
{% block footer %}{% endblock %}
|
Reference in a new issue