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 }