github.com/linchen2chris/hugo@v0.0.0-20230307053224-cec209389705/hugolib/taxonomy_test.go (about)

     1  // Copyright 2019 The Hugo Authors. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package hugolib
    15  
    16  import (
    17  	"fmt"
    18  	"path/filepath"
    19  	"reflect"
    20  	"strings"
    21  	"testing"
    22  
    23  	"github.com/gohugoio/hugo/resources/page"
    24  
    25  	qt "github.com/frankban/quicktest"
    26  
    27  	"github.com/gohugoio/hugo/deps"
    28  )
    29  
    30  func TestTaxonomiesCountOrder(t *testing.T) {
    31  	t.Parallel()
    32  	taxonomies := make(map[string]string)
    33  
    34  	taxonomies["tag"] = "tags"
    35  	taxonomies["category"] = "categories"
    36  
    37  	cfg, fs := newTestCfg()
    38  
    39  	cfg.Set("taxonomies", taxonomies)
    40  
    41  	const pageContent = `---
    42  tags: ['a', 'B', 'c']
    43  categories: 'd'
    44  ---
    45  YAML frontmatter with tags and categories taxonomy.`
    46  
    47  	writeSource(t, fs, filepath.Join("content", "page.md"), pageContent)
    48  
    49  	s := buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg}, BuildCfg{})
    50  
    51  	st := make([]string, 0)
    52  	for _, t := range s.Taxonomies()["tags"].ByCount() {
    53  		st = append(st, t.Page().Title()+":"+t.Name)
    54  	}
    55  
    56  	expect := []string{"a:a", "B:b", "c:c"}
    57  
    58  	if !reflect.DeepEqual(st, expect) {
    59  		t.Fatalf("ordered taxonomies mismatch, expected\n%v\ngot\n%q", expect, st)
    60  	}
    61  }
    62  
    63  func TestTaxonomiesWithAndWithoutContentFile(t *testing.T) {
    64  	for _, uglyURLs := range []bool{false, true} {
    65  		uglyURLs := uglyURLs
    66  		t.Run(fmt.Sprintf("uglyURLs=%t", uglyURLs), func(t *testing.T) {
    67  			t.Parallel()
    68  			doTestTaxonomiesWithAndWithoutContentFile(t, uglyURLs)
    69  		})
    70  	}
    71  }
    72  
    73  func doTestTaxonomiesWithAndWithoutContentFile(t *testing.T, uglyURLs bool) {
    74  	siteConfig := `
    75  baseURL = "http://example.com/blog"
    76  uglyURLs = %t
    77  paginate = 1
    78  defaultContentLanguage = "en"
    79  [Taxonomies]
    80  tag = "tags"
    81  category = "categories"
    82  other = "others"
    83  empty = "empties"
    84  permalinked = "permalinkeds"
    85  [permalinks]
    86  permalinkeds = "/perma/:slug/"
    87  `
    88  
    89  	pageTemplate := `---
    90  title: "%s"
    91  tags:
    92  %s
    93  categories:
    94  %s
    95  others:
    96  %s
    97  permalinkeds:
    98  %s
    99  ---
   100  # Doc
   101  `
   102  
   103  	siteConfig = fmt.Sprintf(siteConfig, uglyURLs)
   104  
   105  	b := newTestSitesBuilder(t).WithConfigFile("toml", siteConfig)
   106  
   107  	b.WithContent(
   108  		"p1.md", fmt.Sprintf(pageTemplate, "t1/c1", "- Tag1", "- cAt1", "- o1", "- Pl1"),
   109  		"p2.md", fmt.Sprintf(pageTemplate, "t2/c1", "- tag2", "- cAt1", "- o1", "- Pl1"),
   110  		"p3.md", fmt.Sprintf(pageTemplate, "t2/c12", "- tag2", "- cat2", "- o1", "- Pl1"),
   111  		"p4.md", fmt.Sprintf(pageTemplate, "Hello World", "", "", "- \"Hello Hugo world\"", "- Pl1"),
   112  		"categories/_index.md", newTestPage("Category Terms", "2017-01-01", 10),
   113  		"tags/Tag1/_index.md", newTestPage("Tag1 List", "2017-01-01", 10),
   114  		// https://github.com/gohugoio/hugo/issues/5847
   115  		"/tags/not-used/_index.md", newTestPage("Unused Tag List", "2018-01-01", 10),
   116  	)
   117  
   118  	b.Build(BuildCfg{})
   119  
   120  	// So what we have now is:
   121  	// 1. categories with terms content page, but no content page for the only c1 category
   122  	// 2. tags with no terms content page, but content page for one of 2 tags (tag1)
   123  	// 3. the "others" taxonomy with no content pages.
   124  	// 4. the "permalinkeds" taxonomy with permalinks configuration.
   125  
   126  	pathFunc := func(s string) string {
   127  		if uglyURLs {
   128  			return strings.Replace(s, "/index.html", ".html", 1)
   129  		}
   130  		return s
   131  	}
   132  
   133  	// 1.
   134  	b.AssertFileContent(pathFunc("public/categories/cat1/index.html"), "List", "cAt1")
   135  	b.AssertFileContent(pathFunc("public/categories/index.html"), "Taxonomy Term Page", "Category Terms")
   136  
   137  	// 2.
   138  	b.AssertFileContent(pathFunc("public/tags/tag2/index.html"), "List", "tag2")
   139  	b.AssertFileContent(pathFunc("public/tags/tag1/index.html"), "List", "Tag1")
   140  	b.AssertFileContent(pathFunc("public/tags/index.html"), "Taxonomy Term Page", "Tags")
   141  
   142  	// 3.
   143  	b.AssertFileContent(pathFunc("public/others/o1/index.html"), "List", "o1")
   144  	b.AssertFileContent(pathFunc("public/others/index.html"), "Taxonomy Term Page", "Others")
   145  
   146  	// 4.
   147  	b.AssertFileContent(pathFunc("public/perma/pl1/index.html"), "List", "Pl1")
   148  
   149  	// This looks kind of funky, but the taxonomy terms do not have a permalinks definition,
   150  	// for good reasons.
   151  	b.AssertFileContent(pathFunc("public/permalinkeds/index.html"), "Taxonomy Term Page", "Permalinkeds")
   152  
   153  	s := b.H.Sites[0]
   154  
   155  	// Make sure that each page.KindTaxonomyTerm page has an appropriate number
   156  	// of page.KindTaxonomy pages in its Pages slice.
   157  	taxonomyTermPageCounts := map[string]int{
   158  		"tags":         3,
   159  		"categories":   2,
   160  		"others":       2,
   161  		"empties":      0,
   162  		"permalinkeds": 1,
   163  	}
   164  
   165  	for taxonomy, count := range taxonomyTermPageCounts {
   166  		msg := qt.Commentf(taxonomy)
   167  		term := s.getPage(page.KindTaxonomy, taxonomy)
   168  		b.Assert(term, qt.Not(qt.IsNil), msg)
   169  		b.Assert(len(term.Pages()), qt.Equals, count, msg)
   170  
   171  		for _, p := range term.Pages() {
   172  			b.Assert(p.Kind(), qt.Equals, page.KindTerm)
   173  		}
   174  	}
   175  
   176  	cat1 := s.getPage(page.KindTerm, "categories", "cat1")
   177  	b.Assert(cat1, qt.Not(qt.IsNil))
   178  	if uglyURLs {
   179  		b.Assert(cat1.RelPermalink(), qt.Equals, "/blog/categories/cat1.html")
   180  	} else {
   181  		b.Assert(cat1.RelPermalink(), qt.Equals, "/blog/categories/cat1/")
   182  	}
   183  
   184  	pl1 := s.getPage(page.KindTerm, "permalinkeds", "pl1")
   185  	permalinkeds := s.getPage(page.KindTaxonomy, "permalinkeds")
   186  	b.Assert(pl1, qt.Not(qt.IsNil))
   187  	b.Assert(permalinkeds, qt.Not(qt.IsNil))
   188  	if uglyURLs {
   189  		b.Assert(pl1.RelPermalink(), qt.Equals, "/blog/perma/pl1.html")
   190  		b.Assert(permalinkeds.RelPermalink(), qt.Equals, "/blog/permalinkeds.html")
   191  	} else {
   192  		b.Assert(pl1.RelPermalink(), qt.Equals, "/blog/perma/pl1/")
   193  		b.Assert(permalinkeds.RelPermalink(), qt.Equals, "/blog/permalinkeds/")
   194  	}
   195  
   196  	helloWorld := s.getPage(page.KindTerm, "others", "hello-hugo-world")
   197  	b.Assert(helloWorld, qt.Not(qt.IsNil))
   198  	b.Assert(helloWorld.Title(), qt.Equals, "Hello Hugo world")
   199  
   200  	// Issue #2977
   201  	b.AssertFileContent(pathFunc("public/empties/index.html"), "Taxonomy Term Page", "Empties")
   202  }
   203  
   204  // https://github.com/gohugoio/hugo/issues/5513
   205  // https://github.com/gohugoio/hugo/issues/5571
   206  func TestTaxonomiesPathSeparation(t *testing.T) {
   207  	t.Parallel()
   208  
   209  	config := `
   210  baseURL = "https://example.com"
   211  [taxonomies]
   212  "news/tag" = "news/tags"
   213  "news/category" = "news/categories"
   214  "t1/t2/t3" = "t1/t2/t3s"
   215  "s1/s2/s3" = "s1/s2/s3s"
   216  `
   217  
   218  	pageContent := `
   219  +++
   220  title = "foo"
   221  "news/categories" = ["a", "b", "c", "d/e", "f/g/h"]
   222  "t1/t2/t3s" = ["t4/t5", "t4/t5/t6"]
   223  +++
   224  Content.
   225  `
   226  
   227  	b := newTestSitesBuilder(t)
   228  	b.WithConfigFile("toml", config)
   229  	b.WithContent("page.md", pageContent)
   230  	b.WithContent("news/categories/b/_index.md", `
   231  ---
   232  title: "This is B"
   233  ---
   234  `)
   235  
   236  	b.WithContent("news/categories/f/g/h/_index.md", `
   237  ---
   238  title: "This is H"
   239  ---
   240  `)
   241  
   242  	b.WithContent("t1/t2/t3s/t4/t5/_index.md", `
   243  ---
   244  title: "This is T5"
   245  ---
   246  `)
   247  
   248  	b.WithContent("s1/s2/s3s/_index.md", `
   249  ---
   250  title: "This is S3s"
   251  ---
   252  `)
   253  
   254  	b.CreateSites().Build(BuildCfg{})
   255  
   256  	s := b.H.Sites[0]
   257  
   258  	filterbyKind := func(kind string) page.Pages {
   259  		var pages page.Pages
   260  		for _, p := range s.Pages() {
   261  			if p.Kind() == kind {
   262  				pages = append(pages, p)
   263  			}
   264  		}
   265  		return pages
   266  	}
   267  
   268  	ta := filterbyKind(page.KindTerm)
   269  	te := filterbyKind(page.KindTaxonomy)
   270  
   271  	b.Assert(len(te), qt.Equals, 4)
   272  	b.Assert(len(ta), qt.Equals, 7)
   273  
   274  	b.AssertFileContent("public/news/categories/a/index.html", "Taxonomy List Page 1|a|Hello|https://example.com/news/categories/a/|")
   275  	b.AssertFileContent("public/news/categories/b/index.html", "Taxonomy List Page 1|This is B|Hello|https://example.com/news/categories/b/|")
   276  	b.AssertFileContent("public/news/categories/d/e/index.html", "Taxonomy List Page 1|d/e|Hello|https://example.com/news/categories/d/e/|")
   277  	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/|")
   278  	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/|")
   279  	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/|")
   280  
   281  	b.AssertFileContent("public/news/categories/index.html", "Taxonomy Term Page 1|News/Categories|Hello|https://example.com/news/categories/|")
   282  	b.AssertFileContent("public/t1/t2/t3s/index.html", "Taxonomy Term Page 1|T1/T2/T3s|Hello|https://example.com/t1/t2/t3s/|")
   283  	b.AssertFileContent("public/s1/s2/s3s/index.html", "Taxonomy Term Page 1|This is S3s|Hello|https://example.com/s1/s2/s3s/|")
   284  }
   285  
   286  // https://github.com/gohugoio/hugo/issues/5719
   287  func TestTaxonomiesNextGenLoops(t *testing.T) {
   288  	b := newTestSitesBuilder(t).WithSimpleConfigFile()
   289  
   290  	b.WithTemplatesAdded("index.html", `
   291  <h1>Tags</h1>
   292  <ul>
   293      {{ range .Site.Taxonomies.tags }}
   294              <li><a href="{{ .Page.Permalink }}">{{ .Page.Title }}</a> {{ .Count }}</li>
   295      {{ end }}
   296  </ul>
   297  
   298  `)
   299  
   300  	b.WithTemplatesAdded("_default/terms.html", `
   301  <h1>Terms</h1>
   302  <ul>
   303      {{ range .Data.Terms.Alphabetical }}
   304              <li><a href="{{ .Page.Permalink }}">{{ .Page.Title }}</a> {{ .Count }}</li>
   305      {{ end }}
   306  </ul>
   307  `)
   308  
   309  	for i := 0; i < 10; i++ {
   310  		b.WithContent(fmt.Sprintf("page%d.md", i+1), `
   311  ---
   312  Title: "Taxonomy!"
   313  tags: ["Hugo Rocks!", "Rocks I say!" ]
   314  categories: ["This is Cool", "And new" ]
   315  ---
   316  
   317  Content.
   318  
   319  		`)
   320  	}
   321  
   322  	b.CreateSites().Build(BuildCfg{})
   323  
   324  	b.AssertFileContent("public/index.html", `<li><a href="http://example.com/tags/hugo-rocks/">Hugo Rocks!</a> 10</li>`)
   325  	b.AssertFileContent("public/categories/index.html", `<li><a href="http://example.com/categories/this-is-cool/">This is Cool</a> 10</li>`)
   326  	b.AssertFileContent("public/tags/index.html", `<li><a href="http://example.com/tags/rocks-i-say/">Rocks I say!</a> 10</li>`)
   327  }
   328  
   329  // Issue 6213
   330  func TestTaxonomiesNotForDrafts(t *testing.T) {
   331  	t.Parallel()
   332  
   333  	b := newTestSitesBuilder(t)
   334  	b.WithContent("draft.md", `---
   335  title: "Draft"
   336  draft: true
   337  categories: ["drafts"]
   338  ---
   339  
   340  `,
   341  		"regular.md", `---
   342  title: "Not Draft"
   343  categories: ["regular"]
   344  ---
   345  
   346  `)
   347  
   348  	b.Build(BuildCfg{})
   349  	s := b.H.Sites[0]
   350  
   351  	b.Assert(b.CheckExists("public/categories/regular/index.html"), qt.Equals, true)
   352  	b.Assert(b.CheckExists("public/categories/drafts/index.html"), qt.Equals, false)
   353  
   354  	reg, _ := s.getPageNew(nil, "categories/regular")
   355  	dra, _ := s.getPageNew(nil, "categories/draft")
   356  	b.Assert(reg, qt.Not(qt.IsNil))
   357  	b.Assert(dra, qt.IsNil)
   358  }
   359  
   360  func TestTaxonomiesIndexDraft(t *testing.T) {
   361  	t.Parallel()
   362  
   363  	b := newTestSitesBuilder(t)
   364  	b.WithContent(
   365  		"categories/_index.md", `---
   366  title: "The Categories"
   367  draft: true
   368  ---
   369  
   370  Content.
   371  
   372  `,
   373  		"page.md", `---
   374  title: "The Page"
   375  categories: ["cool"]
   376  ---
   377  
   378  Content.
   379  
   380  `,
   381  	)
   382  
   383  	b.WithTemplates("index.html", `
   384  {{ range .Site.Pages }}
   385  {{ .RelPermalink }}|{{ .Title }}|{{ .WordCount }}|{{ .Content }}|
   386  {{ end }}
   387  `)
   388  
   389  	b.Build(BuildCfg{})
   390  
   391  	b.AssertFileContentFn("public/index.html", func(s string) bool {
   392  		return !strings.Contains(s, "categories")
   393  	})
   394  }
   395  
   396  // https://github.com/gohugoio/hugo/issues/6927
   397  func TestTaxonomiesHomeDraft(t *testing.T) {
   398  	t.Parallel()
   399  
   400  	b := newTestSitesBuilder(t)
   401  	b.WithContent(
   402  		"_index.md", `---
   403  title: "Home"
   404  draft: true
   405  ---
   406  
   407  Content.
   408  
   409  `,
   410  		"posts/_index.md", `---
   411  title: "Posts"
   412  draft: true
   413  ---
   414  
   415  Content.
   416  
   417  `,
   418  		"posts/page.md", `---
   419  title: "The Page"
   420  categories: ["cool"]
   421  ---
   422  
   423  Content.
   424  
   425  `,
   426  	)
   427  
   428  	b.WithTemplates("index.html", `
   429  NO HOME FOR YOU
   430  `)
   431  
   432  	b.Build(BuildCfg{})
   433  
   434  	b.Assert(b.CheckExists("public/index.html"), qt.Equals, false)
   435  	b.Assert(b.CheckExists("public/categories/index.html"), qt.Equals, false)
   436  	b.Assert(b.CheckExists("public/posts/index.html"), qt.Equals, false)
   437  }
   438  
   439  // https://github.com/gohugoio/hugo/issues/6173
   440  func TestTaxonomiesWithBundledResources(t *testing.T) {
   441  	b := newTestSitesBuilder(t)
   442  	b.WithTemplates("_default/list.html", `
   443  List {{ .Title }}:
   444  {{ range .Resources }}
   445  Resource: {{ .RelPermalink }}|{{ .MediaType }}
   446  {{ end }}
   447  	`)
   448  
   449  	b.WithContent("p1.md", `---
   450  title: Page
   451  categories: ["funny"]
   452  ---
   453  	`,
   454  		"categories/_index.md", "---\ntitle: Categories Page\n---",
   455  		"categories/data.json", "Category data",
   456  		"categories/funny/_index.md", "---\ntitle: Funny Category\n---",
   457  		"categories/funny/funnydata.json", "Category funny data",
   458  	)
   459  
   460  	b.Build(BuildCfg{})
   461  
   462  	b.AssertFileContent("public/categories/index.html", `Resource: /categories/data.json|application/json`)
   463  	b.AssertFileContent("public/categories/funny/index.html", `Resource: /categories/funny/funnydata.json|application/json`)
   464  }
   465  
   466  func TestTaxonomiesRemoveOne(t *testing.T) {
   467  	b := newTestSitesBuilder(t).Running()
   468  	b.WithTemplates("index.html", `
   469  	{{ $cats := .Site.Taxonomies.categories.cats }}
   470  	{{ if $cats }}
   471  	Len cats: {{ len $cats }}
   472  	{{ range $cats }}
   473          Cats:|{{ .Page.RelPermalink }}|
   474      {{ end }}
   475      {{ end }}
   476      {{ $funny := .Site.Taxonomies.categories.funny }}
   477      {{ if $funny }}
   478  	Len funny: {{ len $funny }}
   479      {{ range $funny }}
   480          Funny:|{{ .Page.RelPermalink }}|
   481      {{ end }}
   482      {{ end }}
   483  	`)
   484  
   485  	b.WithContent("p1.md", `---
   486  title: Page
   487  categories: ["funny", "cats"]
   488  ---
   489  	`, "p2.md", `---
   490  title: Page2
   491  categories: ["funny", "cats"]
   492  ---
   493  	`,
   494  	)
   495  
   496  	b.Build(BuildCfg{})
   497  
   498  	b.AssertFileContent("public/index.html", `
   499  Len cats: 2
   500  Len funny: 2
   501  Cats:|/p1/|
   502  Cats:|/p2/|
   503  Funny:|/p1/|
   504  Funny:|/p2/|`)
   505  
   506  	// Remove one category from one of the pages.
   507  	b.EditFiles("content/p1.md", `---
   508  title: Page
   509  categories: ["funny"]
   510  ---
   511  	`)
   512  
   513  	b.Build(BuildCfg{})
   514  
   515  	b.AssertFileContent("public/index.html", `
   516  Len cats: 1
   517  Len funny: 2
   518  Cats:|/p2/|
   519  Funny:|/p1/|
   520  Funny:|/p2/|`)
   521  }
   522  
   523  // https://github.com/gohugoio/hugo/issues/6590
   524  func TestTaxonomiesListPages(t *testing.T) {
   525  	b := newTestSitesBuilder(t)
   526  	b.WithTemplates("_default/list.html", `
   527  
   528  {{ template "print-taxo" "categories.cats" }}
   529  {{ template "print-taxo" "categories.funny" }}
   530  
   531  {{ define "print-taxo" }}
   532  {{ $node := index site.Taxonomies (split $ ".") }}
   533  {{ if $node }}
   534  Len {{ $ }}: {{ len $node }}
   535  {{ range $node }}
   536      {{ $ }}:|{{ .Page.RelPermalink }}|
   537  {{ end }}
   538  {{ else }}
   539  {{ $ }} not found.
   540  {{ end }}
   541  {{ end }}
   542  	`)
   543  
   544  	b.WithContent("_index.md", `---
   545  title: Home
   546  categories: ["funny", "cats"]
   547  ---
   548  	`, "blog/p1.md", `---
   549  title: Page1
   550  categories: ["funny"]
   551  ---
   552  	`, "blog/_index.md", `---
   553  title: Blog Section
   554  categories: ["cats"]
   555  ---
   556  	`,
   557  	)
   558  
   559  	b.Build(BuildCfg{})
   560  
   561  	b.AssertFileContent("public/index.html", `
   562  
   563  Len categories.cats: 2
   564  categories.cats:|/blog/|
   565  categories.cats:|/|
   566  
   567  Len categories.funny: 2
   568  categories.funny:|/|
   569  categories.funny:|/blog/p1/|
   570  `)
   571  }
   572  
   573  func TestTaxonomiesPageCollections(t *testing.T) {
   574  	t.Parallel()
   575  
   576  	b := newTestSitesBuilder(t)
   577  	b.WithContent(
   578  		"_index.md", `---
   579  title: "Home Sweet Home"
   580  categories: [ "dogs", "gorillas"]
   581  ---
   582  `,
   583  		"section/_index.md", `---
   584  title: "Section"
   585  categories: [ "cats", "dogs", "birds"]
   586  ---
   587  `,
   588  		"section/p1.md", `---
   589  title: "Page1"
   590  categories: ["funny", "cats"]
   591  ---
   592  `, "section/p2.md", `---
   593  title: "Page2"
   594  categories: ["funny"]
   595  ---
   596  `)
   597  
   598  	b.WithTemplatesAdded("index.html", `
   599  {{ $home := site.Home }}
   600  {{ $section := site.GetPage "section" }}
   601  {{ $categories := site.GetPage "categories" }}
   602  {{ $funny := site.GetPage "categories/funny" }}
   603  {{ $cats := site.GetPage "categories/cats" }}
   604  {{ $p1 := site.GetPage "section/p1" }}
   605  
   606  Categories Pages: {{ range $categories.Pages}}{{.RelPermalink }}|{{ end }}:END
   607  Funny Pages: {{ range $funny.Pages}}{{.RelPermalink }}|{{ end }}:END
   608  Cats Pages: {{ range $cats.Pages}}{{.RelPermalink }}|{{ end }}:END
   609  P1 Terms: {{ range $p1.GetTerms "categories" }}{{.RelPermalink }}|{{ end }}:END
   610  Section Terms: {{ range $section.GetTerms "categories" }}{{.RelPermalink }}|{{ end }}:END
   611  Home Terms: {{ range $home.GetTerms "categories" }}{{.RelPermalink }}|{{ end }}:END
   612  Category Paginator {{ range $categories.Paginator.Pages }}{{ .RelPermalink }}|{{ end }}:END
   613  Cats Paginator {{ range $cats.Paginator.Pages }}{{ .RelPermalink }}|{{ end }}:END
   614  
   615  `)
   616  	b.WithTemplatesAdded("404.html", `
   617  404 Terms: {{ range .GetTerms "categories" }}{{.RelPermalink }}|{{ end }}:END
   618  	`)
   619  	b.Build(BuildCfg{})
   620  
   621  	cat := b.GetPage("categories")
   622  	funny := b.GetPage("categories/funny")
   623  
   624  	b.Assert(cat, qt.Not(qt.IsNil))
   625  	b.Assert(funny, qt.Not(qt.IsNil))
   626  
   627  	b.Assert(cat.Parent().IsHome(), qt.Equals, true)
   628  	b.Assert(funny.Kind(), qt.Equals, "term")
   629  	b.Assert(funny.Parent(), qt.Equals, cat)
   630  
   631  	b.AssertFileContent("public/index.html", `
   632  Categories Pages: /categories/birds/|/categories/cats/|/categories/dogs/|/categories/funny/|/categories/gorillas/|:END
   633  Funny Pages: /section/p1/|/section/p2/|:END
   634  Cats Pages: /section/p1/|/section/|:END
   635  P1 Terms: /categories/funny/|/categories/cats/|:END
   636  Section Terms: /categories/cats/|/categories/dogs/|/categories/birds/|:END
   637  Home Terms: /categories/dogs/|/categories/gorillas/|:END
   638  Cats Paginator /section/p1/|/section/|:END
   639  Category Paginator /categories/birds/|/categories/cats/|/categories/dogs/|/categories/funny/|/categories/gorillas/|:END`,
   640  	)
   641  	b.AssertFileContent("public/404.html", "\n404 Terms: :END\n\t")
   642  	b.AssertFileContent("public/categories/funny/index.xml", `<link>http://example.com/section/p1/</link>`)
   643  	b.AssertFileContent("public/categories/index.xml", `<link>http://example.com/categories/funny/</link>`)
   644  }
   645  
   646  func TestTaxonomiesDirectoryOverlaps(t *testing.T) {
   647  	t.Parallel()
   648  
   649  	b := newTestSitesBuilder(t).WithContent(
   650  		"abc/_index.md", "---\ntitle: \"abc\"\nabcdefgs: [abc]\n---",
   651  		"abc/p1.md", "---\ntitle: \"abc-p\"\n---",
   652  		"abcdefgh/_index.md", "---\ntitle: \"abcdefgh\"\n---",
   653  		"abcdefgh/p1.md", "---\ntitle: \"abcdefgh-p\"\n---",
   654  		"abcdefghijk/index.md", "---\ntitle: \"abcdefghijk\"\n---",
   655  	)
   656  
   657  	b.WithConfigFile("toml", `
   658  baseURL = "https://example.org"
   659  
   660  [taxonomies]
   661    abcdef = "abcdefs"
   662    abcdefg = "abcdefgs"
   663    abcdefghi = "abcdefghis"
   664  `)
   665  
   666  	b.WithTemplatesAdded("index.html", `
   667  {{ range site.Pages }}Page: {{ template "print-page" . }}
   668  {{ end }}
   669  {{ $abc := site.GetPage "abcdefgs/abc" }}
   670  {{ $abcdefgs := site.GetPage "abcdefgs" }}
   671  abc: {{ template "print-page" $abc }}|IsAncestor: {{ $abc.IsAncestor $abcdefgs }}|IsDescendant: {{ $abc.IsDescendant $abcdefgs }}
   672  abcdefgs: {{ template "print-page" $abcdefgs }}|IsAncestor: {{ $abcdefgs.IsAncestor $abc }}|IsDescendant: {{ $abcdefgs.IsDescendant $abc }}
   673  
   674  {{ define "print-page" }}{{ .RelPermalink }}|{{ .Title }}|{{.Kind }}|Parent: {{ with .Parent }}{{ .RelPermalink }}{{ end }}|CurrentSection: {{ .CurrentSection.RelPermalink}}|FirstSection: {{ .FirstSection.RelPermalink }}{{ end }}
   675  
   676  `)
   677  
   678  	b.Build(BuildCfg{})
   679  
   680  	b.AssertFileContent("public/index.html", `
   681      Page: /||home|Parent: |CurrentSection: /|
   682      Page: /abc/|abc|section|Parent: /|CurrentSection: /abc/|
   683      Page: /abc/p1/|abc-p|page|Parent: /abc/|CurrentSection: /abc/|
   684      Page: /abcdefgh/|abcdefgh|section|Parent: /|CurrentSection: /abcdefgh/|
   685      Page: /abcdefgh/p1/|abcdefgh-p|page|Parent: /abcdefgh/|CurrentSection: /abcdefgh/|
   686      Page: /abcdefghijk/|abcdefghijk|page|Parent: /|CurrentSection: /|
   687      Page: /abcdefghis/|Abcdefghis|taxonomy|Parent: /|CurrentSection: /|
   688      Page: /abcdefgs/|Abcdefgs|taxonomy|Parent: /|CurrentSection: /|
   689      Page: /abcdefs/|Abcdefs|taxonomy|Parent: /|CurrentSection: /|
   690      abc: /abcdefgs/abc/|abc|term|Parent: /abcdefgs/|CurrentSection: /abcdefgs/|
   691      abcdefgs: /abcdefgs/|Abcdefgs|taxonomy|Parent: /|CurrentSection: /|
   692      abc: /abcdefgs/abc/|abc|term|Parent: /abcdefgs/|CurrentSection: /abcdefgs/|FirstSection: /|IsAncestor: false|IsDescendant: true
   693      abcdefgs: /abcdefgs/|Abcdefgs|taxonomy|Parent: /|CurrentSection: /|FirstSection: /|IsAncestor: true|IsDescendant: false
   694  `)
   695  }
   696  
   697  func TestTaxonomiesWeightSort(t *testing.T) {
   698  
   699  	files := `
   700  -- layouts/index.html --
   701  {{ $a := site.GetPage "tags/a"}}
   702  :{{ range $a.Pages }}{{ .RelPermalink }}|{{ end }}:
   703  -- content/p1.md --
   704  ---
   705  title: P1
   706  weight: 100
   707  tags: ['a']
   708  tags_weight: 20
   709  ---
   710  -- content/p3.md --
   711  ---
   712  title: P2
   713  weight: 200
   714  tags: ['a']
   715  tags_weight: 30
   716  ---
   717  -- content/p2.md --
   718  ---
   719  title: P3
   720  weight: 50
   721  tags: ['a']
   722  tags_weight: 40
   723  ---
   724  	`
   725  
   726  	b := NewIntegrationTestBuilder(
   727  		IntegrationTestConfig{
   728  			T:           t,
   729  			TxtarString: files,
   730  		},
   731  	).Build()
   732  
   733  	b.AssertFileContent("public/index.html", `:/p1/|/p3/|/p2/|:`)
   734  }