hugo

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

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

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 }