github.com/neohugo/neohugo@v0.123.8/hugolib/pagebundler_test.go (about)

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