Skip to content

Commit

Permalink
Fixed inverted sections
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Hoisie committed Aug 23, 2010
1 parent ba2a1a8 commit e7ef81d
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 27 deletions.
51 changes: 26 additions & 25 deletions mustache.go
Expand Up @@ -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 {
Expand All @@ -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
}
Expand All @@ -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 {
Expand All @@ -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))
Expand Down
7 changes: 5 additions & 2 deletions mustache_test.go
Expand Up @@ -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"},
Expand All @@ -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) {
Expand Down

0 comments on commit e7ef81d

Please sign in to comment.