hugolib: Restore 0.48 slash handling in taxonomies

Fixes #5571
This commit is contained in:
Bjørn Erik Pedersen 2018-12-29 10:35:46 +01:00
parent 4bae8b04aa
commit 40ffb0484b
8 changed files with 129 additions and 76 deletions

View file

@ -548,7 +548,7 @@ func (h *HugoSites) createMissingPages() error {
if s.isEnabled(KindTaxonomyTerm) { if s.isEnabled(KindTaxonomyTerm) {
foundTaxonomyTermsPage := false foundTaxonomyTermsPage := false
for _, p := range taxonomyTermsPages { for _, p := range taxonomyTermsPages {
if p.sections[0] == plural { if p.sectionsPath() == plural {
foundTaxonomyTermsPage = true foundTaxonomyTermsPage = true
break break
} }
@ -570,11 +570,21 @@ func (h *HugoSites) createMissingPages() error {
key = s.PathSpec.MakePathSanitized(key) key = s.PathSpec.MakePathSanitized(key)
} }
for _, p := range taxonomyPages { for _, p := range taxonomyPages {
sectionsPath := p.sectionsPath()
if !strings.HasPrefix(sectionsPath, plural) {
continue
}
singularKey := strings.TrimPrefix(sectionsPath, plural)
singularKey = strings.TrimPrefix(singularKey, "/")
// Some people may have /authors/MaxMustermann etc. as paths. // Some people may have /authors/MaxMustermann etc. as paths.
// p.sections contains the raw values from the file system. // p.sections contains the raw values from the file system.
// See https://github.com/gohugoio/hugo/issues/4238 // See https://github.com/gohugoio/hugo/issues/4238
singularKey := s.PathSpec.MakePathSanitized(p.sections[1]) singularKey = s.PathSpec.MakePathSanitized(singularKey)
if p.sections[0] == plural && singularKey == key {
if singularKey == key {
foundTaxonomyPage = true foundTaxonomyPage = true
break break
} }
@ -622,7 +632,7 @@ func (h *HugoSites) setupTranslations() {
for _, s := range h.Sites { for _, s := range h.Sites {
for _, p := range s.rawAllPages { for _, p := range s.rawAllPages {
if p.Kind == kindUnknown { if p.Kind == kindUnknown {
p.Kind = p.s.kindFromSections(p.sections) p.Kind = p.kindFromSections()
} }
if !p.s.isEnabled(p.Kind) { if !p.s.isEnabled(p.Kind) {

View file

@ -100,8 +100,8 @@ func doTestMultiSitesMainLangInRoot(t *testing.T, defaultInSubDir bool) {
// Check list pages // Check list pages
b.AssertFileContent(pathMod("public/fr/sect/index.html"), "List", "Bonjour") b.AssertFileContent(pathMod("public/fr/sect/index.html"), "List", "Bonjour")
b.AssertFileContent("public/en/sect/index.html", "List", "Hello") b.AssertFileContent("public/en/sect/index.html", "List", "Hello")
b.AssertFileContent(pathMod("public/fr/plaques/frtag1/index.html"), "List", "Bonjour") b.AssertFileContent(pathMod("public/fr/plaques/frtag1/index.html"), "Taxonomy List", "Bonjour")
b.AssertFileContent("public/en/tags/tag1/index.html", "List", "Hello") b.AssertFileContent("public/en/tags/tag1/index.html", "Taxonomy List", "Hello")
// Check sitemaps // Check sitemaps
// Sitemaps behaves different: In a multilanguage setup there will always be a index file and // Sitemaps behaves different: In a multilanguage setup there will always be a index file and

View file

@ -2048,10 +2048,41 @@ func kindFromFileInfo(fi *fileInfo) string {
return KindPage return KindPage
} }
func (p *Page) sectionsPath() string {
if len(p.sections) == 0 {
return ""
}
if len(p.sections) == 1 {
return p.sections[0]
}
return path.Join(p.sections...)
}
func (p *Page) kindFromSections() string {
if len(p.sections) == 0 || len(p.s.Taxonomies) == 0 {
return KindSection
}
sectionPath := p.sectionsPath()
for k, _ := range p.s.Taxonomies {
if k == sectionPath {
return KindTaxonomyTerm
}
if strings.HasPrefix(sectionPath, k) {
return KindTaxonomy
}
}
return KindSection
}
func (p *Page) setValuesForKind(s *Site) { func (p *Page) setValuesForKind(s *Site) {
if p.Kind == kindUnknown { if p.Kind == kindUnknown {
// This is either a taxonomy list, taxonomy term or a section // This is either a taxonomy list, taxonomy term or a section
nodeType := s.kindFromSections(p.sections) nodeType := p.kindFromSections()
if nodeType == kindUnknown { if nodeType == kindUnknown {
panic(fmt.Sprintf("Unable to determine page kind from %q", p.sections)) panic(fmt.Sprintf("Unable to determine page kind from %q", p.sections))

View file

@ -40,7 +40,7 @@ type PermalinkOverrides map[string]pathPattern
// to be used to replace that tag. // to be used to replace that tag.
var knownPermalinkAttributes map[string]pageToPermaAttribute var knownPermalinkAttributes map[string]pageToPermaAttribute
var attributeRegexp *regexp.Regexp var attributeRegexp = regexp.MustCompile(`:\w+`)
// validate determines if a PathPattern is well-formed // validate determines if a PathPattern is well-formed
func (pp pathPattern) validate() bool { func (pp pathPattern) validate() bool {
@ -187,8 +187,7 @@ func pageToPermalinkSlugElseTitle(p *Page, a string) (string, error) {
} }
func pageToPermalinkSection(p *Page, _ string) (string, error) { func pageToPermalinkSection(p *Page, _ string) (string, error) {
// Page contains Node contains URLPath which has Section return p.Section(), nil
return p.s.PathSpec.URLize(p.Section()), nil
} }
func pageToPermalinkSections(p *Page, _ string) (string, error) { func pageToPermalinkSections(p *Page, _ string) (string, error) {
@ -211,5 +210,4 @@ func init() {
"filename": pageToPermalinkFilename, "filename": pageToPermalinkFilename,
} }
attributeRegexp = regexp.MustCompile(`:\w+`)
} }

View file

@ -14,6 +14,7 @@
package hugolib package hugolib
import ( import (
"path/filepath"
"strings" "strings"
"testing" "testing"
) )
@ -62,7 +63,7 @@ func TestPermalinkValidation(t *testing.T) {
func TestPermalinkExpansion(t *testing.T) { func TestPermalinkExpansion(t *testing.T) {
t.Parallel() t.Parallel()
s := newTestSite(t) s := newTestSite(t)
page, err := s.newPageFrom(strings.NewReader(simplePageJSON), "blue/test-page.md") page, err := s.newPageFrom(strings.NewReader(simplePageJSON), filepath.FromSlash("blue/test-page.md"))
if err != nil { if err != nil {
t.Fatalf("failed before we began, could not parse simplePageJSON: %s", err) t.Fatalf("failed before we began, could not parse simplePageJSON: %s", err)

View file

@ -1586,20 +1586,6 @@ func (s *Site) resetBuildState() {
} }
} }
func (s *Site) kindFromSections(sections []string) string {
if len(sections) == 0 {
return KindSection
}
if _, isTaxonomy := s.Taxonomies[sections[0]]; isTaxonomy {
if len(sections) == 1 {
return KindTaxonomyTerm
}
return KindTaxonomy
}
return KindSection
}
func (s *Site) layouts(p *PageOutput) ([]string, error) { func (s *Site) layouts(p *PageOutput) ([]string, error) {
return s.layoutHandler.For(p.layoutDescriptor, p.outputFormat) return s.layoutHandler.For(p.layoutDescriptor, p.outputFormat)
} }

View file

@ -76,10 +76,8 @@ category = "categories"
other = "others" other = "others"
empty = "empties" empty = "empties"
permalinked = "permalinkeds" permalinked = "permalinkeds"
subcats = "subcats"
[permalinks] [permalinks]
permalinkeds = "/perma/:slug/" permalinkeds = "/perma/:slug/"
subcats = "/subcats/:slug/"
` `
pageTemplate := `--- pageTemplate := `---
@ -92,8 +90,6 @@ others:
%s %s
permalinkeds: permalinkeds:
%s %s
subcats:
%s
--- ---
# Doc # Doc
` `
@ -105,16 +101,23 @@ subcats:
fs := th.Fs fs := th.Fs
writeSource(t, fs, "content/p1.md", fmt.Sprintf(pageTemplate, "t1/c1", "- Tag1", "- cat1\n- \"cAt/dOg\"", "- o1", "- pl1", "")) if preserveTaxonomyNames {
writeSource(t, fs, "content/p2.md", fmt.Sprintf(pageTemplate, "t2/c1", "- tag2", "- cat1", "- o1", "- pl1", "")) writeSource(t, fs, "content/p1.md", fmt.Sprintf(pageTemplate, "t1/c1", "- tag1", "- cat1", "- o1", "- pl1"))
writeSource(t, fs, "content/p3.md", fmt.Sprintf(pageTemplate, "t2/c12", "- tag2", "- cat2", "- o1", "- pl1", "")) } else {
writeSource(t, fs, "content/p4.md", fmt.Sprintf(pageTemplate, "Hello World", "", "", "- \"Hello Hugo world\"", "- pl1", "")) // Check lower-casing of tags
writeSource(t, fs, "content/p5.md", fmt.Sprintf(pageTemplate, "Sub/categories", "", "", "", "", "- \"sc0/sp1\"")) writeSource(t, fs, "content/p1.md", fmt.Sprintf(pageTemplate, "t1/c1", "- Tag1", "- cAt1", "- o1", "- pl1"))
}
writeSource(t, fs, "content/p2.md", fmt.Sprintf(pageTemplate, "t2/c1", "- tag2", "- cat1", "- o1", "- pl1"))
writeSource(t, fs, "content/p3.md", fmt.Sprintf(pageTemplate, "t2/c12", "- tag2", "- cat2", "- o1", "- pl1"))
writeSource(t, fs, "content/p4.md", fmt.Sprintf(pageTemplate, "Hello World", "", "", "- \"Hello Hugo world\"", "- pl1"))
writeNewContentFile(t, fs.Source, "Category Terms", "2017-01-01", "content/categories/_index.md", 10) writeNewContentFile(t, fs.Source, "Category Terms", "2017-01-01", "content/categories/_index.md", 10)
writeNewContentFile(t, fs.Source, "Tag1 List", "2017-01-01", "content/tags/Tag1/_index.md", 10) writeNewContentFile(t, fs.Source, "Tag1 List", "2017-01-01", "content/tags/Tag1/_index.md", 10)
require.NoError(t, h.Build(BuildCfg{})) err := h.Build(BuildCfg{})
require.NoError(t, err)
// So what we have now is: // So what we have now is:
// 1. categories with terms content page, but no content page for the only c1 category // 1. categories with terms content page, but no content page for the only c1 category
@ -132,11 +135,10 @@ subcats:
// 1. // 1.
if preserveTaxonomyNames { if preserveTaxonomyNames {
th.assertFileContent(pathFunc("public/categories/cat1/index.html"), "List", "cat1") th.assertFileContent(pathFunc("public/categories/cat1/index.html"), "List", "cat1")
th.assertFileContent(pathFunc("public/categories/cat-dog/index.html"), "List", "cAt/dOg")
} else { } else {
th.assertFileContent(pathFunc("public/categories/cat1/index.html"), "List", "Cat1") th.assertFileContent(pathFunc("public/categories/cat1/index.html"), "List", "Cat1")
th.assertFileContent(pathFunc("public/categories/cat-dog/index.html"), "List", "Cat/Dog")
} }
th.assertFileContent(pathFunc("public/categories/index.html"), "Terms List", "Category Terms") th.assertFileContent(pathFunc("public/categories/index.html"), "Terms List", "Category Terms")
// 2. // 2.
@ -172,57 +174,41 @@ subcats:
// of KindTaxonomy pages in its Pages slice. // of KindTaxonomy pages in its Pages slice.
taxonomyTermPageCounts := map[string]int{ taxonomyTermPageCounts := map[string]int{
"tags": 2, "tags": 2,
"categories": 3, "categories": 2,
"others": 2, "others": 2,
"empties": 0, "empties": 0,
"permalinkeds": 1, "permalinkeds": 1,
"subcats": 1,
} }
for taxonomy, count := range taxonomyTermPageCounts { for taxonomy, count := range taxonomyTermPageCounts {
term := s.getPage(KindTaxonomyTerm, taxonomy) term := s.getPage(KindTaxonomyTerm, taxonomy)
require.NotNil(t, term) require.NotNil(t, term)
require.Len(t, term.Pages, count, taxonomy) require.Len(t, term.Pages, count)
for _, page := range term.Pages { for _, page := range term.Pages {
require.Equal(t, KindTaxonomy, page.Kind) require.Equal(t, KindTaxonomy, page.Kind)
} }
} }
fixTerm := func(s string) string {
if preserveTaxonomyNames {
return s
}
return strings.ToLower(s)
}
fixURL := func(s string) string {
if uglyURLs {
return strings.TrimRight(s, "/") + ".html"
}
return s
}
cat1 := s.getPage(KindTaxonomy, "categories", "cat1") cat1 := s.getPage(KindTaxonomy, "categories", "cat1")
require.NotNil(t, cat1) require.NotNil(t, cat1)
require.Equal(t, fixURL("/blog/categories/cat1/"), cat1.RelPermalink()) if uglyURLs {
require.Equal(t, "/blog/categories/cat1.html", cat1.RelPermalink())
catdog := s.getPage(KindTaxonomy, "categories", fixTerm("cAt/dOg")) } else {
require.NotNil(t, catdog) require.Equal(t, "/blog/categories/cat1/", cat1.RelPermalink())
require.Equal(t, fixURL("/blog/categories/cat-dog/"), catdog.RelPermalink()) }
pl1 := s.getPage(KindTaxonomy, "permalinkeds", "pl1") pl1 := s.getPage(KindTaxonomy, "permalinkeds", "pl1")
require.NotNil(t, pl1)
require.Equal(t, fixURL("/blog/perma/pl1/"), pl1.RelPermalink())
permalinkeds := s.getPage(KindTaxonomyTerm, "permalinkeds") permalinkeds := s.getPage(KindTaxonomyTerm, "permalinkeds")
require.NotNil(t, pl1)
require.NotNil(t, permalinkeds) require.NotNil(t, permalinkeds)
require.Equal(t, fixURL("/blog/permalinkeds/"), permalinkeds.RelPermalink()) if uglyURLs {
require.Equal(t, "/blog/perma/pl1.html", pl1.RelPermalink())
// Issue #5223 require.Equal(t, "/blog/permalinkeds.html", permalinkeds.RelPermalink())
sp1 := s.getPage(KindTaxonomy, "subcats", "sc0/sp1") } else {
require.NotNil(t, sp1) require.Equal(t, "/blog/perma/pl1/", pl1.RelPermalink())
require.Equal(t, fixURL("/blog/subcats/sc0/sp1/"), sp1.RelPermalink()) require.Equal(t, "/blog/permalinkeds/", permalinkeds.RelPermalink())
}
// Issue #3070 preserveTaxonomyNames // Issue #3070 preserveTaxonomyNames
if preserveTaxonomyNames { if preserveTaxonomyNames {
@ -241,20 +227,26 @@ subcats:
} }
// https://github.com/gohugoio/hugo/issues/5513 // https://github.com/gohugoio/hugo/issues/5513
func TestTaxonomyPathSeparation(t *testing.T) { // https://github.com/gohugoio/hugo/issues/5571
func TestTaxonomiesPathSeparation(t *testing.T) {
t.Parallel() t.Parallel()
assert := require.New(t)
config := ` config := `
baseURL = "https://example.com" baseURL = "https://example.com"
[taxonomies] [taxonomies]
"news/tag" = "news/tags" "news/tag" = "news/tags"
"news/category" = "news/categories" "news/category" = "news/categories"
"t1/t2/t3" = "t1/t2/t3s"
"s1/s2/s3" = "s1/s2/s3s"
` `
pageContent := ` pageContent := `
+++ +++
title = "foo" title = "foo"
"news/categories" = ["a", "b", "c"] "news/categories" = ["a", "b", "c", "d/e", "f/g/h"]
"t1/t2/t3s" = ["t4/t5", "t4/t5/t6"]
+++ +++
Content. Content.
` `
@ -266,11 +258,45 @@ Content.
--- ---
title: "This is B" title: "This is B"
--- ---
`)
b.WithContent("news/categories/f/g/h/_index.md", `
---
title: "This is H"
---
`)
b.WithContent("t1/t2/t3s/t4/t5/_index.md", `
---
title: "This is T5"
---
`)
b.WithContent("s1/s2/s3s/_index.md", `
---
title: "This is S3s"
---
`) `)
b.CreateSites().Build(BuildCfg{}) b.CreateSites().Build(BuildCfg{})
b.AssertFileContent("public/news/categories/index.html", "Taxonomy Term Page 1|News/Categories|Hello|https://example.com/news/categories/|") s := b.H.Sites[0]
ta := s.findPagesByKind(KindTaxonomy)
te := s.findPagesByKind(KindTaxonomyTerm)
assert.Equal(4, len(te))
assert.Equal(7, len(ta))
b.AssertFileContent("public/news/categories/a/index.html", "Taxonomy List Page 1|A|Hello|https://example.com/news/categories/a/|") b.AssertFileContent("public/news/categories/a/index.html", "Taxonomy List Page 1|A|Hello|https://example.com/news/categories/a/|")
b.AssertFileContent("public/news/categories/b/index.html", "Taxonomy List Page 1|This is B|Hello|https://example.com/news/categories/b/|") b.AssertFileContent("public/news/categories/b/index.html", "Taxonomy List Page 1|This is B|Hello|https://example.com/news/categories/b/|")
b.AssertFileContent("public/news/categories/d/e/index.html", "Taxonomy List Page 1|D/E|Hello|https://example.com/news/categories/d/e/|")
b.AssertFileContent("public/news/categories/f/g/h/index.html", "Taxonomy List Page 1|This is H|Hello|https://example.com/news/categories/f/g/h/|")
b.AssertFileContent("public/t1/t2/t3s/t4/t5/index.html", "Taxonomy List Page 1|This is T5|Hello|https://example.com/t1/t2/t3s/t4/t5/|")
b.AssertFileContent("public/t1/t2/t3s/t4/t5/t6/index.html", "Taxonomy List Page 1|T4/T5/T6|Hello|https://example.com/t1/t2/t3s/t4/t5/t6/|")
b.AssertFileContent("public/news/categories/index.html", "Taxonomy Term Page 1|News/Categories|Hello|https://example.com/news/categories/|")
b.AssertFileContent("public/t1/t2/t3s/index.html", "Taxonomy Term Page 1|T1/T2/T3s|Hello|https://example.com/t1/t2/t3s/|")
b.AssertFileContent("public/s1/s2/s3s/index.html", "Taxonomy Term Page 1|This is S3s|Hello|https://example.com/s1/s2/s3s/|")
} }

View file

@ -407,9 +407,7 @@ date: "2018-02-28"
--- ---
# doc1 # doc1
*some "content"* *some "content"*
{{< shortcode >}} {{< shortcode >}}
{{< lingo >}} {{< lingo >}}
` `
@ -420,12 +418,15 @@ date: "2018-02-28"
"content/sect/doc1.nn.md", contentTemplate, "content/sect/doc1.nn.md", contentTemplate,
} }
listTemplateCommon = "{{ $p := .Paginator }}{{ $p.PageNumber }}|{{ .Title }}|{{ i18n \"hello\" }}|{{ .Permalink }}|Pager: {{ template \"_internal/pagination.html\" . }}"
defaultTemplates = []string{ defaultTemplates = []string{
"_default/single.html", "Single: {{ .Title }}|{{ i18n \"hello\" }}|{{.Lang}}|{{ .Content }}", "_default/single.html", "Single: {{ .Title }}|{{ i18n \"hello\" }}|{{.Lang}}|{{ .Content }}",
"_default/list.html", "{{ $p := .Paginator }}List Page {{ $p.PageNumber }}: {{ .Title }}|{{ i18n \"hello\" }}|{{ .Permalink }}|Pager: {{ template \"_internal/pagination.html\" . }}", "_default/list.html", "List Page " + listTemplateCommon,
"index.html", "{{ $p := .Paginator }}Default Home Page {{ $p.PageNumber }}: {{ .Title }}|{{ .IsHome }}|{{ i18n \"hello\" }}|{{ .Permalink }}|{{ .Site.Data.hugo.slogan }}|String Resource: {{ ( \"Hugo Pipes\" | resources.FromString \"text/pipes.txt\").RelPermalink }}", "index.html", "{{ $p := .Paginator }}Default Home Page {{ $p.PageNumber }}: {{ .Title }}|{{ .IsHome }}|{{ i18n \"hello\" }}|{{ .Permalink }}|{{ .Site.Data.hugo.slogan }}|String Resource: {{ ( \"Hugo Pipes\" | resources.FromString \"text/pipes.txt\").RelPermalink }}",
"index.fr.html", "{{ $p := .Paginator }}French Home Page {{ $p.PageNumber }}: {{ .Title }}|{{ .IsHome }}|{{ i18n \"hello\" }}|{{ .Permalink }}|{{ .Site.Data.hugo.slogan }}|String Resource: {{ ( \"Hugo Pipes\" | resources.FromString \"text/pipes.txt\").RelPermalink }}", "index.fr.html", "{{ $p := .Paginator }}French Home Page {{ $p.PageNumber }}: {{ .Title }}|{{ .IsHome }}|{{ i18n \"hello\" }}|{{ .Permalink }}|{{ .Site.Data.hugo.slogan }}|String Resource: {{ ( \"Hugo Pipes\" | resources.FromString \"text/pipes.txt\").RelPermalink }}",
"_default/terms.html", "Taxonomy Term Page " + listTemplateCommon,
"_default/taxonomy.html", "Taxonomy List Page " + listTemplateCommon,
// Shortcodes // Shortcodes
"shortcodes/shortcode.html", "Shortcode: {{ i18n \"hello\" }}", "shortcodes/shortcode.html", "Shortcode: {{ i18n \"hello\" }}",
// A shortcode in multiple languages // A shortcode in multiple languages