github.com/neohugo/neohugo@v0.123.8/hugolib/pagebundler_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 "os" 19 "path/filepath" 20 "testing" 21 22 "github.com/neohugo/neohugo/common/loggers" 23 "github.com/neohugo/neohugo/hugofs" 24 25 "github.com/neohugo/neohugo/config" 26 27 "github.com/neohugo/neohugo/helpers" 28 29 "github.com/neohugo/neohugo/resources/kinds" 30 "github.com/neohugo/neohugo/resources/page" 31 32 "github.com/neohugo/neohugo/htesting" 33 34 "github.com/neohugo/neohugo/deps" 35 36 qt "github.com/frankban/quicktest" 37 ) 38 39 func TestPageBundlerBundleInRoot(t *testing.T) { 40 t.Parallel() 41 files := ` 42 -- hugo.toml -- 43 baseURL = "https://example.com" 44 disableKinds = ["taxonomy", "term"] 45 -- content/root/index.md -- 46 --- 47 title: "Root" 48 --- 49 -- layouts/_default/single.html -- 50 Basic: {{ .Title }}|{{ .Kind }}|{{ .BundleType }}|{{ .RelPermalink }}| 51 Tree: Section: {{ .Section }}|CurrentSection: {{ .CurrentSection.RelPermalink }}|Parent: {{ .Parent.RelPermalink }}|FirstSection: {{ .FirstSection.RelPermalink }} 52 ` 53 b := Test(t, files) 54 55 b.AssertFileContent("public/root/index.html", 56 "Basic: Root|page|leaf|/root/|", 57 "Tree: Section: |CurrentSection: /|Parent: /|FirstSection: /", 58 ) 59 } 60 61 func TestPageBundlerShortcodeInBundledPage(t *testing.T) { 62 t.Parallel() 63 files := ` 64 -- hugo.toml -- 65 baseURL = "https://example.com" 66 disableKinds = ["taxonomy", "term"] 67 -- content/section/mybundle/index.md -- 68 --- 69 title: "Mybundle" 70 --- 71 -- content/section/mybundle/p1.md -- 72 --- 73 title: "P1" 74 --- 75 76 P1 content. 77 78 {{< myShort >}} 79 80 -- layouts/_default/single.html -- 81 Bundled page: {{ .RelPermalink}}|{{ with .Resources.Get "p1.md" }}Title: {{ .Title }}|Content: {{ .Content }}{{ end }}| 82 -- layouts/shortcodes/myShort.html -- 83 MyShort. 84 85 ` 86 b := Test(t, files) 87 88 b.AssertFileContent("public/section/mybundle/index.html", 89 "Bundled page: /section/mybundle/|Title: P1|Content: <p>P1 content.</p>\nMyShort.", 90 ) 91 } 92 93 func TestPageBundlerResourceMultipleOutputFormatsWithDifferentPaths(t *testing.T) { 94 t.Parallel() 95 files := ` 96 -- hugo.toml -- 97 baseURL = "https://example.com" 98 disableKinds = ["taxonomy", "term"] 99 [outputformats] 100 [outputformats.cpath] 101 mediaType = "text/html" 102 path = "cpath" 103 -- content/section/mybundle/index.md -- 104 --- 105 title: "My Bundle" 106 outputs: ["html", "cpath"] 107 --- 108 -- content/section/mybundle/hello.txt -- 109 Hello. 110 -- content/section/mybundle/p1.md -- 111 --- 112 title: "P1" 113 --- 114 P1. 115 116 {{< hello >}} 117 118 -- layouts/shortcodes/hello.html -- 119 Hello HTML. 120 -- layouts/_default/single.html -- 121 Basic: {{ .Title }}|{{ .Kind }}|{{ .BundleType }}|{{ .RelPermalink }}| 122 Resources: {{ range .Resources }}RelPermalink: {{ .RelPermalink }}|Content: {{ .Content }}|{{ end }}| 123 -- layouts/shortcodes/hello.cpath -- 124 Hello CPATH. 125 -- layouts/_default/single.cpath -- 126 Basic: {{ .Title }}|{{ .Kind }}|{{ .BundleType }}|{{ .RelPermalink }}| 127 Resources: {{ range .Resources }}RelPermalink: {{ .RelPermalink }}|Content: {{ .Content }}|{{ end }}| 128 ` 129 130 b := Test(t, files) 131 132 b.AssertFileContent("public/section/mybundle/index.html", 133 "Basic: My Bundle|page|leaf|/section/mybundle/|", 134 "Resources: RelPermalink: |Content: <p>P1.</p>\nHello HTML.\n|RelPermalink: /section/mybundle/hello.txt|Content: Hello.||", 135 ) 136 137 b.AssertFileContent("public/cpath/section/mybundle/index.html", "Basic: My Bundle|page|leaf|/section/mybundle/|\nResources: RelPermalink: |Content: <p>P1.</p>\nHello CPATH.\n|RelPermalink: /section/mybundle/hello.txt|Content: Hello.||") 138 } 139 140 func TestPageBundlerMultilingualTextResource(t *testing.T) { 141 t.Parallel() 142 143 files := ` 144 -- hugo.toml -- 145 baseURL = "https://example.com" 146 disableKinds = ["taxonomy", "term"] 147 defaultContentLanguage = "en" 148 defaultContentLanguageInSubdir = true 149 [languages] 150 [languages.en] 151 weight = 1 152 [languages.en.permalinks] 153 "/" = "/enpages/:slug/" 154 [languages.nn] 155 weight = 2 156 -- content/mybundle/index.md -- 157 --- 158 title: "My Bundle" 159 --- 160 -- content/mybundle/index.nn.md -- 161 --- 162 title: "My Bundle NN" 163 --- 164 -- content/mybundle/f1.txt -- 165 F1 166 -- content/mybundle/f2.txt -- 167 F2 168 -- content/mybundle/f2.nn.txt -- 169 F2 nn. 170 -- layouts/_default/single.html -- 171 {{ .Title }}|{{ .RelPermalink }}|{{ .Lang }}| 172 Resources: {{ range .Resources }}RelPermalink: {{ .RelPermalink }}|Content: {{ .Content }}|{{ end }}| 173 174 ` 175 b := Test(t, files) 176 177 b.AssertFileContent("public/en/enpages/my-bundle/index.html", "My Bundle|/en/enpages/my-bundle/|en|\nResources: RelPermalink: /en/enpages/my-bundle/f1.txt|Content: F1|RelPermalink: /en/enpages/my-bundle/f2.txt|Content: F2||") 178 b.AssertFileContent("public/nn/mybundle/index.html", "My Bundle NN|/nn/mybundle/|nn|\nResources: RelPermalink: /en/enpages/my-bundle/f1.txt|Content: F1|RelPermalink: /nn/mybundle/f2.nn.txt|Content: F2 nn.||") 179 } 180 181 func TestMultilingualDisableLanguage(t *testing.T) { 182 t.Parallel() 183 184 files := ` 185 -- hugo.toml -- 186 baseURL = "https://example.com" 187 disableKinds = ["taxonomy", "term"] 188 defaultContentLanguage = "en" 189 defaultContentLanguageInSubdir = true 190 [languages] 191 [languages.en] 192 weight = 1 193 [languages.nn] 194 weight = 2 195 disabled = true 196 -- content/mysect/_index.md -- 197 --- 198 title: "My Sect En" 199 --- 200 -- content/mysect/p1/index.md -- 201 --- 202 title: "P1" 203 --- 204 P1 205 -- content/mysect/_index.nn.md -- 206 --- 207 title: "My Sect Nn" 208 --- 209 -- content/mysect/p1/index.nn.md -- 210 --- 211 title: "P1nn" 212 --- 213 P1nn 214 -- layouts/index.html -- 215 Len RegularPages: {{ len .Site.RegularPages }}|RegularPages: {{ range site.RegularPages }}{{ .RelPermalink }}: {{ .Title }}|{{ end }}| 216 Len Pages: {{ len .Site.Pages }}| 217 Len Sites: {{ len .Site.Sites }}| 218 -- layouts/_default/single.html -- 219 {{ .Title }}|{{ .Content }}|{{ .Lang }}| 220 221 ` 222 b := Test(t, files) 223 224 b.AssertFileContent("public/en/index.html", "Len RegularPages: 1|") 225 b.AssertFileContent("public/en/mysect/p1/index.html", "P1|<p>P1</p>\n|en|") 226 b.AssertFileExists("public/public/nn/mysect/p1/index.html", false) 227 b.Assert(len(b.H.Sites), qt.Equals, 1) 228 } 229 230 func TestPageBundlerHeadless(t *testing.T) { 231 t.Parallel() 232 233 cfg, fs := newTestCfg() 234 c := qt.New(t) 235 236 workDir := "/work" 237 cfg.Set("workingDir", workDir) 238 cfg.Set("contentDir", "base") 239 cfg.Set("baseURL", "https://example.com") 240 configs, err := loadTestConfigFromProvider(cfg) 241 c.Assert(err, qt.IsNil) 242 243 pageContent := `--- 244 title: "Bundle Galore" 245 slug: s1 246 date: 2017-01-23 247 --- 248 249 TheContent. 250 251 {{< myShort >}} 252 ` 253 254 writeSource(t, fs, filepath.Join(workDir, "layouts", "_default", "single.html"), "single {{ .Content }}") 255 writeSource(t, fs, filepath.Join(workDir, "layouts", "_default", "list.html"), "list") 256 writeSource(t, fs, filepath.Join(workDir, "layouts", "shortcodes", "myShort.html"), "SHORTCODE") 257 258 writeSource(t, fs, filepath.Join(workDir, "base", "a", "index.md"), pageContent) 259 writeSource(t, fs, filepath.Join(workDir, "base", "a", "l1.png"), "PNG image") 260 writeSource(t, fs, filepath.Join(workDir, "base", "a", "l2.png"), "PNG image") 261 262 writeSource(t, fs, filepath.Join(workDir, "base", "b", "index.md"), `--- 263 title: "Headless Bundle in Topless Bar" 264 slug: s2 265 headless: true 266 date: 2017-01-23 267 --- 268 269 TheContent. 270 HEADLESS {{< myShort >}} 271 `) 272 writeSource(t, fs, filepath.Join(workDir, "base", "b", "l1.png"), "PNG image") 273 writeSource(t, fs, filepath.Join(workDir, "base", "b", "l2.png"), "PNG image") 274 writeSource(t, fs, filepath.Join(workDir, "base", "b", "p1.md"), pageContent) 275 276 s := buildSingleSite(t, deps.DepsCfg{Fs: fs, Configs: configs}, BuildCfg{}) 277 278 c.Assert(len(s.RegularPages()), qt.Equals, 1) 279 280 regular := s.getPageOldVersion(kinds.KindPage, "a/index") 281 c.Assert(regular.RelPermalink(), qt.Equals, "/s1/") 282 283 headless := s.getPageOldVersion(kinds.KindPage, "b/index") 284 c.Assert(headless, qt.Not(qt.IsNil)) 285 c.Assert(headless.Title(), qt.Equals, "Headless Bundle in Topless Bar") 286 c.Assert(headless.RelPermalink(), qt.Equals, "") 287 c.Assert(headless.Permalink(), qt.Equals, "") 288 c.Assert(content(headless), qt.Contains, "HEADLESS SHORTCODE") 289 290 headlessResources := headless.Resources() 291 c.Assert(len(headlessResources), qt.Equals, 3) 292 res := headlessResources.Match("l*") 293 c.Assert(len(res), qt.Equals, 2) 294 pageResource := headlessResources.GetMatch("p*") 295 c.Assert(pageResource, qt.Not(qt.IsNil)) 296 p := pageResource.(page.Page) 297 c.Assert(content(p), qt.Contains, "SHORTCODE") 298 c.Assert(p.Name(), qt.Equals, "p1.md") 299 300 th := newTestHelper(s.conf, s.Fs, t) 301 302 th.assertFileContent(filepath.FromSlash("public/s1/index.html"), "TheContent") 303 th.assertFileContent(filepath.FromSlash("public/s1/l1.png"), "PNG") 304 305 th.assertFileNotExist("public/s2/index.html") 306 // But the bundled resources needs to be published 307 th.assertFileContent(filepath.FromSlash("public/s2/l1.png"), "PNG") 308 309 // No headless bundles here, please. 310 // https://github.com/gohugoio/hugo/issues/6492 311 c.Assert(s.RegularPages(), qt.HasLen, 1) 312 c.Assert(s.Pages(), qt.HasLen, 4) 313 c.Assert(s.home.RegularPages(), qt.HasLen, 1) 314 c.Assert(s.home.Pages(), qt.HasLen, 1) 315 } 316 317 func TestPageBundlerHeadlessIssue6552(t *testing.T) { 318 t.Parallel() 319 320 b := newTestSitesBuilder(t) 321 b.WithContent("headless/h1/index.md", ` 322 --- 323 title: My Headless Bundle1 324 headless: true 325 --- 326 `, "headless/h1/p1.md", ` 327 --- 328 title: P1 329 --- 330 `, "headless/h2/index.md", ` 331 --- 332 title: My Headless Bundle2 333 headless: true 334 --- 335 `) 336 337 b.WithTemplatesAdded("index.html", ` 338 {{ $headless1 := .Site.GetPage "headless/h1" }} 339 {{ $headless2 := .Site.GetPage "headless/h2" }} 340 341 HEADLESS1: {{ $headless1.Title }}|{{ $headless1.RelPermalink }}|{{ len $headless1.Resources }}| 342 HEADLESS2: {{ $headless2.Title }}{{ $headless2.RelPermalink }}|{{ len $headless2.Resources }}| 343 344 `) 345 346 b.Build(BuildCfg{}) 347 348 b.AssertFileContent("public/index.html", ` 349 HEADLESS1: My Headless Bundle1||1| 350 HEADLESS2: My Headless Bundle2|0| 351 `) 352 } 353 354 func TestMultiSiteBundles(t *testing.T) { 355 c := qt.New(t) 356 b := newTestSitesBuilder(t) 357 b.WithConfigFile("toml", ` 358 359 baseURL = "http://example.com/" 360 361 defaultContentLanguage = "en" 362 363 [languages] 364 [languages.en] 365 weight = 10 366 contentDir = "content/en" 367 [languages.nn] 368 weight = 20 369 contentDir = "content/nn" 370 371 372 `) 373 374 b.WithContent("en/mybundle/index.md", ` 375 --- 376 headless: true 377 --- 378 379 `) 380 381 b.WithContent("nn/mybundle/index.md", ` 382 --- 383 headless: true 384 --- 385 386 `) 387 388 b.WithContent("en/mybundle/data.yaml", `data en`) 389 b.WithContent("en/mybundle/forms.yaml", `forms en`) 390 b.WithContent("nn/mybundle/data.yaml", `data nn`) 391 392 b.WithContent("en/_index.md", ` 393 --- 394 Title: Home 395 --- 396 397 Home content. 398 399 `) 400 401 b.WithContent("en/section-not-bundle/_index.md", ` 402 --- 403 Title: Section Page 404 --- 405 406 Section content. 407 408 `) 409 410 b.WithContent("en/section-not-bundle/single.md", ` 411 --- 412 Title: Section Single 413 Date: 2018-02-01 414 --- 415 416 Single content. 417 418 `) 419 420 b.Build(BuildCfg{}) 421 422 b.AssertFileContent("public/nn/mybundle/data.yaml", "data nn") 423 b.AssertFileContent("public/mybundle/data.yaml", "data en") 424 b.AssertFileContent("public/mybundle/forms.yaml", "forms en") 425 426 c.Assert(b.CheckExists("public/nn/nn/mybundle/data.yaml"), qt.Equals, false) 427 c.Assert(b.CheckExists("public/en/mybundle/data.yaml"), qt.Equals, false) 428 429 homeEn := b.H.Sites[0].home 430 c.Assert(homeEn, qt.Not(qt.IsNil)) 431 c.Assert(homeEn.Date().Year(), qt.Equals, 2018) 432 433 b.AssertFileContent("public/section-not-bundle/index.html", "Section Page", "Content: <p>Section content.</p>") 434 b.AssertFileContent("public/section-not-bundle/single/index.html", "Section Single", "|<p>Single content.</p>") 435 } 436 437 func TestBundledResourcesMultilingualDuplicateResourceFiles(t *testing.T) { 438 t.Parallel() 439 440 files := ` 441 -- hugo.toml -- 442 baseURL = "https://example.com/" 443 [markup] 444 [markup.goldmark] 445 duplicateResourceFiles = true 446 [languages] 447 [languages.en] 448 weight = 1 449 [languages.en.permalinks] 450 "/" = "/enpages/:slug/" 451 [languages.nn] 452 weight = 2 453 [languages.nn.permalinks] 454 "/" = "/nnpages/:slug/" 455 -- content/mybundle/index.md -- 456 --- 457 title: "My Bundle" 458 --- 459 {{< getresource "f1.txt" >}} 460 {{< getresource "f2.txt" >}} 461 -- content/mybundle/index.nn.md -- 462 --- 463 title: "My Bundle NN" 464 --- 465 {{< getresource "f1.txt" >}} 466 f2.nn.txt is the original name. 467 {{< getresource "f2.nn.txt" >}} 468 {{< getresource "f2.txt" >}} 469 {{< getresource "sub/f3.txt" >}} 470 -- content/mybundle/f1.txt -- 471 F1 en. 472 -- content/mybundle/sub/f3.txt -- 473 F1 en. 474 -- content/mybundle/f2.txt -- 475 F2 en. 476 -- content/mybundle/f2.nn.txt -- 477 F2 nn. 478 -- layouts/shortcodes/getresource.html -- 479 {{ $r := .Page.Resources.Get (.Get 0)}} 480 Resource: {{ (.Get 0) }}|{{ with $r }}{{ .RelPermalink }}|{{ .Content }}|{{ else }}Not found.{{ end}} 481 -- layouts/_default/single.html -- 482 {{ .Title }}|{{ .RelPermalink }}|{{ .Lang }}|{{ .Content }}| 483 ` 484 b := Test(t, files) 485 486 // helpers.PrintFs(b.H.Fs.PublishDir, "", os.Stdout) 487 b.AssertFileContent("public/nn/nnpages/my-bundle-nn/index.html", ` 488 My Bundle NN 489 Resource: f1.txt|/nn/nnpages/my-bundle-nn/f1.txt| 490 Resource: f2.txt|/nn/nnpages/my-bundle-nn/f2.nn.txt|F2 nn.| 491 Resource: f2.nn.txt|/nn/nnpages/my-bundle-nn/f2.nn.txt|F2 nn.| 492 Resource: sub/f3.txt|/nn/nnpages/my-bundle-nn/sub/f3.txt|F1 en.| 493 `) 494 495 b.AssertFileContent("public/enpages/my-bundle/f2.txt", "F2 en.") 496 b.AssertFileContent("public/nn/nnpages/my-bundle-nn/f2.nn.txt", "F2 nn") 497 498 b.AssertFileContent("public/enpages/my-bundle/index.html", ` 499 Resource: f1.txt|/enpages/my-bundle/f1.txt|F1 en.| 500 Resource: f2.txt|/enpages/my-bundle/f2.txt|F2 en.| 501 `) 502 b.AssertFileContent("public/enpages/my-bundle/f1.txt", "F1 en.") 503 504 // Should be duplicated to the nn bundle. 505 b.AssertFileContent("public/nn/nnpages/my-bundle-nn/f1.txt", "F1 en.") 506 } 507 508 // https://github.com/gohugoio/hugo/issues/5858 509 func TestBundledResourcesWhenMultipleOutputFormats(t *testing.T) { 510 t.Parallel() 511 512 files := ` 513 -- hugo.toml -- 514 baseURL = "https://example.org" 515 disableKinds = ["taxonomy", "term"] 516 disableLiveReload = true 517 [outputs] 518 # This looks odd, but it triggers the behavior in #5858 519 # The total output formats list gets sorted, so CSS before HTML. 520 home = [ "CSS" ] 521 -- content/mybundle/index.md -- 522 --- 523 title: Page 524 --- 525 -- content/mybundle/data.json -- 526 MyData 527 -- layouts/_default/single.html -- 528 {{ range .Resources }} 529 {{ .ResourceType }}|{{ .Title }}| 530 {{ end }} 531 ` 532 533 b := TestRunning(t, files) 534 535 b.AssertFileContent("public/mybundle/data.json", "MyData") 536 537 b.EditFileReplaceAll("content/mybundle/data.json", "MyData", "My changed data").Build() 538 539 b.AssertFileContent("public/mybundle/data.json", "My changed data") 540 } 541 542 // https://github.com/gohugoio/hugo/issues/5858 543 544 // https://github.com/gohugoio/hugo/issues/4870 545 func TestBundleSlug(t *testing.T) { 546 t.Parallel() 547 c := qt.New(t) 548 549 const pageTemplate = `--- 550 title: Title 551 slug: %s 552 --- 553 ` 554 555 b := newTestSitesBuilder(t) 556 557 b.WithTemplatesAdded("index.html", `{{ range .Site.RegularPages }}|{{ .RelPermalink }}{{ end }}|`) 558 b.WithSimpleConfigFile(). 559 WithContent("about/services1/misc.md", fmt.Sprintf(pageTemplate, "this-is-the-slug")). 560 WithContent("about/services2/misc/index.md", fmt.Sprintf(pageTemplate, "this-is-another-slug")) 561 562 b.CreateSites().Build(BuildCfg{}) 563 564 b.AssertHome( 565 "|/about/services1/this-is-the-slug/|/", 566 "|/about/services2/this-is-another-slug/|") 567 568 c.Assert(b.CheckExists("public/about/services1/this-is-the-slug/index.html"), qt.Equals, true) 569 c.Assert(b.CheckExists("public/about/services2/this-is-another-slug/index.html"), qt.Equals, true) 570 } 571 572 // See #11663 573 func TestPageBundlerPartialTranslations(t *testing.T) { 574 t.Parallel() 575 files := ` 576 -- hugo.toml -- 577 baseURL = "https://example.com" 578 disableKinds = ["taxonomy", "term"] 579 defaultContentLanguage = "en" 580 defaultContentLanguageInSubDir = true 581 [languages] 582 [languages.nn] 583 weight = 2 584 [languages.en] 585 weight = 1 586 -- content/section/mybundle/index.md -- 587 --- 588 title: "Mybundle" 589 --- 590 -- content/section/mybundle/bundledpage.md -- 591 --- 592 title: "Bundled page en" 593 --- 594 -- content/section/mybundle/bundledpage.nn.md -- 595 --- 596 title: "Bundled page nn" 597 --- 598 599 -- layouts/_default/single.html -- 600 Bundled page: {{ .RelPermalink}}|Len resources: {{ len .Resources }}| 601 602 603 ` 604 b := Test(t, files) 605 606 b.AssertFileContent("public/en/section/mybundle/index.html", 607 "Bundled page: /en/section/mybundle/|Len resources: 1|", 608 ) 609 610 b.AssertFileExists("public/nn/section/mybundle/index.html", false) 611 } 612 613 // #6208 614 func TestBundleIndexInSubFolder(t *testing.T) { 615 config := ` 616 baseURL = "https://example.com" 617 618 ` 619 620 const pageContent = `--- 621 title: %q 622 --- 623 ` 624 createPage := func(s string) string { 625 return fmt.Sprintf(pageContent, s) 626 } 627 628 b := newTestSitesBuilder(t).WithConfigFile("toml", config) 629 b.WithLogger(loggers.NewDefault()) 630 631 b.WithTemplates("_default/single.html", `{{ range .Resources }} 632 {{ .ResourceType }}|{{ .Title }}| 633 {{ end }} 634 635 636 `) 637 638 b.WithContent("bundle/index.md", createPage("bundle index")) 639 b.WithContent("bundle/p1.md", createPage("bundle p1")) 640 b.WithContent("bundle/sub/p2.md", createPage("bundle sub p2")) 641 b.WithContent("bundle/sub/index.md", createPage("bundle sub index")) 642 b.WithContent("bundle/sub/data.json", "data") 643 644 b.Build(BuildCfg{}) 645 646 b.AssertFileContent("public/bundle/index.html", ` 647 application|sub/data.json| 648 page|bundle p1| 649 page|bundle sub index| 650 page|bundle sub p2| 651 `) 652 } 653 654 func TestBundleTransformMany(t *testing.T) { 655 b := newTestSitesBuilder(t).WithSimpleConfigFile().Running() 656 657 for i := 1; i <= 50; i++ { 658 b.WithContent(fmt.Sprintf("bundle%d/index.md", i), fmt.Sprintf(` 659 --- 660 title: "Page" 661 weight: %d 662 --- 663 664 `, i)) 665 b.WithSourceFile(fmt.Sprintf("content/bundle%d/data.yaml", i), fmt.Sprintf(`data: v%d`, i)) 666 b.WithSourceFile(fmt.Sprintf("content/bundle%d/data.json", i), fmt.Sprintf(`{ "data": "v%d" }`, i)) 667 b.WithSourceFile(fmt.Sprintf("assets/data%d/data.yaml", i), fmt.Sprintf(`vdata: v%d`, i)) 668 669 } 670 671 b.WithTemplatesAdded("_default/single.html", ` 672 {{ $bundleYaml := .Resources.GetMatch "*.yaml" }} 673 {{ $bundleJSON := .Resources.GetMatch "*.json" }} 674 {{ $assetsYaml := resources.GetMatch (printf "data%d/*.yaml" .Weight) }} 675 {{ $data1 := $bundleYaml | transform.Unmarshal }} 676 {{ $data2 := $assetsYaml | transform.Unmarshal }} 677 {{ $bundleFingerprinted := $bundleYaml | fingerprint "md5" }} 678 {{ $assetsFingerprinted := $assetsYaml | fingerprint "md5" }} 679 {{ $jsonMin := $bundleJSON | minify }} 680 {{ $jsonMinMin := $jsonMin | minify }} 681 {{ $jsonMinMinMin := $jsonMinMin | minify }} 682 683 data content unmarshaled: {{ $data1.data }} 684 data assets content unmarshaled: {{ $data2.vdata }} 685 bundle fingerprinted: {{ $bundleFingerprinted.RelPermalink }} 686 assets fingerprinted: {{ $assetsFingerprinted.RelPermalink }} 687 688 bundle min min min: {{ $jsonMinMinMin.RelPermalink }} 689 bundle min min key: {{ $jsonMinMin.Key }} 690 691 `) 692 693 for i := 0; i < 3; i++ { 694 695 b.Build(BuildCfg{}) 696 697 for i := 1; i <= 50; i++ { 698 index := fmt.Sprintf("public/bundle%d/index.html", i) 699 b.AssertFileContent(fmt.Sprintf("public/bundle%d/data.yaml", i), fmt.Sprintf("data: v%d", i)) 700 b.AssertFileContent(index, fmt.Sprintf("data content unmarshaled: v%d", i)) 701 b.AssertFileContent(index, fmt.Sprintf("data assets content unmarshaled: v%d", i)) 702 703 md5Asset := helpers.MD5String(fmt.Sprintf(`vdata: v%d`, i)) 704 b.AssertFileContent(index, fmt.Sprintf("assets fingerprinted: /data%d/data.%s.yaml", i, md5Asset)) 705 706 // The original is not used, make sure it's not published. 707 b.Assert(b.CheckExists(fmt.Sprintf("public/data%d/data.yaml", i)), qt.Equals, false) 708 709 md5Bundle := helpers.MD5String(fmt.Sprintf(`data: v%d`, i)) 710 b.AssertFileContent(index, fmt.Sprintf("bundle fingerprinted: /bundle%d/data.%s.yaml", i, md5Bundle)) 711 712 b.AssertFileContent(index, 713 fmt.Sprintf("bundle min min min: /bundle%d/data.min.min.min.json", i), 714 fmt.Sprintf("bundle min min key: /bundle%d/data.min.min.json", i), 715 ) 716 b.Assert(b.CheckExists(fmt.Sprintf("public/bundle%d/data.min.min.min.json", i)), qt.Equals, true) 717 b.Assert(b.CheckExists(fmt.Sprintf("public/bundle%d/data.min.json", i)), qt.Equals, false) 718 b.Assert(b.CheckExists(fmt.Sprintf("public/bundle%d/data.min.min.json", i)), qt.Equals, false) 719 720 } 721 722 b.EditFiles("assets/data/foo.yaml", "FOO") 723 724 } 725 } 726 727 func TestPageBundlerHome(t *testing.T) { 728 t.Parallel() 729 c := qt.New(t) 730 731 workDir, clean, err := htesting.CreateTempDir(hugofs.Os, "hugo-bundler-home") 732 c.Assert(err, qt.IsNil) 733 734 cfg := config.New() 735 cfg.Set("workingDir", workDir) 736 cfg.Set("publishDir", "public") 737 fs := hugofs.NewFromOld(hugofs.Os, cfg) 738 739 os.MkdirAll(filepath.Join(workDir, "content"), 0o777) // nolint 740 741 defer clean() 742 743 b := newTestSitesBuilder(t) 744 b.Fs = fs 745 746 b.WithWorkingDir(workDir).WithViper(cfg) 747 748 b.WithContent("_index.md", "---\ntitle: Home\n---\n![Alt text](image.jpg)") 749 b.WithSourceFile("content/data.json", "DATA") 750 751 b.WithTemplates("index.html", `Title: {{ .Title }}|First Resource: {{ index .Resources 0 }}|Content: {{ .Content }}`) 752 b.WithTemplates("_default/_markup/render-image.html", `Hook Len Page Resources {{ len .Page.Resources }}`) 753 754 b.Build(BuildCfg{}) 755 b.AssertFileContent("public/index.html", ` 756 Title: Home|First Resource: data.json|Content: <p>Hook Len Page Resources 1</p> 757 `) 758 } 759 760 func TestHTMLFilesIsue11999(t *testing.T) { 761 t.Parallel() 762 763 files := ` 764 -- hugo.toml -- 765 disableKinds = ["taxonomy", "term", "rss", "sitemap", "robotsTXT", "404"] 766 [permalinks] 767 posts = "/myposts/:slugorfilename" 768 -- content/posts/markdown-without-frontmatter.md -- 769 -- content/posts/html-without-frontmatter.html -- 770 <html>hello</html> 771 -- content/posts/html-with-frontmatter.html -- 772 --- 773 title: "HTML with frontmatter" 774 --- 775 <html>hello</html> 776 -- content/posts/html-with-commented-out-frontmatter.html -- 777 <!-- 778 --- 779 title: "HTML with commented out frontmatter" 780 --- 781 --> 782 <html>hello</html> 783 -- content/posts/markdown-with-frontmatter.md -- 784 --- 785 title: "Markdown" 786 --- 787 -- content/posts/mybundle/index.md -- 788 --- 789 title: My Bundle 790 --- 791 -- content/posts/mybundle/data.txt -- 792 Data.txt 793 -- content/posts/mybundle/html-in-bundle-without-frontmatter.html -- 794 <html>hell</html> 795 -- content/posts/mybundle/html-in-bundle-with-frontmatter.html -- 796 --- 797 title: Hello 798 --- 799 <html>hello</html> 800 -- content/posts/mybundle/html-in-bundle-with-commented-out-frontmatter.html -- 801 <!-- 802 --- 803 title: "HTML with commented out frontmatter" 804 --- 805 --> 806 <html>hello</html> 807 -- layouts/index.html -- 808 {{ range site.RegularPages }}{{ .RelPermalink }}|{{ end }}$ 809 -- layouts/_default/single.html -- 810 {{ .Title }}|{{ .RelPermalink }}Resources: {{ range .Resources }}{{ .Name }}|{{ end }}$ 811 812 ` 813 b := Test(t, files) 814 815 b.AssertFileContent("public/index.html", "/myposts/html-with-commented-out-frontmatter/|/myposts/html-without-frontmatter/|/myposts/markdown-without-frontmatter/|/myposts/html-with-frontmatter/|/myposts/markdown-with-frontmatter/|/myposts/mybundle/|$") 816 817 b.AssertFileContent("public/myposts/mybundle/index.html", 818 "My Bundle|/myposts/mybundle/Resources: html-in-bundle-with-commented-out-frontmatter.html|html-in-bundle-without-frontmatter.html|html-in-bundle-with-frontmatter.html|data.txt|$") 819 820 b.AssertPublishDir(` 821 index.html 822 myposts/html-with-commented-out-frontmatter 823 myposts/html-with-commented-out-frontmatter/index.html 824 myposts/html-with-frontmatter 825 myposts/html-with-frontmatter/index.html 826 myposts/html-without-frontmatter 827 myposts/html-without-frontmatter/index.html 828 myposts/markdown-with-frontmatter 829 myposts/markdown-with-frontmatter/index.html 830 myposts/markdown-without-frontmatter 831 myposts/markdown-without-frontmatter/index.html 832 myposts/mybundle/data.txt 833 myposts/mybundle/index.html 834 ! myposts/mybundle/html-in-bundle-with-frontmatter.html 835 `) 836 } 837 838 func TestBundleDuplicatePagesAndResources(t *testing.T) { 839 files := ` 840 -- hugo.toml -- 841 baseURL = "https://example.com" 842 disableKinds = ["taxonomy", "term"] 843 -- content/mysection/mybundle/index.md -- 844 -- content/mysection/mybundle/index.html -- 845 -- content/mysection/mybundle/p1.md -- 846 -- content/mysection/mybundle/p1.html -- 847 -- content/mysection/mybundle/foo/p1.html -- 848 -- content/mysection/mybundle/data.txt -- 849 Data txt. 850 -- content/mysection/mybundle/data.en.txt -- 851 Data en txt. 852 -- content/mysection/mybundle/data.json -- 853 Data JSON. 854 -- content/mysection/_index.md -- 855 -- content/mysection/_index.html -- 856 -- content/mysection/sectiondata.json -- 857 Secion data JSON. 858 -- content/mysection/sectiondata.txt -- 859 Section data TXT. 860 -- content/mysection/p2.md -- 861 -- content/mysection/p2.html -- 862 -- content/mysection/foo/p2.md -- 863 -- layouts/_default/single.html -- 864 Single:{{ .Title }}|{{ .Path }}|File LogicalName: {{ with .File }}{{ .LogicalName }}{{ end }}||{{ .RelPermalink }}|{{ .Kind }}|Resources: {{ range .Resources}}{{ .Name }}: {{ .Content }}|{{ end }}$ 865 -- layouts/_default/list.html -- 866 List: {{ .Title }}|{{ .Path }}|File LogicalName: {{ with .File }}{{ .LogicalName }}{{ end }}|{{ .RelPermalink }}|{{ .Kind }}|Resources: {{ range .Resources}}{{ .Name }}: {{ .Content }}|{{ end }}$ 867 RegularPages: {{ range .RegularPages }}{{ .RelPermalink }}|File LogicalName: {{ with .File }}{{ .LogicalName }}|{{ end }}{{ end }}$ 868 ` 869 870 b := Test(t, files) 871 872 // Note that the sort order gives us the most specific data file for the en language (the data.en.json). 873 b.AssertFileContent("public/mysection/mybundle/index.html", `Single:|/mysection/mybundle|File LogicalName: index.md||/mysection/mybundle/|page|Resources: data.en.txt: Data en txt.|data.json: Data JSON.|foo/p1.html: |p1.html: |p1.md: |$`) 874 b.AssertFileContent("public/mysection/index.html", 875 "List: |/mysection|File LogicalName: _index.md|/mysection/|section|Resources: sectiondata.json: Secion data JSON.|sectiondata.txt: Section data TXT.|$", 876 "RegularPages: /mysection/foo/p2/|File LogicalName: p2.md|/mysection/mybundle/|File LogicalName: index.md|/mysection/p2/|File LogicalName: p2.md|$") 877 } 878 879 func TestBundleResourcesGetMatchOriginalName(t *testing.T) { 880 files := ` 881 -- hugo.toml -- 882 baseURL = "https://example.com" 883 -- content/mybundle/index.md -- 884 -- content/mybundle/f1.en.txt -- 885 F1. 886 -- layouts/_default/single.html -- 887 GetMatch: {{ with .Resources.GetMatch "f1.en.*" }}{{ .Name }}: {{ .Content }}|{{ end }} 888 Match: {{ range .Resources.Match "f1.En.*" }}{{ .Name }}: {{ .Content }}|{{ end }} 889 ` 890 891 b := Test(t, files) 892 893 b.AssertFileContent("public/mybundle/index.html", "GetMatch: f1.en.txt: F1.|", "Match: f1.en.txt: F1.|") 894 } 895 896 func TestBundleResourcesWhenLanguageVariantIsDraft(t *testing.T) { 897 files := ` 898 -- hugo.toml -- 899 baseURL = "https://example.com" 900 defaultContentLanguage = "en" 901 [languages] 902 [languages.en] 903 weight = 1 904 [languages.nn] 905 weight = 2 906 -- content/mybundle/index.en.md -- 907 -- content/mybundle/index.nn.md -- 908 --- 909 draft: true 910 --- 911 -- content/mybundle/f1.en.txt -- 912 F1. 913 -- layouts/_default/single.html -- 914 GetMatch: {{ with .Resources.GetMatch "f1.*" }}{{ .Name }}: {{ .Content }}|{{ end }}$ 915 ` 916 917 b := Test(t, files) 918 919 b.AssertFileContent("public/mybundle/index.html", "GetMatch: f1.en.txt: F1.|") 920 }