mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
hugolib: Finish menu vs section content pages
This commit also fixes the default menu sort when the weight is 0. Closes #2974
This commit is contained in:
parent
2a6b26a7a5
commit
a3af4fe46e
9 changed files with 817 additions and 705 deletions
|
@ -167,6 +167,7 @@ func (h *HugoSites) assemble(config *BuildCfg) error {
|
|||
}
|
||||
|
||||
for _, s := range h.Sites {
|
||||
s.assembleMenus()
|
||||
s.refreshPageCaches()
|
||||
s.setupSitePages()
|
||||
}
|
||||
|
|
|
@ -1235,11 +1235,11 @@ lag:
|
|||
return sites
|
||||
}
|
||||
|
||||
func writeSource(t *testing.T, fs *hugofs.Fs, filename, content string) {
|
||||
func writeSource(t testing.TB, fs *hugofs.Fs, filename, content string) {
|
||||
writeToFs(t, fs.Source, filename, content)
|
||||
}
|
||||
|
||||
func writeToFs(t *testing.T, fs afero.Fs, filename, content string) {
|
||||
func writeToFs(t testing.TB, fs afero.Fs, filename, content string) {
|
||||
if err := afero.WriteFile(fs, filepath.FromSlash(filename), []byte(content), 0755); err != nil {
|
||||
t.Fatalf("Failed to write file: %s", err)
|
||||
}
|
||||
|
|
|
@ -157,6 +157,15 @@ var defaultMenuEntrySort = func(m1, m2 *MenuEntry) bool {
|
|||
}
|
||||
return m1.Name < m2.Name
|
||||
}
|
||||
|
||||
if m2.Weight == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
if m1.Weight == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return m1.Weight < m2.Weight
|
||||
}
|
||||
|
||||
|
|
693
hugolib/menu_old_test.go
Normal file
693
hugolib/menu_old_test.go
Normal file
|
@ -0,0 +1,693 @@
|
|||
// Copyright 2016 The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package hugolib
|
||||
|
||||
// TODO(bep) remove this file when the reworked tests in menu_test.go is done.
|
||||
// NOTE: Do not add more tests to this file!
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/hugo/deps"
|
||||
|
||||
"path/filepath"
|
||||
|
||||
toml "github.com/pelletier/go-toml"
|
||||
"github.com/spf13/hugo/source"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
confMenu1 = `
|
||||
[[menu.main]]
|
||||
name = "Go Home"
|
||||
url = "/"
|
||||
weight = 1
|
||||
pre = "<div>"
|
||||
post = "</div>"
|
||||
[[menu.main]]
|
||||
name = "Blog"
|
||||
url = "/posts"
|
||||
[[menu.main]]
|
||||
name = "ext"
|
||||
url = "http://gohugo.io"
|
||||
identifier = "ext"
|
||||
[[menu.main]]
|
||||
name = "ext2"
|
||||
url = "http://foo.local/Zoo/foo"
|
||||
identifier = "ext2"
|
||||
[[menu.grandparent]]
|
||||
name = "grandparent"
|
||||
url = "/grandparent"
|
||||
identifier = "grandparentId"
|
||||
[[menu.grandparent]]
|
||||
name = "parent"
|
||||
url = "/parent"
|
||||
identifier = "parentId"
|
||||
parent = "grandparentId"
|
||||
[[menu.grandparent]]
|
||||
name = "Go Home3"
|
||||
url = "/"
|
||||
identifier = "grandchildId"
|
||||
parent = "parentId"
|
||||
[[menu.tax]]
|
||||
name = "Tax1"
|
||||
url = "/two/key/"
|
||||
identifier="1"
|
||||
[[menu.tax]]
|
||||
name = "Tax2"
|
||||
url = "/two/key/"
|
||||
identifier="2"
|
||||
[[menu.tax]]
|
||||
name = "Tax RSS"
|
||||
url = "/two/key.xml"
|
||||
identifier="xml"
|
||||
[[menu.hash]]
|
||||
name = "Tax With #"
|
||||
url = "/resource#anchor"
|
||||
identifier="hash"
|
||||
[[menu.unicode]]
|
||||
name = "Unicode Russian"
|
||||
identifier = "unicode-russian"
|
||||
url = "/новости-проекта"` // Russian => "news-project"
|
||||
)
|
||||
|
||||
var menuPage1 = []byte(`+++
|
||||
title = "One"
|
||||
weight = 1
|
||||
[menu]
|
||||
[menu.p_one]
|
||||
+++
|
||||
Front Matter with Menu Pages`)
|
||||
|
||||
var menuPage2 = []byte(`+++
|
||||
title = "Two"
|
||||
weight = 2
|
||||
[menu]
|
||||
[menu.p_one]
|
||||
[menu.p_two]
|
||||
identifier = "Two"
|
||||
|
||||
+++
|
||||
Front Matter with Menu Pages`)
|
||||
|
||||
var menuPage3 = []byte(`+++
|
||||
title = "Three"
|
||||
weight = 3
|
||||
[menu]
|
||||
[menu.p_two]
|
||||
Name = "Three"
|
||||
Parent = "Two"
|
||||
+++
|
||||
Front Matter with Menu Pages`)
|
||||
|
||||
var menuPage4 = []byte(`+++
|
||||
title = "Four"
|
||||
weight = 4
|
||||
[menu]
|
||||
[menu.p_two]
|
||||
Name = "Four"
|
||||
Parent = "Three"
|
||||
+++
|
||||
Front Matter with Menu Pages`)
|
||||
|
||||
var menuPageSources = []source.ByteSource{
|
||||
{Name: filepath.FromSlash("sect/doc1.md"), Content: menuPage1},
|
||||
{Name: filepath.FromSlash("sect/doc2.md"), Content: menuPage2},
|
||||
{Name: filepath.FromSlash("sect/doc3.md"), Content: menuPage3},
|
||||
}
|
||||
|
||||
var menuPageSectionsSources = []source.ByteSource{
|
||||
{Name: filepath.FromSlash("first/doc1.md"), Content: menuPage1},
|
||||
{Name: filepath.FromSlash("first/doc2.md"), Content: menuPage2},
|
||||
{Name: filepath.FromSlash("second-section/doc3.md"), Content: menuPage3},
|
||||
{Name: filepath.FromSlash("Fish and Chips/doc4.md"), Content: menuPage4},
|
||||
}
|
||||
|
||||
func tstCreateMenuPageWithNameTOML(title, menu, name string) []byte {
|
||||
return []byte(fmt.Sprintf(`+++
|
||||
title = "%s"
|
||||
weight = 1
|
||||
[menu]
|
||||
[menu.%s]
|
||||
name = "%s"
|
||||
+++
|
||||
Front Matter with Menu with Name`, title, menu, name))
|
||||
}
|
||||
|
||||
func tstCreateMenuPageWithIdentifierTOML(title, menu, identifier string) []byte {
|
||||
return []byte(fmt.Sprintf(`+++
|
||||
title = "%s"
|
||||
weight = 1
|
||||
[menu]
|
||||
[menu.%s]
|
||||
identifier = "%s"
|
||||
name = "somename"
|
||||
+++
|
||||
Front Matter with Menu with Identifier`, title, menu, identifier))
|
||||
}
|
||||
|
||||
func tstCreateMenuPageWithNameYAML(title, menu, name string) []byte {
|
||||
return []byte(fmt.Sprintf(`---
|
||||
title: "%s"
|
||||
weight: 1
|
||||
menu:
|
||||
%s:
|
||||
name: "%s"
|
||||
---
|
||||
Front Matter with Menu with Name`, title, menu, name))
|
||||
}
|
||||
|
||||
func tstCreateMenuPageWithIdentifierYAML(title, menu, identifier string) []byte {
|
||||
return []byte(fmt.Sprintf(`---
|
||||
title: "%s"
|
||||
weight: 1
|
||||
menu:
|
||||
%s:
|
||||
identifier: "%s"
|
||||
name: "somename"
|
||||
---
|
||||
Front Matter with Menu with Identifier`, title, menu, identifier))
|
||||
}
|
||||
|
||||
// Issue 817 - identifier should trump everything
|
||||
func TestPageMenuWithIdentifier(t *testing.T) {
|
||||
t.Parallel()
|
||||
toml := []source.ByteSource{
|
||||
{Name: "sect/doc1.md", Content: tstCreateMenuPageWithIdentifierTOML("t1", "m1", "i1")},
|
||||
{Name: "sect/doc2.md", Content: tstCreateMenuPageWithIdentifierTOML("t1", "m1", "i2")},
|
||||
{Name: "sect/doc3.md", Content: tstCreateMenuPageWithIdentifierTOML("t1", "m1", "i2")}, // duplicate
|
||||
}
|
||||
|
||||
yaml := []source.ByteSource{
|
||||
{Name: "sect/doc1.md", Content: tstCreateMenuPageWithIdentifierYAML("t1", "m1", "i1")},
|
||||
{Name: "sect/doc2.md", Content: tstCreateMenuPageWithIdentifierYAML("t1", "m1", "i2")},
|
||||
{Name: "sect/doc3.md", Content: tstCreateMenuPageWithIdentifierYAML("t1", "m1", "i2")}, // duplicate
|
||||
}
|
||||
|
||||
doTestPageMenuWithIdentifier(t, toml)
|
||||
doTestPageMenuWithIdentifier(t, yaml)
|
||||
|
||||
}
|
||||
|
||||
func doTestPageMenuWithIdentifier(t *testing.T, menuPageSources []source.ByteSource) {
|
||||
|
||||
s := setupMenuTests(t, menuPageSources)
|
||||
|
||||
assert.Equal(t, 3, len(s.RegularPages), "Not enough pages")
|
||||
|
||||
me1 := findTestMenuEntryByID(s, "m1", "i1")
|
||||
me2 := findTestMenuEntryByID(s, "m1", "i2")
|
||||
|
||||
require.NotNil(t, me1)
|
||||
require.NotNil(t, me2)
|
||||
|
||||
assert.True(t, strings.Contains(me1.URL, "doc1"), me1.URL)
|
||||
assert.True(t, strings.Contains(me2.URL, "doc2") || strings.Contains(me2.URL, "doc3"), me2.URL)
|
||||
|
||||
}
|
||||
|
||||
// Issue 817 contd - name should be second identifier in
|
||||
func TestPageMenuWithDuplicateName(t *testing.T) {
|
||||
t.Parallel()
|
||||
toml := []source.ByteSource{
|
||||
{Name: "sect/doc1.md", Content: tstCreateMenuPageWithNameTOML("t1", "m1", "n1")},
|
||||
{Name: "sect/doc2.md", Content: tstCreateMenuPageWithNameTOML("t1", "m1", "n2")},
|
||||
{Name: "sect/doc3.md", Content: tstCreateMenuPageWithNameTOML("t1", "m1", "n2")}, // duplicate
|
||||
}
|
||||
|
||||
yaml := []source.ByteSource{
|
||||
{Name: "sect/doc1.md", Content: tstCreateMenuPageWithNameYAML("t1", "m1", "n1")},
|
||||
{Name: "sect/doc2.md", Content: tstCreateMenuPageWithNameYAML("t1", "m1", "n2")},
|
||||
{Name: "sect/doc3.md", Content: tstCreateMenuPageWithNameYAML("t1", "m1", "n2")}, // duplicate
|
||||
}
|
||||
|
||||
doTestPageMenuWithDuplicateName(t, toml)
|
||||
doTestPageMenuWithDuplicateName(t, yaml)
|
||||
|
||||
}
|
||||
|
||||
func doTestPageMenuWithDuplicateName(t *testing.T, menuPageSources []source.ByteSource) {
|
||||
|
||||
s := setupMenuTests(t, menuPageSources)
|
||||
|
||||
assert.Equal(t, 3, len(s.RegularPages), "Not enough pages")
|
||||
|
||||
me1 := findTestMenuEntryByName(s, "m1", "n1")
|
||||
me2 := findTestMenuEntryByName(s, "m1", "n2")
|
||||
|
||||
require.NotNil(t, me1)
|
||||
require.NotNil(t, me2)
|
||||
|
||||
assert.True(t, strings.Contains(me1.URL, "doc1"), me1.URL)
|
||||
assert.True(t, strings.Contains(me2.URL, "doc2") || strings.Contains(me2.URL, "doc3"), me2.URL)
|
||||
|
||||
}
|
||||
|
||||
func TestPageMenu(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := setupMenuTests(t, menuPageSources)
|
||||
|
||||
if len(s.RegularPages) != 3 {
|
||||
t.Fatalf("Posts not created, expected 3 got %d", len(s.RegularPages))
|
||||
}
|
||||
|
||||
first := s.RegularPages[0]
|
||||
second := s.RegularPages[1]
|
||||
third := s.RegularPages[2]
|
||||
|
||||
pOne := findTestMenuEntryByName(s, "p_one", "One")
|
||||
pTwo := findTestMenuEntryByID(s, "p_two", "Two")
|
||||
|
||||
for i, this := range []struct {
|
||||
menu string
|
||||
page *Page
|
||||
menuItem *MenuEntry
|
||||
isMenuCurrent bool
|
||||
hasMenuCurrent bool
|
||||
}{
|
||||
{"p_one", first, pOne, true, false},
|
||||
{"p_one", first, pTwo, false, false},
|
||||
{"p_one", second, pTwo, false, false},
|
||||
{"p_two", second, pTwo, true, false},
|
||||
{"p_two", third, pTwo, false, true},
|
||||
{"p_one", third, pTwo, false, false},
|
||||
} {
|
||||
|
||||
if i != 4 {
|
||||
continue
|
||||
}
|
||||
|
||||
isMenuCurrent := this.page.IsMenuCurrent(this.menu, this.menuItem)
|
||||
hasMenuCurrent := this.page.HasMenuCurrent(this.menu, this.menuItem)
|
||||
|
||||
if isMenuCurrent != this.isMenuCurrent {
|
||||
t.Errorf("[%d] Wrong result from IsMenuCurrent: %v", i, isMenuCurrent)
|
||||
}
|
||||
|
||||
if hasMenuCurrent != this.hasMenuCurrent {
|
||||
t.Errorf("[%d] Wrong result for menuItem %v for HasMenuCurrent: %v", i, this.menuItem, hasMenuCurrent)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestMenuURL(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := setupMenuTests(t, menuPageSources)
|
||||
|
||||
for i, this := range []struct {
|
||||
me *MenuEntry
|
||||
expectedURL string
|
||||
}{
|
||||
// issue #888
|
||||
{findTestMenuEntryByID(s, "hash", "hash"), "/Zoo/resource#anchor"},
|
||||
// issue #1774
|
||||
{findTestMenuEntryByID(s, "main", "ext"), "http://gohugo.io"},
|
||||
{findTestMenuEntryByID(s, "main", "ext2"), "http://foo.local/Zoo/foo"},
|
||||
} {
|
||||
|
||||
if this.me == nil {
|
||||
t.Errorf("[%d] MenuEntry not found", i)
|
||||
continue
|
||||
}
|
||||
|
||||
if this.me.URL != this.expectedURL {
|
||||
t.Errorf("[%d] Got URL %s expected %s", i, this.me.URL, this.expectedURL)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Issue #1934
|
||||
func TestYAMLMenuWithMultipleEntries(t *testing.T) {
|
||||
t.Parallel()
|
||||
ps1 := []byte(`---
|
||||
title: "Yaml 1"
|
||||
weight: 5
|
||||
menu: ["p_one", "p_two"]
|
||||
---
|
||||
Yaml Front Matter with Menu Pages`)
|
||||
|
||||
ps2 := []byte(`---
|
||||
title: "Yaml 2"
|
||||
weight: 5
|
||||
menu:
|
||||
p_three:
|
||||
p_four:
|
||||
---
|
||||
Yaml Front Matter with Menu Pages`)
|
||||
|
||||
s := setupMenuTests(t, []source.ByteSource{
|
||||
{Name: filepath.FromSlash("sect/yaml1.md"), Content: ps1},
|
||||
{Name: filepath.FromSlash("sect/yaml2.md"), Content: ps2}})
|
||||
|
||||
p1 := s.RegularPages[0]
|
||||
assert.Len(t, p1.Menus(), 2, "List YAML")
|
||||
p2 := s.RegularPages[1]
|
||||
assert.Len(t, p2.Menus(), 2, "Map YAML")
|
||||
|
||||
}
|
||||
|
||||
// issue #719
|
||||
func TestMenuWithUnicodeURLs(t *testing.T) {
|
||||
t.Parallel()
|
||||
for _, canonifyURLs := range []bool{true, false} {
|
||||
doTestMenuWithUnicodeURLs(t, canonifyURLs)
|
||||
}
|
||||
}
|
||||
|
||||
func doTestMenuWithUnicodeURLs(t *testing.T, canonifyURLs bool) {
|
||||
|
||||
s := setupMenuTests(t, menuPageSources, "canonifyURLs", canonifyURLs)
|
||||
|
||||
unicodeRussian := findTestMenuEntryByID(s, "unicode", "unicode-russian")
|
||||
|
||||
expected := "/%D0%BD%D0%BE%D0%B2%D0%BE%D1%81%D1%82%D0%B8-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B0"
|
||||
|
||||
if !canonifyURLs {
|
||||
expected = "/Zoo" + expected
|
||||
}
|
||||
|
||||
assert.Equal(t, expected, unicodeRussian.URL)
|
||||
}
|
||||
|
||||
// Issue #1114
|
||||
func TestSectionPagesMenu2(t *testing.T) {
|
||||
t.Parallel()
|
||||
doTestSectionPagesMenu(true, t)
|
||||
doTestSectionPagesMenu(false, t)
|
||||
}
|
||||
|
||||
func doTestSectionPagesMenu(canonifyURLs bool, t *testing.T) {
|
||||
|
||||
s := setupMenuTests(t, menuPageSectionsSources,
|
||||
"sectionPagesMenu", "spm",
|
||||
"canonifyURLs", canonifyURLs,
|
||||
)
|
||||
|
||||
require.Equal(t, 3, len(s.Sections))
|
||||
|
||||
firstSectionPages := s.Sections["first"]
|
||||
require.Equal(t, 2, len(firstSectionPages))
|
||||
secondSectionPages := s.Sections["second-section"]
|
||||
require.Equal(t, 1, len(secondSectionPages))
|
||||
fishySectionPages := s.Sections["fish-and-chips"]
|
||||
require.Equal(t, 1, len(fishySectionPages))
|
||||
|
||||
nodeFirst := s.getPage(KindSection, "first")
|
||||
require.NotNil(t, nodeFirst)
|
||||
nodeSecond := s.getPage(KindSection, "second-section")
|
||||
require.NotNil(t, nodeSecond)
|
||||
nodeFishy := s.getPage(KindSection, "fish-and-chips")
|
||||
require.Equal(t, "fish-and-chips", nodeFishy.sections[0])
|
||||
|
||||
firstSectionMenuEntry := findTestMenuEntryByID(s, "spm", "first")
|
||||
secondSectionMenuEntry := findTestMenuEntryByID(s, "spm", "second-section")
|
||||
fishySectionMenuEntry := findTestMenuEntryByID(s, "spm", "fish-and-chips")
|
||||
|
||||
require.NotNil(t, firstSectionMenuEntry)
|
||||
require.NotNil(t, secondSectionMenuEntry)
|
||||
require.NotNil(t, nodeFirst)
|
||||
require.NotNil(t, nodeSecond)
|
||||
require.NotNil(t, fishySectionMenuEntry)
|
||||
require.NotNil(t, nodeFishy)
|
||||
|
||||
require.True(t, nodeFirst.IsMenuCurrent("spm", firstSectionMenuEntry))
|
||||
require.False(t, nodeFirst.IsMenuCurrent("spm", secondSectionMenuEntry))
|
||||
require.False(t, nodeFirst.IsMenuCurrent("spm", fishySectionMenuEntry))
|
||||
require.True(t, nodeFishy.IsMenuCurrent("spm", fishySectionMenuEntry))
|
||||
require.Equal(t, "Fish and Chips", fishySectionMenuEntry.Name)
|
||||
|
||||
for _, p := range firstSectionPages {
|
||||
require.True(t, p.Page.HasMenuCurrent("spm", firstSectionMenuEntry))
|
||||
require.False(t, p.Page.HasMenuCurrent("spm", secondSectionMenuEntry))
|
||||
}
|
||||
|
||||
for _, p := range secondSectionPages {
|
||||
require.False(t, p.Page.HasMenuCurrent("spm", firstSectionMenuEntry))
|
||||
require.True(t, p.Page.HasMenuCurrent("spm", secondSectionMenuEntry))
|
||||
}
|
||||
|
||||
for _, p := range fishySectionPages {
|
||||
require.False(t, p.Page.HasMenuCurrent("spm", firstSectionMenuEntry))
|
||||
require.False(t, p.Page.HasMenuCurrent("spm", secondSectionMenuEntry))
|
||||
require.True(t, p.Page.HasMenuCurrent("spm", fishySectionMenuEntry))
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaxonomyNodeMenu(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type taxRenderInfo struct {
|
||||
key string
|
||||
singular string
|
||||
plural string
|
||||
}
|
||||
|
||||
s := setupMenuTests(t, menuPageSources, "canonifyURLs", true)
|
||||
|
||||
for i, this := range []struct {
|
||||
menu string
|
||||
taxInfo taxRenderInfo
|
||||
menuItem *MenuEntry
|
||||
isMenuCurrent bool
|
||||
hasMenuCurrent bool
|
||||
}{
|
||||
{"tax", taxRenderInfo{key: "key", singular: "one", plural: "two"},
|
||||
findTestMenuEntryByID(s, "tax", "1"), true, false},
|
||||
{"tax", taxRenderInfo{key: "key", singular: "one", plural: "two"},
|
||||
findTestMenuEntryByID(s, "tax", "2"), true, false},
|
||||
{"tax", taxRenderInfo{key: "key", singular: "one", plural: "two"},
|
||||
&MenuEntry{Name: "Somewhere else", URL: "/somewhereelse"}, false, false},
|
||||
} {
|
||||
|
||||
p := s.newTaxonomyPage(this.taxInfo.plural, this.taxInfo.key)
|
||||
|
||||
isMenuCurrent := p.IsMenuCurrent(this.menu, this.menuItem)
|
||||
hasMenuCurrent := p.HasMenuCurrent(this.menu, this.menuItem)
|
||||
|
||||
if isMenuCurrent != this.isMenuCurrent {
|
||||
t.Errorf("[%d] Wrong result from IsMenuCurrent: %v", i, isMenuCurrent)
|
||||
}
|
||||
|
||||
if hasMenuCurrent != this.hasMenuCurrent {
|
||||
t.Errorf("[%d] Wrong result for menuItem %v for HasMenuCurrent: %v", i, this.menuItem, hasMenuCurrent)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
menuEntryXML := findTestMenuEntryByID(s, "tax", "xml")
|
||||
|
||||
if strings.HasSuffix(menuEntryXML.URL, "/") {
|
||||
t.Error("RSS menu item should not be padded with trailing slash")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMenuLimit(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := setupMenuTests(t, menuPageSources)
|
||||
m := *s.Menus["main"]
|
||||
|
||||
// main menu has 4 entries
|
||||
firstTwo := m.Limit(2)
|
||||
assert.Equal(t, 2, len(firstTwo))
|
||||
for i := 0; i < 2; i++ {
|
||||
assert.Equal(t, m[i], firstTwo[i])
|
||||
}
|
||||
assert.Equal(t, m, m.Limit(4))
|
||||
assert.Equal(t, m, m.Limit(5))
|
||||
}
|
||||
|
||||
func TestMenuSortByN(t *testing.T) {
|
||||
t.Parallel()
|
||||
for i, this := range []struct {
|
||||
sortFunc func(p Menu) Menu
|
||||
assertFunc func(p Menu) bool
|
||||
}{
|
||||
{(Menu).Sort, func(p Menu) bool { return p[0].Weight == 1 && p[1].Name == "nx" && p[2].Identifier == "ib" }},
|
||||
{(Menu).ByWeight, func(p Menu) bool { return p[0].Weight == 1 && p[1].Name == "nx" && p[2].Identifier == "ib" }},
|
||||
{(Menu).ByName, func(p Menu) bool { return p[0].Name == "na" }},
|
||||
{(Menu).Reverse, func(p Menu) bool { return p[0].Identifier == "ib" && p[len(p)-1].Identifier == "ia" }},
|
||||
} {
|
||||
menu := Menu{&MenuEntry{Weight: 3, Name: "nb", Identifier: "ia"},
|
||||
&MenuEntry{Weight: 1, Name: "na", Identifier: "ic"},
|
||||
&MenuEntry{Weight: 1, Name: "nx", Identifier: "ic"},
|
||||
&MenuEntry{Weight: 2, Name: "nb", Identifier: "ix"},
|
||||
&MenuEntry{Weight: 2, Name: "nb", Identifier: "ib"}}
|
||||
|
||||
sorted := this.sortFunc(menu)
|
||||
|
||||
if !this.assertFunc(sorted) {
|
||||
t.Errorf("[%d] sort error", i)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestHomeNodeMenu(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := setupMenuTests(t, menuPageSources,
|
||||
"canonifyURLs", true,
|
||||
"uglyURLs", false,
|
||||
)
|
||||
|
||||
home := s.getPage(KindHome)
|
||||
homeMenuEntry := &MenuEntry{Name: home.Title, URL: home.URL()}
|
||||
|
||||
for i, this := range []struct {
|
||||
menu string
|
||||
menuItem *MenuEntry
|
||||
isMenuCurrent bool
|
||||
hasMenuCurrent bool
|
||||
}{
|
||||
{"main", homeMenuEntry, true, false},
|
||||
{"doesnotexist", homeMenuEntry, false, false},
|
||||
{"main", &MenuEntry{Name: "Somewhere else", URL: "/somewhereelse"}, false, false},
|
||||
{"grandparent", findTestMenuEntryByID(s, "grandparent", "grandparentId"), false, true},
|
||||
{"grandparent", findTestMenuEntryByID(s, "grandparent", "parentId"), false, true},
|
||||
{"grandparent", findTestMenuEntryByID(s, "grandparent", "grandchildId"), true, false},
|
||||
} {
|
||||
|
||||
isMenuCurrent := home.IsMenuCurrent(this.menu, this.menuItem)
|
||||
hasMenuCurrent := home.HasMenuCurrent(this.menu, this.menuItem)
|
||||
|
||||
if isMenuCurrent != this.isMenuCurrent {
|
||||
fmt.Println("isMenuCurrent", isMenuCurrent)
|
||||
fmt.Printf("this: %#v\n", this)
|
||||
t.Errorf("[%d] Wrong result from IsMenuCurrent: %v for %q", i, isMenuCurrent, this.menuItem)
|
||||
}
|
||||
|
||||
if hasMenuCurrent != this.hasMenuCurrent {
|
||||
fmt.Println("hasMenuCurrent", hasMenuCurrent)
|
||||
fmt.Printf("this: %#v\n", this)
|
||||
t.Errorf("[%d] Wrong result for menu %q menuItem %v for HasMenuCurrent: %v", i, this.menu, this.menuItem, hasMenuCurrent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHopefullyUniqueID(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert.Equal(t, "i", (&MenuEntry{Identifier: "i", URL: "u", Name: "n"}).hopefullyUniqueID())
|
||||
assert.Equal(t, "u", (&MenuEntry{Identifier: "", URL: "u", Name: "n"}).hopefullyUniqueID())
|
||||
assert.Equal(t, "n", (&MenuEntry{Identifier: "", URL: "", Name: "n"}).hopefullyUniqueID())
|
||||
}
|
||||
|
||||
func TestAddMenuEntryChild(t *testing.T) {
|
||||
t.Parallel()
|
||||
root := &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)
|
||||
}
|
||||
|
||||
var testMenuIdentityMatcher = func(me *MenuEntry, id string) bool { return me.Identifier == id }
|
||||
var testMenuNameMatcher = func(me *MenuEntry, id string) bool { return me.Name == id }
|
||||
|
||||
func findTestMenuEntryByID(s *Site, mn string, id string) *MenuEntry {
|
||||
return findTestMenuEntry(s, mn, id, testMenuIdentityMatcher)
|
||||
}
|
||||
func findTestMenuEntryByName(s *Site, mn string, id string) *MenuEntry {
|
||||
return findTestMenuEntry(s, mn, id, testMenuNameMatcher)
|
||||
}
|
||||
|
||||
func findTestMenuEntry(s *Site, mn string, id string, matcher func(me *MenuEntry, id string) bool) *MenuEntry {
|
||||
var found *MenuEntry
|
||||
if menu, ok := s.Menus[mn]; ok {
|
||||
for _, me := range *menu {
|
||||
|
||||
if matcher(me, id) {
|
||||
if found != nil {
|
||||
panic(fmt.Sprintf("Duplicate menu entry in menu %s with id/name %s", mn, id))
|
||||
}
|
||||
found = me
|
||||
}
|
||||
|
||||
descendant := findDescendantTestMenuEntry(me, id, matcher)
|
||||
if descendant != nil {
|
||||
if found != nil {
|
||||
panic(fmt.Sprintf("Duplicate menu entry in menu %s with id/name %s", mn, id))
|
||||
}
|
||||
found = descendant
|
||||
}
|
||||
}
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
func findDescendantTestMenuEntry(parent *MenuEntry, id string, matcher func(me *MenuEntry, id string) bool) *MenuEntry {
|
||||
var found *MenuEntry
|
||||
if parent.HasChildren() {
|
||||
for _, child := range parent.Children {
|
||||
|
||||
if matcher(child, id) {
|
||||
if found != nil {
|
||||
panic(fmt.Sprintf("Duplicate menu entry in menuitem %s with id/name %s", parent.KeyName(), id))
|
||||
}
|
||||
found = child
|
||||
}
|
||||
|
||||
descendant := findDescendantTestMenuEntry(child, id, matcher)
|
||||
if descendant != nil {
|
||||
if found != nil {
|
||||
panic(fmt.Sprintf("Duplicate menu entry in menuitem %s with id/name %s", parent.KeyName(), id))
|
||||
}
|
||||
found = descendant
|
||||
}
|
||||
}
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
func setupMenuTests(t *testing.T, pageSources []source.ByteSource, configKeyValues ...interface{}) *Site {
|
||||
|
||||
var (
|
||||
cfg, fs = newTestCfg()
|
||||
)
|
||||
|
||||
menus, err := tomlToMap(confMenu1)
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg.Set("menu", menus["menu"])
|
||||
cfg.Set("baseURL", "http://foo.local/Zoo/")
|
||||
|
||||
for i := 0; i < len(configKeyValues); i += 2 {
|
||||
cfg.Set(configKeyValues[i].(string), configKeyValues[i+1])
|
||||
}
|
||||
|
||||
for _, src := range pageSources {
|
||||
writeSource(t, fs, filepath.Join("content", src.Name), string(src.Content))
|
||||
|
||||
}
|
||||
|
||||
return buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg}, BuildCfg{SkipRender: true})
|
||||
|
||||
}
|
||||
|
||||
func tomlToMap(s string) (map[string]interface{}, error) {
|
||||
tree, err := toml.Load(s)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tree.ToMap(), nil
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2016 The Hugo Authors. All rights reserved.
|
||||
// Copyright 2017 The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -14,677 +14,81 @@
|
|||
package hugolib
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/hugo/deps"
|
||||
"fmt"
|
||||
|
||||
"path/filepath"
|
||||
|
||||
toml "github.com/pelletier/go-toml"
|
||||
"github.com/spf13/hugo/source"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
confMenu1 = `
|
||||
[[menu.main]]
|
||||
name = "Go Home"
|
||||
url = "/"
|
||||
weight = 1
|
||||
pre = "<div>"
|
||||
post = "</div>"
|
||||
[[menu.main]]
|
||||
name = "Blog"
|
||||
url = "/posts"
|
||||
[[menu.main]]
|
||||
name = "ext"
|
||||
url = "http://gohugo.io"
|
||||
identifier = "ext"
|
||||
[[menu.main]]
|
||||
name = "ext2"
|
||||
url = "http://foo.local/Zoo/foo"
|
||||
identifier = "ext2"
|
||||
[[menu.grandparent]]
|
||||
name = "grandparent"
|
||||
url = "/grandparent"
|
||||
identifier = "grandparentId"
|
||||
[[menu.grandparent]]
|
||||
name = "parent"
|
||||
url = "/parent"
|
||||
identifier = "parentId"
|
||||
parent = "grandparentId"
|
||||
[[menu.grandparent]]
|
||||
name = "Go Home3"
|
||||
url = "/"
|
||||
identifier = "grandchildId"
|
||||
parent = "parentId"
|
||||
[[menu.tax]]
|
||||
name = "Tax1"
|
||||
url = "/two/key/"
|
||||
identifier="1"
|
||||
[[menu.tax]]
|
||||
name = "Tax2"
|
||||
url = "/two/key/"
|
||||
identifier="2"
|
||||
[[menu.tax]]
|
||||
name = "Tax RSS"
|
||||
url = "/two/key.xml"
|
||||
identifier="xml"
|
||||
[[menu.hash]]
|
||||
name = "Tax With #"
|
||||
url = "/resource#anchor"
|
||||
identifier="hash"
|
||||
[[menu.unicode]]
|
||||
name = "Unicode Russian"
|
||||
identifier = "unicode-russian"
|
||||
url = "/новости-проекта"` // Russian => "news-project"
|
||||
menuPageTemplate = `---
|
||||
title: %q
|
||||
weight: %d
|
||||
menu:
|
||||
%s:
|
||||
weight: %d
|
||||
---
|
||||
# Doc Menu
|
||||
`
|
||||
)
|
||||
|
||||
var menuPage1 = []byte(`+++
|
||||
title = "One"
|
||||
weight = 1
|
||||
[menu]
|
||||
[menu.p_one]
|
||||
+++
|
||||
Front Matter with Menu Pages`)
|
||||
|
||||
var menuPage2 = []byte(`+++
|
||||
title = "Two"
|
||||
weight = 2
|
||||
[menu]
|
||||
[menu.p_one]
|
||||
[menu.p_two]
|
||||
identifier = "Two"
|
||||
|
||||
+++
|
||||
Front Matter with Menu Pages`)
|
||||
|
||||
var menuPage3 = []byte(`+++
|
||||
title = "Three"
|
||||
weight = 3
|
||||
[menu]
|
||||
[menu.p_two]
|
||||
Name = "Three"
|
||||
Parent = "Two"
|
||||
+++
|
||||
Front Matter with Menu Pages`)
|
||||
|
||||
var menuPage4 = []byte(`+++
|
||||
title = "Four"
|
||||
weight = 4
|
||||
[menu]
|
||||
[menu.p_two]
|
||||
Name = "Four"
|
||||
Parent = "Three"
|
||||
+++
|
||||
Front Matter with Menu Pages`)
|
||||
|
||||
var menuPageSources = []source.ByteSource{
|
||||
{Name: filepath.FromSlash("sect/doc1.md"), Content: menuPage1},
|
||||
{Name: filepath.FromSlash("sect/doc2.md"), Content: menuPage2},
|
||||
{Name: filepath.FromSlash("sect/doc3.md"), Content: menuPage3},
|
||||
}
|
||||
|
||||
var menuPageSectionsSources = []source.ByteSource{
|
||||
{Name: filepath.FromSlash("first/doc1.md"), Content: menuPage1},
|
||||
{Name: filepath.FromSlash("first/doc2.md"), Content: menuPage2},
|
||||
{Name: filepath.FromSlash("second-section/doc3.md"), Content: menuPage3},
|
||||
{Name: filepath.FromSlash("Fish and Chips/doc4.md"), Content: menuPage4},
|
||||
}
|
||||
|
||||
func tstCreateMenuPageWithNameTOML(title, menu, name string) []byte {
|
||||
return []byte(fmt.Sprintf(`+++
|
||||
title = "%s"
|
||||
weight = 1
|
||||
[menu]
|
||||
[menu.%s]
|
||||
name = "%s"
|
||||
+++
|
||||
Front Matter with Menu with Name`, title, menu, name))
|
||||
}
|
||||
|
||||
func tstCreateMenuPageWithIdentifierTOML(title, menu, identifier string) []byte {
|
||||
return []byte(fmt.Sprintf(`+++
|
||||
title = "%s"
|
||||
weight = 1
|
||||
[menu]
|
||||
[menu.%s]
|
||||
identifier = "%s"
|
||||
name = "somename"
|
||||
+++
|
||||
Front Matter with Menu with Identifier`, title, menu, identifier))
|
||||
}
|
||||
|
||||
func tstCreateMenuPageWithNameYAML(title, menu, name string) []byte {
|
||||
return []byte(fmt.Sprintf(`---
|
||||
title: "%s"
|
||||
weight: 1
|
||||
menu:
|
||||
%s:
|
||||
name: "%s"
|
||||
---
|
||||
Front Matter with Menu with Name`, title, menu, name))
|
||||
}
|
||||
|
||||
func tstCreateMenuPageWithIdentifierYAML(title, menu, identifier string) []byte {
|
||||
return []byte(fmt.Sprintf(`---
|
||||
title: "%s"
|
||||
weight: 1
|
||||
menu:
|
||||
%s:
|
||||
identifier: "%s"
|
||||
name: "somename"
|
||||
---
|
||||
Front Matter with Menu with Identifier`, title, menu, identifier))
|
||||
}
|
||||
|
||||
// Issue 817 - identifier should trump everything
|
||||
func TestPageMenuWithIdentifier(t *testing.T) {
|
||||
t.Parallel()
|
||||
toml := []source.ByteSource{
|
||||
{Name: "sect/doc1.md", Content: tstCreateMenuPageWithIdentifierTOML("t1", "m1", "i1")},
|
||||
{Name: "sect/doc2.md", Content: tstCreateMenuPageWithIdentifierTOML("t1", "m1", "i2")},
|
||||
{Name: "sect/doc3.md", Content: tstCreateMenuPageWithIdentifierTOML("t1", "m1", "i2")}, // duplicate
|
||||
}
|
||||
|
||||
yaml := []source.ByteSource{
|
||||
{Name: "sect/doc1.md", Content: tstCreateMenuPageWithIdentifierYAML("t1", "m1", "i1")},
|
||||
{Name: "sect/doc2.md", Content: tstCreateMenuPageWithIdentifierYAML("t1", "m1", "i2")},
|
||||
{Name: "sect/doc3.md", Content: tstCreateMenuPageWithIdentifierYAML("t1", "m1", "i2")}, // duplicate
|
||||
}
|
||||
|
||||
doTestPageMenuWithIdentifier(t, toml)
|
||||
doTestPageMenuWithIdentifier(t, yaml)
|
||||
|
||||
}
|
||||
|
||||
func doTestPageMenuWithIdentifier(t *testing.T, menuPageSources []source.ByteSource) {
|
||||
|
||||
s := setupMenuTests(t, menuPageSources)
|
||||
|
||||
assert.Equal(t, 3, len(s.RegularPages), "Not enough pages")
|
||||
|
||||
me1 := findTestMenuEntryByID(s, "m1", "i1")
|
||||
me2 := findTestMenuEntryByID(s, "m1", "i2")
|
||||
|
||||
require.NotNil(t, me1)
|
||||
require.NotNil(t, me2)
|
||||
|
||||
assert.True(t, strings.Contains(me1.URL, "doc1"), me1.URL)
|
||||
assert.True(t, strings.Contains(me2.URL, "doc2") || strings.Contains(me2.URL, "doc3"), me2.URL)
|
||||
|
||||
}
|
||||
|
||||
// Issue 817 contd - name should be second identifier in
|
||||
func TestPageMenuWithDuplicateName(t *testing.T) {
|
||||
t.Parallel()
|
||||
toml := []source.ByteSource{
|
||||
{Name: "sect/doc1.md", Content: tstCreateMenuPageWithNameTOML("t1", "m1", "n1")},
|
||||
{Name: "sect/doc2.md", Content: tstCreateMenuPageWithNameTOML("t1", "m1", "n2")},
|
||||
{Name: "sect/doc3.md", Content: tstCreateMenuPageWithNameTOML("t1", "m1", "n2")}, // duplicate
|
||||
}
|
||||
|
||||
yaml := []source.ByteSource{
|
||||
{Name: "sect/doc1.md", Content: tstCreateMenuPageWithNameYAML("t1", "m1", "n1")},
|
||||
{Name: "sect/doc2.md", Content: tstCreateMenuPageWithNameYAML("t1", "m1", "n2")},
|
||||
{Name: "sect/doc3.md", Content: tstCreateMenuPageWithNameYAML("t1", "m1", "n2")}, // duplicate
|
||||
}
|
||||
|
||||
doTestPageMenuWithDuplicateName(t, toml)
|
||||
doTestPageMenuWithDuplicateName(t, yaml)
|
||||
|
||||
}
|
||||
|
||||
func doTestPageMenuWithDuplicateName(t *testing.T, menuPageSources []source.ByteSource) {
|
||||
|
||||
s := setupMenuTests(t, menuPageSources)
|
||||
|
||||
assert.Equal(t, 3, len(s.RegularPages), "Not enough pages")
|
||||
|
||||
me1 := findTestMenuEntryByName(s, "m1", "n1")
|
||||
me2 := findTestMenuEntryByName(s, "m1", "n2")
|
||||
|
||||
require.NotNil(t, me1)
|
||||
require.NotNil(t, me2)
|
||||
|
||||
assert.True(t, strings.Contains(me1.URL, "doc1"), me1.URL)
|
||||
assert.True(t, strings.Contains(me2.URL, "doc2") || strings.Contains(me2.URL, "doc3"), me2.URL)
|
||||
|
||||
}
|
||||
|
||||
func TestPageMenu(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := setupMenuTests(t, menuPageSources)
|
||||
|
||||
if len(s.RegularPages) != 3 {
|
||||
t.Fatalf("Posts not created, expected 3 got %d", len(s.RegularPages))
|
||||
}
|
||||
|
||||
first := s.RegularPages[0]
|
||||
second := s.RegularPages[1]
|
||||
third := s.RegularPages[2]
|
||||
|
||||
pOne := findTestMenuEntryByName(s, "p_one", "One")
|
||||
pTwo := findTestMenuEntryByID(s, "p_two", "Two")
|
||||
|
||||
for i, this := range []struct {
|
||||
menu string
|
||||
page *Page
|
||||
menuItem *MenuEntry
|
||||
isMenuCurrent bool
|
||||
hasMenuCurrent bool
|
||||
}{
|
||||
{"p_one", first, pOne, true, false},
|
||||
{"p_one", first, pTwo, false, false},
|
||||
{"p_one", second, pTwo, false, false},
|
||||
{"p_two", second, pTwo, true, false},
|
||||
{"p_two", third, pTwo, false, true},
|
||||
{"p_one", third, pTwo, false, false},
|
||||
} {
|
||||
|
||||
if i != 4 {
|
||||
continue
|
||||
}
|
||||
|
||||
isMenuCurrent := this.page.IsMenuCurrent(this.menu, this.menuItem)
|
||||
hasMenuCurrent := this.page.HasMenuCurrent(this.menu, this.menuItem)
|
||||
|
||||
if isMenuCurrent != this.isMenuCurrent {
|
||||
t.Errorf("[%d] Wrong result from IsMenuCurrent: %v", i, isMenuCurrent)
|
||||
}
|
||||
|
||||
if hasMenuCurrent != this.hasMenuCurrent {
|
||||
t.Errorf("[%d] Wrong result for menuItem %v for HasMenuCurrent: %v", i, this.menuItem, hasMenuCurrent)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestMenuURL(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := setupMenuTests(t, menuPageSources)
|
||||
|
||||
for i, this := range []struct {
|
||||
me *MenuEntry
|
||||
expectedURL string
|
||||
}{
|
||||
// issue #888
|
||||
{findTestMenuEntryByID(s, "hash", "hash"), "/Zoo/resource#anchor"},
|
||||
// issue #1774
|
||||
{findTestMenuEntryByID(s, "main", "ext"), "http://gohugo.io"},
|
||||
{findTestMenuEntryByID(s, "main", "ext2"), "http://foo.local/Zoo/foo"},
|
||||
} {
|
||||
|
||||
if this.me == nil {
|
||||
t.Errorf("[%d] MenuEntry not found", i)
|
||||
continue
|
||||
}
|
||||
|
||||
if this.me.URL != this.expectedURL {
|
||||
t.Errorf("[%d] Got URL %s expected %s", i, this.me.URL, this.expectedURL)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Issue #1934
|
||||
func TestYAMLMenuWithMultipleEntries(t *testing.T) {
|
||||
t.Parallel()
|
||||
ps1 := []byte(`---
|
||||
title: "Yaml 1"
|
||||
weight: 5
|
||||
menu: ["p_one", "p_two"]
|
||||
---
|
||||
Yaml Front Matter with Menu Pages`)
|
||||
|
||||
ps2 := []byte(`---
|
||||
title: "Yaml 2"
|
||||
weight: 5
|
||||
menu:
|
||||
p_three:
|
||||
p_four:
|
||||
---
|
||||
Yaml Front Matter with Menu Pages`)
|
||||
|
||||
s := setupMenuTests(t, []source.ByteSource{
|
||||
{Name: filepath.FromSlash("sect/yaml1.md"), Content: ps1},
|
||||
{Name: filepath.FromSlash("sect/yaml2.md"), Content: ps2}})
|
||||
|
||||
p1 := s.RegularPages[0]
|
||||
assert.Len(t, p1.Menus(), 2, "List YAML")
|
||||
p2 := s.RegularPages[1]
|
||||
assert.Len(t, p2.Menus(), 2, "Map YAML")
|
||||
|
||||
}
|
||||
|
||||
// issue #719
|
||||
func TestMenuWithUnicodeURLs(t *testing.T) {
|
||||
t.Parallel()
|
||||
for _, canonifyURLs := range []bool{true, false} {
|
||||
doTestMenuWithUnicodeURLs(t, canonifyURLs)
|
||||
}
|
||||
}
|
||||
|
||||
func doTestMenuWithUnicodeURLs(t *testing.T, canonifyURLs bool) {
|
||||
|
||||
s := setupMenuTests(t, menuPageSources, "canonifyURLs", canonifyURLs)
|
||||
|
||||
unicodeRussian := findTestMenuEntryByID(s, "unicode", "unicode-russian")
|
||||
|
||||
expected := "/%D0%BD%D0%BE%D0%B2%D0%BE%D1%81%D1%82%D0%B8-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B0"
|
||||
|
||||
if !canonifyURLs {
|
||||
expected = "/Zoo" + expected
|
||||
}
|
||||
|
||||
assert.Equal(t, expected, unicodeRussian.URL)
|
||||
}
|
||||
|
||||
// Issue #1114
|
||||
func TestSectionPagesMenu(t *testing.T) {
|
||||
t.Parallel()
|
||||
doTestSectionPagesMenu(true, t)
|
||||
doTestSectionPagesMenu(false, t)
|
||||
}
|
||||
|
||||
func doTestSectionPagesMenu(canonifyURLs bool, t *testing.T) {
|
||||
siteConfig := `
|
||||
baseurl = "http://example.com/"
|
||||
title = "Section Menu"
|
||||
sectionPagesMenu = "sect"
|
||||
`
|
||||
|
||||
s := setupMenuTests(t, menuPageSectionsSources,
|
||||
"sectionPagesMenu", "spm",
|
||||
"canonifyURLs", canonifyURLs,
|
||||
th, h := newTestSitesFromConfig(t, siteConfig,
|
||||
"layouts/partials/menu.html", `{{- $p := .page -}}
|
||||
{{- $m := .menu -}}
|
||||
{{ range (index $p.Site.Menus $m) -}}
|
||||
{{- .URL }}|{{ .Name }}|{{ .Weight -}}|
|
||||
{{- if $p.IsMenuCurrent $m . }}IsMenuCurrent{{ else }}-{{ end -}}|
|
||||
{{- if $p.HasMenuCurrent $m . }}HasMenuCurrent{{ else }}-{{ end -}}|
|
||||
{{- end -}}
|
||||
`,
|
||||
"layouts/_default/single.html",
|
||||
`Single|{{ .Title }}
|
||||
Menu Sect: {{ partial "menu.html" (dict "page" . "menu" "sect") }}
|
||||
Menu Main: {{ partial "menu.html" (dict "page" . "menu" "main") }}`,
|
||||
"layouts/_default/list.html", "List|{{ .Title }}|{{ .Content }}",
|
||||
)
|
||||
require.Len(t, h.Sites, 1)
|
||||
|
||||
require.Equal(t, 3, len(s.Sections))
|
||||
fs := th.Fs
|
||||
|
||||
firstSectionPages := s.Sections["first"]
|
||||
require.Equal(t, 2, len(firstSectionPages))
|
||||
secondSectionPages := s.Sections["second-section"]
|
||||
require.Equal(t, 1, len(secondSectionPages))
|
||||
fishySectionPages := s.Sections["fish-and-chips"]
|
||||
require.Equal(t, 1, len(fishySectionPages))
|
||||
writeSource(t, fs, "content/sect1/p1.md", fmt.Sprintf(menuPageTemplate, "p1", 1, "main", 40))
|
||||
writeSource(t, fs, "content/sect1/p2.md", fmt.Sprintf(menuPageTemplate, "p2", 2, "main", 30))
|
||||
writeSource(t, fs, "content/sect2/p3.md", fmt.Sprintf(menuPageTemplate, "p3", 3, "main", 20))
|
||||
writeSource(t, fs, "content/sect2/p4.md", fmt.Sprintf(menuPageTemplate, "p4", 4, "main", 10))
|
||||
writeSource(t, fs, "content/sect3/p5.md", fmt.Sprintf(menuPageTemplate, "p5", 5, "main", 5))
|
||||
|
||||
nodeFirst := s.getPage(KindSection, "first")
|
||||
require.NotNil(t, nodeFirst)
|
||||
nodeSecond := s.getPage(KindSection, "second-section")
|
||||
require.NotNil(t, nodeSecond)
|
||||
nodeFishy := s.getPage(KindSection, "fish-and-chips")
|
||||
require.Equal(t, "fish-and-chips", nodeFishy.sections[0])
|
||||
writeNewContentFile(t, fs, "Section One", "2017-01-01", "content/sect1/_index.md", 100)
|
||||
writeNewContentFile(t, fs, "Section Five", "2017-01-01", "content/sect5/_index.md", 10)
|
||||
|
||||
firstSectionMenuEntry := findTestMenuEntryByID(s, "spm", "first")
|
||||
secondSectionMenuEntry := findTestMenuEntryByID(s, "spm", "second-section")
|
||||
fishySectionMenuEntry := findTestMenuEntryByID(s, "spm", "Fish and Chips")
|
||||
err := h.Build(BuildCfg{})
|
||||
|
||||
require.NotNil(t, firstSectionMenuEntry)
|
||||
require.NotNil(t, secondSectionMenuEntry)
|
||||
require.NotNil(t, nodeFirst)
|
||||
require.NotNil(t, nodeSecond)
|
||||
require.NotNil(t, fishySectionMenuEntry)
|
||||
require.NotNil(t, nodeFishy)
|
||||
|
||||
require.True(t, nodeFirst.IsMenuCurrent("spm", firstSectionMenuEntry))
|
||||
require.False(t, nodeFirst.IsMenuCurrent("spm", secondSectionMenuEntry))
|
||||
require.False(t, nodeFirst.IsMenuCurrent("spm", fishySectionMenuEntry))
|
||||
require.True(t, nodeFishy.IsMenuCurrent("spm", fishySectionMenuEntry))
|
||||
require.Equal(t, "Fish and Chips", fishySectionMenuEntry.Name)
|
||||
|
||||
for _, p := range firstSectionPages {
|
||||
require.True(t, p.Page.HasMenuCurrent("spm", firstSectionMenuEntry))
|
||||
require.False(t, p.Page.HasMenuCurrent("spm", secondSectionMenuEntry))
|
||||
}
|
||||
|
||||
for _, p := range secondSectionPages {
|
||||
require.False(t, p.Page.HasMenuCurrent("spm", firstSectionMenuEntry))
|
||||
require.True(t, p.Page.HasMenuCurrent("spm", secondSectionMenuEntry))
|
||||
}
|
||||
|
||||
for _, p := range fishySectionPages {
|
||||
require.False(t, p.Page.HasMenuCurrent("spm", firstSectionMenuEntry))
|
||||
require.False(t, p.Page.HasMenuCurrent("spm", secondSectionMenuEntry))
|
||||
require.True(t, p.Page.HasMenuCurrent("spm", fishySectionMenuEntry))
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaxonomyNodeMenu(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type taxRenderInfo struct {
|
||||
key string
|
||||
singular string
|
||||
plural string
|
||||
}
|
||||
|
||||
s := setupMenuTests(t, menuPageSources, "canonifyURLs", true)
|
||||
|
||||
for i, this := range []struct {
|
||||
menu string
|
||||
taxInfo taxRenderInfo
|
||||
menuItem *MenuEntry
|
||||
isMenuCurrent bool
|
||||
hasMenuCurrent bool
|
||||
}{
|
||||
{"tax", taxRenderInfo{key: "key", singular: "one", plural: "two"},
|
||||
findTestMenuEntryByID(s, "tax", "1"), true, false},
|
||||
{"tax", taxRenderInfo{key: "key", singular: "one", plural: "two"},
|
||||
findTestMenuEntryByID(s, "tax", "2"), true, false},
|
||||
{"tax", taxRenderInfo{key: "key", singular: "one", plural: "two"},
|
||||
&MenuEntry{Name: "Somewhere else", URL: "/somewhereelse"}, false, false},
|
||||
} {
|
||||
|
||||
p := s.newTaxonomyPage(this.taxInfo.plural, this.taxInfo.key)
|
||||
|
||||
isMenuCurrent := p.IsMenuCurrent(this.menu, this.menuItem)
|
||||
hasMenuCurrent := p.HasMenuCurrent(this.menu, this.menuItem)
|
||||
|
||||
if isMenuCurrent != this.isMenuCurrent {
|
||||
t.Errorf("[%d] Wrong result from IsMenuCurrent: %v", i, isMenuCurrent)
|
||||
}
|
||||
|
||||
if hasMenuCurrent != this.hasMenuCurrent {
|
||||
t.Errorf("[%d] Wrong result for menuItem %v for HasMenuCurrent: %v", i, this.menuItem, hasMenuCurrent)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
menuEntryXML := findTestMenuEntryByID(s, "tax", "xml")
|
||||
|
||||
if strings.HasSuffix(menuEntryXML.URL, "/") {
|
||||
t.Error("RSS menu item should not be padded with trailing slash")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMenuLimit(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := setupMenuTests(t, menuPageSources)
|
||||
m := *s.Menus["main"]
|
||||
|
||||
// main menu has 4 entries
|
||||
firstTwo := m.Limit(2)
|
||||
assert.Equal(t, 2, len(firstTwo))
|
||||
for i := 0; i < 2; i++ {
|
||||
assert.Equal(t, m[i], firstTwo[i])
|
||||
}
|
||||
assert.Equal(t, m, m.Limit(4))
|
||||
assert.Equal(t, m, m.Limit(5))
|
||||
}
|
||||
|
||||
func TestMenuSortByN(t *testing.T) {
|
||||
t.Parallel()
|
||||
for i, this := range []struct {
|
||||
sortFunc func(p Menu) Menu
|
||||
assertFunc func(p Menu) bool
|
||||
}{
|
||||
{(Menu).Sort, func(p Menu) bool { return p[0].Weight == 1 && p[1].Name == "nx" && p[2].Identifier == "ib" }},
|
||||
{(Menu).ByWeight, func(p Menu) bool { return p[0].Weight == 1 && p[1].Name == "nx" && p[2].Identifier == "ib" }},
|
||||
{(Menu).ByName, func(p Menu) bool { return p[0].Name == "na" }},
|
||||
{(Menu).Reverse, func(p Menu) bool { return p[0].Identifier == "ib" && p[len(p)-1].Identifier == "ia" }},
|
||||
} {
|
||||
menu := Menu{&MenuEntry{Weight: 3, Name: "nb", Identifier: "ia"},
|
||||
&MenuEntry{Weight: 1, Name: "na", Identifier: "ic"},
|
||||
&MenuEntry{Weight: 1, Name: "nx", Identifier: "ic"},
|
||||
&MenuEntry{Weight: 2, Name: "nb", Identifier: "ix"},
|
||||
&MenuEntry{Weight: 2, Name: "nb", Identifier: "ib"}}
|
||||
|
||||
sorted := this.sortFunc(menu)
|
||||
|
||||
if !this.assertFunc(sorted) {
|
||||
t.Errorf("[%d] sort error", i)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestHomeNodeMenu(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := setupMenuTests(t, menuPageSources,
|
||||
"canonifyURLs", true,
|
||||
"uglyURLs", false,
|
||||
)
|
||||
|
||||
home := s.getPage(KindHome)
|
||||
homeMenuEntry := &MenuEntry{Name: home.Title, URL: home.URL()}
|
||||
|
||||
for i, this := range []struct {
|
||||
menu string
|
||||
menuItem *MenuEntry
|
||||
isMenuCurrent bool
|
||||
hasMenuCurrent bool
|
||||
}{
|
||||
{"main", homeMenuEntry, true, false},
|
||||
{"doesnotexist", homeMenuEntry, false, false},
|
||||
{"main", &MenuEntry{Name: "Somewhere else", URL: "/somewhereelse"}, false, false},
|
||||
{"grandparent", findTestMenuEntryByID(s, "grandparent", "grandparentId"), false, true},
|
||||
{"grandparent", findTestMenuEntryByID(s, "grandparent", "parentId"), false, true},
|
||||
{"grandparent", findTestMenuEntryByID(s, "grandparent", "grandchildId"), true, false},
|
||||
} {
|
||||
|
||||
isMenuCurrent := home.IsMenuCurrent(this.menu, this.menuItem)
|
||||
hasMenuCurrent := home.HasMenuCurrent(this.menu, this.menuItem)
|
||||
|
||||
if isMenuCurrent != this.isMenuCurrent {
|
||||
fmt.Println("isMenuCurrent", isMenuCurrent)
|
||||
fmt.Printf("this: %#v\n", this)
|
||||
t.Errorf("[%d] Wrong result from IsMenuCurrent: %v for %q", i, isMenuCurrent, this.menuItem)
|
||||
}
|
||||
|
||||
if hasMenuCurrent != this.hasMenuCurrent {
|
||||
fmt.Println("hasMenuCurrent", hasMenuCurrent)
|
||||
fmt.Printf("this: %#v\n", this)
|
||||
t.Errorf("[%d] Wrong result for menu %q menuItem %v for HasMenuCurrent: %v", i, this.menu, this.menuItem, hasMenuCurrent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHopefullyUniqueID(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert.Equal(t, "i", (&MenuEntry{Identifier: "i", URL: "u", Name: "n"}).hopefullyUniqueID())
|
||||
assert.Equal(t, "u", (&MenuEntry{Identifier: "", URL: "u", Name: "n"}).hopefullyUniqueID())
|
||||
assert.Equal(t, "n", (&MenuEntry{Identifier: "", URL: "", Name: "n"}).hopefullyUniqueID())
|
||||
}
|
||||
|
||||
func TestAddMenuEntryChild(t *testing.T) {
|
||||
t.Parallel()
|
||||
root := &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)
|
||||
}
|
||||
|
||||
var testMenuIdentityMatcher = func(me *MenuEntry, id string) bool { return me.Identifier == id }
|
||||
var testMenuNameMatcher = func(me *MenuEntry, id string) bool { return me.Name == id }
|
||||
|
||||
func findTestMenuEntryByID(s *Site, mn string, id string) *MenuEntry {
|
||||
return findTestMenuEntry(s, mn, id, testMenuIdentityMatcher)
|
||||
}
|
||||
func findTestMenuEntryByName(s *Site, mn string, id string) *MenuEntry {
|
||||
return findTestMenuEntry(s, mn, id, testMenuNameMatcher)
|
||||
}
|
||||
|
||||
func findTestMenuEntry(s *Site, mn string, id string, matcher func(me *MenuEntry, id string) bool) *MenuEntry {
|
||||
var found *MenuEntry
|
||||
if menu, ok := s.Menus[mn]; ok {
|
||||
for _, me := range *menu {
|
||||
|
||||
if matcher(me, id) {
|
||||
if found != nil {
|
||||
panic(fmt.Sprintf("Duplicate menu entry in menu %s with id/name %s", mn, id))
|
||||
}
|
||||
found = me
|
||||
}
|
||||
|
||||
descendant := findDescendantTestMenuEntry(me, id, matcher)
|
||||
if descendant != nil {
|
||||
if found != nil {
|
||||
panic(fmt.Sprintf("Duplicate menu entry in menu %s with id/name %s", mn, id))
|
||||
}
|
||||
found = descendant
|
||||
}
|
||||
}
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
func findDescendantTestMenuEntry(parent *MenuEntry, id string, matcher func(me *MenuEntry, id string) bool) *MenuEntry {
|
||||
var found *MenuEntry
|
||||
if parent.HasChildren() {
|
||||
for _, child := range parent.Children {
|
||||
|
||||
if matcher(child, id) {
|
||||
if found != nil {
|
||||
panic(fmt.Sprintf("Duplicate menu entry in menuitem %s with id/name %s", parent.KeyName(), id))
|
||||
}
|
||||
found = child
|
||||
}
|
||||
|
||||
descendant := findDescendantTestMenuEntry(child, id, matcher)
|
||||
if descendant != nil {
|
||||
if found != nil {
|
||||
panic(fmt.Sprintf("Duplicate menu entry in menuitem %s with id/name %s", parent.KeyName(), id))
|
||||
}
|
||||
found = descendant
|
||||
}
|
||||
}
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
func setupMenuTests(t *testing.T, pageSources []source.ByteSource, configKeyValues ...interface{}) *Site {
|
||||
|
||||
var (
|
||||
cfg, fs = newTestCfg()
|
||||
)
|
||||
|
||||
menus, err := tomlToMap(confMenu1)
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg.Set("menu", menus["menu"])
|
||||
cfg.Set("baseURL", "http://foo.local/Zoo/")
|
||||
s := h.Sites[0]
|
||||
|
||||
for i := 0; i < len(configKeyValues); i += 2 {
|
||||
cfg.Set(configKeyValues[i].(string), configKeyValues[i+1])
|
||||
}
|
||||
require.Len(t, s.Menus, 2)
|
||||
|
||||
for _, src := range pageSources {
|
||||
writeSource(t, fs, filepath.Join("content", src.Name), string(src.Content))
|
||||
p1 := s.RegularPages[0].Menus()
|
||||
|
||||
}
|
||||
// There is only one menu in the page, but it is "member of" 2
|
||||
require.Len(t, p1, 1)
|
||||
|
||||
return buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg}, BuildCfg{SkipRender: true})
|
||||
|
||||
}
|
||||
|
||||
func tomlToMap(s string) (map[string]interface{}, error) {
|
||||
tree, err := toml.Load(s)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tree.ToMap(), nil
|
||||
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|-|-|",
|
||||
"Menu Main: /sect3/p5/|p5|5|-|-|/sect2/p4/|p4|10|-|-|/sect2/p3/|p3|20|-|-|/sect1/p2/|p2|30|-|-|/sect1/p1/|p1|40|IsMenuCurrent|-|",
|
||||
)
|
||||
|
||||
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|-|-|")
|
||||
|
||||
}
|
||||
|
|
|
@ -621,6 +621,9 @@ func (p *Page) Type() string {
|
|||
}
|
||||
|
||||
func (p *Page) Section() string {
|
||||
if p.Kind == KindSection {
|
||||
return p.sections[0]
|
||||
}
|
||||
return p.Source.Section()
|
||||
}
|
||||
|
||||
|
@ -1167,8 +1170,16 @@ func (p *Page) HasMenuCurrent(menuID string, me *MenuEntry) bool {
|
|||
sectionPagesMenu := p.Site.sectionPagesMenu
|
||||
|
||||
// page is labeled as "shadow-member" of the menu with the same identifier as the section
|
||||
if sectionPagesMenu != "" && p.Section() != "" && sectionPagesMenu == menuID && p.Section() == me.Identifier {
|
||||
return true
|
||||
if sectionPagesMenu != "" {
|
||||
section := p.Section()
|
||||
|
||||
if !p.s.Info.preserveTaxonomyNames {
|
||||
section = p.s.PathSpec.MakePathSanitized(section)
|
||||
}
|
||||
|
||||
if section != "" && sectionPagesMenu == menuID && section == me.Identifier {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if !me.HasChildren() {
|
||||
|
@ -1537,7 +1548,7 @@ func (p *Page) prepareData(s *Site) error {
|
|||
case KindHome:
|
||||
pages = s.RegularPages
|
||||
case KindSection:
|
||||
sectionData, ok := s.Sections[p.sections[0]]
|
||||
sectionData, ok := s.Sections[p.Section()]
|
||||
if !ok {
|
||||
return fmt.Errorf("Data for section %s not found", p.Section())
|
||||
}
|
||||
|
|
|
@ -1366,8 +1366,6 @@ func (s *Site) buildSiteMeta() (err error) {
|
|||
|
||||
s.assembleSections()
|
||||
|
||||
s.assembleMenus()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1442,42 +1440,20 @@ func (s *Site) assembleMenus() {
|
|||
pages := s.Pages
|
||||
|
||||
if sectionPagesMenu != "" {
|
||||
// Create menu entries for section pages with content
|
||||
for _, p := range pages {
|
||||
if p.Kind == KindSection {
|
||||
// menu with same id defined in config, let that one win
|
||||
if _, ok := flat[twoD{sectionPagesMenu, p.Section()}]; ok {
|
||||
id := p.Section()
|
||||
if _, ok := flat[twoD{sectionPagesMenu, id}]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
me := MenuEntry{Identifier: p.Section(),
|
||||
me := MenuEntry{Identifier: id,
|
||||
Name: p.LinkTitle(),
|
||||
Weight: p.Weight,
|
||||
URL: p.RelPermalink()}
|
||||
|
||||
flat[twoD{sectionPagesMenu, me.KeyName()}] = &me
|
||||
}
|
||||
}
|
||||
|
||||
// Create entries for remaining content-less section pages
|
||||
sectionPagesMenus := make(map[string]interface{})
|
||||
for _, p := range pages {
|
||||
if _, ok := sectionPagesMenus[p.Section()]; !ok {
|
||||
if p.Section() != "" {
|
||||
// menu with same id defined in config, let that one win
|
||||
if _, ok := flat[twoD{sectionPagesMenu, p.Section()}]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
me := MenuEntry{Identifier: p.Section(),
|
||||
Name: helpers.MakeTitle(helpers.FirstUpper(p.Section())),
|
||||
URL: s.Info.createNodeMenuEntryURL(p.addLangPathPrefix("/"+p.Section()) + "/")}
|
||||
|
||||
flat[twoD{sectionPagesMenu, me.KeyName()}] = &me
|
||||
sectionPagesMenus[p.Section()] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add menu entries provided by pages
|
||||
|
@ -1610,7 +1586,8 @@ func (s *Site) assembleSections() {
|
|||
sectionPages := s.findPagesByKind(KindSection)
|
||||
|
||||
for i, p := range regularPages {
|
||||
s.Sections.add(s.getTaxonomyKey(p.Section()), WeightedPage{regularPages[i].Weight, regularPages[i]})
|
||||
section := s.getTaxonomyKey(p.Section())
|
||||
s.Sections.add(section, WeightedPage{regularPages[i].Weight, regularPages[i]})
|
||||
}
|
||||
|
||||
// Add sections without regular pages, but with a content page
|
||||
|
@ -2135,7 +2112,6 @@ func (s *Site) newTaxonomyPage(plural, key string) *Page {
|
|||
}
|
||||
|
||||
func (s *Site) newSectionPage(name string, section WeightedPages) *Page {
|
||||
|
||||
p := s.newNodePage(KindSection)
|
||||
p.sections = []string{name}
|
||||
|
||||
|
|
|
@ -19,11 +19,9 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/afero"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/spf13/hugo/deps"
|
||||
"github.com/spf13/hugo/hugofs"
|
||||
)
|
||||
|
||||
func TestByCountOrderOfTaxonomies(t *testing.T) {
|
||||
|
@ -79,19 +77,10 @@ others:
|
|||
# Doc
|
||||
`
|
||||
|
||||
mf := afero.NewMemMapFs()
|
||||
th, h := newTestSitesFromConfigWithDefaultTemplates(t, siteConfig)
|
||||
require.Len(t, h.Sites, 1)
|
||||
|
||||
writeToFs(t, mf, "config.toml", siteConfig)
|
||||
|
||||
cfg, err := LoadConfig(mf, "", "config.toml")
|
||||
require.NoError(t, err)
|
||||
|
||||
fs := hugofs.NewFrom(mf, cfg)
|
||||
th := testHelper{cfg, fs, t}
|
||||
|
||||
writeSource(t, fs, "layouts/_default/single.html", "Single|{{ .Title }}|{{ .Content }}")
|
||||
writeSource(t, fs, "layouts/_default/list.html", "List|{{ .Title }}|{{ .Content }}")
|
||||
writeSource(t, fs, "layouts/_default/terms.html", "Terms List|{{ .Title }}|{{ .Content }}")
|
||||
fs := th.Fs
|
||||
|
||||
writeSource(t, fs, "content/p1.md", fmt.Sprintf(pageTemplate, "t1/c1", "- tag1", "- cat1", "- o1"))
|
||||
writeSource(t, fs, "content/p2.md", fmt.Sprintf(pageTemplate, "t2/c1", "- tag2", "- cat1", "- o1"))
|
||||
|
@ -99,12 +88,7 @@ others:
|
|||
writeNewContentFile(t, fs, "Category Terms", "2017-01-01", "content/categories/_index.md", 10)
|
||||
writeNewContentFile(t, fs, "Tag1 List", "2017-01-01", "content/tags/tag1/_index.md", 10)
|
||||
|
||||
h, err := NewHugoSites(deps.DepsCfg{Fs: fs, Cfg: cfg})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Len(t, h.Sites, 1)
|
||||
|
||||
err = h.Build(BuildCfg{})
|
||||
err := h.Build(BuildCfg{})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
|
|
|
@ -6,12 +6,13 @@ import (
|
|||
|
||||
"regexp"
|
||||
|
||||
"github.com/spf13/hugo/config"
|
||||
"github.com/spf13/hugo/deps"
|
||||
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/afero"
|
||||
"github.com/spf13/hugo/config"
|
||||
"github.com/spf13/hugo/deps"
|
||||
|
||||
"github.com/spf13/hugo/helpers"
|
||||
"github.com/spf13/hugo/source"
|
||||
"github.com/spf13/hugo/tpl"
|
||||
|
@ -113,6 +114,39 @@ func newTestSite(t testing.TB, configKeyValues ...interface{}) *Site {
|
|||
return s
|
||||
}
|
||||
|
||||
func newTestSitesFromConfig(t testing.TB, tomlConfig string, layoutPathContentPairs ...string) (testHelper, *HugoSites) {
|
||||
if len(layoutPathContentPairs)%2 != 0 {
|
||||
t.Fatalf("Layouts must be provided in pairs")
|
||||
}
|
||||
mf := afero.NewMemMapFs()
|
||||
|
||||
writeToFs(t, mf, "config.toml", tomlConfig)
|
||||
|
||||
cfg, err := LoadConfig(mf, "", "config.toml")
|
||||
require.NoError(t, err)
|
||||
|
||||
fs := hugofs.NewFrom(mf, cfg)
|
||||
th := testHelper{cfg, fs, t}
|
||||
|
||||
for i := 0; i < len(layoutPathContentPairs); i += 2 {
|
||||
writeSource(t, fs, layoutPathContentPairs[i], layoutPathContentPairs[i+1])
|
||||
}
|
||||
|
||||
h, err := NewHugoSites(deps.DepsCfg{Fs: fs, Cfg: cfg})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
return th, h
|
||||
}
|
||||
|
||||
func newTestSitesFromConfigWithDefaultTemplates(t testing.TB, tomlConfig string) (testHelper, *HugoSites) {
|
||||
return newTestSitesFromConfig(t, tomlConfig,
|
||||
"layouts/_default/single.html", "Single|{{ .Title }}|{{ .Content }}",
|
||||
"layouts/_default/list.html", "List|{{ .Title }}|{{ .Content }}",
|
||||
"layouts/_default/terms.html", "Terms List|{{ .Title }}|{{ .Content }}",
|
||||
)
|
||||
}
|
||||
|
||||
func newDebugLogger() *jww.Notepad {
|
||||
return jww.NewNotepad(jww.LevelDebug, jww.LevelError, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue