From 40ffb0484b96b7b77fb66202b33073b241807199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Sat, 29 Dec 2018 10:35:46 +0100 Subject: [PATCH] hugolib: Restore 0.48 slash handling in taxonomies Fixes #5571 --- hugolib/hugo_sites.go | 18 +++-- hugolib/hugo_sites_build_test.go | 4 +- hugolib/page.go | 33 ++++++++- hugolib/permalinks.go | 6 +- hugolib/permalinks_test.go | 3 +- hugolib/site.go | 14 ---- hugolib/taxonomy_test.go | 118 +++++++++++++++++++------------ hugolib/testhelpers_test.go | 9 +-- 8 files changed, 129 insertions(+), 76 deletions(-) diff --git a/hugolib/hugo_sites.go b/hugolib/hugo_sites.go index 6a4893473..9ce1c438e 100644 --- a/hugolib/hugo_sites.go +++ b/hugolib/hugo_sites.go @@ -548,7 +548,7 @@ func (h *HugoSites) createMissingPages() error { if s.isEnabled(KindTaxonomyTerm) { foundTaxonomyTermsPage := false for _, p := range taxonomyTermsPages { - if p.sections[0] == plural { + if p.sectionsPath() == plural { foundTaxonomyTermsPage = true break } @@ -570,11 +570,21 @@ func (h *HugoSites) createMissingPages() error { key = s.PathSpec.MakePathSanitized(key) } 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. // p.sections contains the raw values from the file system. // See https://github.com/gohugoio/hugo/issues/4238 - singularKey := s.PathSpec.MakePathSanitized(p.sections[1]) - if p.sections[0] == plural && singularKey == key { + singularKey = s.PathSpec.MakePathSanitized(singularKey) + + if singularKey == key { foundTaxonomyPage = true break } @@ -622,7 +632,7 @@ func (h *HugoSites) setupTranslations() { for _, s := range h.Sites { for _, p := range s.rawAllPages { if p.Kind == kindUnknown { - p.Kind = p.s.kindFromSections(p.sections) + p.Kind = p.kindFromSections() } if !p.s.isEnabled(p.Kind) { diff --git a/hugolib/hugo_sites_build_test.go b/hugolib/hugo_sites_build_test.go index 91ae8434d..f772ce192 100644 --- a/hugolib/hugo_sites_build_test.go +++ b/hugolib/hugo_sites_build_test.go @@ -100,8 +100,8 @@ func doTestMultiSitesMainLangInRoot(t *testing.T, defaultInSubDir bool) { // Check list pages b.AssertFileContent(pathMod("public/fr/sect/index.html"), "List", "Bonjour") b.AssertFileContent("public/en/sect/index.html", "List", "Hello") - b.AssertFileContent(pathMod("public/fr/plaques/frtag1/index.html"), "List", "Bonjour") - b.AssertFileContent("public/en/tags/tag1/index.html", "List", "Hello") + b.AssertFileContent(pathMod("public/fr/plaques/frtag1/index.html"), "Taxonomy List", "Bonjour") + b.AssertFileContent("public/en/tags/tag1/index.html", "Taxonomy List", "Hello") // Check sitemaps // Sitemaps behaves different: In a multilanguage setup there will always be a index file and diff --git a/hugolib/page.go b/hugolib/page.go index 15ed631c1..9f09dc9bd 100644 --- a/hugolib/page.go +++ b/hugolib/page.go @@ -2048,10 +2048,41 @@ func kindFromFileInfo(fi *fileInfo) string { 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) { if p.Kind == kindUnknown { // This is either a taxonomy list, taxonomy term or a section - nodeType := s.kindFromSections(p.sections) + nodeType := p.kindFromSections() if nodeType == kindUnknown { panic(fmt.Sprintf("Unable to determine page kind from %q", p.sections)) diff --git a/hugolib/permalinks.go b/hugolib/permalinks.go index 55dcd7db6..3d261a113 100644 --- a/hugolib/permalinks.go +++ b/hugolib/permalinks.go @@ -40,7 +40,7 @@ type PermalinkOverrides map[string]pathPattern // to be used to replace that tag. var knownPermalinkAttributes map[string]pageToPermaAttribute -var attributeRegexp *regexp.Regexp +var attributeRegexp = regexp.MustCompile(`:\w+`) // validate determines if a PathPattern is well-formed func (pp pathPattern) validate() bool { @@ -187,8 +187,7 @@ func pageToPermalinkSlugElseTitle(p *Page, a string) (string, error) { } func pageToPermalinkSection(p *Page, _ string) (string, error) { - // Page contains Node contains URLPath which has Section - return p.s.PathSpec.URLize(p.Section()), nil + return p.Section(), nil } func pageToPermalinkSections(p *Page, _ string) (string, error) { @@ -211,5 +210,4 @@ func init() { "filename": pageToPermalinkFilename, } - attributeRegexp = regexp.MustCompile(`:\w+`) } diff --git a/hugolib/permalinks_test.go b/hugolib/permalinks_test.go index b542e1665..7bc242955 100644 --- a/hugolib/permalinks_test.go +++ b/hugolib/permalinks_test.go @@ -14,6 +14,7 @@ package hugolib import ( + "path/filepath" "strings" "testing" ) @@ -62,7 +63,7 @@ func TestPermalinkValidation(t *testing.T) { func TestPermalinkExpansion(t *testing.T) { t.Parallel() 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 { t.Fatalf("failed before we began, could not parse simplePageJSON: %s", err) diff --git a/hugolib/site.go b/hugolib/site.go index 1b3a317a1..9c225b332 100644 --- a/hugolib/site.go +++ b/hugolib/site.go @@ -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) { return s.layoutHandler.For(p.layoutDescriptor, p.outputFormat) } diff --git a/hugolib/taxonomy_test.go b/hugolib/taxonomy_test.go index 6ea397173..1ae9fae22 100644 --- a/hugolib/taxonomy_test.go +++ b/hugolib/taxonomy_test.go @@ -76,10 +76,8 @@ category = "categories" other = "others" empty = "empties" permalinked = "permalinkeds" -subcats = "subcats" [permalinks] permalinkeds = "/perma/:slug/" -subcats = "/subcats/:slug/" ` pageTemplate := `--- @@ -92,8 +90,6 @@ others: %s permalinkeds: %s -subcats: -%s --- # Doc ` @@ -105,16 +101,23 @@ subcats: fs := th.Fs - writeSource(t, fs, "content/p1.md", fmt.Sprintf(pageTemplate, "t1/c1", "- Tag1", "- cat1\n- \"cAt/dOg\"", "- 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", "")) - writeSource(t, fs, "content/p5.md", fmt.Sprintf(pageTemplate, "Sub/categories", "", "", "", "", "- \"sc0/sp1\"")) + if preserveTaxonomyNames { + writeSource(t, fs, "content/p1.md", fmt.Sprintf(pageTemplate, "t1/c1", "- tag1", "- cat1", "- o1", "- pl1")) + } else { + // Check lower-casing of tags + 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, "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: // 1. categories with terms content page, but no content page for the only c1 category @@ -132,11 +135,10 @@ subcats: // 1. if preserveTaxonomyNames { th.assertFileContent(pathFunc("public/categories/cat1/index.html"), "List", "cat1") - th.assertFileContent(pathFunc("public/categories/cat-dog/index.html"), "List", "cAt/dOg") } else { 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") // 2. @@ -172,57 +174,41 @@ subcats: // of KindTaxonomy pages in its Pages slice. taxonomyTermPageCounts := map[string]int{ "tags": 2, - "categories": 3, + "categories": 2, "others": 2, "empties": 0, "permalinkeds": 1, - "subcats": 1, } for taxonomy, count := range taxonomyTermPageCounts { term := s.getPage(KindTaxonomyTerm, taxonomy) require.NotNil(t, term) - require.Len(t, term.Pages, count, taxonomy) + require.Len(t, term.Pages, count) for _, page := range term.Pages { 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") require.NotNil(t, cat1) - require.Equal(t, fixURL("/blog/categories/cat1/"), cat1.RelPermalink()) - - catdog := s.getPage(KindTaxonomy, "categories", fixTerm("cAt/dOg")) - require.NotNil(t, catdog) - require.Equal(t, fixURL("/blog/categories/cat-dog/"), catdog.RelPermalink()) + if uglyURLs { + require.Equal(t, "/blog/categories/cat1.html", cat1.RelPermalink()) + } else { + require.Equal(t, "/blog/categories/cat1/", cat1.RelPermalink()) + } pl1 := s.getPage(KindTaxonomy, "permalinkeds", "pl1") - require.NotNil(t, pl1) - require.Equal(t, fixURL("/blog/perma/pl1/"), pl1.RelPermalink()) - permalinkeds := s.getPage(KindTaxonomyTerm, "permalinkeds") + require.NotNil(t, pl1) require.NotNil(t, permalinkeds) - require.Equal(t, fixURL("/blog/permalinkeds/"), permalinkeds.RelPermalink()) - - // Issue #5223 - sp1 := s.getPage(KindTaxonomy, "subcats", "sc0/sp1") - require.NotNil(t, sp1) - require.Equal(t, fixURL("/blog/subcats/sc0/sp1/"), sp1.RelPermalink()) + if uglyURLs { + require.Equal(t, "/blog/perma/pl1.html", pl1.RelPermalink()) + require.Equal(t, "/blog/permalinkeds.html", permalinkeds.RelPermalink()) + } else { + require.Equal(t, "/blog/perma/pl1/", pl1.RelPermalink()) + require.Equal(t, "/blog/permalinkeds/", permalinkeds.RelPermalink()) + } // Issue #3070 preserveTaxonomyNames if preserveTaxonomyNames { @@ -241,20 +227,26 @@ subcats: } // 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() + assert := require.New(t) + config := ` baseURL = "https://example.com" [taxonomies] "news/tag" = "news/tags" "news/category" = "news/categories" +"t1/t2/t3" = "t1/t2/t3s" +"s1/s2/s3" = "s1/s2/s3s" ` pageContent := ` +++ 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. ` @@ -266,11 +258,45 @@ Content. --- 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.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/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/|") + } diff --git a/hugolib/testhelpers_test.go b/hugolib/testhelpers_test.go index a60ca2905..64d1ff96a 100644 --- a/hugolib/testhelpers_test.go +++ b/hugolib/testhelpers_test.go @@ -407,9 +407,7 @@ date: "2018-02-28" --- # doc1 *some "content"* - {{< shortcode >}} - {{< lingo >}} ` @@ -420,12 +418,15 @@ date: "2018-02-28" "content/sect/doc1.nn.md", contentTemplate, } + listTemplateCommon = "{{ $p := .Paginator }}{{ $p.PageNumber }}|{{ .Title }}|{{ i18n \"hello\" }}|{{ .Permalink }}|Pager: {{ template \"_internal/pagination.html\" . }}" + defaultTemplates = []string{ "_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.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/shortcode.html", "Shortcode: {{ i18n \"hello\" }}", // A shortcode in multiple languages