tplimpl_integration_test.go - hugo - [fork] hugo port for 9front
 (HTM) git clone https://git.drkhsh.at/hugo.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
       tplimpl_integration_test.go (15412B)
       ---
            1 // Copyright 2025 The Hugo Authors. All rights reserved.
            2 //
            3 // Portions Copyright The Go Authors.
            4 
            5 // Licensed under the Apache License, Version 2.0 (the "License");
            6 // you may not use this file except in compliance with the License.
            7 // You may obtain a copy of the License at
            8 // http://www.apache.org/licenses/LICENSE-2.0
            9 //
           10 // Unless required by applicable law or agreed to in writing, software
           11 // distributed under the License is distributed on an "AS IS" BASIS,
           12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
           13 // See the License for the specific language governing permissions and
           14 // limitations under the License.
           15 
           16 package tplimpl_test
           17 
           18 import (
           19         "strings"
           20         "testing"
           21 
           22         qt "github.com/frankban/quicktest"
           23         "github.com/gohugoio/hugo/hugolib"
           24 )
           25 
           26 // Verify that the new keywords in Go 1.18 is available.
           27 func TestGo18Constructs(t *testing.T) {
           28         t.Parallel()
           29 
           30         files := `
           31 -- config.toml --
           32 baseURL = 'http://example.com/'
           33 disableKinds = ["section", "home", "rss", "taxonomy",  "term", "rss"]
           34 -- content/p1.md --
           35 ---
           36 title: "P1"
           37 ---
           38 -- layouts/partials/counter.html --
           39 {{ if .Scratch.Get "counter" }}{{ .Scratch.Add "counter" 1 }}{{ else }}{{ .Scratch.Set "counter" 1 }}{{ end }}{{ return true }}
           40 -- layouts/_default/single.html --
           41 continue:{{ range seq 5 }}{{ if eq . 2 }}{{continue}}{{ end }}{{ . }}{{ end }}:END:
           42 break:{{ range seq 5 }}{{ if eq . 2 }}{{break}}{{ end }}{{ . }}{{ end }}:END:
           43 continue2:{{ range seq 5 }}{{ if eq . 2 }}{{ continue }}{{ end }}{{ . }}{{ end }}:END:
           44 break2:{{ range seq 5 }}{{ if eq . 2 }}{{ break }}{{ end }}{{ . }}{{ end }}:END:
           45 
           46 counter1: {{ partial "counter.html" . }}/{{ .Scratch.Get "counter" }}
           47 and1: {{ if (and false (partial "counter.html" .)) }}true{{ else }}false{{ end }}
           48 or1: {{ if (or true (partial "counter.html" .)) }}true{{ else }}false{{ end }}
           49 and2: {{ if (and true (partial "counter.html" .)) }}true{{ else }}false{{ end }}
           50 or2: {{ if (or false (partial "counter.html" .)) }}true{{ else }}false{{ end }}
           51 
           52 
           53 counter2: {{ .Scratch.Get "counter" }}
           54 
           55 
           56         `
           57 
           58         b := hugolib.NewIntegrationTestBuilder(
           59                 hugolib.IntegrationTestConfig{
           60                         T:           t,
           61                         TxtarString: files,
           62                         NeedsOsFS:   true,
           63                 },
           64         )
           65         b.Build()
           66 
           67         b.AssertFileContent("public/p1/index.html", `
           68 continue:1345:END:
           69 break:1:END:
           70 continue2:1345:END:
           71 break2:1:END:
           72 counter1: true/1
           73 and1: false
           74 or1: true
           75 and2: true
           76 or2: true
           77 counter2: 3
           78 `)
           79 }
           80 
           81 func TestGo23ElseWith(t *testing.T) {
           82         t.Parallel()
           83 
           84         files := `
           85 -- hugo.toml --
           86 title = "Hugo"
           87 -- layouts/index.html --
           88 {{ with false }}{{ else with .Site }}{{ .Title }}{{ end }}|
           89 `
           90         b := hugolib.Test(t, files)
           91 
           92         b.AssertFileContent("public/index.html", "Hugo|")
           93 }
           94 
           95 // Issue 10495
           96 func TestCommentsBeforeBlockDefinition(t *testing.T) {
           97         t.Parallel()
           98 
           99         files := `
          100 -- config.toml --
          101 baseURL = 'http://example.com/'
          102 -- content/s1/p1.md --
          103 ---
          104 title: "S1P1"
          105 ---
          106 -- content/s2/p1.md --
          107 ---
          108 title: "S2P1"
          109 ---
          110 -- content/s3/p1.md --
          111 ---
          112 title: "S3P1"
          113 ---
          114 -- layouts/_default/baseof.html --
          115 {{ block "main" . }}{{ end }}
          116 -- layouts/s1/single.html --
          117 {{/* foo */}}
          118 {{ define "main" }}{{ .Title }}{{ end }}
          119 -- layouts/s2/single.html --
          120 {{- /* foo */}}
          121 {{ define "main" }}{{ .Title }}{{ end }}
          122 -- layouts/s3/single.html --
          123 {{- /* foo */ -}}
          124 {{ define "main" }}{{ .Title }}{{ end }}
          125         `
          126 
          127         b := hugolib.NewIntegrationTestBuilder(
          128                 hugolib.IntegrationTestConfig{
          129                         T:           t,
          130                         TxtarString: files,
          131                 },
          132         )
          133         b.Build()
          134 
          135         b.AssertFileContent("public/s1/p1/index.html", `S1P1`)
          136         b.AssertFileContent("public/s2/p1/index.html", `S2P1`)
          137         b.AssertFileContent("public/s3/p1/index.html", `S3P1`)
          138 }
          139 
          140 func TestGoTemplateBugs(t *testing.T) {
          141         t.Run("Issue 11112", func(t *testing.T) {
          142                 t.Parallel()
          143 
          144                 files := `
          145 -- config.toml --
          146 -- layouts/index.html --
          147 {{ $m := dict "key" "value" }}
          148 {{ $k := "" }}
          149 {{ $v := "" }}
          150 {{ range $k, $v = $m }}
          151 {{ $k }} = {{ $v }}
          152 {{ end }}
          153         `
          154 
          155                 b := hugolib.NewIntegrationTestBuilder(
          156                         hugolib.IntegrationTestConfig{
          157                                 T:           t,
          158                                 TxtarString: files,
          159                         },
          160                 )
          161                 b.Build()
          162 
          163                 b.AssertFileContent("public/index.html", `key = value`)
          164         })
          165 }
          166 
          167 func TestSecurityAllowActionJSTmpl(t *testing.T) {
          168         filesTemplate := `
          169 -- config.toml --
          170 SECURITYCONFIG
          171 -- layouts/index.html --
          172 <script>
          173 var a = §§{{.Title }}§§;
          174 </script>
          175         `
          176 
          177         files := strings.ReplaceAll(filesTemplate, "SECURITYCONFIG", "")
          178 
          179         b, err := hugolib.NewIntegrationTestBuilder(
          180                 hugolib.IntegrationTestConfig{
          181                         T:           t,
          182                         TxtarString: files,
          183                 },
          184         ).BuildE()
          185 
          186         // This used to fail, but not in >= Hugo 0.121.0.
          187         b.Assert(err, qt.IsNil)
          188 }
          189 
          190 func TestGoogleAnalyticsTemplate(t *testing.T) {
          191         t.Parallel()
          192 
          193         files := `
          194 -- hugo.toml --
          195 disableKinds = ['page','section','rss','sitemap','taxonomy','term']
          196 [privacy.googleAnalytics]
          197 disable = false
          198 respectDoNotTrack = true
          199 [services.googleAnalytics]
          200 id = 'G-0123456789'
          201 -- layouts/index.html --
          202 {{ template "_internal/google_analytics.html" . }}
          203 `
          204 
          205         b := hugolib.Test(t, files)
          206 
          207         b.AssertFileContent("public/index.html",
          208                 `<script async src="https://www.googletagmanager.com/gtag/js?id=G-0123456789"></script>`,
          209                 `var dnt = (navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack);`,
          210         )
          211 }
          212 
          213 func TestDisqusTemplate(t *testing.T) {
          214         t.Parallel()
          215 
          216         files := `
          217 -- hugo.toml --
          218 disableKinds = ['page','section','rss','sitemap','taxonomy','term']
          219 [services.disqus]
          220 shortname = 'foo'
          221 [privacy.disqus]
          222 disable = false
          223 -- layouts/index.html --
          224 {{ template "_internal/disqus.html" . }}
          225 `
          226 
          227         b := hugolib.Test(t, files)
          228 
          229         b.AssertFileContent("public/index.html",
          230                 `s.src = '//' + "foo" + '.disqus.com/embed.js';`,
          231         )
          232 }
          233 
          234 func TestSitemap(t *testing.T) {
          235         t.Parallel()
          236 
          237         files := `
          238 -- hugo.toml --
          239 disableKinds = ['home','rss','section','taxonomy','term']
          240 [sitemap]
          241 disable = true
          242 -- content/p1.md --
          243 ---
          244 title: p1
          245 sitemap:
          246   p1_disable: foo
          247 ---
          248 -- content/p2.md --
          249 ---
          250 title: p2
          251 
          252 ---
          253 -- layouts/_default/single.html --
          254 {{ .Title }}
          255 `
          256 
          257         // Test A: Exclude all pages via site config.
          258         b := hugolib.Test(t, files)
          259         b.AssertFileContentExact("public/sitemap.xml",
          260                 "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"\n  xmlns:xhtml=\"http://www.w3.org/1999/xhtml\">\n  \n</urlset>\n",
          261         )
          262 
          263         // Test B: Include all pages via site config.
          264         files_b := strings.ReplaceAll(files, "disable = true", "disable = false")
          265         b = hugolib.Test(t, files_b)
          266         b.AssertFileContentExact("public/sitemap.xml",
          267                 "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"\n  xmlns:xhtml=\"http://www.w3.org/1999/xhtml\">\n  <url>\n    <loc>/p1/</loc>\n  </url><url>\n    <loc>/p2/</loc>\n  </url>\n</urlset>\n",
          268         )
          269 
          270         // Test C: Exclude all pages via site config, but include p1 via front matter.
          271         files_c := strings.ReplaceAll(files, "p1_disable: foo", "disable: false")
          272         b = hugolib.Test(t, files_c)
          273         b.AssertFileContentExact("public/sitemap.xml",
          274                 "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"\n  xmlns:xhtml=\"http://www.w3.org/1999/xhtml\">\n  <url>\n    <loc>/p1/</loc>\n  </url>\n</urlset>\n",
          275         )
          276 
          277         // Test D:  Include all pages via site config, but exclude p1 via front matter.
          278         files_d := strings.ReplaceAll(files_b, "p1_disable: foo", "disable: true")
          279         b = hugolib.Test(t, files_d)
          280         b.AssertFileContentExact("public/sitemap.xml",
          281                 "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"\n  xmlns:xhtml=\"http://www.w3.org/1999/xhtml\">\n  <url>\n    <loc>/p2/</loc>\n  </url>\n</urlset>\n",
          282         )
          283 }
          284 
          285 // Issue 12418
          286 func TestOpengraph(t *testing.T) {
          287         t.Parallel()
          288 
          289         files := `
          290 -- hugo.toml --
          291 capitalizeListTitles = false
          292 disableKinds = ['rss','sitemap']
          293 languageCode = 'en-US'
          294 [markup.goldmark.renderer]
          295 unsafe = true
          296 [params]
          297 description = "m <em>n</em> and **o** can't."
          298 [params.social]
          299 facebook_admin = 'foo'
          300 [taxonomies]
          301 series = 'series'
          302 tag = 'tags'
          303 -- layouts/_default/list.html --
          304 {{ template "_internal/opengraph.html" . }}
          305 -- layouts/_default/single.html --
          306 {{ template "_internal/opengraph.html" . }}
          307 -- content/s1/p1.md --
          308 ---
          309 title: p1
          310 date: 2024-04-24T08:00:00-07:00
          311 lastmod: 2024-04-24T11:00:00-07:00
          312 images: [a.jpg,b.jpg]
          313 audio: [c.mp3,d.mp3]
          314 videos: [e.mp4,f.mp4]
          315 series: [series-1]
          316 tags: [t1,t2]
          317 ---
          318 a <em>b</em> and **c** can't.
          319 -- content/s1/p2.md --
          320 ---
          321 title: p2
          322 series: [series-1]
          323 ---
          324 d <em>e</em> and **f** can't.
          325 <!--more-->
          326 -- content/s1/p3.md --
          327 ---
          328 title: p3
          329 series: [series-1]
          330 summary: g <em>h</em> and **i** can't.
          331 ---
          332 -- content/s1/p4.md --
          333 ---
          334 title: p4
          335 series: [series-1]
          336 description: j <em>k</em> and **l** can't.
          337 ---
          338 -- content/s1/p5.md --
          339 ---
          340 title: p5
          341 series: [series-1]
          342 ---
          343 `
          344 
          345         b := hugolib.Test(t, files)
          346 
          347         b.AssertFileContent("public/s1/p1/index.html", `
          348                 <meta property="og:url" content="/s1/p1/">
          349                 <meta property="og:title" content="p1">
          350                 <meta property="og:description" content="a b and c can’t.">
          351                 <meta property="og:locale" content="en_US">
          352                 <meta property="og:type" content="article">
          353                 <meta property="article:section" content="s1">
          354                 <meta property="article:published_time" content="2024-04-24T08:00:00-07:00">
          355                 <meta property="article:modified_time" content="2024-04-24T11:00:00-07:00">
          356                 <meta property="article:tag" content="t1">
          357                 <meta property="article:tag" content="t2">
          358                 <meta property="og:image" content="/a.jpg">
          359                 <meta property="og:image" content="/b.jpg">
          360                 <meta property="og:audio" content="/c.mp3">
          361                 <meta property="og:audio" content="/d.mp3">
          362                 <meta property="og:video" content="/e.mp4">
          363                 <meta property="og:video" content="/f.mp4">
          364                 <meta property="og:see_also" content="/s1/p2/">
          365                 <meta property="og:see_also" content="/s1/p3/">
          366                 <meta property="og:see_also" content="/s1/p4/">
          367                 <meta property="og:see_also" content="/s1/p5/">
          368                 <meta property="fb:admins" content="foo">
          369                 `,
          370         )
          371 
          372         b.AssertFileContent("public/s1/p2/index.html",
          373                 `<meta property="og:description" content="d e and f can’t.">`,
          374         )
          375 
          376         b.AssertFileContent("public/s1/p3/index.html",
          377                 `<meta property="og:description" content="g h and i can’t.">`,
          378         )
          379 
          380         // The markdown is intentionally not rendered to HTML.
          381         b.AssertFileContent("public/s1/p4/index.html",
          382                 `<meta property="og:description" content="j k and **l** can&#39;t.">`,
          383         )
          384 
          385         // The markdown is intentionally not rendered to HTML.
          386         b.AssertFileContent("public/s1/p5/index.html",
          387                 `<meta property="og:description" content="m n and **o** can&#39;t.">`,
          388         )
          389 }
          390 
          391 // Issue 12432
          392 func TestSchema(t *testing.T) {
          393         t.Parallel()
          394 
          395         files := `
          396 -- hugo.toml --
          397 capitalizeListTitles = false
          398 disableKinds = ['rss','sitemap']
          399 [markup.goldmark.renderer]
          400 unsafe = true
          401 [params]
          402 description = "m <em>n</em> and **o** can't."
          403 [taxonomies]
          404 tag = 'tags'
          405 -- layouts/_default/list.html --
          406 {{ template "_internal/schema.html" . }}
          407 -- layouts/_default/single.html --
          408 {{ template "_internal/schema.html" . }}
          409 -- content/s1/p1.md --
          410 ---
          411 title: p1
          412 date: 2024-04-24T08:00:00-07:00
          413 lastmod: 2024-04-24T11:00:00-07:00
          414 images: [a.jpg,b.jpg]
          415 tags: [t1,t2]
          416 ---
          417 a <em>b</em> and **c** can't.
          418 -- content/s1/p2.md --
          419 ---
          420 title: p2
          421 ---
          422 d <em>e</em> and **f** can't.
          423 <!--more-->
          424 -- content/s1/p3.md --
          425 ---
          426 title: p3
          427 summary: g <em>h</em> and **i** can't.
          428 ---
          429 -- content/s1/p4.md --
          430 ---
          431 title: p4
          432 description: j <em>k</em> and **l** can't.
          433 ---
          434 -- content/s1/p5.md --
          435 ---
          436 title: p5
          437 ---
          438 `
          439 
          440         b := hugolib.Test(t, files)
          441 
          442         b.AssertFileContent("public/s1/p1/index.html", `
          443                 <meta itemprop="name" content="p1">
          444                 <meta itemprop="description" content="a b and c can’t.">
          445                 <meta itemprop="datePublished" content="2024-04-24T08:00:00-07:00">
          446                 <meta itemprop="dateModified" content="2024-04-24T11:00:00-07:00">
          447                 <meta itemprop="wordCount" content="5">
          448                 <meta itemprop="image" content="/a.jpg">
          449                 <meta itemprop="image" content="/b.jpg">
          450                 <meta itemprop="keywords" content="t1,t2">
          451                   `,
          452         )
          453 
          454         b.AssertFileContent("public/s1/p2/index.html",
          455                 `<meta itemprop="description" content="d e and f can’t.">`,
          456         )
          457 
          458         b.AssertFileContent("public/s1/p3/index.html",
          459                 `<meta itemprop="description" content="g h and i can’t.">`,
          460         )
          461 
          462         // The markdown is intentionally not rendered to HTML.
          463         b.AssertFileContent("public/s1/p4/index.html",
          464                 `<meta itemprop="description" content="j k and **l** can&#39;t.">`,
          465         )
          466 
          467         // The markdown is intentionally not rendered to HTML.
          468         b.AssertFileContent("public/s1/p5/index.html",
          469                 `<meta itemprop="description" content="m n and **o** can&#39;t.">`,
          470         )
          471 }
          472 
          473 // Issue 12433
          474 func TestTwitterCards(t *testing.T) {
          475         t.Parallel()
          476 
          477         files := `
          478 -- hugo.toml --
          479 capitalizeListTitles = false
          480 disableKinds = ['rss','sitemap','taxonomy','term']
          481 [markup.goldmark.renderer]
          482 unsafe = true
          483 [params]
          484 description = "m <em>n</em> and **o** can't."
          485 [params.social]
          486 twitter = 'foo'
          487 -- layouts/_default/list.html --
          488 {{ template "_internal/twitter_cards.html" . }}
          489 -- layouts/_default/single.html --
          490 {{ template "_internal/twitter_cards.html" . }}
          491 -- content/s1/p1.md --
          492 ---
          493 title: p1
          494 images: [a.jpg,b.jpg]
          495 ---
          496 a <em>b</em> and **c** can't.
          497 -- content/s1/p2.md --
          498 ---
          499 title: p2
          500 ---
          501 d <em>e</em> and **f** can't.
          502 <!--more-->
          503 -- content/s1/p3.md --
          504 ---
          505 title: p3
          506 summary: g <em>h</em> and **i** can't.
          507 ---
          508 -- content/s1/p4.md --
          509 ---
          510 title: p4
          511 description: j <em>k</em> and **l** can't.
          512 ---
          513 -- content/s1/p5.md --
          514 ---
          515 title: p5
          516 ---
          517 `
          518 
          519         b := hugolib.Test(t, files)
          520 
          521         b.AssertFileContent("public/s1/p1/index.html", `
          522                 <meta name="twitter:card" content="summary_large_image">
          523                 <meta name="twitter:image" content="/a.jpg">
          524                 <meta name="twitter:title" content="p1">
          525                 <meta name="twitter:description" content="a b and c can’t.">
          526                 <meta name="twitter:site" content="@foo">
          527                 `,
          528         )
          529 
          530         b.AssertFileContent("public/s1/p2/index.html",
          531                 `<meta name="twitter:card" content="summary">`,
          532                 `<meta name="twitter:description" content="d e and f can’t.">`,
          533         )
          534 
          535         b.AssertFileContent("public/s1/p3/index.html",
          536                 `<meta name="twitter:description" content="g h and i can’t.">`,
          537         )
          538 
          539         // The markdown is intentionally not rendered to HTML.
          540         b.AssertFileContent("public/s1/p4/index.html",
          541                 `<meta name="twitter:description" content="j k and **l** can&#39;t.">`,
          542         )
          543 
          544         // The markdown is intentionally not rendered to HTML.
          545         b.AssertFileContent("public/s1/p5/index.html",
          546                 `<meta name="twitter:description" content="m n and **o** can&#39;t.">`,
          547         )
          548 }
          549 
          550 // Issue 12963
          551 func TestEditBaseofParseAfterExecute(t *testing.T) {
          552         files := `
          553 -- hugo.toml --
          554 baseURL = "https://example.com"
          555 disableLiveReload = true
          556 disableKinds = ["taxonomy", "term", "rss", "404", "sitemap"]
          557 [internal]
          558 fastRenderMode = true
          559 -- layouts/_default/baseof.html --
          560 Baseof!
          561 {{ block "main" . }}default{{ end }}
          562 {{ with (templates.Defer (dict "key" "global")) }}
          563 Now. {{ now }}
          564 {{ end }}
          565 -- layouts/_default/single.html --
          566 {{ define "main" }}
          567 Single.
          568 {{ end }}
          569 -- layouts/_default/list.html --
          570 {{ define "main" }}
          571 List.
          572 {{ .Content }}
          573 {{ range .Pages }}{{ .Title }}{{ end }}|
          574 {{ end }}
          575 -- content/mybundle1/index.md --
          576 ---
          577 title: "My Bundle 1"
          578 ---
          579 -- content/mybundle2/index.md --
          580 ---
          581 title: "My Bundle 2"
          582 ---
          583 -- content/_index.md --
          584 ---
          585 title: "Home"
          586 ---
          587 Home!
          588 `
          589 
          590         b := hugolib.TestRunning(t, files)
          591         b.AssertFileContent("public/index.html", "Home!")
          592         b.EditFileReplaceAll("layouts/_default/baseof.html", "baseof", "Baseof!").Build()
          593         b.BuildPartial("/")
          594         b.AssertFileContent("public/index.html", "Baseof!")
          595         b.BuildPartial("/mybundle1/")
          596         b.AssertFileContent("public/mybundle1/index.html", "Baseof!")
          597 }