template_test.go (21201B)
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
461 // Issue 7528
462 func TestPartialWithZeroedArgs(t *testing.T) {
463 b := newTestSitesBuilder(t)
464 b.WithTemplatesAdded("index.html",
465 `
466 X{{ partial "retval" dict }}X
467 X{{ partial "retval" slice }}X
468 X{{ partial "retval" "" }}X
469 X{{ partial "retval" false }}X
470 X{{ partial "retval" 0 }}X
471 {{ define "partials/retval" }}
472 {{ return 123 }}
473 {{ end }}`)
474
475 b.WithContentAdded("p.md", ``)
476 b.Build(BuildCfg{})
477 b.AssertFileContent("public/index.html",
478 `
479 X123X
480 X123X
481 X123X
482 X123X
483 X123X
484 `)
485 }
486
487 func TestPartialCached(t *testing.T) {
488 b := newTestSitesBuilder(t)
489
490 b.WithTemplatesAdded(
491 "index.html", `
492 {{ $key1 := (dict "a" "av" ) }}
493 {{ $key2 := (dict "a" "av2" ) }}
494 Partial cached1: {{ partialCached "p1" "input1" $key1 }}
495 Partial cached2: {{ partialCached "p1" "input2" $key1 }}
496 Partial cached3: {{ partialCached "p1" "input3" $key2 }}
497 `,
498
499 "partials/p1.html", `partial: {{ . }}`,
500 )
501
502 b.Build(BuildCfg{})
503
504 b.AssertFileContent("public/index.html", `
505 Partial cached1: partial: input1
506 Partial cached2: partial: input1
507 Partial cached3: partial: input3
508 `)
509 }
510
511 // https://github.com/gohugoio/hugo/issues/6615
512 func TestTemplateTruth(t *testing.T) {
513 b := newTestSitesBuilder(t)
514 b.WithTemplatesAdded("index.html", `
515 {{ $p := index site.RegularPages 0 }}
516 {{ $zero := $p.ExpiryDate }}
517 {{ $notZero := time.Now }}
518
519 if: Zero: {{ if $zero }}FAIL{{ else }}OK{{ end }}
520 if: Not Zero: {{ if $notZero }}OK{{ else }}Fail{{ end }}
521 not: Zero: {{ if not $zero }}OK{{ else }}FAIL{{ end }}
522 not: Not Zero: {{ if not $notZero }}FAIL{{ else }}OK{{ end }}
523
524 with: Zero {{ with $zero }}FAIL{{ else }}OK{{ end }}
525
526 `)
527
528 b.Build(BuildCfg{})
529
530 b.AssertFileContent("public/index.html", `
531 if: Zero: OK
532 if: Not Zero: OK
533 not: Zero: OK
534 not: Not Zero: OK
535 with: Zero OK
536 `)
537 }
538
539 func TestTemplateDependencies(t *testing.T) {
540 b := newTestSitesBuilder(t).Running()
541
542 b.WithTemplates("index.html", `
543 {{ $p := site.GetPage "p1" }}
544 {{ partial "p1.html" $p }}
545 {{ partialCached "p2.html" "foo" }}
546 {{ partials.Include "p3.html" "data" }}
547 {{ partials.IncludeCached "p4.html" "foo" }}
548 {{ $p := partial "p5" }}
549 {{ partial "sub/p6.html" }}
550 {{ partial "P7.html" }}
551 {{ template "_default/foo.html" }}
552 Partial nested: {{ partial "p10" }}
553
554 `,
555 "partials/p1.html", `ps: {{ .Render "li" }}`,
556 "partials/p2.html", `p2`,
557 "partials/p3.html", `p3`,
558 "partials/p4.html", `p4`,
559 "partials/p5.html", `p5`,
560 "partials/sub/p6.html", `p6`,
561 "partials/P7.html", `p7`,
562 "partials/p8.html", `p8 {{ partial "p9.html" }}`,
563 "partials/p9.html", `p9`,
564 "partials/p10.html", `p10 {{ partial "p11.html" }}`,
565 "partials/p11.html", `p11`,
566 "_default/foo.html", `foo`,
567 "_default/li.html", `li {{ partial "p8.html" }}`,
568 )
569
570 b.WithContent("p1.md", `---
571 title: P1
572 ---
573
574
575 `)
576
577 b.Build(BuildCfg{})
578
579 s := b.H.Sites[0]
580
581 templ, found := s.lookupTemplate("index.html")
582 b.Assert(found, qt.Equals, true)
583
584 idset := make(map[identity.Identity]bool)
585 collectIdentities(idset, templ.(tpl.Info))
586 b.Assert(idset, qt.HasLen, 11)
587 }
588
589 func TestTemplateGoIssues(t *testing.T) {
590 b := newTestSitesBuilder(t)
591
592 b.WithTemplatesAdded(
593 "index.html", `
594 {{ $title := "a & b" }}
595 <script type="application/ld+json">{"@type":"WebPage","headline":"{{$title}}"}</script>
596
597 {{/* Action/commands newlines, from Go 1.16, see https://github.com/golang/go/issues/29770 */}}
598 {{ $norway := dict
599 "country" "Norway"
600 "population" "5 millions"
601 "language" "Norwegian"
602 "language_code" "nb"
603 "weather" "freezing cold"
604 "capitol" "Oslo"
605 "largest_city" "Oslo"
606 "currency" "Norwegian krone"
607 "dialing_code" "+47"
608 }}
609
610 Population in Norway is {{
611 $norway.population
612 | lower
613 | upper
614 }}
615
616 `,
617 )
618
619 b.Build(BuildCfg{})
620
621 b.AssertFileContent("public/index.html", `
622 <script type="application/ld+json">{"@type":"WebPage","headline":"a \u0026 b"}</script>
623 Population in Norway is 5 MILLIONS
624
625 `)
626 }
627
628 func collectIdentities(set map[identity.Identity]bool, provider identity.Provider) {
629 if ids, ok := provider.(identity.IdentitiesProvider); ok {
630 for _, id := range ids.GetIdentities() {
631 collectIdentities(set, id)
632 }
633 } else {
634 set[provider.GetIdentity()] = true
635 }
636 }
637
638 func ident(level int) string {
639 return strings.Repeat(" ", level)
640 }
641
642 func TestPartialInline(t *testing.T) {
643 b := newTestSitesBuilder(t)
644
645 b.WithContent("p1.md", "")
646
647 b.WithTemplates(
648 "index.html", `
649
650 {{ $p1 := partial "p1" . }}
651 {{ $p2 := partial "p2" . }}
652
653 P1: {{ $p1 }}
654 P2: {{ $p2 }}
655
656 {{ define "partials/p1" }}Inline: p1{{ end }}
657
658 {{ define "partials/p2" }}
659 {{ $value := 32 }}
660 {{ return $value }}
661 {{ end }}
662
663
664 `,
665 )
666
667 b.CreateSites().Build(BuildCfg{})
668
669 b.AssertFileContent("public/index.html",
670 `
671 P1: Inline: p1
672 P2: 32`,
673 )
674 }
675
676 func TestPartialInlineBase(t *testing.T) {
677 b := newTestSitesBuilder(t)
678
679 b.WithContent("p1.md", "")
680
681 b.WithTemplates(
682 "baseof.html", `{{ $p3 := partial "p3" . }}P3: {{ $p3 }}
683 {{ block "main" . }}{{ end }}{{ define "partials/p3" }}Inline: p3{{ end }}`,
684 "index.html", `
685 {{ define "main" }}
686
687 {{ $p1 := partial "p1" . }}
688 {{ $p2 := partial "p2" . }}
689
690 P1: {{ $p1 }}
691 P2: {{ $p2 }}
692
693 {{ end }}
694
695
696 {{ define "partials/p1" }}Inline: p1{{ end }}
697
698 {{ define "partials/p2" }}
699 {{ $value := 32 }}
700 {{ return $value }}
701 {{ end }}
702
703
704 `,
705 )
706
707 b.CreateSites().Build(BuildCfg{})
708
709 b.AssertFileContent("public/index.html",
710 `
711 P1: Inline: p1
712 P2: 32
713 P3: Inline: p3
714 `,
715 )
716 }
717
718 // https://github.com/gohugoio/hugo/issues/7478
719 func TestBaseWithAndWithoutDefine(t *testing.T) {
720 b := newTestSitesBuilder(t)
721
722 b.WithContent("p1.md", "---\ntitle: P\n---\nContent")
723
724 b.WithTemplates(
725 "_default/baseof.html", `
726 ::Header Start:{{ block "header" . }}{{ end }}:Header End:
727 ::{{ block "main" . }}Main{{ end }}::
728 `, "index.html", `
729 {{ define "header" }}
730 Home Header
731 {{ end }}
732 {{ define "main" }}
733 This is home main
734 {{ end }}
735 `,
736
737 "_default/single.html", `
738 {{ define "main" }}
739 This is single main
740 {{ end }}
741 `,
742 )
743
744 b.CreateSites().Build(BuildCfg{})
745
746 b.AssertFileContent("public/index.html", `
747 Home Header
748 This is home main
749 `,
750 )
751
752 b.AssertFileContent("public/p1/index.html", `
753 ::Header Start::Header End:
754 This is single main
755 `,
756 )
757 }
758
759 // Issue 9393.
760 func TestApplyWithNamespace(t *testing.T) {
761 b := newTestSitesBuilder(t)
762
763 b.WithTemplates(
764 "index.html", `
765 {{ $b := slice " a " " b " " c" }}
766 {{ $a := apply $b "strings.Trim" "." " " }}
767 a: {{ $a }}
768 `,
769 ).WithContent("p1.md", "")
770
771 b.Build(BuildCfg{})
772
773 b.AssertFileContent("public/index.html", `a: [a b c]`)
774 }