Unify page lookups

This commit unifies the core internal page index for all page kinds.

This enables the `ref` and `relref` shortcodes to support all pages kinds, and adds a new page-relative  `.GetPage` method with simplified signature.

See #4147
See #4727
See #4728
See #4728
See #4726
See #4652
This commit is contained in:
Vas Sudanagunta 2018-05-29 21:35:27 -04:00 committed by Bjørn Erik Pedersen
parent fd1f4a7860
commit b93417aa1d
16 changed files with 294 additions and 153 deletions

View file

@ -130,7 +130,7 @@ func assertDisabledKinds(th testHelper, s *Site, disabled ...string) {
}, disabled, KindPage, "public/sect/p1/index.html", "Single|P1") }, disabled, KindPage, "public/sect/p1/index.html", "Single|P1")
assertDisabledKind(th, assertDisabledKind(th,
func(isDisabled bool) bool { func(isDisabled bool) bool {
p := s.getPage(KindHome) p, _ := s.getPage(nil, "/")
if isDisabled { if isDisabled {
return p == nil return p == nil
} }
@ -138,7 +138,7 @@ func assertDisabledKinds(th testHelper, s *Site, disabled ...string) {
}, disabled, KindHome, "public/index.html", "Home") }, disabled, KindHome, "public/index.html", "Home")
assertDisabledKind(th, assertDisabledKind(th,
func(isDisabled bool) bool { func(isDisabled bool) bool {
p := s.getPage(KindSection, "sect") p, _ := s.getPage(nil, "sect")
if isDisabled { if isDisabled {
return p == nil return p == nil
} }
@ -146,7 +146,7 @@ func assertDisabledKinds(th testHelper, s *Site, disabled ...string) {
}, disabled, KindSection, "public/sect/index.html", "Sects") }, disabled, KindSection, "public/sect/index.html", "Sects")
assertDisabledKind(th, assertDisabledKind(th,
func(isDisabled bool) bool { func(isDisabled bool) bool {
p := s.getPage(KindTaxonomy, "tags", "tag1") p, _ := s.getPage(nil, "tags/tag1")
if isDisabled { if isDisabled {
return p == nil return p == nil
@ -156,7 +156,7 @@ func assertDisabledKinds(th testHelper, s *Site, disabled ...string) {
}, disabled, KindTaxonomy, "public/tags/tag1/index.html", "Tag1") }, disabled, KindTaxonomy, "public/tags/tag1/index.html", "Tag1")
assertDisabledKind(th, assertDisabledKind(th,
func(isDisabled bool) bool { func(isDisabled bool) bool {
p := s.getPage(KindTaxonomyTerm, "tags") p, _ := s.getPage(nil, "tags")
if isDisabled { if isDisabled {
return p == nil return p == nil
} }
@ -165,7 +165,7 @@ func assertDisabledKinds(th testHelper, s *Site, disabled ...string) {
}, disabled, KindTaxonomyTerm, "public/tags/index.html", "Tags") }, disabled, KindTaxonomyTerm, "public/tags/index.html", "Tags")
assertDisabledKind(th, assertDisabledKind(th,
func(isDisabled bool) bool { func(isDisabled bool) bool {
p := s.getPage(KindTaxonomyTerm, "categories") p, _ := s.getPage(nil, "categories")
if isDisabled { if isDisabled {
return p == nil return p == nil
@ -175,7 +175,7 @@ func assertDisabledKinds(th testHelper, s *Site, disabled ...string) {
}, disabled, KindTaxonomyTerm, "public/categories/index.html", "Category Terms") }, disabled, KindTaxonomyTerm, "public/categories/index.html", "Category Terms")
assertDisabledKind(th, assertDisabledKind(th,
func(isDisabled bool) bool { func(isDisabled bool) bool {
p := s.getPage(KindTaxonomy, "categories", "hugo") p, _ := s.getPage(nil, "categories/hugo")
if isDisabled { if isDisabled {
return p == nil return p == nil
} }

View file

@ -186,12 +186,12 @@ p1 = "p1en"
assert.Len(sites, 2) assert.Len(sites, 2)
nnSite := sites[0] nnSite := sites[0]
nnHome := nnSite.getPage(KindHome) nnHome, _ := nnSite.getPage(nil, "/")
assert.Len(nnHome.AllTranslations(), 2) assert.Len(nnHome.AllTranslations(), 2)
assert.Len(nnHome.Translations(), 1) assert.Len(nnHome.Translations(), 1)
assert.True(nnHome.IsTranslated()) assert.True(nnHome.IsTranslated())
enHome := sites[1].getPage(KindHome) enHome, _ := sites[1].getPage(nil, "/")
p1, err := enHome.Param("p1") p1, err := enHome.Param("p1")
assert.NoError(err) assert.NoError(err)
@ -242,7 +242,7 @@ func doTestMultiSitesBuild(t *testing.T, configTemplate, configSuffix string) {
require.Nil(t, gp2) require.Nil(t, gp2)
enSite := sites[0] enSite := sites[0]
enSiteHome := enSite.getPage(KindHome) enSiteHome, _ := enSite.getPage(nil, "/")
require.True(t, enSiteHome.IsTranslated()) require.True(t, enSiteHome.IsTranslated())
require.Equal(t, "en", enSite.Language.Lang) require.Equal(t, "en", enSite.Language.Lang)
@ -310,10 +310,10 @@ func doTestMultiSitesBuild(t *testing.T, configTemplate, configSuffix string) {
// isn't ideal in a multilingual setup. You want a way to get the current language version if available. // isn't ideal in a multilingual setup. You want a way to get the current language version if available.
// Now you can do lookups with translation base name to get that behaviour. // Now you can do lookups with translation base name to get that behaviour.
// Let us test all the regular page variants: // Let us test all the regular page variants:
getPageDoc1En := enSite.getPage(KindPage, filepath.ToSlash(doc1en.Path())) getPageDoc1En, _ := enSite.getPage(nil, filepath.ToSlash(doc1en.Path()))
getPageDoc1EnBase := enSite.getPage(KindPage, "sect/doc1") getPageDoc1EnBase, _ := enSite.getPage(nil, "sect/doc1")
getPageDoc1Fr := frSite.getPage(KindPage, filepath.ToSlash(doc1fr.Path())) getPageDoc1Fr, _ := frSite.getPage(nil, filepath.ToSlash(doc1fr.Path()))
getPageDoc1FrBase := frSite.getPage(KindPage, "sect/doc1") getPageDoc1FrBase, _ := frSite.getPage(nil, "sect/doc1")
require.Equal(t, doc1en, getPageDoc1En) require.Equal(t, doc1en, getPageDoc1En)
require.Equal(t, doc1fr, getPageDoc1Fr) require.Equal(t, doc1fr, getPageDoc1Fr)
require.Equal(t, doc1en, getPageDoc1EnBase) require.Equal(t, doc1en, getPageDoc1EnBase)
@ -331,7 +331,7 @@ func doTestMultiSitesBuild(t *testing.T, configTemplate, configSuffix string) {
b.AssertFileContent("public/en/sect/doc1-slug/index.html", "Single", "Shortcode: Hello", "LingoDefault") b.AssertFileContent("public/en/sect/doc1-slug/index.html", "Single", "Shortcode: Hello", "LingoDefault")
// Check node translations // Check node translations
homeEn := enSite.getPage(KindHome) homeEn, _ := enSite.getPage(nil, "/")
require.NotNil(t, homeEn) require.NotNil(t, homeEn)
require.Len(t, homeEn.Translations(), 3) require.Len(t, homeEn.Translations(), 3)
require.Equal(t, "fr", homeEn.Translations()[0].Lang()) require.Equal(t, "fr", homeEn.Translations()[0].Lang())
@ -341,7 +341,7 @@ func doTestMultiSitesBuild(t *testing.T, configTemplate, configSuffix string) {
require.Equal(t, "På bokmål", homeEn.Translations()[2].title, configSuffix) require.Equal(t, "På bokmål", homeEn.Translations()[2].title, configSuffix)
require.Equal(t, "Bokmål", homeEn.Translations()[2].Language().LanguageName, configSuffix) require.Equal(t, "Bokmål", homeEn.Translations()[2].Language().LanguageName, configSuffix)
sectFr := frSite.getPage(KindSection, "sect") sectFr, _ := frSite.getPage(nil, "sect")
require.NotNil(t, sectFr) require.NotNil(t, sectFr)
require.Equal(t, "fr", sectFr.Lang()) require.Equal(t, "fr", sectFr.Lang())
@ -351,12 +351,12 @@ func doTestMultiSitesBuild(t *testing.T, configTemplate, configSuffix string) {
nnSite := sites[2] nnSite := sites[2]
require.Equal(t, "nn", nnSite.Language.Lang) require.Equal(t, "nn", nnSite.Language.Lang)
taxNn := nnSite.getPage(KindTaxonomyTerm, "lag") taxNn, _ := nnSite.getPage(nil, "lag")
require.NotNil(t, taxNn) require.NotNil(t, taxNn)
require.Len(t, taxNn.Translations(), 1) require.Len(t, taxNn.Translations(), 1)
require.Equal(t, "nb", taxNn.Translations()[0].Lang()) require.Equal(t, "nb", taxNn.Translations()[0].Lang())
taxTermNn := nnSite.getPage(KindTaxonomy, "lag", "sogndal") taxTermNn, _ := nnSite.getPage(nil, "lag/sogndal")
require.NotNil(t, taxTermNn) require.NotNil(t, taxTermNn)
require.Len(t, taxTermNn.Translations(), 1) require.Len(t, taxTermNn.Translations(), 1)
require.Equal(t, "nb", taxTermNn.Translations()[0].Lang()) require.Equal(t, "nb", taxTermNn.Translations()[0].Lang())
@ -411,7 +411,7 @@ func doTestMultiSitesBuild(t *testing.T, configTemplate, configSuffix string) {
} }
// Check bundles // Check bundles
bundleFr := frSite.getPage(KindPage, "bundles/b1/index.md") bundleFr, _ := frSite.getPage(nil, "bundles/b1/index.md")
require.NotNil(t, bundleFr) require.NotNil(t, bundleFr)
require.Equal(t, "/blog/fr/bundles/b1/", bundleFr.RelPermalink()) require.Equal(t, "/blog/fr/bundles/b1/", bundleFr.RelPermalink())
require.Equal(t, 1, len(bundleFr.Resources)) require.Equal(t, 1, len(bundleFr.Resources))
@ -420,7 +420,7 @@ func doTestMultiSitesBuild(t *testing.T, configTemplate, configSuffix string) {
require.Equal(t, "/blog/fr/bundles/b1/logo.png", logoFr.RelPermalink()) require.Equal(t, "/blog/fr/bundles/b1/logo.png", logoFr.RelPermalink())
b.AssertFileContent("public/fr/bundles/b1/logo.png", "PNG Data") b.AssertFileContent("public/fr/bundles/b1/logo.png", "PNG Data")
bundleEn := enSite.getPage(KindPage, "bundles/b1/index.en.md") bundleEn, _ := enSite.getPage(nil, "bundles/b1/index.en.md")
require.NotNil(t, bundleEn) require.NotNil(t, bundleEn)
require.Equal(t, "/blog/en/bundles/b1/", bundleEn.RelPermalink()) require.Equal(t, "/blog/en/bundles/b1/", bundleEn.RelPermalink())
require.Equal(t, 1, len(bundleEn.Resources)) require.Equal(t, 1, len(bundleEn.Resources))
@ -582,7 +582,7 @@ func TestMultiSitesRebuild(t *testing.T) {
docFr := readDestination(t, fs, "public/fr/sect/doc1/index.html") docFr := readDestination(t, fs, "public/fr/sect/doc1/index.html")
require.True(t, strings.Contains(docFr, "Salut"), "No Salut") require.True(t, strings.Contains(docFr, "Salut"), "No Salut")
homeEn := enSite.getPage(KindHome) homeEn, _ := enSite.getPage(nil, "/")
require.NotNil(t, homeEn) require.NotNil(t, homeEn)
assert.Len(homeEn.Translations(), 3) assert.Len(homeEn.Translations(), 3)
require.Equal(t, "fr", homeEn.Translations()[0].Lang()) require.Equal(t, "fr", homeEn.Translations()[0].Lang())
@ -678,7 +678,7 @@ title = "Svenska"
require.True(t, svSite.Language.Lang == "sv", svSite.Language.Lang) require.True(t, svSite.Language.Lang == "sv", svSite.Language.Lang)
require.True(t, frSite.Language.Lang == "fr", frSite.Language.Lang) require.True(t, frSite.Language.Lang == "fr", frSite.Language.Lang)
homeEn := enSite.getPage(KindHome) homeEn, _ := enSite.getPage(nil, "/")
require.NotNil(t, homeEn) require.NotNil(t, homeEn)
require.Len(t, homeEn.Translations(), 4) require.Len(t, homeEn.Translations(), 4)
require.Equal(t, "sv", homeEn.Translations()[0].Lang()) require.Equal(t, "sv", homeEn.Translations()[0].Lang())

View file

@ -55,7 +55,7 @@ languageName = "Nynorsk"
s1 := b.H.Sites[0] s1 := b.H.Sites[0]
s1h := s1.getPage(KindHome) s1h, _ := s1.getPage(nil, "/")
assert.True(s1h.IsTranslated()) assert.True(s1h.IsTranslated())
assert.Len(s1h.Translations(), 2) assert.Len(s1h.Translations(), 2)
assert.Equal("https://example.com/docs/", s1h.Permalink()) assert.Equal("https://example.com/docs/", s1h.Permalink())
@ -66,7 +66,7 @@ languageName = "Nynorsk"
// For multihost, we never want any content in the root. // For multihost, we never want any content in the root.
// //
// check url in front matter: // check url in front matter:
pageWithURLInFrontMatter := s1.getPage(KindPage, "sect/doc3.en.md") pageWithURLInFrontMatter, _ := s1.getPage(nil, "sect/doc3.en.md")
assert.NotNil(pageWithURLInFrontMatter) assert.NotNil(pageWithURLInFrontMatter)
assert.Equal("/superbob", pageWithURLInFrontMatter.URL()) assert.Equal("/superbob", pageWithURLInFrontMatter.URL())
assert.Equal("/docs/superbob/", pageWithURLInFrontMatter.RelPermalink()) assert.Equal("/docs/superbob/", pageWithURLInFrontMatter.RelPermalink())
@ -78,7 +78,7 @@ languageName = "Nynorsk"
s2 := b.H.Sites[1] s2 := b.H.Sites[1]
s2h := s2.getPage(KindHome) s2h, _ := s2.getPage(nil, "/")
assert.Equal("https://example.fr/", s2h.Permalink()) assert.Equal("https://example.fr/", s2h.Permalink())
b.AssertFileContent("public/fr/index.html", "French Home Page") b.AssertFileContent("public/fr/index.html", "French Home Page")
@ -92,7 +92,7 @@ languageName = "Nynorsk"
// Check bundles // Check bundles
bundleEn := s1.getPage(KindPage, "bundles/b1/index.en.md") bundleEn, _ := s1.getPage(nil, "bundles/b1/index.en.md")
require.NotNil(t, bundleEn) require.NotNil(t, bundleEn)
require.Equal(t, "/docs/bundles/b1/", bundleEn.RelPermalink()) require.Equal(t, "/docs/bundles/b1/", bundleEn.RelPermalink())
require.Equal(t, 1, len(bundleEn.Resources)) require.Equal(t, 1, len(bundleEn.Resources))
@ -101,7 +101,7 @@ languageName = "Nynorsk"
require.Equal(t, "/docs/bundles/b1/logo.png", logoEn.RelPermalink()) require.Equal(t, "/docs/bundles/b1/logo.png", logoEn.RelPermalink())
b.AssertFileContent("public/en/bundles/b1/logo.png", "PNG Data") b.AssertFileContent("public/en/bundles/b1/logo.png", "PNG Data")
bundleFr := s2.getPage(KindPage, "bundles/b1/index.md") bundleFr, _ := s2.getPage(nil, "bundles/b1/index.md")
require.NotNil(t, bundleFr) require.NotNil(t, bundleFr)
require.Equal(t, "/bundles/b1/", bundleFr.RelPermalink()) require.Equal(t, "/bundles/b1/", bundleFr.RelPermalink())
require.Equal(t, 1, len(bundleFr.Resources)) require.Equal(t, 1, len(bundleFr.Resources))

View file

@ -244,7 +244,7 @@ Content.
b.AssertFileContent("/my/project/public/sv/sect/mybundle/logo.png", "PNG Data") b.AssertFileContent("/my/project/public/sv/sect/mybundle/logo.png", "PNG Data")
b.AssertFileContent("/my/project/public/nn/sect/mybundle/logo.png", "PNG Data") b.AssertFileContent("/my/project/public/nn/sect/mybundle/logo.png", "PNG Data")
nnSect := nnSite.getPage(KindSection, "sect") nnSect, _ := nnSite.getPage(nil, "sect")
assert.NotNil(nnSect) assert.NotNil(nnSect)
assert.Equal(12, len(nnSect.Pages)) assert.Equal(12, len(nnSect.Pages))
nnHome, _ := nnSite.Info.Home() nnHome, _ := nnSite.Info.Home()

View file

@ -1874,6 +1874,28 @@ func (p *Page) FullFilePath() string {
return filepath.Join(p.Dir(), p.LogicalName()) return filepath.Join(p.Dir(), p.LogicalName())
} }
// Returns the canonical, absolute fully-qualifed logical reference used by
// methods such as GetPage and ref/relref shortcodes to unambiguously refer to
// this page. As an absolute path, it is prefixed with a "/".
//
// For pages that have a backing file in the content directory, it is returns
// the path to this file as an absolute path rooted in the content dir. For
// pages or nodes that do not, it returns the virtual path, consistent with
// where you would add a backing content file.
//
// The "/" prefix and support for pages without backing files should be the
// only difference with FullFilePath()
func (p *Page) absoluteSourceRef() string {
sourcePath := p.Source.Path()
if sourcePath != "" {
return "/" + filepath.ToSlash(sourcePath)
} else if len(p.sections) > 0 {
// no backing file, return the virtual source path
return "/" + path.Join(p.sections...)
}
return ""
}
// Pre render prepare steps // Pre render prepare steps
func (p *Page) prepareLayouts() error { func (p *Page) prepareLayouts() error {
@ -2007,14 +2029,23 @@ func (p *Page) Hugo() *HugoInfo {
return hugoInfo return hugoInfo
} }
// GetPage looks up a page for the given ref.
// {{ with .GetPage "blog" }}{{ .Title }}{{ end }}
//
// This will return nil when no page could be found, and will return
// an error if the ref is ambiguous.
func (p *Page) GetPage(ref string) (*Page, error) {
return p.s.getPage(p, ref)
}
func (p *Page) Ref(refs ...string) (string, error) { func (p *Page) Ref(refs ...string) (string, error) {
if len(refs) == 0 { if len(refs) == 0 {
return "", nil return "", nil
} }
if len(refs) > 1 { if len(refs) > 1 {
return p.Site.Ref(refs[0], nil, refs[1]) return p.Site.Ref(refs[0], p, refs[1])
} }
return p.Site.Ref(refs[0], nil) return p.Site.Ref(refs[0], p)
} }
func (p *Page) RelRef(refs ...string) (string, error) { func (p *Page) RelRef(refs ...string) (string, error) {
@ -2022,17 +2053,16 @@ func (p *Page) RelRef(refs ...string) (string, error) {
return "", nil return "", nil
} }
if len(refs) > 1 { if len(refs) > 1 {
return p.Site.RelRef(refs[0], nil, refs[1]) return p.Site.RelRef(refs[0], p, refs[1])
} }
return p.Site.RelRef(refs[0], nil) return p.Site.RelRef(refs[0], p)
} }
func (p *Page) String() string { func (p *Page) String() string {
if p.Path() != "" { if p.absoluteSourceRef() != "" {
return fmt.Sprintf("Page(%s)", p.Path()) return fmt.Sprintf("Page(%s)", p.absoluteSourceRef())
} }
return fmt.Sprintf("Page(%q)", p.title) return fmt.Sprintf("Page(%q)", p.title)
} }
// Scratch returns the writable context associated with this Page. // Scratch returns the writable context associated with this Page.

View file

@ -48,6 +48,7 @@ func TestPageBundlerSiteRegular(t *testing.T) {
for _, ugly := range []bool{false, true} { for _, ugly := range []bool{false, true} {
t.Run(fmt.Sprintf("ugly=%t", ugly), t.Run(fmt.Sprintf("ugly=%t", ugly),
func(t *testing.T) { func(t *testing.T) {
var samePage *Page
assert := require.New(t) assert := require.New(t)
fs, cfg := newTestBundleSources(t) fs, cfg := newTestBundleSources(t)
@ -83,12 +84,14 @@ func TestPageBundlerSiteRegular(t *testing.T) {
assert.Len(s.RegularPages, 8) assert.Len(s.RegularPages, 8)
singlePage := s.getPage(KindPage, "a/1.md") singlePage, _ := s.getPage(nil, "a/1.md")
assert.Equal("", singlePage.BundleType()) assert.Equal("", singlePage.BundleType())
assert.NotNil(singlePage) assert.NotNil(singlePage)
assert.Equal(singlePage, s.getPage("page", "a/1")) samePage, _ = s.getPage(nil, "a/1")
assert.Equal(singlePage, s.getPage("page", "1")) assert.Equal(singlePage, samePage)
samePage, _ = s.getPage(nil, "1")
assert.Equal(singlePage, samePage)
assert.Contains(singlePage.content(), "TheContent") assert.Contains(singlePage.content(), "TheContent")
@ -106,18 +109,18 @@ func TestPageBundlerSiteRegular(t *testing.T) {
// This should be just copied to destination. // This should be just copied to destination.
th.assertFileContent(filepath.FromSlash("/work/public/assets/pic1.png"), "content") th.assertFileContent(filepath.FromSlash("/work/public/assets/pic1.png"), "content")
leafBundle1 := s.getPage(KindPage, "b/my-bundle/index.md") leafBundle1, _ := s.getPage(nil, "b/my-bundle/index.md")
assert.NotNil(leafBundle1) assert.NotNil(leafBundle1)
assert.Equal("leaf", leafBundle1.BundleType()) assert.Equal("leaf", leafBundle1.BundleType())
assert.Equal("b", leafBundle1.Section()) assert.Equal("b", leafBundle1.Section())
sectionB := s.getPage(KindSection, "b") sectionB, _ := s.getPage(nil, "/b")
assert.NotNil(sectionB) assert.NotNil(sectionB)
home, _ := s.Info.Home() home, _ := s.Info.Home()
assert.Equal("branch", home.BundleType()) assert.Equal("branch", home.BundleType())
// This is a root bundle and should live in the "home section" // This is a root bundle and should live in the "home section"
// See https://github.com/gohugoio/hugo/issues/4332 // See https://github.com/gohugoio/hugo/issues/4332
rootBundle := s.getPage(KindPage, "root") rootBundle, _ := s.getPage(nil, "root")
assert.NotNil(rootBundle) assert.NotNil(rootBundle)
assert.True(rootBundle.Parent().IsHome()) assert.True(rootBundle.Parent().IsHome())
if ugly { if ugly {
@ -126,9 +129,9 @@ func TestPageBundlerSiteRegular(t *testing.T) {
assert.Equal("/root/", rootBundle.RelPermalink()) assert.Equal("/root/", rootBundle.RelPermalink())
} }
leafBundle2 := s.getPage(KindPage, "a/b/index.md") leafBundle2, _ := s.getPage(nil, "a/b/index.md")
assert.NotNil(leafBundle2) assert.NotNil(leafBundle2)
unicodeBundle := s.getPage(KindPage, "c/bundle/index.md") unicodeBundle, _ := s.getPage(nil, "c/bundle/index.md")
assert.NotNil(unicodeBundle) assert.NotNil(unicodeBundle)
pageResources := leafBundle1.Resources.ByType(pageResourceType) pageResources := leafBundle1.Resources.ByType(pageResourceType)
@ -211,6 +214,7 @@ func TestPageBundlerSiteMultilingual(t *testing.T) {
for _, ugly := range []bool{false, true} { for _, ugly := range []bool{false, true} {
t.Run(fmt.Sprintf("ugly=%t", ugly), t.Run(fmt.Sprintf("ugly=%t", ugly),
func(t *testing.T) { func(t *testing.T) {
var samePage *Page
assert := require.New(t) assert := require.New(t)
fs, cfg := newTestBundleSourcesMultilingual(t) fs, cfg := newTestBundleSourcesMultilingual(t)
@ -230,7 +234,7 @@ func TestPageBundlerSiteMultilingual(t *testing.T) {
assert.Equal(16, len(s.Pages)) assert.Equal(16, len(s.Pages))
assert.Equal(31, len(s.AllPages)) assert.Equal(31, len(s.AllPages))
bundleWithSubPath := s.getPage(KindPage, "lb/index") bundleWithSubPath, _ := s.getPage(nil, "lb/index")
assert.NotNil(bundleWithSubPath) assert.NotNil(bundleWithSubPath)
// See https://github.com/gohugoio/hugo/issues/4312 // See https://github.com/gohugoio/hugo/issues/4312
@ -244,22 +248,28 @@ func TestPageBundlerSiteMultilingual(t *testing.T) {
// and probably also just b (aka "my-bundle") // and probably also just b (aka "my-bundle")
// These may also be translated, so we also need to test that. // These may also be translated, so we also need to test that.
// "bf", "my-bf-bundle", "index.md + nn // "bf", "my-bf-bundle", "index.md + nn
bfBundle := s.getPage(KindPage, "bf/my-bf-bundle/index") bfBundle, _ := s.getPage(nil, "bf/my-bf-bundle/index")
assert.NotNil(bfBundle) assert.NotNil(bfBundle)
assert.Equal("en", bfBundle.Lang()) assert.Equal("en", bfBundle.Lang())
assert.Equal(bfBundle, s.getPage(KindPage, "bf/my-bf-bundle/index.md")) samePage, _ = s.getPage(nil, "bf/my-bf-bundle/index.md")
assert.Equal(bfBundle, s.getPage(KindPage, "bf/my-bf-bundle")) assert.Equal(bfBundle, samePage)
assert.Equal(bfBundle, s.getPage(KindPage, "my-bf-bundle")) samePage, _ = s.getPage(nil, "bf/my-bf-bundle")
assert.Equal(bfBundle, samePage)
samePage, _ = s.getPage(nil, "my-bf-bundle")
assert.Equal(bfBundle, samePage)
nnSite := sites.Sites[1] nnSite := sites.Sites[1]
assert.Equal(7, len(nnSite.RegularPages)) assert.Equal(7, len(nnSite.RegularPages))
bfBundleNN := nnSite.getPage(KindPage, "bf/my-bf-bundle/index") bfBundleNN, _ := nnSite.getPage(nil, "bf/my-bf-bundle/index")
assert.NotNil(bfBundleNN) assert.NotNil(bfBundleNN)
assert.Equal("nn", bfBundleNN.Lang()) assert.Equal("nn", bfBundleNN.Lang())
assert.Equal(bfBundleNN, nnSite.getPage(KindPage, "bf/my-bf-bundle/index.nn.md")) samePage, _ = nnSite.getPage(nil, "bf/my-bf-bundle/index.nn.md")
assert.Equal(bfBundleNN, nnSite.getPage(KindPage, "bf/my-bf-bundle")) assert.Equal(bfBundleNN, samePage)
assert.Equal(bfBundleNN, nnSite.getPage(KindPage, "my-bf-bundle")) samePage, _ = nnSite.getPage(nil, "bf/my-bf-bundle")
assert.Equal(bfBundleNN, samePage)
samePage, _ = nnSite.getPage(nil, "my-bf-bundle")
assert.Equal(bfBundleNN, samePage)
// See https://github.com/gohugoio/hugo/issues/4295 // See https://github.com/gohugoio/hugo/issues/4295
// Every resource should have its Name prefixed with its base folder. // Every resource should have its Name prefixed with its base folder.
@ -334,7 +344,7 @@ func TestPageBundlerSiteWitSymbolicLinksInContent(t *testing.T) {
th := testHelper{s.Cfg, s.Fs, t} th := testHelper{s.Cfg, s.Fs, t}
assert.Equal(7, len(s.RegularPages)) assert.Equal(7, len(s.RegularPages))
a1Bundle := s.getPage(KindPage, "symbolic2/a1/index.md") a1Bundle, _ := s.getPage(nil, "symbolic2/a1/index.md")
assert.NotNil(a1Bundle) assert.NotNil(a1Bundle)
assert.Equal(2, len(a1Bundle.Resources)) assert.Equal(2, len(a1Bundle.Resources))
assert.Equal(1, len(a1Bundle.Resources.ByType(pageResourceType))) assert.Equal(1, len(a1Bundle.Resources.ByType(pageResourceType)))
@ -394,10 +404,10 @@ HEADLESS {{< myShort >}}
assert.Equal(1, len(s.RegularPages)) assert.Equal(1, len(s.RegularPages))
assert.Equal(1, len(s.headlessPages)) assert.Equal(1, len(s.headlessPages))
regular := s.getPage(KindPage, "a/index") regular, _ := s.getPage(nil, "a/index")
assert.Equal("/a/s1/", regular.RelPermalink()) assert.Equal("/a/s1/", regular.RelPermalink())
headless := s.getPage(KindPage, "b/index") headless, _ := s.getPage(nil, "b/index")
assert.NotNil(headless) assert.NotNil(headless)
assert.True(headless.headless) assert.True(headless.headless)
assert.Equal("Headless Bundle in Topless Bar", headless.Title()) assert.Equal("Headless Bundle in Topless Bar", headless.Title())

View file

@ -14,11 +14,12 @@
package hugolib package hugolib
import ( import (
"fmt"
"path" "path"
"path/filepath" "path/filepath"
"strings" "strings"
"sync"
"github.com/gohugoio/hugo/cache"
"github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/helpers"
) )
@ -48,9 +49,30 @@ type PageCollections struct {
// Includes headless bundles, i.e. bundles that produce no output for its content page. // Includes headless bundles, i.e. bundles that produce no output for its content page.
headlessPages Pages headlessPages Pages
pageCache *cache.PartitionedLazyCache pageIndex
} }
type pageIndex struct {
initSync sync.Once
index map[string]*Page
load func() map[string]*Page
}
func (pi *pageIndex) init() {
pi.initSync.Do(func() {
pi.index = pi.load()
})
}
// Get initializes the index if not already done so, then
// looks up the given page ref, returns nil if no value found.
func (pi *pageIndex) Get(ref string) *Page {
pi.init()
return pi.index[ref]
}
var ambiguityFlag = &Page{Kind: "dummy", title: "ambiguity flag"}
func (c *PageCollections) refreshPageCaches() { func (c *PageCollections) refreshPageCaches() {
c.indexPages = c.findPagesByKindNotIn(KindPage, c.Pages) c.indexPages = c.findPagesByKindNotIn(KindPage, c.Pages)
c.RegularPages = c.findPagesByKindIn(KindPage, c.Pages) c.RegularPages = c.findPagesByKindIn(KindPage, c.Pages)
@ -62,60 +84,82 @@ func (c *PageCollections) refreshPageCaches() {
s = c.Pages[0].s s = c.Pages[0].s
} }
cacheLoader := func(kind string) func() (map[string]interface{}, error) { indexLoader := func() map[string]*Page {
return func() (map[string]interface{}, error) { index := make(map[string]*Page)
cache := make(map[string]interface{})
switch kind {
case KindPage:
// Note that we deliberately use the pages from all sites // Note that we deliberately use the pages from all sites
// in this cache, as we intend to use this in the ref and relref // in this index, as we intend to use this in the ref and relref
// shortcodes. If the user says "sect/doc1.en.md", he/she knows // shortcodes. If the user says "sect/doc1.en.md", he/she knows
// what he/she is looking for. // what he/she is looking for.
for _, pageCollection := range []Pages{c.AllRegularPages, c.headlessPages} { for _, pageCollection := range []Pages{c.AllRegularPages, c.headlessPages} {
for _, p := range pageCollection { for _, p := range pageCollection {
cache[filepath.ToSlash(p.Source.Path())] = p
sourceRef := p.absoluteSourceRef()
if sourceRef != "" {
// index the canonical, unambiguous ref
// e.g. /section/article.md
indexPage(index, sourceRef, p)
// also index the legacy canonical lookup (not guaranteed to be unambiguous)
// e.g. section/article.md
indexPage(index, sourceRef[1:], p)
}
if s != nil && p.s == s { if s != nil && p.s == s {
// Ref/Relref supports this potentially ambiguous lookup. // Ref/Relref supports this potentially ambiguous lookup.
cache[p.Source.LogicalName()] = p indexPage(index, p.Source.LogicalName(), p)
translasionBaseName := p.Source.TranslationBaseName() translationBaseName := p.Source.TranslationBaseName()
dir := filepath.ToSlash(strings.TrimSuffix(p.Dir(), helpers.FilePathSeparator)) dir := filepath.ToSlash(strings.TrimSuffix(p.Dir(), helpers.FilePathSeparator))
if translasionBaseName == "index" { if translationBaseName == "index" {
_, name := path.Split(dir) _, name := path.Split(dir)
cache[name] = p indexPage(index, name, p)
cache[dir] = p indexPage(index, dir, p)
} else { } else {
// Again, ambigous // Again, ambiguous
cache[translasionBaseName] = p indexPage(index, translationBaseName, p)
} }
// We need a way to get to the current language version. // We need a way to get to the current language version.
pathWithNoExtensions := path.Join(dir, translasionBaseName) pathWithNoExtensions := path.Join(dir, translationBaseName)
cache[pathWithNoExtensions] = p indexPage(index, pathWithNoExtensions, p)
}
} }
} }
}
default:
for _, p := range c.indexPages { for _, p := range c.indexPages {
key := path.Join(p.sections...) // index the canonical, unambiguous ref for any backing file
cache[key] = p // e.g. /section/_index.md
} sourceRef := p.absoluteSourceRef()
if sourceRef != "" {
indexPage(index, sourceRef, p)
} }
return cache, nil ref := path.Join(p.sections...)
// index the canonical, unambiguous virtual ref
// e.g. /section
// (this may already have been indexed above)
indexPage(index, "/"+ref, p)
// index the legacy canonical ref (not guaranteed to be unambiguous)
// e.g. section
indexPage(index, ref, p)
} }
return index
} }
partitions := make([]cache.Partition, len(allKindsInPages)) c.pageIndex = pageIndex{load: indexLoader}
for i, kind := range allKindsInPages {
partitions[i] = cache.Partition{Key: kind, Load: cacheLoader(kind)}
} }
c.pageCache = cache.NewPartitionedLazyCache(partitions...) func indexPage(index map[string]*Page, ref string, p *Page) {
existing := index[ref]
if existing == nil {
index[ref] = p
} else if existing != ambiguityFlag && existing != p {
index[ref] = ambiguityFlag
}
} }
func newPageCollections() *PageCollections { func newPageCollections() *PageCollections {
@ -126,20 +170,39 @@ func newPageCollectionsFromPages(pages Pages) *PageCollections {
return &PageCollections{rawAllPages: pages} return &PageCollections{rawAllPages: pages}
} }
func (c *PageCollections) getPage(typ string, sections ...string) *Page { // context: page used to resolve relative paths
var key string // ref: either unix-style paths (i.e. callers responsible for
if len(sections) == 1 { // calling filepath.ToSlash as necessary) or shorthand refs.
key = filepath.ToSlash(sections[0]) func (c *PageCollections) getPage(context *Page, ref string) (*Page, error) {
} else {
key = path.Join(sections...) var result *Page
if len(ref) > 0 && ref[0:1] == "/" {
// it's an absolute path
result = c.pageIndex.Get(ref)
} else { // either relative path or other supported ref
// If there's a page context. relative ref interpretation takes precedence.
if context != nil {
// For relative refs `filepath.Join` will properly resolve ".." (parent dir)
// and other elements in the path
apath := path.Join("/", strings.Join(context.sections, "/"), ref)
result = c.pageIndex.Get(apath)
} }
p, _ := c.pageCache.Get(typ, key) // finally, let's try it as-is for a match against all the alternate refs indexed for each page
if p == nil { if result == nil {
return nil result = c.pageIndex.Get(ref)
}
return p.(*Page)
if result == ambiguityFlag {
return nil, fmt.Errorf("The reference \"%s\" in %q resolves to more than one page. Use either an absolute path (begins with \"/\") or relative path to the content directory target.", ref, context.absoluteSourceRef())
}
}
}
return result, nil
} }
func (*PageCollections) findPagesByKindIn(kind string, inPages Pages) Pages { func (*PageCollections) findPagesByKindIn(kind string, inPages Pages) Pages {

View file

@ -55,12 +55,12 @@ func BenchmarkGetPage(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
home := s.getPage(KindHome) home, _ := s.getPage(nil, "/")
if home == nil { if home == nil {
b.Fatal("Home is nil") b.Fatal("Home is nil")
} }
p := s.getPage(KindSection, pagePaths[i]) p, _ := s.getPage(nil, pagePaths[i])
if p == nil { if p == nil {
b.Fatal("Section is nil") b.Fatal("Section is nil")
} }
@ -91,7 +91,7 @@ func BenchmarkGetPageRegular(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
page := s.getPage(KindPage, pagePaths[i]) page, _ := s.getPage(nil, pagePaths[i])
require.NotNil(b, page) require.NotNil(b, page)
} }
} }
@ -131,10 +131,27 @@ func TestGetPage(t *testing.T) {
for i, test := range tests { for i, test := range tests {
errorMsg := fmt.Sprintf("Test %d", i) errorMsg := fmt.Sprintf("Test %d", i)
page := s.getPage(test.kind, test.path...)
// test legacy public Site.GetPage
page, _ := s.Info.GetPage(test.kind, test.path...)
assert.NotNil(page, errorMsg) assert.NotNil(page, errorMsg)
assert.Equal(test.kind, page.Kind, errorMsg) assert.Equal(test.kind, page.Kind, errorMsg)
assert.Equal(test.expectedTitle, page.title) assert.Equal(test.expectedTitle, page.title)
// test new internal Site.getPage
var ref string
if len(test.path) == 1 {
ref = filepath.ToSlash(test.path[0])
} else {
ref = path.Join(test.path...)
} }
page2, _ := s.getPage(nil, ref)
assert.NotNil(page2, errorMsg)
assert.Equal(test.kind, page2.Kind, errorMsg)
assert.Equal(test.expectedTitle, page2.title)
}
// vas(todo) add ambiguity detection tests
} }

View file

@ -68,8 +68,8 @@ func TestMergeLanguages(t *testing.T) {
assert.Equal(4, len(firstNN.Sites())) assert.Equal(4, len(firstNN.Sites()))
assert.Equal("en", firstNN.Sites().First().Language.Lang) assert.Equal("en", firstNN.Sites().First().Language.Lang)
nnBundle := nnSite.getPage("page", "bundle") nnBundle, _ := nnSite.getPage(nil, "bundle")
enBundle := enSite.getPage("page", "bundle") enBundle, _ := enSite.getPage(nil, "bundle")
assert.Equal(6, len(enBundle.Resources)) assert.Equal(6, len(enBundle.Resources))
assert.Equal(2, len(nnBundle.Resources)) assert.Equal(2, len(nnBundle.Resources))

View file

@ -687,7 +687,7 @@ NotFound: {{< thisDoesNotExist >}}
require.Len(t, h.Sites, 1) require.Len(t, h.Sites, 1)
s := h.Sites[0] s := h.Sites[0]
home := s.getPage(KindHome) home, _ := s.getPage(nil, "/")
require.NotNil(t, home) require.NotNil(t, home)
require.Len(t, home.outputFormats, 3) require.Len(t, home.outputFormats, 3)

View file

@ -21,6 +21,7 @@ import (
"mime" "mime"
"net/url" "net/url"
"os" "os"
"path"
"path/filepath" "path/filepath"
"sort" "sort"
"strconv" "strconv"
@ -492,7 +493,6 @@ func (s *SiteInfo) refLink(ref string, page *Page, relative bool, outputFormat s
var err error var err error
ref = filepath.ToSlash(ref) ref = filepath.ToSlash(ref)
ref = strings.TrimPrefix(ref, "/")
refURL, err = url.Parse(ref) refURL, err = url.Parse(ref)
@ -504,7 +504,11 @@ func (s *SiteInfo) refLink(ref string, page *Page, relative bool, outputFormat s
var link string var link string
if refURL.Path != "" { if refURL.Path != "" {
target := s.getPage(KindPage, refURL.Path) target, err := s.getPage(page, refURL.Path)
if err != nil {
return "", err
}
if target == nil { if target == nil {
return "", fmt.Errorf("No page found with path or logical name \"%s\".\n", refURL.Path) return "", fmt.Errorf("No page found with path or logical name \"%s\".\n", refURL.Path)
@ -1598,13 +1602,20 @@ func (s *Site) appendThemeTemplates(in []string) []string {
} }
// GetPage looks up a page of a given type in the path given. // GetPage looks up a page of a given type for the given ref.
// {{ with .Site.GetPage "section" "blog" }}{{ .Title }}{{ end }} // {{ with .Site.GetPage "section" "blog" }}{{ .Title }}{{ end }}
// //
// This will return nil when no page could be found, and will return the // This will return nil when no page could be found, and will return an
// first page found if the key is ambigous. // error if the key is ambiguous.
func (s *SiteInfo) GetPage(typ string, path ...string) (*Page, error) { func (s *SiteInfo) GetPage(typ string, ref ...string) (*Page, error) {
return s.getPage(typ, path...), nil var key string
if len(ref) == 1 {
key = filepath.ToSlash(ref[0])
} else {
key = path.Join(ref...)
}
return s.getPage(nil, key)
} }
func (s *Site) permalinkForOutputFormat(link string, f output.Format) (string, error) { func (s *Site) permalinkForOutputFormat(link string, f output.Format) (string, error) {

View file

@ -150,7 +150,7 @@ Len Pages: {{ .Kind }} {{ len .Site.RegularPages }} Page Number: {{ .Paginator.P
s := h.Sites[0] s := h.Sites[0]
require.Equal(t, "en", s.Language.Lang) require.Equal(t, "en", s.Language.Lang)
home := s.getPage(KindHome) home, _ := s.getPage(nil, "/")
require.NotNil(t, home) require.NotNil(t, home)
@ -325,7 +325,7 @@ baseName = "customdelimbase"
th.assertFileContent("public/customdelimbase_del", "custom delim") th.assertFileContent("public/customdelimbase_del", "custom delim")
s := h.Sites[0] s := h.Sites[0]
home := s.getPage(KindHome) home, _ := s.getPage(nil, "/")
require.NotNil(t, home) require.NotNil(t, home)
outputs := home.OutputFormats() outputs := home.OutputFormats()

View file

@ -135,19 +135,19 @@ PAG|{{ .Title }}|{{ $sect.InSection . }}
}}, }},
{"empty1", func(p *Page) { {"empty1", func(p *Page) {
// > b,c // > b,c
assert.NotNil(p.s.getPage(KindSection, "empty1", "b")) assert.NotNil(p.s.getPage(nil, "empty1/b"))
assert.NotNil(p.s.getPage(KindSection, "empty1", "b", "c")) assert.NotNil(p.s.getPage(nil, "empty1/b/c"))
}}, }},
{"empty2", func(p *Page) { {"empty2", func(p *Page) {
// > b,c,d where b and d have content files. // > b,c,d where b and d have content files.
b := p.s.getPage(KindSection, "empty2", "b") b, _ := p.s.getPage(nil, "empty2/b")
assert.NotNil(b) assert.NotNil(b)
assert.Equal("T40_-1", b.title) assert.Equal("T40_-1", b.title)
c := p.s.getPage(KindSection, "empty2", "b", "c") c, _ := p.s.getPage(nil, "empty2/b/c")
assert.NotNil(c) assert.NotNil(c)
assert.Equal("Cs", c.title) assert.Equal("Cs", c.title)
d := p.s.getPage(KindSection, "empty2", "b", "c", "d") d, _ := p.s.getPage(nil, "empty2/b/c/d")
assert.NotNil(d) assert.NotNil(d)
assert.Equal("T41_-1", d.title) assert.Equal("T41_-1", d.title)
@ -156,9 +156,9 @@ PAG|{{ .Title }}|{{ $sect.InSection . }}
assert.False(c.Eq("asdf")) assert.False(c.Eq("asdf"))
}}, }},
{"empty3", func(p *Page) { {"/empty3", func(p *Page) {
// b,c,d with regular page in b // b,c,d with regular page in b
b := p.s.getPage(KindSection, "empty3", "b") b, _ := p.s.getPage(nil, "/empty3/b")
assert.NotNil(b) assert.NotNil(b)
assert.Len(b.Pages, 1) assert.Len(b.Pages, 1)
assert.Equal("empty3.md", b.Pages[0].File.LogicalName()) assert.Equal("empty3.md", b.Pages[0].File.LogicalName())
@ -200,7 +200,8 @@ PAG|{{ .Title }}|{{ $sect.InSection . }}
active, err = p.InSection(child) active, err = p.InSection(child)
assert.NoError(err) assert.NoError(err)
assert.True(active) assert.True(active)
active, err = p.InSection(p.s.getPage(KindHome)) homePage, _ := p.s.getPage(nil, "/")
active, err = p.InSection(homePage)
assert.NoError(err) assert.NoError(err)
assert.False(active) assert.False(active)
@ -235,7 +236,7 @@ PAG|{{ .Title }}|{{ $sect.InSection . }}
assert.Equal("T2_-1", p.Parent().title) assert.Equal("T2_-1", p.Parent().title)
assert.Len(p.Sections(), 0) assert.Len(p.Sections(), 0)
l1 := p.s.getPage(KindSection, "l1") l1, _ := p.s.getPage(nil, "l1")
isDescendant, err := l1.IsDescendant(p) isDescendant, err := l1.IsDescendant(p)
assert.NoError(err) assert.NoError(err)
assert.False(isDescendant) assert.False(isDescendant)
@ -265,16 +266,18 @@ PAG|{{ .Title }}|{{ $sect.InSection . }}
}}, }},
} }
home := s.getPage(KindHome) home, _ := s.getPage(nil, "/")
for _, test := range tests { for _, test := range tests {
sections := strings.Split(test.sections, ",") sections := strings.Split(test.sections, ",")
p := s.getPage(KindSection, sections...) p, _ := s.Info.GetPage(KindSection, sections...)
assert.NotNil(p, fmt.Sprint(sections)) assert.NotNil(p, fmt.Sprint(sections))
if p.Pages != nil { if p.Pages != nil {
assert.Equal(p.Pages, p.data["Pages"]) assert.Equal(p.Pages, p.data["Pages"])
} }
fmt.Println(p, test.sections)
assert.NotNil(p.Parent(), fmt.Sprintf("Parent nil: %q", test.sections)) assert.NotNil(p.Parent(), fmt.Sprintf("Parent nil: %q", test.sections))
test.verify(p) test.verify(p)
} }
@ -284,7 +287,7 @@ PAG|{{ .Title }}|{{ $sect.InSection . }}
assert.Len(home.Sections(), 9) assert.Len(home.Sections(), 9)
assert.Equal(home.Sections(), s.Info.Sections()) assert.Equal(home.Sections(), s.Info.Sections())
rootPage := s.getPage(KindPage, "mypage.md") rootPage, _ := s.getPage(nil, "mypage.md")
assert.NotNil(rootPage) assert.NotNil(rootPage)
assert.True(rootPage.Parent().IsHome()) assert.True(rootPage.Parent().IsHome())
@ -294,7 +297,7 @@ PAG|{{ .Title }}|{{ $sect.InSection . }}
// If we later decide to do something about this, we will have to do some normalization in // If we later decide to do something about this, we will have to do some normalization in
// getPage. // getPage.
// TODO(bep) // TODO(bep)
sectionWithSpace := s.getPage(KindSection, "Spaces in Section") sectionWithSpace, _ := s.getPage(nil, "Spaces in Section")
require.NotNil(t, sectionWithSpace) require.NotNil(t, sectionWithSpace)
require.Equal(t, "/spaces-in-section/", sectionWithSpace.RelPermalink()) require.Equal(t, "/spaces-in-section/", sectionWithSpace.RelPermalink())

View file

@ -628,7 +628,8 @@ func TestOrderedPages(t *testing.T) {
s := buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg}, BuildCfg{SkipRender: true}) s := buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg}, BuildCfg{SkipRender: true})
if s.getPage(KindSection, "sect").Pages[1].title != "Three" || s.getPage(KindSection, "sect").Pages[2].title != "Four" { sect, _ := s.getPage(nil, "sect")
if sect.Pages[1].title != "Three" || sect.Pages[2].title != "Four" {
t.Error("Pages in unexpected order.") t.Error("Pages in unexpected order.")
} }
@ -874,8 +875,10 @@ func TestWeightedTaxonomies(t *testing.T) {
func setupLinkingMockSite(t *testing.T) *Site { func setupLinkingMockSite(t *testing.T) *Site {
sources := [][2]string{ sources := [][2]string{
{filepath.FromSlash("level2/unique.md"), ""}, {filepath.FromSlash("level2/unique.md"), ""},
{filepath.FromSlash("_index.md"), ""},
{filepath.FromSlash("rootfile.md"), ""}, {filepath.FromSlash("rootfile.md"), ""},
{filepath.FromSlash("root-image.png"), ""}, {filepath.FromSlash("root-image.png"), ""},
{filepath.FromSlash("common.md"), ""},
{filepath.FromSlash("level2/2-root.md"), ""}, {filepath.FromSlash("level2/2-root.md"), ""},
{filepath.FromSlash("level2/common.md"), ""}, {filepath.FromSlash("level2/common.md"), ""},
@ -883,7 +886,7 @@ func setupLinkingMockSite(t *testing.T) *Site {
{filepath.FromSlash("level2/2-image.png"), ""}, {filepath.FromSlash("level2/2-image.png"), ""},
{filepath.FromSlash("level2/common.png"), ""}, {filepath.FromSlash("level2/common.png"), ""},
{filepath.FromSlash("level2/level3/start.md"), ""}, {filepath.FromSlash("level2/level3/current.md"), ""},
{filepath.FromSlash("level2/level3/3-root.md"), ""}, {filepath.FromSlash("level2/level3/3-root.md"), ""},
{filepath.FromSlash("level2/level3/common.md"), ""}, {filepath.FromSlash("level2/level3/common.md"), ""},
{filepath.FromSlash("level2/level3/3-image.png"), ""}, {filepath.FromSlash("level2/level3/3-image.png"), ""},
@ -910,7 +913,7 @@ func TestRefLinking(t *testing.T) {
t.Parallel() t.Parallel()
site := setupLinkingMockSite(t) site := setupLinkingMockSite(t)
currentPage := site.getPage(KindPage, "level2/level3/start.md") currentPage, _ := site.getPage(nil, "level2/level3/current.md")
if currentPage == nil { if currentPage == nil {
t.Fatalf("failed to find current page in site") t.Fatalf("failed to find current page in site")
} }
@ -921,12 +924,16 @@ func TestRefLinking(t *testing.T) {
relative bool relative bool
expected string expected string
}{ }{
{"unique.md", "", true, "/level2/unique/"}, {"/level2/unique.md", "", true, "/level2/unique/"},
{"level2/common.md", "", true, "/level2/common/"}, {"../unique.md", "", true, "/level2/unique/"},
{"/level2/common.md", "", true, "/level2/common/"},
{"../common.md", "", true, "/level2/common/"},
{"common.md", "", true, "/level2/level3/common/"},
{"/common.md", "", true, "/common/"},
{"3-root.md", "", true, "/level2/level3/3-root/"}, {"3-root.md", "", true, "/level2/level3/3-root/"},
} { } {
if out, err := site.Info.refLink(test.link, currentPage, test.relative, test.outputFormat); err != nil || out != test.expected { if out, err := site.Info.refLink(test.link, currentPage, test.relative, test.outputFormat); err != nil || out != test.expected {
t.Errorf("[%d] Expected %s to resolve to (%s), got (%s) - error: %s", i, test.link, test.expected, out, err) t.Errorf("[%d] Expected %q from %q to resolve to %q, got %q - error: %s", i, test.link, currentPage.absoluteSourceRef(), test.expected, out, err)
} }
} }

View file

@ -117,12 +117,12 @@ Do not go gentle into that good night.
assert.Len(s.RegularPages, 2) assert.Len(s.RegularPages, 2)
notUgly := s.getPage(KindPage, "sect1/p1.md") notUgly, _ := s.getPage(nil, "sect1/p1.md")
assert.NotNil(notUgly) assert.NotNil(notUgly)
assert.Equal("sect1", notUgly.Section()) assert.Equal("sect1", notUgly.Section())
assert.Equal("/sect1/p1/", notUgly.RelPermalink()) assert.Equal("/sect1/p1/", notUgly.RelPermalink())
ugly := s.getPage(KindPage, "sect2/p2.md") ugly, _ := s.getPage(nil, "sect2/p2.md")
assert.NotNil(ugly) assert.NotNil(ugly)
assert.Equal("sect2", ugly.Section()) assert.Equal("sect2", ugly.Section())
assert.Equal("/sect2/p2.html", ugly.RelPermalink()) assert.Equal("/sect2/p2.html", ugly.RelPermalink())
@ -175,7 +175,7 @@ Do not go gentle into that good night.
assert.Len(s.RegularPages, 10) assert.Len(s.RegularPages, 10)
sect1 := s.getPage(KindSection, "sect1") sect1, _ := s.getPage(nil, "sect1")
assert.NotNil(sect1) assert.NotNil(sect1)
assert.Equal("/ss1/", sect1.RelPermalink()) assert.Equal("/ss1/", sect1.RelPermalink())
th.assertFileContent(filepath.Join("public", "ss1", "index.html"), "P1|URL: /ss1/|Next: /ss1/page/2/") th.assertFileContent(filepath.Join("public", "ss1", "index.html"), "P1|URL: /ss1/|Next: /ss1/page/2/")

View file

@ -167,7 +167,7 @@ permalinkeds:
} }
for taxonomy, count := range taxonomyTermPageCounts { for taxonomy, count := range taxonomyTermPageCounts {
term := s.getPage(KindTaxonomyTerm, taxonomy) term, _ := s.getPage(nil, taxonomy)
require.NotNil(t, term) require.NotNil(t, term)
require.Len(t, term.Pages, count) require.Len(t, term.Pages, count)
@ -176,7 +176,7 @@ permalinkeds:
} }
} }
cat1 := s.getPage(KindTaxonomy, "categories", "cat1") cat1, _ := s.getPage(nil, "categories/cat1")
require.NotNil(t, cat1) require.NotNil(t, cat1)
if uglyURLs { if uglyURLs {
require.Equal(t, "/blog/categories/cat1.html", cat1.RelPermalink()) require.Equal(t, "/blog/categories/cat1.html", cat1.RelPermalink())
@ -184,8 +184,8 @@ permalinkeds:
require.Equal(t, "/blog/categories/cat1/", cat1.RelPermalink()) require.Equal(t, "/blog/categories/cat1/", cat1.RelPermalink())
} }
pl1 := s.getPage(KindTaxonomy, "permalinkeds", "pl1") pl1, _ := s.getPage(nil, "permalinkeds/pl1")
permalinkeds := s.getPage(KindTaxonomyTerm, "permalinkeds") permalinkeds, _ := s.getPage(nil, "permalinkeds")
require.NotNil(t, pl1) require.NotNil(t, pl1)
require.NotNil(t, permalinkeds) require.NotNil(t, permalinkeds)
if uglyURLs { if uglyURLs {
@ -198,11 +198,11 @@ permalinkeds:
// Issue #3070 preserveTaxonomyNames // Issue #3070 preserveTaxonomyNames
if preserveTaxonomyNames { if preserveTaxonomyNames {
helloWorld := s.getPage(KindTaxonomy, "others", "Hello Hugo world") helloWorld, _ := s.getPage(nil, "others/Hello Hugo world")
require.NotNil(t, helloWorld) require.NotNil(t, helloWorld)
require.Equal(t, "Hello Hugo world", helloWorld.title) require.Equal(t, "Hello Hugo world", helloWorld.title)
} else { } else {
helloWorld := s.getPage(KindTaxonomy, "others", "hello-hugo-world") helloWorld, _ := s.getPage(nil, "others/hello-hugo-world")
require.NotNil(t, helloWorld) require.NotNil(t, helloWorld)
require.Equal(t, "Hello Hugo World", helloWorld.title) require.Equal(t, "Hello Hugo World", helloWorld.title)
} }