From ea529c847ebc0267c6d0426cc8f77d5c76c73fe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Fri, 19 Apr 2019 09:18:12 +0200 Subject: [PATCH] Fix menu URL when multiple permalinkable output formats In Hugo `0.55` we introduced the `permalinkable` config attribute on Output Format, default enabled for `AMP` and `HTML`. This meant that a Page could have different `RelPermalink` and `Permalink` depending on the rendering format. The menu `URL` did not reflect that fact. Fixes #5849 --- hugolib/menu_test.go | 75 ++++++++++++++++++++++++++++++++++++----- hugolib/site.go | 7 ++-- navigation/menu.go | 45 ++++++++++++++++--------- navigation/pagemenus.go | 10 +++--- 4 files changed, 105 insertions(+), 32 deletions(-) diff --git a/hugolib/menu_test.go b/hugolib/menu_test.go index 5c692d2e7..f1db3cb3a 100644 --- a/hugolib/menu_test.go +++ b/hugolib/menu_test.go @@ -92,10 +92,10 @@ Menu Main: {{ partial "menu.html" (dict "page" . "menu" "main") }}`, th.assertFileContent("public/sect1/p1/index.html", "Single", "Menu Sect: "+ - "/sect5/|Section Five||10|-|-|"+ - "/sect1/|Section One||100|-|HasMenuCurrent|"+ - "/sect2/|Sect2s||0|-|-|"+ - "/sect3/|Sect3s||0|-|-|", + "/sect5/|Section Five|Section Five|10|-|-|"+ + "/sect1/|Section One|Section One|100|-|HasMenuCurrent|"+ + "/sect2/|Sect2s|Sect2s|0|-|-|"+ + "/sect3/|Sect3s|Sect3s|0|-|-|", "Menu Main: "+ "/sect3/p5/|p5|atitle5|5|-|-|"+ "/sect2/p4/|p4|atitle4|10|-|-|"+ @@ -106,10 +106,10 @@ Menu Main: {{ partial "menu.html" (dict "page" . "menu" "main") }}`, th.assertFileContent("public/sect2/p3/index.html", "Single", "Menu Sect: "+ - "/sect5/|Section Five||10|-|-|"+ - "/sect1/|Section One||100|-|-|"+ - "/sect2/|Sect2s||0|-|HasMenuCurrent|"+ - "/sect3/|Sect3s||0|-|-|") + "/sect5/|Section Five|Section Five|10|-|-|"+ + "/sect1/|Section One|Section One|100|-|-|"+ + "/sect2/|Sect2s|Sect2s|0|-|HasMenuCurrent|"+ + "/sect3/|Sect3s|Sect3s|0|-|-|") } @@ -163,3 +163,62 @@ menu: ) } + +// https://github.com/gohugoio/hugo/issues/5849 +func TestMenuPageMultipleOutputFormats(t *testing.T) { + + config := ` +baseURL = "https://example.com" + +# DAMP is similar to AMP, but not permalinkable. +[outputFormats] +[outputFormats.damp] +mediaType = "text/html" +path = "damp" + +` + + b := newTestSitesBuilder(t).WithConfigFile("toml", config) + b.WithContent("_index.md", ` +--- +Title: Home Sweet Home +outputs: [ "html", "amp" ] +menu: "main" +--- + +`) + + b.WithContent("blog/html-amp.md", ` +--- +Title: AMP and HTML +outputs: [ "html", "amp" ] +menu: "main" +--- + +`) + + b.WithContent("blog/html.md", ` +--- +Title: HTML only +outputs: [ "html" ] +menu: "main" +--- + +`) + + b.WithContent("blog/amp.md", ` +--- +Title: AMP only +outputs: [ "amp" ] +menu: "main" +--- + +`) + + b.WithTemplatesAdded("index.html", `{{ range .Site.Menus.main }}{{ .Title }}|{{ .URL }}|{{ end }}`) + + b.Build(BuildCfg{}) + + b.AssertFileContent("public/index.html", "AMP and HTML|/blog/html-amp/|AMP only|/amp/blog/amp/|HTML only|/blog/html/|Home Sweet Home|/|") + b.AssertFileContent("public/amp/index.html", "AMP and HTML|/amp/blog/html-amp/|AMP only|/amp/blog/amp/|HTML only|/blog/html/|Home Sweet Home|/amp/|") +} diff --git a/hugolib/site.go b/hugolib/site.go index 693c79f67..495225093 100644 --- a/hugolib/site.go +++ b/hugolib/site.go @@ -1416,7 +1416,8 @@ func (s *Site) getMenusFromConfig() navigation.Menus { } menuEntry.MarshallMap(ime) - menuEntry.URL = s.Info.createNodeMenuEntryURL(menuEntry.URL) + // TODO(bep) clean up all of this + menuEntry.ConfiguredURL = s.Info.createNodeMenuEntryURL(menuEntry.ConfiguredURL) if ret[name] == nil { ret[name] = navigation.Menu{} @@ -1477,7 +1478,7 @@ func (s *Site) assembleMenus() { me := navigation.MenuEntry{Identifier: id, Name: p.LinkTitle(), Weight: p.Weight(), - URL: p.RelPermalink()} + Page: p} flat[twoD{sectionPagesMenu, me.KeyName()}] = &me } } @@ -1506,7 +1507,7 @@ func (s *Site) assembleMenus() { _, ok := flat[twoD{p.MenuName, p.EntryName}] if !ok { // if parent does not exist, create one without a URL - flat[twoD{p.MenuName, p.EntryName}] = &navigation.MenuEntry{Name: p.EntryName, URL: ""} + flat[twoD{p.MenuName, p.EntryName}] = &navigation.MenuEntry{Name: p.EntryName} } flat[twoD{p.MenuName, p.EntryName}].Children = childmenu } diff --git a/navigation/menu.go b/navigation/menu.go index 66721ea8a..47d40a3c7 100644 --- a/navigation/menu.go +++ b/navigation/menu.go @@ -14,6 +14,8 @@ package navigation import ( + "github.com/gohugoio/hugo/common/types" + "html/template" "sort" "strings" @@ -24,17 +26,29 @@ import ( // MenuEntry represents a menu item defined in either Page front matter // or in the site config. type MenuEntry struct { - URL string - Page Page - Name string - Menu string - Identifier string - title string - Pre template.HTML - Post template.HTML - Weight int - Parent string - Children Menu + ConfiguredURL string // The URL value from front matter / config. + Page Page + Name string + Menu string + Identifier string + title string + Pre template.HTML + Post template.HTML + Weight int + Parent string + Children Menu +} + +func (m *MenuEntry) URL() string { + if m.ConfiguredURL != "" { + return m.ConfiguredURL + } + + if !types.IsNil(m.Page) { + return m.Page.RelPermalink() + } + + return "" } // A narrow version of page.Page. @@ -72,8 +86,8 @@ func (m *MenuEntry) KeyName() string { func (m *MenuEntry) hopefullyUniqueID() string { if m.Identifier != "" { return m.Identifier - } else if m.URL != "" { - return m.URL + } else if m.URL() != "" { + return m.URL() } else { return m.Name } @@ -87,7 +101,8 @@ func (m *MenuEntry) IsEqual(inme *MenuEntry) bool { // 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 + murl, inmeurl := m.URL(), inme.URL() + return murl != "" && inmeurl != "" && murl == inmeurl } func (m *MenuEntry) MarshallMap(ime map[string]interface{}) { @@ -95,7 +110,7 @@ func (m *MenuEntry) MarshallMap(ime map[string]interface{}) { loki := strings.ToLower(k) switch loki { case "url": - m.URL = cast.ToString(v) + m.ConfiguredURL = cast.ToString(v) case "weight": m.Weight = cast.ToInt(v) case "name": diff --git a/navigation/pagemenus.go b/navigation/pagemenus.go index c0d809ee3..4d2c45767 100644 --- a/navigation/pagemenus.go +++ b/navigation/pagemenus.go @@ -50,9 +50,7 @@ func PageMenusFromPage(p Page) (PageMenus, error) { return nil, nil } - link := p.RelPermalink() - - me := MenuEntry{Page: p, Name: p.LinkTitle(), Weight: p.Weight(), URL: link} + me := MenuEntry{Page: p, Name: p.LinkTitle(), Weight: p.Weight()} // Could be the name of the menu to attach it to mname, err := cast.ToStringE(ms) @@ -81,7 +79,7 @@ func PageMenusFromPage(p Page) (PageMenus, error) { } for name, menu := range menus { - menuEntry := MenuEntry{Page: p, Name: p.LinkTitle(), URL: link, Weight: p.Weight(), Menu: name} + menuEntry := MenuEntry{Page: p, Name: p.LinkTitle(), Weight: p.Weight(), Menu: name} if menu != nil { ime, err := cast.ToStringMapE(menu) if err != nil { @@ -153,7 +151,7 @@ func (pm *pageMenus) HasMenuCurrent(menuID string, me *MenuEntry) bool { // The following logic is kept from back when Hugo had both Page and Node types. // TODO(bep) consolidate / clean - nme := MenuEntry{Page: pm.p, Name: pm.p.LinkTitle(), URL: pm.p.RelPermalink()} + nme := MenuEntry{Page: pm.p, Name: pm.p.LinkTitle()} for _, child := range me.Children { if nme.IsSameResource(child) { @@ -183,7 +181,7 @@ func (pm *pageMenus) IsMenuCurrent(menuID string, inme *MenuEntry) bool { // The following logic is kept from back when Hugo had both Page and Node types. // TODO(bep) consolidate / clean - me := MenuEntry{Page: pm.p, Name: pm.p.LinkTitle(), URL: pm.p.RelPermalink()} + me := MenuEntry{Page: pm.p, Name: pm.p.LinkTitle()} if !me.IsSameResource(inme) { return false