diff --git a/common/maps/maps.go b/common/maps/maps.go index 79fcc23d..b5e9ba2f 100644 --- a/common/maps/maps.go +++ b/common/maps/maps.go @@ -17,6 +17,8 @@ import ( "fmt" "strings" + "github.com/gohugoio/hugo/common/types" + "github.com/gobwas/glob" "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. +// If in is nil, an empty map is returned. // See PrepareParams. func ToParamsAndPrepare(in interface{}) (Params, bool) { + if types.IsNil(in) { + return Params{}, true + } m, err := ToStringMapE(in) if err != nil { return nil, false diff --git a/common/maps/maps_test.go b/common/maps/maps_test.go index ba3c2508..f0c32b9f 100644 --- a/common/maps/maps_test.go +++ b/common/maps/maps_test.go @@ -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) { c := qt.New(t) diff --git a/hugolib/menu_test.go b/hugolib/menu_test.go index a647c5bf..796ac3be 100644 --- a/hugolib/menu_test.go +++ b/hugolib/menu_test.go @@ -350,6 +350,25 @@ menu: 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) { b := newTestSitesBuilder(t).WithConfigFile("toml", ` [[menus.main]] diff --git a/hugolib/site.go b/hugolib/site.go index e687710b..18c9bfc8 100644 --- a/hugolib/site.go +++ b/hugolib/site.go @@ -1400,17 +1400,25 @@ func (s *Site) getMenusFromConfig() navigation.Menus { s.Log.Errorf("unable to process menus in site config\n") s.Log.Errorln(err) } 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 { s.Log.Debugf("found menu: %q, in site config\n", name) menuEntry := navigation.MenuEntry{Menu: name} ime, err := maps.ToStringMapE(entry) - if err != nil { - s.Log.Errorf("unable to process menus in site config\n") - s.Log.Errorln(err) - } + handleErr(err) + + err = menuEntry.MarshallMap(ime) + handleErr(err) - menuEntry.MarshallMap(ime) // TODO(bep) clean up all of this menuEntry.ConfiguredURL = s.Info.createNodeMenuEntryURL(menuEntry.ConfiguredURL) diff --git a/navigation/menu.go b/navigation/menu.go index dd62f825..b4f5e7af 100644 --- a/navigation/menu.go +++ b/navigation/menu.go @@ -14,10 +14,13 @@ package navigation import ( + "fmt" "html/template" "sort" "strings" + "github.com/pkg/errors" + "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/compare" @@ -65,6 +68,7 @@ func (m *MenuEntry) URL() string { type Page interface { LinkTitle() string RelPermalink() string + Path() string Section() string Weight() int IsPage() bool @@ -127,7 +131,8 @@ func (m *MenuEntry) isSamePage(p Page) bool { 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 { loki := strings.ToLower(k) switch loki { @@ -150,10 +155,19 @@ func (m *MenuEntry) MarshallMap(ime map[string]interface{}) { case "parent": m.Parent = cast.ToString(v) 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 { diff --git a/navigation/pagemenus.go b/navigation/pagemenus.go index f783e30c..46ed5221 100644 --- a/navigation/pagemenus.go +++ b/navigation/pagemenus.go @@ -75,10 +75,14 @@ func PageMenusFromPage(p Page) (PageMenus, error) { 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 menus, err := maps.ToStringMapE(ms) 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 { @@ -86,10 +90,12 @@ func PageMenusFromPage(p Page) (PageMenus, error) { if menu != nil { ime, err := maps.ToStringMapE(menu) 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 }