From dc7d8a9eac43760b0cd4599312de9bff072fffd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Wed, 23 Mar 2016 00:29:39 +0100 Subject: [PATCH] Spring cleaning of the menu code --- hugolib/menu.go | 97 ++++++++++++++++++++++++++------------------ hugolib/menu_test.go | 4 +- hugolib/page.go | 2 +- hugolib/site.go | 8 ++-- 4 files changed, 65 insertions(+), 46 deletions(-) diff --git a/hugolib/menu.go b/hugolib/menu.go index 6c3738953..116545a9a 100644 --- a/hugolib/menu.go +++ b/hugolib/menu.go @@ -21,6 +21,8 @@ import ( "github.com/spf13/cast" ) +// MenuEntry represents a menu item defined in either Page front matter +// or in the site config. type MenuEntry struct { URL string Name string @@ -33,67 +35,79 @@ type MenuEntry struct { Children Menu } +// Menu is a collection of menu entries. type Menu []*MenuEntry + +// Menus is a dictionary of menus. type Menus map[string]*Menu + +// PageMenus is a dictionary of menus defined in the Pages. type PageMenus map[string]*MenuEntry -func (me *MenuEntry) AddChild(child *MenuEntry) { - me.Children = append(me.Children, child) - me.Children.Sort() +// addChild adds a new child to this menu entry. +// The default sort order will then be applied. +func (m *MenuEntry) addChild(child *MenuEntry) { + m.Children = append(m.Children, child) + m.Children.Sort() } -func (me *MenuEntry) HasChildren() bool { - return me.Children != nil +// HasChildren returns whether this menu item has any children. +func (m *MenuEntry) HasChildren() bool { + return m.Children != nil } -func (me *MenuEntry) KeyName() string { - if me.Identifier != "" { - return me.Identifier +// KeyName returns the key used to identify this menu entry. +func (m *MenuEntry) KeyName() string { + if m.Identifier != "" { + return m.Identifier } - return me.Name + return m.Name } -func (me *MenuEntry) hopefullyUniqueID() string { - if me.Identifier != "" { - return me.Identifier - } else if me.URL != "" { - return me.URL +func (m *MenuEntry) hopefullyUniqueID() string { + if m.Identifier != "" { + return m.Identifier + } else if m.URL != "" { + return m.URL } else { - return me.Name + return m.Name } } -func (me *MenuEntry) IsEqual(inme *MenuEntry) bool { - return me.hopefullyUniqueID() == inme.hopefullyUniqueID() && me.Parent == inme.Parent +// IsEqual returns whether the two menu entries represents the same menu entry. +func (m *MenuEntry) IsEqual(inme *MenuEntry) bool { + return m.hopefullyUniqueID() == inme.hopefullyUniqueID() && m.Parent == inme.Parent } -func (me *MenuEntry) IsSameResource(inme *MenuEntry) bool { - return me.URL != "" && inme.URL != "" && me.URL == inme.URL +// IsSameResource returns whether the two menu entries points to the same +// resource (URL). +func (m *MenuEntry) IsSameResource(inme *MenuEntry) bool { + return m.URL != "" && inme.URL != "" && m.URL == inme.URL } -func (me *MenuEntry) MarshallMap(ime map[string]interface{}) { +func (m *MenuEntry) marshallMap(ime map[string]interface{}) { for k, v := range ime { loki := strings.ToLower(k) switch loki { case "url": - me.URL = cast.ToString(v) + m.URL = cast.ToString(v) case "weight": - me.Weight = cast.ToInt(v) + m.Weight = cast.ToInt(v) case "name": - me.Name = cast.ToString(v) + m.Name = cast.ToString(v) case "pre": - me.Pre = template.HTML(cast.ToString(v)) + m.Pre = template.HTML(cast.ToString(v)) case "post": - me.Post = template.HTML(cast.ToString(v)) + m.Post = template.HTML(cast.ToString(v)) case "identifier": - me.Identifier = cast.ToString(v) + m.Identifier = cast.ToString(v) case "parent": - me.Parent = cast.ToString(v) + m.Parent = cast.ToString(v) } } } -func (m Menu) Add(me *MenuEntry) Menu { +func (m Menu) add(me *MenuEntry) Menu { app := func(slice Menu, x ...*MenuEntry) Menu { n := len(slice) + len(x) if n > cap(slice) { @@ -120,16 +134,16 @@ func (m Menu) Add(me *MenuEntry) Menu { */ // A type to implement the sort interface for Menu -type MenuSorter struct { +type menuSorter struct { menu Menu - by MenuEntryBy + by menuEntryBy } // Closure used in the Sort.Less method. -type MenuEntryBy func(m1, m2 *MenuEntry) bool +type menuEntryBy func(m1, m2 *MenuEntry) bool -func (by MenuEntryBy) Sort(menu Menu) { - ms := &MenuSorter{ +func (by menuEntryBy) Sort(menu Menu) { + ms := &menuSorter{ menu: menu, by: by, // The Sort method's receiver is the function (closure) that defines the sort order. } @@ -146,17 +160,19 @@ var defaultMenuEntrySort = func(m1, m2 *MenuEntry) bool { return m1.Weight < m2.Weight } -func (ms *MenuSorter) Len() int { return len(ms.menu) } -func (ms *MenuSorter) Swap(i, j int) { ms.menu[i], ms.menu[j] = ms.menu[j], ms.menu[i] } +func (ms *menuSorter) Len() int { return len(ms.menu) } +func (ms *menuSorter) Swap(i, j int) { ms.menu[i], ms.menu[j] = ms.menu[j], ms.menu[i] } // Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter. -func (ms *MenuSorter) Less(i, j int) bool { return ms.by(ms.menu[i], ms.menu[j]) } +func (ms *menuSorter) Less(i, j int) bool { return ms.by(ms.menu[i], ms.menu[j]) } +// Sort sorts the menu by weight, name and then by identifier. func (m Menu) Sort() Menu { - MenuEntryBy(defaultMenuEntrySort).Sort(m) + menuEntryBy(defaultMenuEntrySort).Sort(m) return m } +// Limit limits the returned menu to n entries. func (m Menu) Limit(n int) Menu { if len(m) > n { return m[0:n] @@ -164,20 +180,23 @@ func (m Menu) Limit(n int) Menu { return m } +// ByWeight sorts the menu by the weight defined in the menu configuration. func (m Menu) ByWeight() Menu { - MenuEntryBy(defaultMenuEntrySort).Sort(m) + menuEntryBy(defaultMenuEntrySort).Sort(m) return m } +// ByName sorts the menu by the name defined in the menu configuration. func (m Menu) ByName() Menu { title := func(m1, m2 *MenuEntry) bool { return m1.Name < m2.Name } - MenuEntryBy(title).Sort(m) + menuEntryBy(title).Sort(m) return m } +// Reverse reverses the order of the menu entries. func (m Menu) Reverse() Menu { for i, j := 0, len(m)-1; i < j; i, j = i+1, j-1 { m[i], m[j] = m[j], m[i] diff --git a/hugolib/menu_test.go b/hugolib/menu_test.go index 8e35fd705..609a87d01 100644 --- a/hugolib/menu_test.go +++ b/hugolib/menu_test.go @@ -600,8 +600,8 @@ func TestHopefullyUniqueID(t *testing.T) { func TestAddMenuEntryChild(t *testing.T) { root := &MenuEntry{Weight: 1} - root.AddChild(&MenuEntry{Weight: 2}) - root.AddChild(&MenuEntry{Weight: 1}) + root.addChild(&MenuEntry{Weight: 2}) + root.addChild(&MenuEntry{Weight: 1}) assert.Equal(t, 2, len(root.Children)) assert.Equal(t, 1, root.Children[0].Weight) } diff --git a/hugolib/page.go b/hugolib/page.go index fa403a421..5d1b495f4 100644 --- a/hugolib/page.go +++ b/hugolib/page.go @@ -780,7 +780,7 @@ func (p *Page) Menus() PageMenus { jww.ERROR.Printf("unable to process menus for %q: %s", p.Title, err) } - menuEntry.MarshallMap(ime) + menuEntry.marshallMap(ime) } p.pageMenus[name] = &menuEntry } diff --git a/hugolib/site.go b/hugolib/site.go index 32c013489..6c60af3c5 100644 --- a/hugolib/site.go +++ b/hugolib/site.go @@ -1173,13 +1173,13 @@ func (s *Site) getMenusFromConfig() Menus { jww.ERROR.Println(err) } - menuEntry.MarshallMap(ime) + menuEntry.marshallMap(ime) menuEntry.URL = s.Info.createNodeMenuEntryURL(menuEntry.URL) if ret[name] == nil { ret[name] = &Menu{} } - *ret[name] = ret[name].Add(&menuEntry) + *ret[name] = ret[name].add(&menuEntry) } } } @@ -1249,7 +1249,7 @@ func (s *Site) assembleMenus() { // Create Children Menus First for _, e := range flat { if e.Parent != "" { - children[twoD{e.Menu, e.Parent}] = children[twoD{e.Menu, e.Parent}].Add(e) + children[twoD{e.Menu, e.Parent}] = children[twoD{e.Menu, e.Parent}].add(e) } } @@ -1270,7 +1270,7 @@ func (s *Site) assembleMenus() { if !ok { s.Menus[menu.MenuName] = &Menu{} } - *s.Menus[menu.MenuName] = s.Menus[menu.MenuName].Add(e) + *s.Menus[menu.MenuName] = s.Menus[menu.MenuName].add(e) } } }