github.com/neohugo/neohugo@v0.123.8/hugolib/content_map_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  	"path/filepath"
    19  	"testing"
    20  
    21  	qt "github.com/frankban/quicktest"
    22  )
    23  
    24  func TestContentMapSite(t *testing.T) {
    25  	b := newTestSitesBuilder(t)
    26  
    27  	pageTempl := `
    28  ---
    29  title: "Page %d"
    30  date: "2019-06-0%d"	
    31  lastMod: "2019-06-0%d"
    32  categories: [%q]
    33  ---
    34  
    35  Page content.
    36  `
    37  	createPage := func(i int) string {
    38  		return fmt.Sprintf(pageTempl, i, i, i+1, "funny")
    39  	}
    40  
    41  	createPageInCategory := func(i int, category string) string {
    42  		return fmt.Sprintf(pageTempl, i, i, i+1, category)
    43  	}
    44  
    45  	draftTemplate := `---
    46  title: "Draft"
    47  draft: true
    48  ---
    49  
    50  `
    51  
    52  	b.WithContent("_index.md", `
    53  ---
    54  title: "Hugo Home"
    55  cascade:
    56      description: "Common Description"
    57      
    58  ---
    59  
    60  Home Content.
    61  `)
    62  
    63  	b.WithContent("blog/page1.md", createPage(1))
    64  	b.WithContent("blog/page2.md", createPage(2))
    65  	b.WithContent("blog/page3.md", createPage(3))
    66  	b.WithContent("blog/bundle/index.md", createPage(12))
    67  	b.WithContent("blog/bundle/data.json", "data")
    68  	b.WithContent("blog/bundle/page.md", createPage(99))
    69  	b.WithContent("blog/subsection/_index.md", createPage(3))
    70  	b.WithContent("blog/subsection/subdata.json", "data")
    71  	b.WithContent("blog/subsection/page4.md", createPage(8))
    72  	b.WithContent("blog/subsection/page5.md", createPage(10))
    73  	b.WithContent("blog/subsection/draft/index.md", draftTemplate)
    74  	b.WithContent("blog/subsection/draft/data.json", "data")
    75  	b.WithContent("blog/draftsection/_index.md", draftTemplate)
    76  	b.WithContent("blog/draftsection/page/index.md", createPage(12))
    77  	b.WithContent("blog/draftsection/page/folder/data.json", "data")
    78  	b.WithContent("blog/draftsection/sub/_index.md", createPage(12))
    79  	b.WithContent("blog/draftsection/sub/page.md", createPage(13))
    80  	b.WithContent("docs/page6.md", createPage(11))
    81  	b.WithContent("tags/_index.md", createPageInCategory(32, "sad"))
    82  	b.WithContent("overlap/_index.md", createPageInCategory(33, "sad"))
    83  	b.WithContent("overlap2/_index.md", createPage(34))
    84  
    85  	b.WithTemplatesAdded("layouts/index.html", `
    86  Num Regular: {{ len .Site.RegularPages }}|{{ range .Site.RegularPages }}{{ .RelPermalink }}|{{ end }}$
    87  Main Sections: {{ .Site.Params.mainSections }}
    88  Pag Num Pages: {{ len .Paginator.Pages }}
    89  {{ $home := .Site.Home }}
    90  {{ $blog := .Site.GetPage "blog" }}
    91  {{ $categories := .Site.GetPage "categories" }}
    92  {{ $funny := .Site.GetPage "categories/funny" }}
    93  {{ $blogSub := .Site.GetPage "blog/subsection" }}
    94  {{ $page := .Site.GetPage "blog/page1" }}
    95  {{ $page2 := .Site.GetPage "blog/page2" }}
    96  {{ $page4 := .Site.GetPage "blog/subsection/page4" }}
    97  {{ $bundle := .Site.GetPage "blog/bundle" }}
    98  {{ $overlap1 := .Site.GetPage "overlap" }}
    99  {{ $overlap2 := .Site.GetPage "overlap2" }}
   100  
   101  Home: {{ template "print-page" $home }}
   102  Blog Section: {{ template "print-page" $blog }}
   103  Blog Sub Section: {{ template "print-page" $blogSub }}
   104  Page: {{ template "print-page" $page }}
   105  Bundle: {{ template "print-page" $bundle }}
   106  IsDescendant: true: {{ $page.IsDescendant $blog }} true: {{ $blogSub.IsDescendant $blog }} true: {{ $bundle.IsDescendant $blog }} true: {{ $page4.IsDescendant $blog }} true: {{ $blog.IsDescendant $home }} false: {{ $blog.IsDescendant $blog }} false: {{ $home.IsDescendant $blog }}
   107  IsAncestor: true: {{ $blog.IsAncestor $page }} true: {{ $home.IsAncestor $blog }} true: {{ $blog.IsAncestor $blogSub }} true: {{ $blog.IsAncestor $bundle }} true: {{ $blog.IsAncestor $page4 }} true: {{ $home.IsAncestor $page }} false: {{ $blog.IsAncestor $blog }} false: {{ $page.IsAncestor $blog }} false: {{ $blog.IsAncestor $home }}  false: {{ $blogSub.IsAncestor $blog }}
   108  IsDescendant overlap1: false: {{ $overlap1.IsDescendant $overlap2 }}
   109  IsDescendant overlap2: false: {{ $overlap2.IsDescendant $overlap1 }}
   110  IsAncestor overlap1: false: {{ $overlap1.IsAncestor $overlap2 }}
   111  IsAncestor overlap2: false: {{ $overlap2.IsAncestor $overlap1 }}
   112  FirstSection: {{ $blogSub.FirstSection.RelPermalink }} {{ $blog.FirstSection.RelPermalink }} {{ $home.FirstSection.RelPermalink }} {{ $page.FirstSection.RelPermalink }}
   113  InSection: true: {{ $page.InSection $blog }} false: {{ $page.InSection $blogSub }} 
   114  Next: {{ $page2.Next.RelPermalink }}
   115  NextInSection: {{ $page2.NextInSection.RelPermalink }}
   116  Pages: {{ range $blog.Pages }}{{ .RelPermalink }}|{{ end }}
   117  Sections: {{ range $home.Sections }}{{ .RelPermalink }}|{{ end }}:END
   118  Categories: {{ range .Site.Taxonomies.categories }}{{ .Page.RelPermalink }}; {{ .Page.Title }}; {{ .Count }}|{{ end }}:END
   119  Category Terms:  {{ $categories.Kind}}: {{ range $categories.Data.Terms.Alphabetical }}{{ .Page.RelPermalink }}; {{ .Page.Title }}; {{ .Count }}|{{ end }}:END
   120  Category Funny:  {{ $funny.Kind}}; {{ $funny.Data.Term }}: {{ range $funny.Pages }}{{ .RelPermalink }};|{{ end }}:END
   121  Pag Num Pages: {{ len .Paginator.Pages }}
   122  Pag Blog Num Pages: {{ len $blog.Paginator.Pages }}
   123  Blog Num RegularPages: {{ len $blog.RegularPages }}|{{ range $blog.RegularPages }}P: {{ .RelPermalink }}|{{ end }}
   124  Blog Num Pages: {{ len $blog.Pages }}
   125  
   126  Draft1: {{ if (.Site.GetPage "blog/subsection/draft") }}FOUND{{ end }}|
   127  Draft2: {{ if (.Site.GetPage "blog/draftsection") }}FOUND{{ end }}|
   128  Draft3: {{ if (.Site.GetPage "blog/draftsection/page") }}FOUND{{ end }}|
   129  Draft4: {{ if (.Site.GetPage "blog/draftsection/sub") }}FOUND{{ end }}|
   130  Draft5: {{ if (.Site.GetPage "blog/draftsection/sub/page") }}FOUND{{ end }}|
   131  
   132  {{ define "print-page" }}{{ .Title }}|{{ .RelPermalink }}|{{ .Date.Format "2006-01-02" }}|Current Section: {{ with .CurrentSection }}{{ .Path }}{{ else }}NIL{{ end }}|Resources: {{ range .Resources }}{{ .ResourceType }}: {{ .RelPermalink }}|{{ end }}{{ end }}
   133  `)
   134  
   135  	b.Build(BuildCfg{})
   136  
   137  	b.AssertFileContent("public/index.html",
   138  
   139  		`
   140  	 Num Regular: 9
   141          Main Sections: [blog]
   142          Pag Num Pages: 9
   143          
   144        Home: Hugo Home|/|2019-06-08|Current Section: /|Resources: 
   145          Blog Section: Blogs|/blog/|2019-06-08|Current Section: /blog|Resources: 
   146          Blog Sub Section: Page 3|/blog/subsection/|2019-06-03|Current Section: /blog/subsection|Resources: application: /blog/subsection/subdata.json|
   147          Page: Page 1|/blog/page1/|2019-06-01|Current Section: /blog|Resources: 
   148          Bundle: Page 12|/blog/bundle/|0001-01-01|Current Section: /blog|Resources: application: /blog/bundle/data.json|page: |
   149          IsDescendant: true: true true: true true: true true: true true: true false: false false: false
   150          IsAncestor: true: true true: true true: true true: true true: true true: true false: false false: false false: false  false: false
   151          IsDescendant overlap1: false: false
   152          IsDescendant overlap2: false: false
   153          IsAncestor overlap1: false: false
   154          IsAncestor overlap2: false: false
   155          FirstSection: /blog/ /blog/ / /blog/
   156          InSection: true: true false: false 
   157          Next: /blog/page3/
   158          NextInSection: /blog/page3/
   159          Pages: /blog/page3/|/blog/subsection/|/blog/page2/|/blog/page1/|/blog/bundle/|
   160          Sections: /blog/|/docs/|/overlap/|/overlap2/|:END
   161  		Categories: /categories/funny/; Funny; 12|/categories/sad/; Sad; 2|:END
   162          Category Terms:  taxonomy: /categories/funny/; Funny; 12|/categories/sad/; Sad; 2|:END
   163  		Category Funny:  term; funny: /blog/subsection/page4/;|/blog/page3/;|/blog/subsection/;|/blog/page2/;|/blog/page1/;|/blog/subsection/page5/;|/docs/page6/;|/blog/bundle/;|/blog/draftsection/page/;|/blog/draftsection/sub/;|/blog/draftsection/sub/page/;|/overlap2/;|:END
   164   		Pag Num Pages: 9
   165          Pag Blog Num Pages: 4
   166          Blog Num RegularPages: 4
   167          Blog Num Pages: 5
   168          
   169          Draft1: |
   170          Draft2: FOUND|
   171          Draft3: FOUND|
   172          Draft4: FOUND|
   173          Draft5: FOUND|
   174             
   175  `)
   176  }
   177  
   178  func TestIntegrationTestTemplate(t *testing.T) {
   179  	t.Parallel()
   180  	c := qt.New(t)
   181  
   182  	files := `
   183  -- config.toml --
   184  title = "Integration Test"
   185  disableKinds=["page", "section", "taxonomy", "term", "sitemap", "robotsTXT", "RSS"]
   186  -- layouts/index.html --
   187  Home: {{ .Title }}|
   188  		
   189  	`
   190  
   191  	b := NewIntegrationTestBuilder(
   192  		IntegrationTestConfig{
   193  			T:           c,
   194  			TxtarString: files,
   195  		}).Build()
   196  
   197  	b.AssertFileContent("public/index.html", "Home: Integration Test|")
   198  }
   199  
   200  // Issue #11840
   201  func TestBundleResourceLanguageBestMatch(t *testing.T) {
   202  	files := `
   203  -- hugo.toml --
   204  defaultContentLanguage = "fr"
   205  defaultContentLanguageInSubdir = true
   206  [languages]
   207  [languages.en]
   208  weight = 1
   209  [languages.fr]
   210  weight = 2
   211  [languages.de]
   212  weight = 3
   213  -- layouts/index.html --
   214  {{ $bundle := site.GetPage "bundle" }}
   215  {{ $r := $bundle.Resources.GetMatch "*.txt" }}
   216  {{ .Language.Lang }}: {{ $r.RelPermalink }}|{{ $r.Content }}
   217  -- content/bundle/index.fr.md --
   218  ---
   219  title: "Bundle Fr"
   220  ---
   221  -- content/bundle/index.en.md --
   222  ---
   223  title: "Bundle En"
   224  ---
   225  -- content/bundle/index.de.md --
   226  ---
   227  title: "Bundle De"
   228  ---
   229  -- content/bundle/data.fr.txt --
   230  Data fr
   231  -- content/bundle/data.en.txt --
   232  Data en
   233  
   234  `
   235  	b := Test(t, files)
   236  
   237  	b.AssertFileContent("public/fr/index.html", "fr: /fr/bundle/data.fr.txt|Data fr")
   238  	b.AssertFileContent("public/en/index.html", "en: /en/bundle/data.en.txt|Data en")
   239  	b.AssertFileContent("public/de/index.html", "de: /fr/bundle/data.fr.txt|Data fr")
   240  }
   241  
   242  func TestBundleMultipleContentPageWithSamePath(t *testing.T) {
   243  	files := `
   244  -- hugo.toml --
   245  -- content/bundle/index.md --
   246  ---
   247  title: "Bundle md"
   248  foo: md
   249  ---
   250  -- content/bundle/index.html --
   251  ---
   252  title: "Bundle html"
   253  foo: html
   254  ---
   255  -- content/bundle/data.txt --
   256  Data.
   257  -- content/p1.md --
   258  ---
   259  title: "P1 md"
   260  foo: md
   261  ---
   262  -- content/p1.html --
   263  ---
   264  title: "P1 html"
   265  foo: html
   266  ---
   267  -- layouts/index.html --
   268  {{ $bundle := site.GetPage "bundle" }}
   269  Bundle: {{ $bundle.Title }}|{{ $bundle.Params.foo }}|{{ $bundle.File.Filename }}|
   270  {{ $p1 := site.GetPage "p1" }}
   271  P1: {{ $p1.Title }}|{{ $p1.Params.foo }}|{{ $p1.File.Filename }}|
   272  `
   273  
   274  	b := Test(t, files)
   275  
   276  	// There's multiple content files sharing the same logical path and language.
   277  	// This is a little arbitrary, but we have to pick one and prefer the Markdown version.
   278  	b.AssertFileContent("public/index.html",
   279  		filepath.FromSlash("Bundle: Bundle md|md|/content/bundle/index.md|"),
   280  		filepath.FromSlash("P1: P1 md|md|/content/p1.md|"),
   281  	)
   282  }
   283  
   284  // Issue #11944
   285  func TestBundleResourcesGetWithSpacesInFilename(t *testing.T) {
   286  	files := `
   287  -- hugo.toml --
   288  baseURL = "https://example.com"
   289  disableKinds = ["taxonomy", "term"]
   290  -- content/bundle/index.md --
   291  -- content/bundle/data with Spaces.txt --
   292  Data.
   293  -- layouts/index.html --
   294  {{ $bundle := site.GetPage "bundle" }}
   295  {{ $r := $bundle.Resources.Get "data with Spaces.txt" }}
   296  R: {{ with $r }}{{ .Content }}{{ end }}|
   297  `
   298  	b := Test(t, files)
   299  
   300  	b.AssertFileContent("public/index.html", "R: Data.")
   301  }
   302  
   303  // Issue #11946.
   304  func TestBundleResourcesGetDuplicateSortOrder(t *testing.T) {
   305  	files := `
   306  -- hugo.toml --
   307  baseURL = "https://example.com"
   308  -- content/bundle/index.md --
   309  -- content/bundle/data-1.txt --
   310  data-1.txt
   311  -- content/bundle/data 1.txt --
   312  data 1.txt
   313  -- content/bundle/Data 1.txt --
   314  Data 1.txt
   315  -- content/bundle/Data-1.txt --
   316  Data-1.txt
   317  -- layouts/index.html --
   318  {{ $bundle := site.GetPage "bundle" }}
   319  {{ $r := $bundle.Resources.Get "data-1.txt" }}
   320  R: {{ with $r }}{{ .Content }}{{ end }}|Len: {{ len $bundle.Resources }}|$
   321  
   322  `
   323  
   324  	for i := 0; i < 3; i++ {
   325  		b := Test(t, files)
   326  		b.AssertFileContent("public/index.html", "R: Data 1.txt|", "Len: 1|")
   327  	}
   328  }
   329  
   330  func TestBundleResourcesNoPublishedIssue12198(t *testing.T) {
   331  	t.Parallel()
   332  
   333  	files := `
   334  -- hugo.toml --
   335  disableKinds = ['home','rss','sitemap','taxonomy','term']
   336  -- content/s1/p1.md --
   337  ---
   338  title: p1
   339  ---
   340  -- content/s1/foo.txt --
   341  foo.txt
   342  -- content/s1/p1.txt --
   343  p1.txt
   344  -- content/s1/p1-foo.txt --
   345  p1-foo.txt
   346  -- layouts/_default/list.html --
   347  {{.Title }}|
   348  -- layouts/_default/single.html --
   349  {{.Title }}|
   350  	`
   351  
   352  	b := Test(t, files)
   353  	b.Build()
   354  
   355  	b.AssertFileExists("public/s1/index.html", true)
   356  	b.AssertFileExists("public/s1/foo.txt", true)
   357  	b.AssertFileExists("public/s1/p1.txt", true)     // failing test
   358  	b.AssertFileExists("public/s1/p1-foo.txt", true) // failing test
   359  	b.AssertFileExists("public/s1/p1/index.html", true)
   360  }