diff --git a/mustache.go b/mustache.go index 2b2179d..2648d1c 100644 --- a/mustache.go +++ b/mustache.go @@ -315,7 +315,7 @@ func call(v reflect.Value, method reflect.Method) reflect.Value { // Evaluate interfaces and pointers looking for a value that can look up the name, via a // struct field, method, or map key, and return the result of the lookup. func lookup(contextChain *vector.Vector, name string) reflect.Value { - Outer: +Outer: for i := contextChain.Len() - 1; i >= 0; i-- { v := contextChain.At(i).(reflect.Value) for v != nil { @@ -340,17 +340,17 @@ func lookup(contextChain *vector.Vector, name string) reflect.Value { case *reflect.StructValue: ret := av.FieldByName(name) if ret != nil { - return ret - } else { - continue Outer - } + return ret + } else { + continue Outer + } case *reflect.MapValue: ret := av.Elem(reflect.NewValue(name)) if ret != nil { - return ret - } else { - continue Outer - } + return ret + } else { + continue Outer + } default: continue Outer } @@ -359,6 +359,20 @@ func lookup(contextChain *vector.Vector, name string) reflect.Value { return nil } +func isNil(v reflect.Value) bool { + if v == nil || v.Interface() == nil { + return true + } + + valueInd := indirect(v) + switch val := valueInd.(type) { + case *reflect.BoolValue: + return !val.Get() + } + + return false +} + func indirect(v reflect.Value) reflect.Value { loop: for v != nil { @@ -379,25 +393,12 @@ func renderSection(section *sectionElement, contextChain *vector.Vector, buf io. var context = contextChain.At(contextChain.Len() - 1).(reflect.Value) var contexts = new(vector.Vector) // if the value is nil, check if it's an inverted section - if value == nil || value.Interface() == nil { - if section.inverted { - contexts.Push(context) - } else { - return - } + isNil := isNil(value) + if isNil && !section.inverted || !isNil && section.inverted { + return } else { valueInd := indirect(value) switch val := valueInd.(type) { - case *reflect.BoolValue: - if !val.Get() { - if section.inverted { - contexts.Push(context) - } else { - return - } - } else { - contexts.Push(context) - } case *reflect.SliceValue: for i := 0; i < val.Len(); i++ { contexts.Push(val.Elem(i)) diff --git a/mustache_test.go b/mustache_test.go index 918f28a..bb7ad12 100644 --- a/mustache_test.go +++ b/mustache_test.go @@ -116,6 +116,9 @@ var tests = []Test{ //inverted section tests Test{`{{a}}{{^b}}b{{/b}}{{c}}`, map[string]string{"a": "a", "c": "c"}, "abc"}, Test{`{{a}}{{^b}}b{{/b}}{{c}}`, map[string]interface{}{"a": "a", "b": false, "c": "c"}, "abc"}, + Test{`{{^a}}b{{/a}}`, map[string]interface{}{"a": false}, "b"}, + Test{`{{^a}}b{{/a}}`, map[string]interface{}{"a": true}, ""}, + Test{`{{^a}}b{{/a}}`, map[string]interface{}{"a": "nonempty string"}, ""}, //function tests Test{`{{#users}}{{func1}}{{/users}}`, map[string]interface{}{"users": []User{User{"Mike", 1}}}, "Mike"}, @@ -134,8 +137,8 @@ var tests = []Test{ //context chaining Test{`hello {{#section}}{{name}}{{/section}}`, map[string]interface{}{"section": map[string]string{"name": "world"}}, "hello world"}, Test{`hello {{#section}}{{name}}{{/section}}`, map[string]interface{}{"name": "bob", "section": map[string]string{"name": "world"}}, "hello world"}, - Test{`hello {{#bool}}{{#section}}{{name}}{{/section}}{{/bool}}`, map[string]interface{}{"bool":true, "section": map[string]string{"name": "world"}}, "hello world"}, - Test{`{{#users}}{{canvas}}{{/users}}`, map[string]interface{}{"canvas":"hello", "users": []User{User{"Mike", 1}}}, "hello"}, + Test{`hello {{#bool}}{{#section}}{{name}}{{/section}}{{/bool}}`, map[string]interface{}{"bool": true, "section": map[string]string{"name": "world"}}, "hello world"}, + Test{`{{#users}}{{canvas}}{{/users}}`, map[string]interface{}{"canvas": "hello", "users": []User{User{"Mike", 1}}}, "hello"}, } func TestBasic(t *testing.T) {