github.com/neohugo/neohugo@v0.123.8/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/neohugo/neohugo/resources/kinds" 24 "github.com/neohugo/neohugo/resources/page" 25 26 qt "github.com/frankban/quicktest" 27 28 "github.com/neohugo/neohugo/deps" 29 ) 30 31 func TestTaxonomiesCountOrder(t *testing.T) { 32 t.Parallel() 33 c := qt.New(t) 34 35 taxonomies := make(map[string]string) 36 taxonomies["tag"] = "tags" 37 taxonomies["category"] = "categories" 38 39 cfg, fs := newTestCfg() 40 41 cfg.Set("titleCaseStyle", "none") 42 cfg.Set("taxonomies", taxonomies) 43 configs, err := loadTestConfigFromProvider(cfg) 44 c.Assert(err, qt.IsNil) 45 46 const pageContent = `--- 47 tags: ['a', 'B', 'c'] 48 categories: 'd' 49 --- 50 YAML frontmatter with tags and categories taxonomy.` 51 52 writeSource(t, fs, filepath.Join("content", "page.md"), pageContent) 53 54 s := buildSingleSite(t, deps.DepsCfg{Fs: fs, Configs: configs}, BuildCfg{}) 55 56 st := make([]string, 0) 57 for _, t := range s.Taxonomies()["tags"].ByCount() { 58 st = append(st, t.Page().Title()+":"+t.Name) 59 } 60 61 expect := []string{"a:a", "B:b", "c:c"} 62 63 if !reflect.DeepEqual(st, expect) { 64 t.Fatalf("ordered taxonomies mismatch, expected\n%v\ngot\n%q", expect, st) 65 } 66 } 67 68 func TestTaxonomiesWithAndWithoutContentFile(t *testing.T) { 69 for _, uglyURLs := range []bool{false, true} { 70 uglyURLs := uglyURLs 71 t.Run(fmt.Sprintf("uglyURLs=%t", uglyURLs), func(t *testing.T) { 72 t.Parallel() 73 doTestTaxonomiesWithAndWithoutContentFile(t, uglyURLs) 74 }) 75 } 76 } 77 78 func doTestTaxonomiesWithAndWithoutContentFile(t *testing.T, uglyURLs bool) { 79 siteConfig := ` 80 baseURL = "http://example.com/blog" 81 titleCaseStyle = "firstupper" 82 uglyURLs = %t 83 paginate = 1 84 defaultContentLanguage = "en" 85 [Taxonomies] 86 tag = "tags" 87 category = "categories" 88 other = "others" 89 empty = "empties" 90 permalinked = "permalinkeds" 91 [permalinks] 92 permalinkeds = "/perma/:slug/" 93 ` 94 95 pageTemplate := `--- 96 title: "%s" 97 tags: 98 %s 99 categories: 100 %s 101 others: 102 %s 103 permalinkeds: 104 %s 105 --- 106 # Doc 107 ` 108 109 siteConfig = fmt.Sprintf(siteConfig, uglyURLs) 110 111 b := newTestSitesBuilder(t).WithConfigFile("toml", siteConfig) 112 113 b.WithContent( 114 "p1.md", fmt.Sprintf(pageTemplate, "t1/c1", "- Tag1", "- cAt1", "- o1", "- Pl1"), 115 "p2.md", fmt.Sprintf(pageTemplate, "t2/c1", "- tag2", "- cAt1", "- o1", "- Pl1"), 116 "p3.md", fmt.Sprintf(pageTemplate, "t2/c12", "- tag2", "- cat2", "- o1", "- Pl1"), 117 "p4.md", fmt.Sprintf(pageTemplate, "Hello World", "", "", "- \"Hello Hugo world\"", "- Pl1"), 118 "categories/_index.md", newTestPage("Category Terms", "2017-01-01", 10), 119 "tags/Tag1/_index.md", newTestPage("Tag1 List", "2017-01-01", 10), 120 // https://github.com/gohugoio/hugo/issues/5847 121 "/tags/not-used/_index.md", newTestPage("Unused Tag List", "2018-01-01", 10), 122 ) 123 124 b.Build(BuildCfg{}) 125 126 // So what we have now is: 127 // 1. categories with terms content page, but no content page for the only c1 category 128 // 2. tags with no terms content page, but content page for one of 2 tags (tag1) 129 // 3. the "others" taxonomy with no content pages. 130 // 4. the "permalinkeds" taxonomy with permalinks configuration. 131 132 pathFunc := func(s string) string { 133 if uglyURLs { 134 return strings.Replace(s, "/index.html", ".html", 1) 135 } 136 return s 137 } 138 139 // 1. 140 b.AssertFileContent(pathFunc("public/categories/cat1/index.html"), "List", "CAt1") 141 b.AssertFileContent(pathFunc("public/categories/index.html"), "Taxonomy Term Page", "Category Terms") 142 143 // 2. 144 b.AssertFileContent(pathFunc("public/tags/tag2/index.html"), "List", "tag2") 145 b.AssertFileContent(pathFunc("public/tags/tag1/index.html"), "List", "Tag1") 146 b.AssertFileContent(pathFunc("public/tags/index.html"), "Taxonomy Term Page", "Tags") 147 148 // 3. 149 b.AssertFileContent(pathFunc("public/others/o1/index.html"), "List", "o1") 150 b.AssertFileContent(pathFunc("public/others/index.html"), "Taxonomy Term Page", "Others") 151 152 // 4. 153 b.AssertFileContent(pathFunc("public/perma/pl1/index.html"), "List", "Pl1") 154 155 // This looks kind of funky, but the taxonomy terms do not have a permalinks definition, 156 // for good reasons. 157 b.AssertFileContent(pathFunc("public/permalinkeds/index.html"), "Taxonomy Term Page", "Permalinkeds") 158 159 s := b.H.Sites[0] 160 161 // Make sure that each kinds.KindTaxonomyTerm page has an appropriate number 162 // of kinds.KindTaxonomy pages in its Pages slice. 163 taxonomyTermPageCounts := map[string]int{ 164 "tags": 3, 165 "categories": 2, 166 "others": 2, 167 "empties": 0, 168 "permalinkeds": 1, 169 } 170 171 for taxonomy, count := range taxonomyTermPageCounts { 172 msg := qt.Commentf(taxonomy) 173 term := s.getPageOldVersion(kinds.KindTaxonomy, taxonomy) 174 b.Assert(term, qt.Not(qt.IsNil), msg) 175 b.Assert(len(term.Pages()), qt.Equals, count, msg) 176 177 for _, p := range term.Pages() { 178 b.Assert(p.Kind(), qt.Equals, kinds.KindTerm) 179 } 180 } 181 182 cat1 := s.getPageOldVersion(kinds.KindTerm, "categories", "cat1") 183 b.Assert(cat1, qt.Not(qt.IsNil)) 184 if uglyURLs { 185 b.Assert(cat1.RelPermalink(), qt.Equals, "/blog/categories/cat1.html") 186 } else { 187 b.Assert(cat1.RelPermalink(), qt.Equals, "/blog/categories/cat1/") 188 } 189 190 pl1 := s.getPageOldVersion(kinds.KindTerm, "permalinkeds", "pl1") 191 permalinkeds := s.getPageOldVersion(kinds.KindTaxonomy, "permalinkeds") 192 b.Assert(pl1, qt.Not(qt.IsNil)) 193 b.Assert(permalinkeds, qt.Not(qt.IsNil)) 194 if uglyURLs { 195 b.Assert(pl1.RelPermalink(), qt.Equals, "/blog/perma/pl1.html") 196 b.Assert(permalinkeds.RelPermalink(), qt.Equals, "/blog/permalinkeds.html") 197 } else { 198 b.Assert(pl1.RelPermalink(), qt.Equals, "/blog/perma/pl1/") 199 b.Assert(permalinkeds.RelPermalink(), qt.Equals, "/blog/permalinkeds/") 200 } 201 202 helloWorld := s.getPageOldVersion(kinds.KindTerm, "others", "hello-hugo-world") 203 b.Assert(helloWorld, qt.Not(qt.IsNil)) 204 b.Assert(helloWorld.Title(), qt.Equals, "Hello Hugo world") 205 206 // Issue #2977 207 b.AssertFileContent(pathFunc("public/empties/index.html"), "Taxonomy Term Page", "Empties") 208 } 209 210 // https://github.com/gohugoio/hugo/issues/5513 211 // https://github.com/gohugoio/hugo/issues/5571 212 func TestTaxonomiesPathSeparation(t *testing.T) { 213 t.Parallel() 214 215 config := ` 216 baseURL = "https://example.com" 217 titleCaseStyle = "none" 218 [taxonomies] 219 "news/tag" = "news/tags" 220 "news/category" = "news/categories" 221 "t1/t2/t3" = "t1/t2/t3s" 222 "s1/s2/s3" = "s1/s2/s3s" 223 ` 224 225 pageContent := ` 226 +++ 227 title = "foo" 228 "news/categories" = ["a", "b", "c", "d/e", "f/g/h"] 229 "t1/t2/t3s" = ["t4/t5", "t4/t5/t6"] 230 +++ 231 Content. 232 ` 233 234 b := newTestSitesBuilder(t) 235 b.WithConfigFile("toml", config) 236 b.WithContent("page.md", pageContent) 237 b.WithContent("news/categories/b/_index.md", ` 238 --- 239 title: "This is B" 240 --- 241 `) 242 243 b.WithContent("news/categories/f/g/h/_index.md", ` 244 --- 245 title: "This is H" 246 --- 247 `) 248 249 b.WithContent("t1/t2/t3s/t4/t5/_index.md", ` 250 --- 251 title: "This is T5" 252 --- 253 `) 254 255 b.WithContent("s1/s2/s3s/_index.md", ` 256 --- 257 title: "This is S3s" 258 --- 259 `) 260 261 b.CreateSites().Build(BuildCfg{}) 262 263 s := b.H.Sites[0] 264 265 filterbyKind := func(kind string) page.Pages { 266 var pages page.Pages 267 for _, p := range s.Pages() { 268 if p.Kind() == kind { 269 pages = append(pages, p) 270 } 271 } 272 return pages 273 } 274 275 ta := filterbyKind(kinds.KindTerm) 276 te := filterbyKind(kinds.KindTaxonomy) 277 278 b.Assert(len(te), qt.Equals, 4) 279 b.Assert(len(ta), qt.Equals, 7) 280 281 b.AssertFileContent("public/news/categories/a/index.html", "Taxonomy List Page 1|a|Hello|https://example.com/news/categories/a/|") 282 b.AssertFileContent("public/news/categories/b/index.html", "Taxonomy List Page 1|This is B|Hello|https://example.com/news/categories/b/|") 283 b.AssertFileContent("public/news/categories/d/e/index.html", "Taxonomy List Page 1|d/e|Hello|https://example.com/news/categories/d/e/|") 284 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/|") 285 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/|") 286 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/|") 287 288 b.AssertFileContent("public/news/categories/index.html", "Taxonomy Term Page 1|categories|Hello|https://example.com/news/categories/|") 289 b.AssertFileContent("public/t1/t2/t3s/index.html", "Taxonomy Term Page 1|t3s|Hello|https://example.com/t1/t2/t3s/|") 290 b.AssertFileContent("public/s1/s2/s3s/index.html", "Taxonomy Term Page 1|This is S3s|Hello|https://example.com/s1/s2/s3s/|") 291 } 292 293 // https://github.com/gohugoio/hugo/issues/5719 294 func TestTaxonomiesNextGenLoops(t *testing.T) { 295 b := newTestSitesBuilder(t).WithSimpleConfigFile() 296 297 b.WithTemplatesAdded("index.html", ` 298 <h1>Tags</h1> 299 <ul> 300 {{ range .Site.Taxonomies.tags }} 301 <li><a href="{{ .Page.Permalink }}">{{ .Page.Title }}</a> {{ .Count }}</li> 302 {{ end }} 303 </ul> 304 305 `) 306 307 b.WithTemplatesAdded("_default/terms.html", ` 308 <h1>Terms</h1> 309 <ul> 310 {{ range .Data.Terms.Alphabetical }} 311 <li><a href="{{ .Page.Permalink }}">{{ .Page.Title }}</a> {{ .Count }}</li> 312 {{ end }} 313 </ul> 314 `) 315 316 for i := 0; i < 10; i++ { 317 b.WithContent(fmt.Sprintf("page%d.md", i+1), ` 318 --- 319 Title: "Taxonomy!" 320 tags: ["Hugo Rocks!", "Rocks I say!" ] 321 categories: ["This is Cool", "And new" ] 322 --- 323 324 Content. 325 326 `) 327 } 328 329 b.CreateSites().Build(BuildCfg{}) 330 331 b.AssertFileContent("public/index.html", `<li><a href="http://example.com/tags/hugo-rocks/">Hugo Rocks!</a> 10</li>`) 332 b.AssertFileContent("public/categories/index.html", `<li><a href="http://example.com/categories/this-is-cool/">This Is Cool</a> 10</li>`) 333 b.AssertFileContent("public/tags/index.html", `<li><a href="http://example.com/tags/rocks-i-say/">Rocks I Say!</a> 10</li>`) 334 } 335 336 // Issue 6213 337 func TestTaxonomiesNotForDrafts(t *testing.T) { 338 t.Parallel() 339 340 b := newTestSitesBuilder(t) 341 b.WithContent("draft.md", `--- 342 title: "Draft" 343 draft: true 344 categories: ["drafts"] 345 --- 346 347 `, 348 "regular.md", `--- 349 title: "Not Draft" 350 categories: ["regular"] 351 --- 352 353 `) 354 355 b.Build(BuildCfg{}) 356 s := b.H.Sites[0] 357 358 b.Assert(b.CheckExists("public/categories/regular/index.html"), qt.Equals, true) 359 b.Assert(b.CheckExists("public/categories/drafts/index.html"), qt.Equals, false) 360 361 reg, _ := s.getPage(nil, "categories/regular") 362 dra, _ := s.getPage(nil, "categories/draft") 363 b.Assert(reg, qt.Not(qt.IsNil)) 364 b.Assert(dra, qt.IsNil) 365 } 366 367 func TestTaxonomiesIndexDraft(t *testing.T) { 368 t.Parallel() 369 b := newTestSitesBuilder(t) 370 b.WithContent( 371 "categories/_index.md", `--- 372 title: "The Categories" 373 draft: true 374 --- 375 376 Content. 377 378 `, 379 "page.md", `--- 380 title: "The Page" 381 categories: ["cool"] 382 --- 383 384 Content. 385 386 `, 387 ) 388 389 b.WithTemplates("index.html", ` 390 {{ range .Site.Pages }} 391 {{ .RelPermalink }}|{{ .Title }}|{{ .WordCount }}|{{ .Content }}| 392 {{ end }} 393 `) 394 395 b.Build(BuildCfg{}) 396 397 b.AssertFileContentFn("public/index.html", func(s string) bool { 398 return !strings.Contains(s, "/categories/|") 399 }) 400 } 401 402 // https://github.com/gohugoio/hugo/issues/6927 403 func TestTaxonomiesHomeDraft(t *testing.T) { 404 t.Parallel() 405 406 b := newTestSitesBuilder(t) 407 b.WithContent( 408 "_index.md", `--- 409 title: "Home" 410 draft: true 411 --- 412 413 Content. 414 415 `, 416 "posts/_index.md", `--- 417 title: "Posts" 418 draft: true 419 --- 420 421 Content. 422 423 `, 424 "posts/page.md", `--- 425 title: "The Page" 426 categories: ["cool"] 427 --- 428 429 Content. 430 431 `, 432 ) 433 434 b.WithTemplates("index.html", ` 435 NO HOME FOR YOU 436 `) 437 438 b.Build(BuildCfg{}) 439 440 b.Assert(b.CheckExists("public/index.html"), qt.Equals, false) 441 b.Assert(b.CheckExists("public/categories/index.html"), qt.Equals, false) 442 b.Assert(b.CheckExists("public/posts/index.html"), qt.Equals, false) 443 } 444 445 // https://github.com/gohugoio/hugo/issues/6173 446 func TestTaxonomiesWithBundledResources(t *testing.T) { 447 b := newTestSitesBuilder(t) 448 b.WithTemplates("_default/list.html", ` 449 List {{ .Title }}: 450 {{ range .Resources }} 451 Resource: {{ .RelPermalink }}|{{ .MediaType }} 452 {{ end }} 453 `) 454 455 b.WithContent("p1.md", `--- 456 title: Page 457 categories: ["funny"] 458 --- 459 `, 460 "categories/_index.md", "---\ntitle: Categories Page\n---", 461 "categories/data.json", "Category data", 462 "categories/funny/_index.md", "---\ntitle: Funny Category\n---", 463 "categories/funny/funnydata.json", "Category funny data", 464 ) 465 466 b.Build(BuildCfg{}) 467 468 b.AssertFileContent("public/categories/index.html", `Resource: /categories/data.json|application/json`) 469 b.AssertFileContent("public/categories/funny/index.html", `Resource: /categories/funny/funnydata.json|application/json`) 470 } 471 472 func TestTaxonomiesRemoveOne(t *testing.T) { 473 files := ` 474 -- hugo.toml -- 475 disableLiveReload = true 476 -- layouts/index.html -- 477 {{ $cats := .Site.Taxonomies.categories.cats }} 478 {{ if $cats }} 479 Len cats: {{ len $cats }} 480 {{ range $cats }} 481 Cats:|{{ .Page.RelPermalink }}| 482 {{ end }} 483 {{ end }} 484 {{ $funny := .Site.Taxonomies.categories.funny }} 485 {{ if $funny }} 486 Len funny: {{ len $funny }} 487 {{ range $funny }} 488 Funny:|{{ .Page.RelPermalink }}| 489 {{ end }} 490 {{ end }} 491 -- content/p1.md -- 492 --- 493 title: Page 494 categories: ["funny", "cats"] 495 --- 496 -- content/p2.md -- 497 --- 498 title: Page2 499 categories: ["funny", "cats"] 500 --- 501 502 ` 503 b := TestRunning(t, files) 504 505 b.AssertFileContent("public/index.html", ` 506 Len cats: 2 507 Len funny: 2 508 Cats:|/p1/| 509 Cats:|/p2/| 510 Funny:|/p1/| 511 Funny:|/p2/|`) 512 513 // Remove one category from one of the pages. 514 b.EditFiles("content/p1.md", `--- 515 title: Page 516 categories: ["funny"] 517 --- 518 `) 519 520 b.Build() 521 522 b.AssertFileContent("public/index.html", ` 523 Len cats: 1 524 Len funny: 2 525 Cats:|/p2/| 526 Funny:|/p1/| 527 Funny:|/p2/|`) 528 } 529 530 // https://github.com/gohugoio/hugo/issues/6590 531 func TestTaxonomiesListPages(t *testing.T) { 532 b := newTestSitesBuilder(t) 533 b.WithTemplates("_default/list.html", ` 534 535 {{ template "print-taxo" "categories.cats" }} 536 {{ template "print-taxo" "categories.funny" }} 537 538 {{ define "print-taxo" }} 539 {{ $node := index site.Taxonomies (split $ ".") }} 540 {{ if $node }} 541 Len {{ $ }}: {{ len $node }} 542 {{ range $node }} 543 {{ $ }}:|{{ .Page.RelPermalink }}| 544 {{ end }} 545 {{ else }} 546 {{ $ }} not found. 547 {{ end }} 548 {{ end }} 549 `) 550 551 b.WithContent("_index.md", `--- 552 title: Home 553 categories: ["funny", "cats"] 554 --- 555 `, "blog/p1.md", `--- 556 title: Page1 557 categories: ["funny"] 558 --- 559 `, "blog/_index.md", `--- 560 title: Blog Section 561 categories: ["cats"] 562 --- 563 `, 564 ) 565 566 b.Build(BuildCfg{}) 567 568 b.AssertFileContent("public/index.html", ` 569 570 Len categories.cats: 2 571 categories.cats:|/blog/| 572 categories.cats:|/| 573 574 Len categories.funny: 2 575 categories.funny:|/| 576 categories.funny:|/blog/p1/| 577 `) 578 } 579 580 func TestTaxonomiesPageCollections(t *testing.T) { 581 t.Parallel() 582 583 b := newTestSitesBuilder(t) 584 b.WithContent( 585 "_index.md", `--- 586 title: "Home Sweet Home" 587 categories: [ "dogs", "gorillas"] 588 --- 589 `, 590 "section/_index.md", `--- 591 title: "Section" 592 categories: [ "cats", "dogs", "birds"] 593 --- 594 `, 595 "section/p1.md", `--- 596 title: "Page1" 597 categories: ["funny", "cats"] 598 --- 599 `, "section/p2.md", `--- 600 title: "Page2" 601 categories: ["funny"] 602 --- 603 `) 604 605 b.WithTemplatesAdded("index.html", ` 606 {{ $home := site.Home }} 607 {{ $section := site.GetPage "section" }} 608 {{ $categories := site.GetPage "categories" }} 609 {{ $funny := site.GetPage "categories/funny" }} 610 {{ $cats := site.GetPage "categories/cats" }} 611 {{ $p1 := site.GetPage "section/p1" }} 612 613 Categories Pages: {{ range $categories.Pages}}{{.RelPermalink }}|{{ end }}:END 614 Funny Pages: {{ range $funny.Pages}}{{.RelPermalink }}|{{ end }}:END 615 Cats Pages: {{ range $cats.Pages}}{{.RelPermalink }}|{{ end }}:END 616 P1 Terms: {{ range $p1.GetTerms "categories" }}{{.RelPermalink }}|{{ end }}:END 617 Section Terms: {{ range $section.GetTerms "categories" }}{{.RelPermalink }}|{{ end }}:END 618 Home Terms: {{ range $home.GetTerms "categories" }}{{.RelPermalink }}|{{ end }}:END 619 Category Paginator {{ range $categories.Paginator.Pages }}{{ .RelPermalink }}|{{ end }}:END 620 Cats Paginator {{ range $cats.Paginator.Pages }}{{ .RelPermalink }}|{{ end }}:END 621 622 `) 623 b.WithTemplatesAdded("404.html", ` 624 404 Terms: {{ range .GetTerms "categories" }}{{.RelPermalink }}|{{ end }}:END 625 `) 626 b.Build(BuildCfg{}) 627 628 cat := b.GetPage("categories") 629 funny := b.GetPage("categories/funny") 630 631 b.Assert(cat, qt.Not(qt.IsNil)) 632 b.Assert(funny, qt.Not(qt.IsNil)) 633 634 b.Assert(cat.Parent().IsHome(), qt.Equals, true) 635 b.Assert(funny.Kind(), qt.Equals, "term") 636 b.Assert(funny.Parent(), qt.Equals, cat) 637 638 b.AssertFileContent("public/index.html", ` 639 Categories Pages: /categories/birds/|/categories/cats/|/categories/dogs/|/categories/funny/|/categories/gorillas/|:END 640 Funny Pages: /section/p1/|/section/p2/|:END 641 Cats Pages: /section/p1/|/section/|:END 642 P1 Terms: /categories/funny/|/categories/cats/|:END 643 Section Terms: /categories/cats/|/categories/dogs/|/categories/birds/|:END 644 Home Terms: /categories/dogs/|/categories/gorillas/|:END 645 Cats Paginator /section/p1/|/section/|:END 646 Category Paginator /categories/birds/|/categories/cats/|/categories/dogs/|/categories/funny/|/categories/gorillas/|:END`, 647 ) 648 b.AssertFileContent("public/404.html", "\n404 Terms: :END\n\t") 649 b.AssertFileContent("public/categories/funny/index.xml", `<link>http://example.com/section/p1/</link>`) 650 b.AssertFileContent("public/categories/index.xml", `<link>http://example.com/categories/funny/</link>`) 651 } 652 653 func TestTaxonomiesDirectoryOverlaps(t *testing.T) { 654 t.Parallel() 655 656 b := newTestSitesBuilder(t).WithContent( 657 "abc/_index.md", "---\ntitle: \"abc\"\nabcdefgs: [abc]\n---", 658 "abc/p1.md", "---\ntitle: \"abc-p\"\n---", 659 "abcdefgh/_index.md", "---\ntitle: \"abcdefgh\"\n---", 660 "abcdefgh/p1.md", "---\ntitle: \"abcdefgh-p\"\n---", 661 "abcdefghijk/index.md", "---\ntitle: \"abcdefghijk\"\n---", 662 ) 663 664 b.WithConfigFile("toml", ` 665 baseURL = "https://example.org" 666 titleCaseStyle = "none" 667 668 [taxonomies] 669 abcdef = "abcdefs" 670 abcdefg = "abcdefgs" 671 abcdefghi = "abcdefghis" 672 `) 673 674 b.WithTemplatesAdded("index.html", ` 675 {{ range site.Pages }}Page: {{ template "print-page" . }} 676 {{ end }} 677 {{ $abc := site.GetPage "abcdefgs/abc" }} 678 {{ $abcdefgs := site.GetPage "abcdefgs" }} 679 abc: {{ template "print-page" $abc }}|IsAncestor: {{ $abc.IsAncestor $abcdefgs }}|IsDescendant: {{ $abc.IsDescendant $abcdefgs }} 680 abcdefgs: {{ template "print-page" $abcdefgs }}|IsAncestor: {{ $abcdefgs.IsAncestor $abc }}|IsDescendant: {{ $abcdefgs.IsDescendant $abc }} 681 682 {{ define "print-page" }}{{ .RelPermalink }}|{{ .Title }}|{{.Kind }}|Parent: {{ with .Parent }}{{ .RelPermalink }}{{ end }}|CurrentSection: {{ .CurrentSection.RelPermalink}}|FirstSection: {{ .FirstSection.RelPermalink }}{{ end }} 683 684 `) 685 686 b.Build(BuildCfg{}) 687 688 b.AssertFileContent("public/index.html", ` 689 Page: /||home|Parent: |CurrentSection: /| 690 Page: /abc/|abc|section|Parent: /|CurrentSection: /abc/| 691 Page: /abc/p1/|abc-p|page|Parent: /abc/|CurrentSection: /abc/| 692 Page: /abcdefgh/|abcdefgh|section|Parent: /|CurrentSection: /abcdefgh/| 693 Page: /abcdefgh/p1/|abcdefgh-p|page|Parent: /abcdefgh/|CurrentSection: /abcdefgh/| 694 Page: /abcdefghijk/|abcdefghijk|page|Parent: /|CurrentSection: /| 695 Page: /abcdefghis/|abcdefghis|taxonomy|Parent: /|CurrentSection: /abcdefghis/| 696 Page: /abcdefgs/|abcdefgs|taxonomy|Parent: /|CurrentSection: /abcdefgs/| 697 Page: /abcdefs/|abcdefs|taxonomy|Parent: /|CurrentSection: /abcdefs/| 698 abc: /abcdefgs/abc/|abc|term|Parent: /abcdefgs/|CurrentSection: /abcdefgs/abc/| 699 abcdefgs: /abcdefgs/|abcdefgs|taxonomy|Parent: /|CurrentSection: /abcdefgs/| 700 abc: /abcdefgs/abc/|abc|term|Parent: /abcdefgs/|CurrentSection: /abcdefgs/abc/|FirstSection: /abcdefgs/|IsAncestor: false|IsDescendant: true 701 abcdefgs: /abcdefgs/|abcdefgs|taxonomy|Parent: /|CurrentSection: /abcdefgs/|FirstSection: /abcdefgs/|IsAncestor: true|IsDescendant: false 702 `) 703 } 704 705 func TestTaxonomiesWeightSort(t *testing.T) { 706 files := ` 707 -- layouts/index.html -- 708 {{ $a := site.GetPage "tags/a"}} 709 :{{ range $a.Pages }}{{ .RelPermalink }}|{{ end }}: 710 -- content/p1.md -- 711 --- 712 title: P1 713 weight: 100 714 tags: ['a'] 715 tags_weight: 20 716 --- 717 -- content/p3.md -- 718 --- 719 title: P2 720 weight: 200 721 tags: ['a'] 722 tags_weight: 30 723 --- 724 -- content/p2.md -- 725 --- 726 title: P3 727 weight: 50 728 tags: ['a'] 729 tags_weight: 40 730 --- 731 ` 732 733 b := Test(t, files) 734 735 b.AssertFileContent("public/index.html", `:/p1/|/p3/|/p2/|:`) 736 } 737 738 func TestTaxonomiesEmptyTagsString(t *testing.T) { 739 t.Parallel() 740 741 files := ` 742 -- hugo.toml -- 743 [taxonomies] 744 tag = 'tags' 745 -- content/p1.md -- 746 +++ 747 title = "P1" 748 tags = '' 749 +++ 750 -- layouts/_default/single.html -- 751 Single. 752 753 ` 754 Test(t, files) 755 } 756 757 func TestTaxonomiesSpaceInName(t *testing.T) { 758 t.Parallel() 759 760 files := ` 761 -- hugo.toml -- 762 [taxonomies] 763 authors = 'book authors' 764 -- content/p1.md -- 765 --- 766 title: Good Omens 767 book authors: 768 - Neil Gaiman 769 - Terry Pratchett 770 --- 771 -- layouts/index.html -- 772 {{- $taxonomy := "book authors" }} 773 Len Book Authors: {{ len (index .Site.Taxonomies $taxonomy) }} 774 ` 775 b := Test(t, files) 776 777 b.AssertFileContent("public/index.html", "Len Book Authors: 2") 778 } 779 780 func TestTaxonomiesListTermsHome(t *testing.T) { 781 files := ` 782 -- hugo.toml -- 783 baseURL = "https://example.com" 784 [taxonomies] 785 tag = "tags" 786 -- content/_index.md -- 787 --- 788 title: "Home" 789 tags: ["a", "b", "c", "hello world"] 790 --- 791 -- content/tags/a/_index.md -- 792 --- 793 title: "A" 794 --- 795 -- content/tags/b/_index.md -- 796 --- 797 title: "B" 798 --- 799 -- content/tags/c/_index.md -- 800 --- 801 title: "C" 802 --- 803 -- content/tags/d/_index.md -- 804 --- 805 title: "D" 806 --- 807 -- content/tags/hello-world/_index.md -- 808 --- 809 title: "Hello World!" 810 --- 811 -- layouts/home.html -- 812 Terms: {{ range site.Taxonomies.tags }}{{ .Page.Title }}: {{ .Count }}|{{ end }}$ 813 ` 814 b := Test(t, files) 815 816 b.AssertFileContent("public/index.html", "Terms: A: 1|B: 1|C: 1|Hello World!: 1|$") 817 } 818 819 func TestTaxonomiesTermTitleAndTerm(t *testing.T) { 820 files := ` 821 -- hugo.toml -- 822 baseURL = "https://example.com" 823 [taxonomies] 824 tag = "tags" 825 -- content/_index.md -- 826 --- 827 title: "Home" 828 tags: ["hellO world"] 829 --- 830 -- layouts/_default/term.html -- 831 {{ .Title }}|{{ .Kind }}|{{ .Data.Singular }}|{{ .Data.Plural }}|{{ .Page.Data.Term }}| 832 ` 833 834 b := Test(t, files) 835 836 b.AssertFileContent("public/tags/hello-world/index.html", "HellO World|term|tag|tags|hellO world|") 837 } 838 839 func TestTermDraft(t *testing.T) { 840 t.Parallel() 841 842 files := ` 843 -- layouts/_default/list.html -- 844 |{{ .Title }}| 845 -- content/p1.md -- 846 --- 847 title: p1 848 tags: [a] 849 --- 850 -- content/tags/a/_index.md -- 851 --- 852 title: tag-a-title-override 853 draft: true 854 --- 855 ` 856 857 b := Test(t, files) 858 859 b.AssertFileExists("public/tags/a/index.html", false) 860 } 861 862 func TestTermBuildNeverRenderNorList(t *testing.T) { 863 t.Parallel() 864 865 files := ` 866 -- layouts/index.html -- 867 |{{ len site.Taxonomies.tags }}| 868 -- content/p1.md -- 869 --- 870 title: p1 871 tags: [a] 872 --- 873 -- content/tags/a/_index.md -- 874 --- 875 title: tag-a-title-override 876 build: 877 render: never 878 list: never 879 --- 880 881 ` 882 883 b := Test(t, files) 884 885 b.AssertFileExists("public/tags/a/index.html", false) 886 b.AssertFileContent("public/index.html", "|0|") 887 } 888 889 func TestTaxonomiesTermLookup(t *testing.T) { 890 t.Parallel() 891 892 files := ` 893 -- hugo.toml -- 894 baseURL = "https://example.com" 895 [taxonomies] 896 tag = "tags" 897 -- content/_index.md -- 898 --- 899 title: "Home" 900 tags: ["a", "b"] 901 --- 902 -- layouts/taxonomy/tag.html -- 903 Tag: {{ .Title }}| 904 -- content/tags/a/_index.md -- 905 --- 906 title: tag-a-title-override 907 --- 908 ` 909 910 b := Test(t, files) 911 912 b.AssertFileContent("public/tags/a/index.html", "Tag: tag-a-title-override|") 913 } 914 915 func TestTaxonomyLookupIssue12193(t *testing.T) { 916 t.Parallel() 917 918 files := ` 919 -- hugo.toml -- 920 disableKinds = ['page','rss','section','sitemap'] 921 [taxonomies] 922 author = 'authors' 923 -- layouts/_default/list.html -- 924 {{ .Title }}| 925 -- layouts/_default/author.terms.html -- 926 layouts/_default/author.terms.html 927 -- content/authors/_index.md -- 928 --- 929 title: Authors Page 930 --- 931 ` 932 933 b := Test(t, files) 934 935 b.AssertFileExists("public/index.html", true) 936 b.AssertFileExists("public/authors/index.html", true) 937 b.AssertFileContent("public/authors/index.html", "layouts/_default/author.terms.html") // failing test 938 } 939 940 func TestTaxonomyNestedEmptySectionsIssue12188(t *testing.T) { 941 t.Parallel() 942 943 files := ` 944 -- hugo.toml -- 945 disableKinds = ['rss','sitemap'] 946 defaultContentLanguage = 'en' 947 defaultContentLanguageInSubdir = true 948 [languages.en] 949 weight = 1 950 [languages.ja] 951 weight = 2 952 [taxonomies] 953 's1/category' = 's1/category' 954 -- layouts/_default/single.html -- 955 {{ .Title }}| 956 -- layouts/_default/list.html -- 957 {{ .Title }}| 958 -- content/s1/p1.en.md -- 959 --- 960 title: p1 961 --- 962 ` 963 964 b := Test(t, files) 965 966 b.AssertFileExists("public/en/s1/index.html", true) 967 b.AssertFileExists("public/en/s1/p1/index.html", true) 968 b.AssertFileExists("public/en/s1/category/index.html", true) 969 970 b.AssertFileExists("public/ja/s1/index.html", false) // failing test 971 b.AssertFileExists("public/ja/s1/category/index.html", true) 972 }