diff options
author | Bjørn Erik Pedersen <[email protected]> | 2023-01-04 18:24:36 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <[email protected]> | 2023-05-16 18:01:29 +0200 |
commit | 241b21b0fd34d91fccb2ce69874110dceae6f926 (patch) | |
tree | d4e0118eac7e9c42f065815447a70805f8d6ad3e /navigation | |
parent | 6aededf6b42011c3039f5f66487a89a8dd65e0e7 (diff) | |
download | hugo-241b21b0fd34d91fccb2ce69874110dceae6f926.tar.gz hugo-241b21b0fd34d91fccb2ce69874110dceae6f926.zip |
Create a struct with all of Hugo's config options
Primary motivation is documentation, but it will also hopefully simplify the code.
Also,
* Lower case the default output format names; this is in line with the custom ones (map keys) and how
it's treated all the places. This avoids doing `stringds.EqualFold` everywhere.
Closes #10896
Closes #10620
Diffstat (limited to 'navigation')
-rw-r--r-- | navigation/menu.go | 157 | ||||
-rw-r--r-- | navigation/menu_cache_test.go | 4 | ||||
-rw-r--r-- | navigation/pagemenus.go | 12 |
3 files changed, 89 insertions, 84 deletions
diff --git a/navigation/menu.go b/navigation/menu.go index cb280823c..a5b74b6fa 100644 --- a/navigation/menu.go +++ b/navigation/menu.go @@ -15,14 +15,14 @@ package navigation import ( - "fmt" "html/template" "sort" - "strings" "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/compare" + "github.com/gohugoio/hugo/config" + "github.com/mitchellh/mapstructure" "github.com/spf13/cast" ) @@ -32,44 +32,20 @@ var smc = newMenuCache() // MenuEntry represents a menu item defined in either Page front matter // or in the site config. type MenuEntry struct { - // The URL value from front matter / config. - ConfiguredURL string - - // The Page connected to this menu entry. - Page Page - - // The path to the page, only relevant for menus defined in site config. - PageRef string - - // The name of the menu entry. - Name string + // The menu entry configuration. + MenuConfig // The menu containing this menu entry. Menu string - // Used to identify this menu entry. - Identifier string - - title string - - // If set, will be rendered before this menu entry. - Pre template.HTML - - // If set, will be rendered after this menu entry. - Post template.HTML - - // The weight of this menu entry, used for sorting. - // Set to a non-zero value, negative or positive. - Weight int + // The URL value from front matter / config. + ConfiguredURL string - // Identifier of the parent menu entry. - Parent string + // The Page connected to this menu entry. + Page Page // Child entries. Children Menu - - // User defined params. - Params maps.Params } func (m *MenuEntry) URL() string { @@ -88,9 +64,24 @@ func (m *MenuEntry) URL() string { return m.ConfiguredURL } +// SetPageValues sets the Page and URL values for this menu entry. +func SetPageValues(m *MenuEntry, p Page) { + m.Page = p + if m.MenuConfig.Name == "" { + m.MenuConfig.Name = p.LinkTitle() + } + if m.MenuConfig.Title == "" { + m.MenuConfig.Title = p.Title() + } + if m.MenuConfig.Weight == 0 { + m.MenuConfig.Weight = p.Weight() + } +} + // A narrow version of page.Page. type Page interface { LinkTitle() string + Title() string RelPermalink() string Path() string Section() string @@ -155,46 +146,23 @@ func (m *MenuEntry) isSamePage(p Page) bool { return false } -// For internal use. -func (m *MenuEntry) MarshallMap(ime map[string]any) error { - var err error - for k, v := range ime { - loki := strings.ToLower(k) - switch loki { - case "url": - m.ConfiguredURL = cast.ToString(v) - case "pageref": - m.PageRef = cast.ToString(v) - case "weight": - m.Weight = cast.ToInt(v) - case "name": - m.Name = cast.ToString(v) - case "title": - m.title = cast.ToString(v) - case "pre": - m.Pre = template.HTML(cast.ToString(v)) - case "post": - m.Post = template.HTML(cast.ToString(v)) - case "identifier": - m.Identifier = cast.ToString(v) - case "parent": - m.Parent = cast.ToString(v) - case "params": - var ok bool - m.Params, ok = maps.ToParamsAndPrepare(v) - if !ok { - err = fmt.Errorf("cannot convert %T to Params", v) - } - } - } - - if err != nil { - return fmt.Errorf("failed to marshal menu entry %q: %w", m.KeyName(), err) - } - - return nil +// MenuConfig holds the configuration for a menu. +type MenuConfig struct { + Identifier string + Parent string + Name string + Pre template.HTML + Post template.HTML + URL string + PageRef string + Weight int + Title string + // User defined params. + Params maps.Params } +// For internal use. + // This is for internal use only. func (m Menu) Add(me *MenuEntry) Menu { m = append(m, me) @@ -303,14 +271,49 @@ func (m Menu) Clone() Menu { return append(Menu(nil), m...) } -func (m *MenuEntry) Title() string { - if m.title != "" { - return m.title - } +func DecodeConfig(in any) (*config.ConfigNamespace[map[string]MenuConfig, Menus], error) { + buildConfig := func(in any) (Menus, any, error) { + ret := Menus{} + + if in == nil { + return ret, map[string]any{}, nil + } + + menus, err := maps.ToStringMapE(in) + if err != nil { + return ret, nil, err + } + menus = maps.CleanConfigStringMap(menus) + + for name, menu := range menus { + m, err := cast.ToSliceE(menu) + if err != nil { + return ret, nil, err + } else { + + for _, entry := range m { + var menuConfig MenuConfig + if err := mapstructure.WeakDecode(entry, &menuConfig); err != nil { + return ret, nil, err + } + maps.PrepareParams(menuConfig.Params) + menuEntry := MenuEntry{ + Menu: name, + MenuConfig: menuConfig, + } + menuEntry.ConfiguredURL = menuEntry.MenuConfig.URL + + if ret[name] == nil { + ret[name] = Menu{} + } + ret[name] = ret[name].Add(&menuEntry) + } + } + } + + return ret, menus, nil - if m.Page != nil { - return m.Page.LinkTitle() } - return "" + return config.DecodeNamespace[map[string]MenuConfig](in, buildConfig) } diff --git a/navigation/menu_cache_test.go b/navigation/menu_cache_test.go index 4bb8921bf..9943db517 100644 --- a/navigation/menu_cache_test.go +++ b/navigation/menu_cache_test.go @@ -36,7 +36,7 @@ func TestMenuCache(t *testing.T) { c1 := newMenuCache() changeFirst := func(m Menu) { - m[0].title = "changed" + m[0].MenuConfig.Title = "changed" } var o1 uint64 @@ -73,7 +73,7 @@ func TestMenuCache(t *testing.T) { c.Assert(c3, qt.Equals, !atomic.CompareAndSwapUint64(&o2, uint64(k), uint64(k+1))) l2.Unlock() c.Assert(m3, qt.Not(qt.IsNil)) - c.Assert("changed", qt.Equals, m3[0].title) + c.Assert("changed", qt.Equals, m3[0].Title) } }() } diff --git a/navigation/pagemenus.go b/navigation/pagemenus.go index 7b4f6f648..9c368f3ab 100644 --- a/navigation/pagemenus.go +++ b/navigation/pagemenus.go @@ -18,6 +18,7 @@ import ( "github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/types" + "github.com/mitchellh/mapstructure" "github.com/spf13/cast" ) @@ -54,7 +55,8 @@ func PageMenusFromPage(p Page) (PageMenus, error) { return nil, nil } - me := MenuEntry{Page: p, Name: p.LinkTitle(), Weight: p.Weight()} + me := MenuEntry{} + SetPageValues(&me, p) // Could be the name of the menu to attach it to mname, err := cast.ToStringE(ms) @@ -87,17 +89,17 @@ func PageMenusFromPage(p Page) (PageMenus, error) { } for name, menu := range menus { - menuEntry := MenuEntry{Page: p, Name: p.LinkTitle(), Weight: p.Weight(), Menu: name} + menuEntry := MenuEntry{Menu: name} if menu != nil { ime, err := maps.ToStringMapE(menu) if err != nil { return pm, wrapErr(err) } - - if err = menuEntry.MarshallMap(ime); err != nil { - return pm, wrapErr(err) + if err := mapstructure.WeakDecode(ime, &menuEntry.MenuConfig); err != nil { + return pm, err } } + SetPageValues(&menuEntry, p) pm[name] = &menuEntry } |