aboutsummaryrefslogtreecommitdiffhomepage
path: root/navigation
diff options
context:
space:
mode:
Diffstat (limited to 'navigation')
-rw-r--r--navigation/menu.go157
-rw-r--r--navigation/menu_cache_test.go4
-rw-r--r--navigation/pagemenus.go12
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
}