hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

taxonomy_test.go (19505B)

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