mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-27 22:09:53 +02:00
Fix Params case handling in the index, sort and where func
This means that you can now do: ``` {{ range where .Site.Pages "Params.MYPARAM" "foo" }} ```
This commit is contained in:
@@ -19,76 +19,89 @@ import (
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
// Params is a map where all keys are lower case.
|
||||
type Params map[string]interface{}
|
||||
|
||||
// Get does a lower case and nested search in this map.
|
||||
// It will return nil if none found.
|
||||
func (p Params) Get(indices ...string) interface{} {
|
||||
v, _, _ := getNested(p, indices)
|
||||
return v
|
||||
}
|
||||
|
||||
func getNested(m map[string]interface{}, indices []string) (interface{}, string, map[string]interface{}) {
|
||||
if len(indices) == 0 {
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
first := indices[0]
|
||||
v, found := m[strings.ToLower(cast.ToString(first))]
|
||||
if !found {
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
if len(indices) == 1 {
|
||||
return v, first, m
|
||||
}
|
||||
|
||||
switch m2 := v.(type) {
|
||||
case Params:
|
||||
return getNested(m2, indices[1:])
|
||||
case map[string]interface{}:
|
||||
return getNested(m2, indices[1:])
|
||||
default:
|
||||
return nil, "", nil
|
||||
}
|
||||
}
|
||||
|
||||
// GetNestedParam gets the first match of the keyStr in the candidates given.
|
||||
// It will first try the exact match and then try to find it as a nested map value,
|
||||
// using the given separator, e.g. "mymap.name".
|
||||
// It assumes that all the maps given have lower cased keys.
|
||||
func GetNestedParam(keyStr, separator string, candidates ...map[string]interface{}) (interface{}, error) {
|
||||
func GetNestedParam(keyStr, separator string, candidates ...Params) (interface{}, error) {
|
||||
keyStr = strings.ToLower(keyStr)
|
||||
|
||||
lookupFn := func(key string) interface{} {
|
||||
for _, m := range candidates {
|
||||
if v, ok := m[key]; ok {
|
||||
return v
|
||||
}
|
||||
// Try exact match first
|
||||
for _, m := range candidates {
|
||||
if v, ok := m[keyStr]; ok {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
v, _, _, err := GetNestedParamFn(keyStr, separator, lookupFn)
|
||||
return v, err
|
||||
}
|
||||
|
||||
func GetNestedParamFn(keyStr, separator string, lookupFn func(key string) interface{}) (interface{}, string, map[string]interface{}, error) {
|
||||
result, _ := traverseDirectParams(keyStr, lookupFn)
|
||||
if result != nil {
|
||||
return result, keyStr, nil, nil
|
||||
}
|
||||
|
||||
keySegments := strings.Split(keyStr, separator)
|
||||
if len(keySegments) == 1 {
|
||||
return nil, keyStr, nil, nil
|
||||
for _, m := range candidates {
|
||||
if v := m.Get(keySegments...); v != nil {
|
||||
return v, nil
|
||||
}
|
||||
}
|
||||
|
||||
return traverseNestedParams(keySegments, lookupFn)
|
||||
return nil, nil
|
||||
|
||||
}
|
||||
|
||||
func traverseDirectParams(keyStr string, lookupFn func(key string) interface{}) (interface{}, error) {
|
||||
return lookupFn(keyStr), nil
|
||||
}
|
||||
|
||||
func traverseNestedParams(keySegments []string, lookupFn func(key string) interface{}) (interface{}, string, map[string]interface{}, error) {
|
||||
firstKey, rest := keySegments[0], keySegments[1:]
|
||||
result := lookupFn(firstKey)
|
||||
if result == nil || len(rest) == 0 {
|
||||
return result, firstKey, nil, nil
|
||||
}
|
||||
|
||||
switch m := result.(type) {
|
||||
case map[string]interface{}:
|
||||
v, key, owner := traverseParams(rest, m)
|
||||
return v, key, owner, nil
|
||||
default:
|
||||
func GetNestedParamFn(keyStr, separator string, lookupFn func(key string) interface{}) (interface{}, string, map[string]interface{}, error) {
|
||||
keySegments := strings.Split(strings.ToLower(keyStr), separator)
|
||||
if len(keySegments) == 0 {
|
||||
return nil, "", nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func traverseParams(keys []string, m map[string]interface{}) (interface{}, string, map[string]interface{}) {
|
||||
// Shift first element off.
|
||||
firstKey, rest := keys[0], keys[1:]
|
||||
result := m[firstKey]
|
||||
|
||||
// No point in continuing here.
|
||||
if result == nil {
|
||||
return result, "", nil
|
||||
first := lookupFn(keySegments[0])
|
||||
if first == nil {
|
||||
return nil, "", nil, nil
|
||||
}
|
||||
|
||||
if len(rest) == 0 {
|
||||
// That was the last key.
|
||||
return result, firstKey, m
|
||||
if len(keySegments) == 1 {
|
||||
return first, keySegments[0], nil, nil
|
||||
}
|
||||
|
||||
// That was not the last key.
|
||||
return traverseParams(rest, cast.ToStringMap(result))
|
||||
switch m := first.(type) {
|
||||
case map[string]interface{}:
|
||||
v, key, owner := getNested(m, keySegments[1:])
|
||||
return v, key, owner, nil
|
||||
case Params:
|
||||
v, key, owner := getNested(m, keySegments[1:])
|
||||
return v, key, owner, nil
|
||||
}
|
||||
|
||||
return nil, "", nil, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user