github.com/gohugoio/hugo@v0.88.1/hugolib/template_test.go (about) 1 // Copyright 2016 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 "strings" 20 "testing" 21 22 "github.com/gohugoio/hugo/config" 23 "github.com/gohugoio/hugo/identity" 24 25 qt "github.com/frankban/quicktest" 26 "github.com/gohugoio/hugo/deps" 27 "github.com/gohugoio/hugo/hugofs" 28 "github.com/gohugoio/hugo/tpl" 29 ) 30 31 func TestTemplateLookupOrder(t *testing.T) { 32 var ( 33 fs *hugofs.Fs 34 cfg config.Provider 35 th testHelper 36 ) 37 38 // Variants base templates: 39 // 1. <current-path>/<template-name>-baseof.<suffix>, e.g. list-baseof.<suffix>. 40 // 2. <current-path>/baseof.<suffix> 41 // 3. _default/<template-name>-baseof.<suffix>, e.g. list-baseof.<suffix>. 42 // 4. _default/baseof.<suffix> 43 for _, this := range []struct { 44 name string 45 setup func(t *testing.T) 46 assert func(t *testing.T) 47 }{ 48 { 49 "Variant 1", 50 func(t *testing.T) { 51 writeSource(t, fs, filepath.Join("layouts", "section", "sect1-baseof.html"), `Base: {{block "main" .}}block{{end}}`) 52 writeSource(t, fs, filepath.Join("layouts", "section", "sect1.html"), `{{define "main"}}sect{{ end }}`) 53 }, 54 func(t *testing.T) { 55 th.assertFileContent(filepath.Join("public", "sect1", "index.html"), "Base: sect") 56 }, 57 }, 58 { 59 "Variant 2", 60 func(t *testing.T) { 61 writeSource(t, fs, filepath.Join("layouts", "baseof.html"), `Base: {{block "main" .}}block{{end}}`) 62 writeSource(t, fs, filepath.Join("layouts", "index.html"), `{{define "main"}}index{{ end }}`) 63 }, 64 func(t *testing.T) { 65 th.assertFileContent(filepath.Join("public", "index.html"), "Base: index") 66 }, 67 }, 68 { 69 "Variant 3", 70 func(t *testing.T) { 71 writeSource(t, fs, filepath.Join("layouts", "_default", "list-baseof.html"), `Base: {{block "main" .}}block{{end}}`) 72 writeSource(t, fs, filepath.Join("layouts", "_default", "list.html"), `{{define "main"}}list{{ end }}`) 73 }, 74 func(t *testing.T) { 75 th.assertFileContent(filepath.Join("public", "sect1", "index.html"), "Base: list") 76 }, 77 }, 78 { 79 "Variant 4", 80 func(t *testing.T) { 81 writeSource(t, fs, filepath.Join("layouts", "_default", "baseof.html"), `Base: {{block "main" .}}block{{end}}`) 82 writeSource(t, fs, filepath.Join("layouts", "_default", "list.html"), `{{define "main"}}list{{ end }}`) 83 }, 84 func(t *testing.T) { 85 th.assertFileContent(filepath.Join("public", "sect1", "index.html"), "Base: list") 86 }, 87 }, 88 { 89 "Variant 1, theme, use site base", 90 func(t *testing.T) { 91 cfg.Set("theme", "mytheme") 92 writeSource(t, fs, filepath.Join("layouts", "section", "sect1-baseof.html"), `Base: {{block "main" .}}block{{end}}`) 93 writeSource(t, fs, filepath.Join("themes", "mytheme", "layouts", "section", "sect-baseof.html"), `Base Theme: {{block "main" .}}block{{end}}`) 94 writeSource(t, fs, filepath.Join("layouts", "section", "sect1.html"), `{{define "main"}}sect{{ end }}`) 95 }, 96 func(t *testing.T) { 97 th.assertFileContent(filepath.Join("public", "sect1", "index.html"), "Base: sect") 98 }, 99 }, 100 { 101 "Variant 1, theme, use theme base", 102 func(t *testing.T) { 103 cfg.Set("theme", "mytheme") 104 writeSource(t, fs, filepath.Join("themes", "mytheme", "layouts", "section", "sect1-baseof.html"), `Base Theme: {{block "main" .}}block{{end}}`) 105 writeSource(t, fs, filepath.Join("layouts", "section", "sect1.html"), `{{define "main"}}sect{{ end }}`) 106 }, 107 func(t *testing.T) { 108 th.assertFileContent(filepath.Join("public", "sect1", "index.html"), "Base Theme: sect") 109 }, 110 }, 111 { 112 "Variant 4, theme, use site base", 113 func(t *testing.T) { 114 cfg.Set("theme", "mytheme") 115 writeSource(t, fs, filepath.Join("layouts", "_default", "baseof.html"), `Base: {{block "main" .}}block{{end}}`) 116 writeSource(t, fs, filepath.Join("themes", "mytheme", "layouts", "_default", "baseof.html"), `Base Theme: {{block "main" .}}block{{end}}`) 117 writeSource(t, fs, filepath.Join("themes", "mytheme", "layouts", "_default", "list.html"), `{{define "main"}}list{{ end }}`) 118 writeSource(t, fs, filepath.Join("themes", "mytheme", "layouts", "index.html"), `{{define "main"}}index{{ end }}`) 119 }, 120 func(t *testing.T) { 121 th.assertFileContent(filepath.Join("public", "sect1", "index.html"), "Base: list") 122 th.assertFileContent(filepath.Join("public", "index.html"), "Base: index") // Issue #3505 123 }, 124 }, 125 { 126 "Variant 4, theme, use themes base", 127 func(t *testing.T) { 128 cfg.Set("theme", "mytheme") 129 writeSource(t, fs, filepath.Join("themes", "mytheme", "layouts", "_default", "baseof.html"), `Base Theme: {{block "main" .}}block{{end}}`) 130 writeSource(t, fs, filepath.Join("themes", "mytheme", "layouts", "_default", "list.html"), `{{define "main"}}list{{ end }}`) 131 }, 132 func(t *testing.T) { 133 th.assertFileContent(filepath.Join("public", "sect1", "index.html"), "Base Theme: list") 134 }, 135 }, 136 { 137 // Issue #3116 138 "Test section list and single template selection", 139 func(t *testing.T) { 140 cfg.Set("theme", "mytheme") 141 142 writeSource(t, fs, filepath.Join("layouts", "_default", "baseof.html"), `Base: {{block "main" .}}block{{end}}`) 143 144 // Both single and list template in /SECTION/ 145 writeSource(t, fs, filepath.Join("themes", "mytheme", "layouts", "sect1", "list.html"), `sect list`) 146 writeSource(t, fs, filepath.Join("themes", "mytheme", "layouts", "_default", "list.html"), `default list`) 147 writeSource(t, fs, filepath.Join("themes", "mytheme", "layouts", "sect1", "single.html"), `sect single`) 148 writeSource(t, fs, filepath.Join("themes", "mytheme", "layouts", "_default", "single.html"), `default single`) 149 150 // sect2 with list template in /section 151 writeSource(t, fs, filepath.Join("themes", "mytheme", "layouts", "section", "sect2.html"), `sect2 list`) 152 }, 153 func(t *testing.T) { 154 th.assertFileContent(filepath.Join("public", "sect1", "index.html"), "sect list") 155 th.assertFileContent(filepath.Join("public", "sect1", "page1", "index.html"), "sect single") 156 th.assertFileContent(filepath.Join("public", "sect2", "index.html"), "sect2 list") 157 }, 158 }, 159 { 160 // Issue #2995 161 "Test section list and single template selection with base template", 162 func(t *testing.T) { 163 writeSource(t, fs, filepath.Join("layouts", "_default", "baseof.html"), `Base Default: {{block "main" .}}block{{end}}`) 164 writeSource(t, fs, filepath.Join("layouts", "sect1", "baseof.html"), `Base Sect1: {{block "main" .}}block{{end}}`) 165 writeSource(t, fs, filepath.Join("layouts", "section", "sect2-baseof.html"), `Base Sect2: {{block "main" .}}block{{end}}`) 166 167 // Both single and list + base template in /SECTION/ 168 writeSource(t, fs, filepath.Join("layouts", "sect1", "list.html"), `{{define "main"}}sect1 list{{ end }}`) 169 writeSource(t, fs, filepath.Join("layouts", "_default", "list.html"), `{{define "main"}}default list{{ end }}`) 170 writeSource(t, fs, filepath.Join("layouts", "sect1", "single.html"), `{{define "main"}}sect single{{ end }}`) 171 writeSource(t, fs, filepath.Join("layouts", "_default", "single.html"), `{{define "main"}}default single{{ end }}`) 172 173 // sect2 with list template in /section 174 writeSource(t, fs, filepath.Join("layouts", "section", "sect2.html"), `{{define "main"}}sect2 list{{ end }}`) 175 }, 176 func(t *testing.T) { 177 th.assertFileContent(filepath.Join("public", "sect1", "index.html"), "Base Sect1", "sect1 list") 178 th.assertFileContent(filepath.Join("public", "sect1", "page1", "index.html"), "Base Sect1", "sect single") 179 th.assertFileContent(filepath.Join("public", "sect2", "index.html"), "Base Sect2", "sect2 list") 180 181 // Note that this will get the default base template and not the one in /sect2 -- because there are no 182 // single template defined in /sect2. 183 th.assertFileContent(filepath.Join("public", "sect2", "page2", "index.html"), "Base Default", "default single") 184 }, 185 }, 186 } { 187 188 this := this 189 t.Run(this.name, func(t *testing.T) { 190 // TODO(bep) there are some function vars need to pull down here to enable => t.Parallel() 191 cfg, fs = newTestCfg() 192 th = newTestHelper(cfg, fs, t) 193 194 for i := 1; i <= 3; i++ { 195 writeSource(t, fs, filepath.Join("content", fmt.Sprintf("sect%d", i), fmt.Sprintf("page%d.md", i)), `--- 196 title: Template test 197 --- 198 Some content 199 `) 200 } 201 202 this.setup(t) 203 204 buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg}, BuildCfg{}) 205 // helpers.PrintFs(s.BaseFs.Layouts.Fs, "", os.Stdout) 206 this.assert(t) 207 }) 208 209 } 210 } 211 212 // https://github.com/gohugoio/hugo/issues/4895 213 func TestTemplateBOM(t *testing.T) { 214 b := newTestSitesBuilder(t).WithSimpleConfigFile() 215 bom := "\ufeff" 216 217 b.WithTemplatesAdded( 218 "_default/baseof.html", bom+` 219 Base: {{ block "main" . }}base main{{ end }}`, 220 "_default/single.html", bom+`{{ define "main" }}Hi!?{{ end }}`) 221 222 b.WithContent("page.md", `--- 223 title: "Page" 224 --- 225 226 Page Content 227 `) 228 229 b.CreateSites().Build(BuildCfg{}) 230 231 b.AssertFileContent("public/page/index.html", "Base: Hi!?") 232 } 233 234 func TestTemplateManyBaseTemplates(t *testing.T) { 235 t.Parallel() 236 b := newTestSitesBuilder(t).WithSimpleConfigFile() 237 238 numPages := 100 // To get some parallelism 239 240 pageTemplate := `--- 241 title: "Page %d" 242 layout: "layout%d" 243 --- 244 245 Content. 246 ` 247 248 singleTemplate := ` 249 {{ define "main" }}%d{{ end }} 250 ` 251 baseTemplate := ` 252 Base %d: {{ block "main" . }}FOO{{ end }} 253 ` 254 255 for i := 0; i < numPages; i++ { 256 id := i + 1 257 b.WithContent(fmt.Sprintf("page%d.md", id), fmt.Sprintf(pageTemplate, id, id)) 258 b.WithTemplates(fmt.Sprintf("_default/layout%d.html", id), fmt.Sprintf(singleTemplate, id)) 259 b.WithTemplates(fmt.Sprintf("_default/layout%d-baseof.html", id), fmt.Sprintf(baseTemplate, id)) 260 } 261 262 b.Build(BuildCfg{}) 263 for i := 0; i < numPages; i++ { 264 id := i + 1 265 b.AssertFileContent(fmt.Sprintf("public/page%d/index.html", id), fmt.Sprintf(`Base %d: %d`, id, id)) 266 } 267 } 268 269 // https://github.com/gohugoio/hugo/issues/6790 270 func TestTemplateNoBasePlease(t *testing.T) { 271 t.Parallel() 272 b := newTestSitesBuilder(t).WithSimpleConfigFile() 273 274 b.WithTemplates("_default/list.html", ` 275 {{ define "main" }} 276 Bonjour 277 {{ end }} 278 279 {{ printf "list" }} 280 281 282 `) 283 284 b.WithTemplates( 285 "_default/single.html", ` 286 {{ printf "single" }} 287 {{ define "main" }} 288 Bonjour 289 {{ end }} 290 291 292 `) 293 294 b.WithContent("blog/p1.md", `--- 295 title: The Page 296 --- 297 `) 298 299 b.Build(BuildCfg{}) 300 301 b.AssertFileContent("public/blog/p1/index.html", `single`) 302 b.AssertFileContent("public/blog/index.html", `list`) 303 } 304 305 // https://github.com/gohugoio/hugo/issues/6816 306 func TestTemplateBaseWithComment(t *testing.T) { 307 t.Parallel() 308 b := newTestSitesBuilder(t).WithSimpleConfigFile() 309 b.WithTemplatesAdded( 310 "baseof.html", `Base: {{ block "main" . }}{{ end }}`, 311 "index.html", ` 312 {{/* A comment */}} 313 {{ define "main" }} 314 Bonjour 315 {{ end }} 316 317 318 `) 319 320 b.Build(BuildCfg{}) 321 b.AssertFileContent("public/index.html", `Base: 322 Bonjour`) 323 } 324 325 func TestTemplateLookupSite(t *testing.T) { 326 t.Run("basic", func(t *testing.T) { 327 t.Parallel() 328 b := newTestSitesBuilder(t).WithSimpleConfigFile() 329 b.WithTemplates( 330 "_default/single.html", `Single: {{ .Title }}`, 331 "_default/list.html", `List: {{ .Title }}`, 332 ) 333 334 createContent := func(title string) string { 335 return fmt.Sprintf(`--- 336 title: %s 337 ---`, title) 338 } 339 340 b.WithContent( 341 "_index.md", createContent("Home Sweet Home"), 342 "p1.md", createContent("P1")) 343 344 b.CreateSites().Build(BuildCfg{}) 345 b.AssertFileContent("public/index.html", `List: Home Sweet Home`) 346 b.AssertFileContent("public/p1/index.html", `Single: P1`) 347 }) 348 349 t.Run("baseof", func(t *testing.T) { 350 t.Parallel() 351 b := newTestSitesBuilder(t).WithDefaultMultiSiteConfig() 352 353 b.WithTemplatesAdded( 354 "index.html", `{{ define "main" }}Main Home En{{ end }}`, 355 "index.fr.html", `{{ define "main" }}Main Home Fr{{ end }}`, 356 "baseof.html", `Baseof en: {{ block "main" . }}main block{{ end }}`, 357 "baseof.fr.html", `Baseof fr: {{ block "main" . }}main block{{ end }}`, 358 "mysection/baseof.html", `Baseof mysection: {{ block "main" . }}mysection block{{ end }}`, 359 "_default/single.html", `{{ define "main" }}Main Default Single{{ end }}`, 360 "_default/list.html", `{{ define "main" }}Main Default List{{ end }}`, 361 ) 362 363 b.WithContent("mysection/p1.md", `--- 364 title: My Page 365 --- 366 367 `) 368 369 b.CreateSites().Build(BuildCfg{}) 370 371 b.AssertFileContent("public/en/index.html", `Baseof en: Main Home En`) 372 b.AssertFileContent("public/fr/index.html", `Baseof fr: Main Home Fr`) 373 b.AssertFileContent("public/en/mysection/index.html", `Baseof mysection: Main Default List`) 374 b.AssertFileContent("public/en/mysection/p1/index.html", `Baseof mysection: Main Default Single`) 375 }) 376 } 377 378 func TestTemplateFuncs(t *testing.T) { 379 b := newTestSitesBuilder(t).WithDefaultMultiSiteConfig() 380 381 homeTpl := `Site: {{ site.Language.Lang }} / {{ .Site.Language.Lang }} / {{ site.BaseURL }} 382 Sites: {{ site.Sites.First.Home.Language.Lang }} 383 Hugo: {{ hugo.Generator }} 384 ` 385 386 b.WithTemplatesAdded( 387 "index.html", homeTpl, 388 "index.fr.html", homeTpl, 389 ) 390 391 b.CreateSites().Build(BuildCfg{}) 392 393 b.AssertFileContent("public/en/index.html", 394 "Site: en / en / http://example.com/blog", 395 "Sites: en", 396 "Hugo: <meta name=\"generator\" content=\"Hugo") 397 b.AssertFileContent("public/fr/index.html", 398 "Site: fr / fr / http://example.com/blog", 399 "Sites: en", 400 "Hugo: <meta name=\"generator\" content=\"Hugo", 401 ) 402 } 403 404 func TestPartialWithReturn(t *testing.T) { 405 c := qt.New(t) 406 407 newBuilder := func(t testing.TB) *sitesBuilder { 408 b := newTestSitesBuilder(t).WithSimpleConfigFile() 409 b.WithTemplatesAdded( 410 "partials/add42.tpl", ` 411 {{ $v := add . 42 }} 412 {{ return $v }} 413 `, 414 "partials/dollarContext.tpl", ` 415 {{ $v := add $ 42 }} 416 {{ return $v }} 417 `, 418 "partials/dict.tpl", ` 419 {{ $v := add $.adder 42 }} 420 {{ return $v }} 421 `, 422 "partials/complex.tpl", ` 423 {{ return add . 42 }} 424 `, "partials/hello.tpl", ` 425 {{ $v := printf "hello %s" . }} 426 {{ return $v }} 427 `, 428 ) 429 430 return b 431 } 432 433 c.Run("Return", func(c *qt.C) { 434 b := newBuilder(c) 435 436 b.WithTemplatesAdded( 437 "index.html", ` 438 Test Partials With Return Values: 439 440 add42: 50: {{ partial "add42.tpl" 8 }} 441 hello world: {{ partial "hello.tpl" "world" }} 442 dollarContext: 60: {{ partial "dollarContext.tpl" 18 }} 443 adder: 70: {{ partial "dict.tpl" (dict "adder" 28) }} 444 complex: 80: {{ partial "complex.tpl" 38 }} 445 `, 446 ) 447 448 b.CreateSites().Build(BuildCfg{}) 449 450 b.AssertFileContent("public/index.html", ` 451 add42: 50: 50 452 hello world: hello world 453 dollarContext: 60: 60 454 adder: 70: 70 455 complex: 80: 80 456 `, 457 ) 458 }) 459 460 c.Run("Zero argument", func(c *qt.C) { 461 b := newBuilder(c) 462 463 b.WithTemplatesAdded( 464 "index.html", ` 465 Test Partials With Return Values: 466 467 add42: fail: {{ partial "add42.tpl" 0 }} 468 469 `, 470 ) 471 472 e := b.CreateSites().BuildE(BuildCfg{}) 473 b.Assert(e, qt.Not(qt.IsNil)) 474 }) 475 } 476 477 func TestPartialCached(t *testing.T) { 478 b := newTestSitesBuilder(t) 479 480 b.WithTemplatesAdded( 481 "index.html", ` 482 {{ $key1 := (dict "a" "av" ) }} 483 {{ $key2 := (dict "a" "av2" ) }} 484 Partial cached1: {{ partialCached "p1" "input1" $key1 }} 485 Partial cached2: {{ partialCached "p1" "input2" $key1 }} 486 Partial cached3: {{ partialCached "p1" "input3" $key2 }} 487 `, 488 489 "partials/p1.html", `partial: {{ . }}`, 490 ) 491 492 b.Build(BuildCfg{}) 493 494 b.AssertFileContent("public/index.html", ` 495 Partial cached1: partial: input1 496 Partial cached2: partial: input1 497 Partial cached3: partial: input3 498 `) 499 } 500 501 // https://github.com/gohugoio/hugo/issues/6615 502 func TestTemplateTruth(t *testing.T) { 503 b := newTestSitesBuilder(t) 504 b.WithTemplatesAdded("index.html", ` 505 {{ $p := index site.RegularPages 0 }} 506 {{ $zero := $p.ExpiryDate }} 507 {{ $notZero := time.Now }} 508 509 if: Zero: {{ if $zero }}FAIL{{ else }}OK{{ end }} 510 if: Not Zero: {{ if $notZero }}OK{{ else }}Fail{{ end }} 511 not: Zero: {{ if not $zero }}OK{{ else }}FAIL{{ end }} 512 not: Not Zero: {{ if not $notZero }}FAIL{{ else }}OK{{ end }} 513 514 with: Zero {{ with $zero }}FAIL{{ else }}OK{{ end }} 515 516 `) 517 518 b.Build(BuildCfg{}) 519 520 b.AssertFileContent("public/index.html", ` 521 if: Zero: OK 522 if: Not Zero: OK 523 not: Zero: OK 524 not: Not Zero: OK 525 with: Zero OK 526 `) 527 } 528 529 func TestTemplateDependencies(t *testing.T) { 530 b := newTestSitesBuilder(t).Running() 531 532 b.WithTemplates("index.html", ` 533 {{ $p := site.GetPage "p1" }} 534 {{ partial "p1.html" $p }} 535 {{ partialCached "p2.html" "foo" }} 536 {{ partials.Include "p3.html" "data" }} 537 {{ partials.IncludeCached "p4.html" "foo" }} 538 {{ $p := partial "p5" }} 539 {{ partial "sub/p6.html" }} 540 {{ partial "P7.html" }} 541 {{ template "_default/foo.html" }} 542 Partial nested: {{ partial "p10" }} 543 544 `, 545 "partials/p1.html", `ps: {{ .Render "li" }}`, 546 "partials/p2.html", `p2`, 547 "partials/p3.html", `p3`, 548 "partials/p4.html", `p4`, 549 "partials/p5.html", `p5`, 550 "partials/sub/p6.html", `p6`, 551 "partials/P7.html", `p7`, 552 "partials/p8.html", `p8 {{ partial "p9.html" }}`, 553 "partials/p9.html", `p9`, 554 "partials/p10.html", `p10 {{ partial "p11.html" }}`, 555 "partials/p11.html", `p11`, 556 "_default/foo.html", `foo`, 557 "_default/li.html", `li {{ partial "p8.html" }}`, 558 ) 559 560 b.WithContent("p1.md", `--- 561 title: P1 562 --- 563 564 565 `) 566 567 b.Build(BuildCfg{}) 568 569 s := b.H.Sites[0] 570 571 templ, found := s.lookupTemplate("index.html") 572 b.Assert(found, qt.Equals, true) 573 574 idset := make(map[identity.Identity]bool) 575 collectIdentities(idset, templ.(tpl.Info)) 576 b.Assert(idset, qt.HasLen, 11) 577 } 578 579 func TestTemplateGoIssues(t *testing.T) { 580 b := newTestSitesBuilder(t) 581 582 b.WithTemplatesAdded( 583 "index.html", ` 584 {{ $title := "a & b" }} 585 <script type="application/ld+json">{"@type":"WebPage","headline":"{{$title}}"}</script> 586 587 {{/* Action/commands newlines, from Go 1.16, see https://github.com/golang/go/issues/29770 */}} 588 {{ $norway := dict 589 "country" "Norway" 590 "population" "5 millions" 591 "language" "Norwegian" 592 "language_code" "nb" 593 "weather" "freezing cold" 594 "capitol" "Oslo" 595 "largest_city" "Oslo" 596 "currency" "Norwegian krone" 597 "dialing_code" "+47" 598 }} 599 600 Population in Norway is {{ 601 $norway.population 602 | lower 603 | upper 604 }} 605 606 `, 607 ) 608 609 b.Build(BuildCfg{}) 610 611 b.AssertFileContent("public/index.html", ` 612 <script type="application/ld+json">{"@type":"WebPage","headline":"a \u0026 b"}</script> 613 Population in Norway is 5 MILLIONS 614 615 `) 616 } 617 618 func collectIdentities(set map[identity.Identity]bool, provider identity.Provider) { 619 if ids, ok := provider.(identity.IdentitiesProvider); ok { 620 for _, id := range ids.GetIdentities() { 621 collectIdentities(set, id) 622 } 623 } else { 624 set[provider.GetIdentity()] = true 625 } 626 } 627 628 func ident(level int) string { 629 return strings.Repeat(" ", level) 630 } 631 632 func TestPartialInline(t *testing.T) { 633 b := newTestSitesBuilder(t) 634 635 b.WithContent("p1.md", "") 636 637 b.WithTemplates( 638 "index.html", ` 639 640 {{ $p1 := partial "p1" . }} 641 {{ $p2 := partial "p2" . }} 642 643 P1: {{ $p1 }} 644 P2: {{ $p2 }} 645 646 {{ define "partials/p1" }}Inline: p1{{ end }} 647 648 {{ define "partials/p2" }} 649 {{ $value := 32 }} 650 {{ return $value }} 651 {{ end }} 652 653 654 `, 655 ) 656 657 b.CreateSites().Build(BuildCfg{}) 658 659 b.AssertFileContent("public/index.html", 660 ` 661 P1: Inline: p1 662 P2: 32`, 663 ) 664 } 665 666 func TestPartialInlineBase(t *testing.T) { 667 b := newTestSitesBuilder(t) 668 669 b.WithContent("p1.md", "") 670 671 b.WithTemplates( 672 "baseof.html", `{{ $p3 := partial "p3" . }}P3: {{ $p3 }} 673 {{ block "main" . }}{{ end }}{{ define "partials/p3" }}Inline: p3{{ end }}`, 674 "index.html", ` 675 {{ define "main" }} 676 677 {{ $p1 := partial "p1" . }} 678 {{ $p2 := partial "p2" . }} 679 680 P1: {{ $p1 }} 681 P2: {{ $p2 }} 682 683 {{ end }} 684 685 686 {{ define "partials/p1" }}Inline: p1{{ end }} 687 688 {{ define "partials/p2" }} 689 {{ $value := 32 }} 690 {{ return $value }} 691 {{ end }} 692 693 694 `, 695 ) 696 697 b.CreateSites().Build(BuildCfg{}) 698 699 b.AssertFileContent("public/index.html", 700 ` 701 P1: Inline: p1 702 P2: 32 703 P3: Inline: p3 704 `, 705 ) 706 } 707 708 // https://github.com/gohugoio/hugo/issues/7478 709 func TestBaseWithAndWithoutDefine(t *testing.T) { 710 b := newTestSitesBuilder(t) 711 712 b.WithContent("p1.md", "---\ntitle: P\n---\nContent") 713 714 b.WithTemplates( 715 "_default/baseof.html", ` 716 ::Header Start:{{ block "header" . }}{{ end }}:Header End: 717 ::{{ block "main" . }}Main{{ end }}:: 718 `, "index.html", ` 719 {{ define "header" }} 720 Home Header 721 {{ end }} 722 {{ define "main" }} 723 This is home main 724 {{ end }} 725 `, 726 727 "_default/single.html", ` 728 {{ define "main" }} 729 This is single main 730 {{ end }} 731 `, 732 ) 733 734 b.CreateSites().Build(BuildCfg{}) 735 736 b.AssertFileContent("public/index.html", ` 737 Home Header 738 This is home main 739 `, 740 ) 741 742 b.AssertFileContent("public/p1/index.html", ` 743 ::Header Start::Header End: 744 This is single main 745 `, 746 ) 747 }