Improve handling of <nil> Params

Fixes #8825
This commit is contained in:
Bjørn Erik Pedersen 2021-07-30 10:56:45 +02:00
parent 268065cb2d
commit e3dc5240f0
6 changed files with 74 additions and 11 deletions

View file

@ -17,6 +17,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/gohugoio/hugo/common/types"
"github.com/gobwas/glob" "github.com/gobwas/glob"
"github.com/spf13/cast" "github.com/spf13/cast"
) )
@ -39,8 +41,12 @@ func ToStringMapE(in interface{}) (map[string]interface{}, error) {
} }
// ToParamsAndPrepare converts in to Params and prepares it for use. // ToParamsAndPrepare converts in to Params and prepares it for use.
// If in is nil, an empty map is returned.
// See PrepareParams. // See PrepareParams.
func ToParamsAndPrepare(in interface{}) (Params, bool) { func ToParamsAndPrepare(in interface{}) (Params, bool) {
if types.IsNil(in) {
return Params{}, true
}
m, err := ToStringMapE(in) m, err := ToStringMapE(in)
if err != nil { if err != nil {
return nil, false return nil, false

View file

@ -114,6 +114,16 @@ func TestToSliceStringMap(t *testing.T) {
} }
} }
func TestToParamsAndPrepare(t *testing.T) {
c := qt.New(t)
_, ok := ToParamsAndPrepare(map[string]interface{}{"A": "av"})
c.Assert(ok, qt.IsTrue)
params, ok := ToParamsAndPrepare(nil)
c.Assert(ok, qt.IsTrue)
c.Assert(params, qt.DeepEquals, Params{})
}
func TestRenameKeys(t *testing.T) { func TestRenameKeys(t *testing.T) {
c := qt.New(t) c := qt.New(t)

View file

@ -350,6 +350,25 @@ menu:
b.AssertFileContent("public/index.html", "A|Children:C|B|") b.AssertFileContent("public/index.html", "A|Children:C|B|")
} }
// Issue #8825
func TestMenuParamsEmptyYaml(t *testing.T) {
b := newTestSitesBuilder(t).WithConfigFile("yaml", `
`)
b.WithTemplates("index.html", `{{ site.Menus }}`)
b.WithContent("p1.md", `---
menus:
main:
identity: journal
weight: 2
params:
---
`)
b.Build(BuildCfg{})
}
func TestMenuParams(t *testing.T) { func TestMenuParams(t *testing.T) {
b := newTestSitesBuilder(t).WithConfigFile("toml", ` b := newTestSitesBuilder(t).WithConfigFile("toml", `
[[menus.main]] [[menus.main]]

View file

@ -1400,17 +1400,25 @@ func (s *Site) getMenusFromConfig() navigation.Menus {
s.Log.Errorf("unable to process menus in site config\n") s.Log.Errorf("unable to process menus in site config\n")
s.Log.Errorln(err) s.Log.Errorln(err)
} else { } else {
handleErr := func(err error) {
if err == nil {
return
}
s.Log.Errorf("unable to process menus in site config\n")
s.Log.Errorln(err)
}
for _, entry := range m { for _, entry := range m {
s.Log.Debugf("found menu: %q, in site config\n", name) s.Log.Debugf("found menu: %q, in site config\n", name)
menuEntry := navigation.MenuEntry{Menu: name} menuEntry := navigation.MenuEntry{Menu: name}
ime, err := maps.ToStringMapE(entry) ime, err := maps.ToStringMapE(entry)
if err != nil { handleErr(err)
s.Log.Errorf("unable to process menus in site config\n")
s.Log.Errorln(err) err = menuEntry.MarshallMap(ime)
} handleErr(err)
menuEntry.MarshallMap(ime)
// TODO(bep) clean up all of this // TODO(bep) clean up all of this
menuEntry.ConfiguredURL = s.Info.createNodeMenuEntryURL(menuEntry.ConfiguredURL) menuEntry.ConfiguredURL = s.Info.createNodeMenuEntryURL(menuEntry.ConfiguredURL)

View file

@ -14,10 +14,13 @@
package navigation package navigation
import ( import (
"fmt"
"html/template" "html/template"
"sort" "sort"
"strings" "strings"
"github.com/pkg/errors"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/compare" "github.com/gohugoio/hugo/compare"
@ -65,6 +68,7 @@ func (m *MenuEntry) URL() string {
type Page interface { type Page interface {
LinkTitle() string LinkTitle() string
RelPermalink() string RelPermalink() string
Path() string
Section() string Section() string
Weight() int Weight() int
IsPage() bool IsPage() bool
@ -127,7 +131,8 @@ func (m *MenuEntry) isSamePage(p Page) bool {
return false return false
} }
func (m *MenuEntry) MarshallMap(ime map[string]interface{}) { func (m *MenuEntry) MarshallMap(ime map[string]interface{}) error {
var err error
for k, v := range ime { for k, v := range ime {
loki := strings.ToLower(k) loki := strings.ToLower(k)
switch loki { switch loki {
@ -150,10 +155,19 @@ func (m *MenuEntry) MarshallMap(ime map[string]interface{}) {
case "parent": case "parent":
m.Parent = cast.ToString(v) m.Parent = cast.ToString(v)
case "params": case "params":
m.Params = maps.MustToParamsAndPrepare(v) var ok bool
m.Params, ok = maps.ToParamsAndPrepare(v)
if !ok {
err = fmt.Errorf("cannot convert %T to Params", v)
}
}
}
if err != nil {
return errors.Wrapf(err, "failed to marshal menu entry %q", m.KeyName())
} }
}
return nil
} }
func (m Menu) Add(me *MenuEntry) Menu { func (m Menu) Add(me *MenuEntry) Menu {

View file

@ -75,10 +75,14 @@ func PageMenusFromPage(p Page) (PageMenus, error) {
return pm, nil return pm, nil
} }
var wrapErr = func(err error) error {
return errors.Wrapf(err, "unable to process menus for page %q", p.Path())
}
// Could be a structured menu entry // Could be a structured menu entry
menus, err := maps.ToStringMapE(ms) menus, err := maps.ToStringMapE(ms)
if err != nil { if err != nil {
return pm, errors.Wrapf(err, "unable to process menus for %q", p.LinkTitle()) return pm, wrapErr(err)
} }
for name, menu := range menus { for name, menu := range menus {
@ -86,10 +90,12 @@ func PageMenusFromPage(p Page) (PageMenus, error) {
if menu != nil { if menu != nil {
ime, err := maps.ToStringMapE(menu) ime, err := maps.ToStringMapE(menu)
if err != nil { if err != nil {
return pm, errors.Wrapf(err, "unable to process menus for %q", p.LinkTitle()) return pm, wrapErr(err)
} }
menuEntry.MarshallMap(ime) if err = menuEntry.MarshallMap(ime); err != nil {
return pm, wrapErr(err)
}
} }
pm[name] = &menuEntry pm[name] = &menuEntry
} }