github.com/anakojm/hugo-katex@v0.0.0-20231023141351-42d6f5de9c0b/create/content_test.go (about) 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 create_test 15 16 import ( 17 "fmt" 18 "os" 19 "path/filepath" 20 "strings" 21 "testing" 22 23 "github.com/gohugoio/hugo/config" 24 "github.com/gohugoio/hugo/config/allconfig" 25 "github.com/gohugoio/hugo/config/testconfig" 26 27 "github.com/gohugoio/hugo/deps" 28 29 "github.com/gohugoio/hugo/hugolib" 30 31 "github.com/gohugoio/hugo/hugofs" 32 33 qt "github.com/frankban/quicktest" 34 "github.com/gohugoio/hugo/create" 35 "github.com/gohugoio/hugo/helpers" 36 "github.com/spf13/afero" 37 ) 38 39 // TODO(bep) clean this up. Export the test site builder in Hugolib or something. 40 func TestNewContentFromFile(t *testing.T) { 41 cases := []struct { 42 name string 43 kind string 44 path string 45 expected any 46 }{ 47 {"Post", "post", "post/sample-1.md", []string{`title = "Post Arch title"`, `test = "test1"`, "date = \"2015-01-12T19:20:04-07:00\""}}, 48 {"Post org-mode", "post", "post/org-1.org", []string{`#+title: ORG-1`}}, 49 {"Post, unknown content filetype", "post", "post/sample-1.pdoc", false}, 50 {"Empty date", "emptydate", "post/sample-ed.md", []string{`title = "Empty Date Arch title"`, `test = "test1"`}}, 51 {"Archetype file not found", "stump", "stump/sample-2.md", []string{`title: "Sample 2"`}}, // no archetype file 52 {"No archetype", "", "sample-3.md", []string{`title: "Sample 3"`}}, // no archetype 53 {"Empty archetype", "product", "product/sample-4.md", []string{`title = "SAMPLE-4"`}}, // empty archetype front matter 54 {"Filenames", "filenames", "content/mypage/index.md", []string{"title = \"INDEX\"\n+++\n\n\nContentBaseName: mypage"}}, 55 {"Branch Name", "name", "content/tags/tag-a/_index.md", []string{"+++\ntitle = 'Tag A'\n+++"}}, 56 57 {"Lang 1", "lang", "post/lang-1.md", []string{`Site Lang: en|Name: Lang 1|i18n: Hugo Rocks!`}}, 58 {"Lang 2", "lang", "post/lang-2.en.md", []string{`Site Lang: en|Name: Lang 2|i18n: Hugo Rocks!`}}, 59 {"Lang nn file", "lang", "content/post/lang-3.nn.md", []string{`Site Lang: nn|Name: Lang 3|i18n: Hugo Rokkar!`}}, 60 {"Lang nn dir", "lang", "content_nn/post/lang-4.md", []string{`Site Lang: nn|Name: Lang 4|i18n: Hugo Rokkar!`}}, 61 {"Lang en in nn dir", "lang", "content_nn/post/lang-5.en.md", []string{`Site Lang: en|Name: Lang 5|i18n: Hugo Rocks!`}}, 62 {"Lang en default", "lang", "post/my-bundle/index.md", []string{`Site Lang: en|Name: My Bundle|i18n: Hugo Rocks!`}}, 63 {"Lang en file", "lang", "post/my-bundle/index.en.md", []string{`Site Lang: en|Name: My Bundle|i18n: Hugo Rocks!`}}, 64 {"Lang nn bundle", "lang", "content/post/my-bundle/index.nn.md", []string{`Site Lang: nn|Name: My Bundle|i18n: Hugo Rokkar!`}}, 65 {"Site", "site", "content/mypage/index.md", []string{"RegularPages .Site: 10", "RegularPages site: 10"}}, 66 {"Shortcodes", "shortcodes", "shortcodes/go.md", []string{ 67 `title = "GO"`, 68 "{{< myshortcode >}}", 69 "{{% myshortcode %}}", 70 "{{</* comment */>}}\n{{%/* comment */%}}", 71 }}, // shortcodes 72 } 73 74 c := qt.New(t) 75 76 for i, cas := range cases { 77 cas := cas 78 79 c.Run(cas.name, func(c *qt.C) { 80 c.Parallel() 81 82 mm := afero.NewMemMapFs() 83 c.Assert(initFs(mm), qt.IsNil) 84 cfg, fs := newTestCfg(c, mm) 85 conf := testconfig.GetTestConfigs(fs.Source, cfg) 86 h, err := hugolib.NewHugoSites(deps.DepsCfg{Configs: conf, Fs: fs}) 87 c.Assert(err, qt.IsNil) 88 err = create.NewContent(h, cas.kind, cas.path, false) 89 90 if b, ok := cas.expected.(bool); ok && !b { 91 if !b { 92 c.Assert(err, qt.Not(qt.IsNil)) 93 } 94 return 95 } 96 97 c.Assert(err, qt.IsNil) 98 99 fname := filepath.FromSlash(cas.path) 100 if !strings.HasPrefix(fname, "content") { 101 fname = filepath.Join("content", fname) 102 } 103 104 content := readFileFromFs(c, fs.Source, fname) 105 106 for _, v := range cas.expected.([]string) { 107 found := strings.Contains(content, v) 108 if !found { 109 c.Fatalf("[%d] %q missing from output:\n%q", i, v, content) 110 } 111 } 112 }) 113 114 } 115 } 116 117 func TestNewContentFromDir(t *testing.T) { 118 mm := afero.NewMemMapFs() 119 c := qt.New(t) 120 121 archetypeDir := filepath.Join("archetypes", "my-bundle") 122 c.Assert(mm.MkdirAll(archetypeDir, 0o755), qt.IsNil) 123 124 archetypeThemeDir := filepath.Join("themes", "mytheme", "archetypes", "my-theme-bundle") 125 c.Assert(mm.MkdirAll(archetypeThemeDir, 0o755), qt.IsNil) 126 127 contentFile := ` 128 File: %s 129 Site Lang: {{ .Site.Language.Lang }} 130 Name: {{ replace .Name "-" " " | title }} 131 i18n: {{ T "hugo" }} 132 ` 133 134 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "index.md"), []byte(fmt.Sprintf(contentFile, "index.md")), 0o755), qt.IsNil) 135 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "index.nn.md"), []byte(fmt.Sprintf(contentFile, "index.nn.md")), 0o755), qt.IsNil) 136 137 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "pages", "bio.md"), []byte(fmt.Sprintf(contentFile, "bio.md")), 0o755), qt.IsNil) 138 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "resources", "hugo1.json"), []byte(`hugo1: {{ printf "no template handling in here" }}`), 0o755), qt.IsNil) 139 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "resources", "hugo2.xml"), []byte(`hugo2: {{ printf "no template handling in here" }}`), 0o755), qt.IsNil) 140 141 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeThemeDir, "index.md"), []byte(fmt.Sprintf(contentFile, "index.md")), 0o755), qt.IsNil) 142 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeThemeDir, "resources", "hugo1.json"), []byte(`hugo1: {{ printf "no template handling in here" }}`), 0o755), qt.IsNil) 143 144 c.Assert(initFs(mm), qt.IsNil) 145 cfg, fs := newTestCfg(c, mm) 146 147 conf := testconfig.GetTestConfigs(fs.Source, cfg) 148 h, err := hugolib.NewHugoSites(deps.DepsCfg{Configs: conf, Fs: fs}) 149 c.Assert(err, qt.IsNil) 150 c.Assert(len(h.Sites), qt.Equals, 2) 151 152 c.Assert(create.NewContent(h, "my-bundle", "post/my-post", false), qt.IsNil) 153 154 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/resources/hugo1.json")), `hugo1: {{ printf "no template handling in here" }}`) 155 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/resources/hugo2.xml")), `hugo2: {{ printf "no template handling in here" }}`) 156 157 // Content files should get the correct site context. 158 // TODO(bep) archetype check i18n 159 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/index.md")), `File: index.md`, `Site Lang: en`, `Name: My Post`, `i18n: Hugo Rocks!`) 160 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/index.nn.md")), `File: index.nn.md`, `Site Lang: nn`, `Name: My Post`, `i18n: Hugo Rokkar!`) 161 162 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/pages/bio.md")), `File: bio.md`, `Site Lang: en`, `Name: Bio`) 163 164 c.Assert(create.NewContent(h, "my-theme-bundle", "post/my-theme-post", false), qt.IsNil) 165 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-theme-post/index.md")), `File: index.md`, `Site Lang: en`, `Name: My Theme Post`, `i18n: Hugo Rocks!`) 166 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-theme-post/resources/hugo1.json")), `hugo1: {{ printf "no template handling in here" }}`) 167 } 168 169 func TestNewContentFromDirSiteFunction(t *testing.T) { 170 mm := afero.NewMemMapFs() 171 c := qt.New(t) 172 173 archetypeDir := filepath.Join("archetypes", "my-bundle") 174 defaultArchetypeDir := filepath.Join("archetypes", "default") 175 c.Assert(mm.MkdirAll(archetypeDir, 0o755), qt.IsNil) 176 c.Assert(mm.MkdirAll(defaultArchetypeDir, 0o755), qt.IsNil) 177 178 contentFile := ` 179 File: %s 180 site RegularPages: {{ len site.RegularPages }} 181 182 ` 183 184 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "index.md"), []byte(fmt.Sprintf(contentFile, "index.md")), 0o755), qt.IsNil) 185 c.Assert(afero.WriteFile(mm, filepath.Join(defaultArchetypeDir, "index.md"), []byte("default archetype index.md"), 0o755), qt.IsNil) 186 187 c.Assert(initFs(mm), qt.IsNil) 188 cfg, fs := newTestCfg(c, mm) 189 190 conf := testconfig.GetTestConfigs(fs.Source, cfg) 191 h, err := hugolib.NewHugoSites(deps.DepsCfg{Configs: conf, Fs: fs}) 192 c.Assert(err, qt.IsNil) 193 c.Assert(len(h.Sites), qt.Equals, 2) 194 195 c.Assert(create.NewContent(h, "my-bundle", "post/my-post", false), qt.IsNil) 196 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/index.md")), `site RegularPages: 10`) 197 198 // Default bundle archetype 199 c.Assert(create.NewContent(h, "", "post/my-post2", false), qt.IsNil) 200 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post2/index.md")), `default archetype index.md`) 201 202 // Regular file with bundle kind. 203 c.Assert(create.NewContent(h, "my-bundle", "post/foo.md", false), qt.IsNil) 204 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/foo.md")), `draft: true`) 205 206 // Regular files should fall back to the default archetype (we have no regular file archetype). 207 c.Assert(create.NewContent(h, "my-bundle", "mypage.md", false), qt.IsNil) 208 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "mypage.md")), `draft: true`) 209 210 } 211 212 func TestNewContentFromDirNoSite(t *testing.T) { 213 mm := afero.NewMemMapFs() 214 c := qt.New(t) 215 216 archetypeDir := filepath.Join("archetypes", "my-bundle") 217 c.Assert(mm.MkdirAll(archetypeDir, 0o755), qt.IsNil) 218 219 archetypeThemeDir := filepath.Join("themes", "mytheme", "archetypes", "my-theme-bundle") 220 c.Assert(mm.MkdirAll(archetypeThemeDir, 0o755), qt.IsNil) 221 222 contentFile := ` 223 File: %s 224 Name: {{ replace .Name "-" " " | title }} 225 i18n: {{ T "hugo" }} 226 ` 227 228 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "index.md"), []byte(fmt.Sprintf(contentFile, "index.md")), 0o755), qt.IsNil) 229 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "index.nn.md"), []byte(fmt.Sprintf(contentFile, "index.nn.md")), 0o755), qt.IsNil) 230 231 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "pages", "bio.md"), []byte(fmt.Sprintf(contentFile, "bio.md")), 0o755), qt.IsNil) 232 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "resources", "hugo1.json"), []byte(`hugo1: {{ printf "no template handling in here" }}`), 0o755), qt.IsNil) 233 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "resources", "hugo2.xml"), []byte(`hugo2: {{ printf "no template handling in here" }}`), 0o755), qt.IsNil) 234 235 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeThemeDir, "index.md"), []byte(fmt.Sprintf(contentFile, "index.md")), 0o755), qt.IsNil) 236 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeThemeDir, "resources", "hugo1.json"), []byte(`hugo1: {{ printf "no template handling in here" }}`), 0o755), qt.IsNil) 237 238 c.Assert(initFs(mm), qt.IsNil) 239 cfg, fs := newTestCfg(c, mm) 240 conf := testconfig.GetTestConfigs(fs.Source, cfg) 241 h, err := hugolib.NewHugoSites(deps.DepsCfg{Configs: conf, Fs: fs}) 242 c.Assert(err, qt.IsNil) 243 c.Assert(len(h.Sites), qt.Equals, 2) 244 245 c.Assert(create.NewContent(h, "my-bundle", "post/my-post", false), qt.IsNil) 246 247 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/resources/hugo1.json")), `hugo1: {{ printf "no template handling in here" }}`) 248 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/resources/hugo2.xml")), `hugo2: {{ printf "no template handling in here" }}`) 249 250 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/index.md")), `File: index.md`, `Name: My Post`, `i18n: Hugo Rocks!`) 251 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/index.nn.md")), `File: index.nn.md`, `Name: My Post`, `i18n: Hugo Rokkar!`) 252 253 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-post/pages/bio.md")), `File: bio.md`, `Name: Bio`) 254 255 c.Assert(create.NewContent(h, "my-theme-bundle", "post/my-theme-post", false), qt.IsNil) 256 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-theme-post/index.md")), `File: index.md`, `Name: My Theme Post`, `i18n: Hugo Rocks!`) 257 cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "post/my-theme-post/resources/hugo1.json")), `hugo1: {{ printf "no template handling in here" }}`) 258 } 259 260 func TestNewContentForce(t *testing.T) { 261 mm := afero.NewMemMapFs() 262 c := qt.New(t) 263 264 archetypeDir := filepath.Join("archetypes", "my-bundle") 265 c.Assert(mm.MkdirAll(archetypeDir, 0o755), qt.IsNil) 266 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "index.md"), []byte(""), 0o755), qt.IsNil) 267 c.Assert(afero.WriteFile(mm, filepath.Join(archetypeDir, "index.nn.md"), []byte(""), 0o755), qt.IsNil) 268 269 c.Assert(initFs(mm), qt.IsNil) 270 cfg, fs := newTestCfg(c, mm) 271 272 conf := testconfig.GetTestConfigs(fs.Source, cfg) 273 h, err := hugolib.NewHugoSites(deps.DepsCfg{Configs: conf, Fs: fs}) 274 c.Assert(err, qt.IsNil) 275 c.Assert(len(h.Sites), qt.Equals, 2) 276 277 // from file 278 c.Assert(create.NewContent(h, "post", "post/my-post.md", false), qt.IsNil) 279 c.Assert(create.NewContent(h, "post", "post/my-post.md", false), qt.IsNotNil) 280 c.Assert(create.NewContent(h, "post", "post/my-post.md", true), qt.IsNil) 281 282 // from dir 283 c.Assert(create.NewContent(h, "my-bundle", "post/my-post", false), qt.IsNil) 284 c.Assert(create.NewContent(h, "my-bundle", "post/my-post", false), qt.IsNotNil) 285 c.Assert(create.NewContent(h, "my-bundle", "post/my-post", true), qt.IsNil) 286 } 287 288 func initFs(fs afero.Fs) error { 289 perm := os.FileMode(0o755) 290 var err error 291 292 // create directories 293 dirs := []string{ 294 "archetypes", 295 "content", 296 filepath.Join("themes", "sample", "archetypes"), 297 } 298 for _, dir := range dirs { 299 err = fs.Mkdir(dir, perm) 300 if err != nil && !os.IsExist(err) { 301 return err 302 } 303 } 304 305 // create some dummy content 306 for i := 1; i <= 10; i++ { 307 filename := filepath.Join("content", fmt.Sprintf("page%d.md", i)) 308 afero.WriteFile(fs, filename, []byte(`--- 309 title: Test 310 --- 311 `), 0666) 312 } 313 314 // create archetype files 315 for _, v := range []struct { 316 path string 317 content string 318 }{ 319 { 320 path: filepath.Join("archetypes", "post.md"), 321 content: "+++\ndate = \"2015-01-12T19:20:04-07:00\"\ntitle = \"Post Arch title\"\ntest = \"test1\"\n+++\n", 322 }, 323 { 324 path: filepath.Join("archetypes", "post.org"), 325 content: "#+title: {{ .BaseFileName | upper }}", 326 }, 327 { 328 path: filepath.Join("archetypes", "name.md"), 329 content: `+++ 330 title = '{{ replace .Name "-" " " | title }}' 331 +++`, 332 }, 333 { 334 path: filepath.Join("archetypes", "product.md"), 335 content: `+++ 336 title = "{{ .BaseFileName | upper }}" 337 +++`, 338 }, 339 { 340 path: filepath.Join("archetypes", "filenames.md"), 341 content: `... 342 title = "{{ .BaseFileName | upper }}" 343 +++ 344 345 346 ContentBaseName: {{ .File.ContentBaseName }} 347 348 `, 349 }, 350 { 351 path: filepath.Join("archetypes", "site.md"), 352 content: `... 353 title = "{{ .BaseFileName | upper }}" 354 +++ 355 356 Len RegularPages .Site: {{ len .Site.RegularPages }} 357 Len RegularPages site: {{ len site.RegularPages }} 358 359 360 `, 361 }, 362 { 363 path: filepath.Join("archetypes", "emptydate.md"), 364 content: "+++\ndate =\"\"\ntitle = \"Empty Date Arch title\"\ntest = \"test1\"\n+++\n", 365 }, 366 { 367 path: filepath.Join("archetypes", "lang.md"), 368 content: `Site Lang: {{ site.Language.Lang }}|Name: {{ replace .Name "-" " " | title }}|i18n: {{ T "hugo" }}`, 369 }, 370 // #3623x 371 { 372 path: filepath.Join("archetypes", "shortcodes.md"), 373 content: `+++ 374 title = "{{ .BaseFileName | upper }}" 375 +++ 376 377 {{< myshortcode >}} 378 379 Some text. 380 381 {{% myshortcode %}} 382 {{</* comment */>}} 383 {{%/* comment */%}} 384 385 386 `, 387 }, 388 } { 389 f, err := fs.Create(v.path) 390 if err != nil { 391 return err 392 } 393 defer f.Close() 394 395 _, err = f.Write([]byte(v.content)) 396 if err != nil { 397 return err 398 } 399 } 400 401 return nil 402 } 403 404 func cContains(c *qt.C, v any, matches ...string) { 405 for _, m := range matches { 406 c.Assert(v, qt.Contains, m) 407 } 408 } 409 410 // TODO(bep) extract common testing package with this and some others 411 func readFileFromFs(t testing.TB, fs afero.Fs, filename string) string { 412 t.Helper() 413 filename = filepath.FromSlash(filename) 414 b, err := afero.ReadFile(fs, filename) 415 if err != nil { 416 // Print some debug info 417 root := strings.Split(filename, helpers.FilePathSeparator)[0] 418 afero.Walk(fs, root, func(path string, info os.FileInfo, err error) error { 419 if info != nil && !info.IsDir() { 420 fmt.Println(" ", path) 421 } 422 423 return nil 424 }) 425 t.Fatalf("Failed to read file: %s", err) 426 } 427 return string(b) 428 } 429 430 func newTestCfg(c *qt.C, mm afero.Fs) (config.Provider, *hugofs.Fs) { 431 cfg := ` 432 433 theme = "mytheme" 434 [languages] 435 [languages.en] 436 weight = 1 437 languageName = "English" 438 [languages.nn] 439 weight = 2 440 languageName = "Nynorsk" 441 442 [module] 443 [[module.mounts]] 444 source = 'archetypes' 445 target = 'archetypes' 446 [[module.mounts]] 447 source = 'content' 448 target = 'content' 449 lang = 'en' 450 [[module.mounts]] 451 source = 'content_nn' 452 target = 'content' 453 lang = 'nn' 454 ` 455 if mm == nil { 456 mm = afero.NewMemMapFs() 457 } 458 459 mm.MkdirAll(filepath.FromSlash("content_nn"), 0o777) 460 461 mm.MkdirAll(filepath.FromSlash("themes/mytheme"), 0o777) 462 463 c.Assert(afero.WriteFile(mm, filepath.Join("i18n", "en.toml"), []byte(`[hugo] 464 other = "Hugo Rocks!"`), 0o755), qt.IsNil) 465 c.Assert(afero.WriteFile(mm, filepath.Join("i18n", "nn.toml"), []byte(`[hugo] 466 other = "Hugo Rokkar!"`), 0o755), qt.IsNil) 467 468 c.Assert(afero.WriteFile(mm, "config.toml", []byte(cfg), 0o755), qt.IsNil) 469 470 res, err := allconfig.LoadConfig(allconfig.ConfigSourceDescriptor{Fs: mm, Filename: "config.toml"}) 471 c.Assert(err, qt.IsNil) 472 473 return res.LoadingInfo.Cfg, hugofs.NewFrom(mm, res.LoadingInfo.BaseConfig) 474 }