Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions mustache.go
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,26 @@ Outer:
return v, nil
}
switch av := v; av.Kind() {
case reflect.Func:
typ := av.Type()
// Ensure the function takes one argument and it's a string.
if typ.NumIn() != 1 || typ.In(0).Kind() != reflect.String {
continue Outer
}
out := av.Call([]reflect.Value{reflect.ValueOf(name)})

// We can have either 1 or 2 return values.
if len(out) < 1 || len(out) > 2 {
continue Outer
}

// If we have 2 return values, the second must be a bool and
// represents if the variable exists or not.
if len(out) == 2 && (out[1].Kind() != reflect.Bool || !out[1].Bool()) {
continue Outer
}

return out[0], nil
case reflect.Ptr:
v = av.Elem()
case reflect.Interface:
Expand Down
62 changes: 62 additions & 0 deletions mustache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,68 @@ func TestMultiContext(t *testing.T) {
}
}

func TestDynamic(t *testing.T) {
tmpl := `{{hello}}{{something}}`
lookupFunc := func(name string) (interface{}, bool) {
if name == "hello" {
return "world", true
}

return nil, false
}

output, err := Render(tmpl, lookupFunc)
if err != nil {
t.Fatal(err)
}
expect := "world"
if output != expect {
t.Fatalf("TestLambda expected %q got %q", expect, output)
}
}

func TestSimpleDynamic(t *testing.T) {
tmpl := `{{hello}}{{something}}`
lookupFunc := func(name string) string {
if name == "hello" {
return "world"
}

return ""
}

output, err := Render(tmpl, lookupFunc)
if err != nil {
t.Fatal(err)
}
expect := "world"
if output != expect {
t.Fatalf("TestLambda expected %q got %q", expect, output)
}
}

func TestComplexDynamic(t *testing.T) {
tmpl := `{{hello.world}}{{something}}`
lookupFunc := func(name string) interface{} {
if name == "hello" {
return map[string]string{
"world": "some value",
}
}

return ""
}

output, err := Render(tmpl, lookupFunc)
if err != nil {
t.Fatal(err)
}
expect := "some value"
if output != expect {
t.Fatalf("TestLambda expected %q got %q", expect, output)
}
}

func TestLambda(t *testing.T) {
tmpl := `{{#lambda}}Hello {{name}}. {{#sub}}{{.}} {{/sub}}{{^negsub}}nothing{{/negsub}}{{/lambda}}`
data := map[string]interface{}{
Expand Down