From 4eb2fec67c3a72a3ac98aa834dc56fd4504626d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Sat, 27 Jan 2018 18:03:06 +0100 Subject: [PATCH] Fix handling of top-level page bundles Fixes #4332 --- create/content_template_handler.go | 2 +- hugolib/fileInfo.go | 2 +- hugolib/page.go | 14 ++++-- hugolib/page_bundler_capture_test.go | 5 ++- hugolib/page_bundler_test.go | 66 ++++++++++++++++++---------- source/fileInfo.go | 17 ++++--- source/fileInfo_test.go | 7 ++- source/filesystem.go | 2 +- 8 files changed, 75 insertions(+), 40 deletions(-) diff --git a/create/content_template_handler.go b/create/content_template_handler.go index 0a444abf6..3b1f850c5 100644 --- a/create/content_template_handler.go +++ b/create/content_template_handler.go @@ -82,7 +82,7 @@ func executeArcheTypeAsTemplate(s *hugolib.Site, kind, targetPath, archetypeFile ) sp := source.NewSourceSpec(s.Deps.Cfg, s.Deps.Fs) - f := sp.NewFileInfo("", targetPath, nil) + f := sp.NewFileInfo("", targetPath, false, nil) data := ArchetypeFileData{ Type: kind, diff --git a/hugolib/fileInfo.go b/hugolib/fileInfo.go index b146aede9..f819f6bfc 100644 --- a/hugolib/fileInfo.go +++ b/hugolib/fileInfo.go @@ -57,7 +57,7 @@ func (fi *fileInfo) isContentFile() bool { func newFileInfo(sp *source.SourceSpec, baseDir, filename string, fi os.FileInfo, tp bundleDirType) *fileInfo { - baseFi := sp.NewFileInfo(baseDir, filename, fi) + baseFi := sp.NewFileInfo(baseDir, filename, tp == bundleLeaf, fi) f := &fileInfo{ bundleTp: tp, ReadableFile: baseFi, diff --git a/hugolib/page.go b/hugolib/page.go index b7afc5065..fd6278bb4 100644 --- a/hugolib/page.go +++ b/hugolib/page.go @@ -772,7 +772,7 @@ func (s *Site) newPageFromFile(fi *fileInfo) *Page { Keywords: []string{}, Sitemap: Sitemap{Priority: -1}, params: make(map[string]interface{}), translations: make(Pages, 0), - sections: sectionsFromDir(fi.Dir()), + sections: sectionsFromFile(fi), Site: &s.Info, s: s, } @@ -2000,12 +2000,20 @@ func (p *Page) addLangPathPrefixIfFlagSet(outfile string, should bool) string { return outfile } -func sectionsFromDir(dirname string) []string { +func sectionsFromFile(fi *fileInfo) []string { + dirname := fi.Dir() dirname = strings.Trim(dirname, helpers.FilePathSeparator) if dirname == "" { return nil } - return strings.Split(dirname, helpers.FilePathSeparator) + parts := strings.Split(dirname, helpers.FilePathSeparator) + + if fi.bundleTp == bundleLeaf && len(parts) > 0 { + // my-section/mybundle/index.md => my-section + return parts[:len(parts)-1] + } + + return parts } func kindFromFileInfo(fi *fileInfo) string { diff --git a/hugolib/page_bundler_capture_test.go b/hugolib/page_bundler_capture_test.go index a7a7054b4..3f9a57146 100644 --- a/hugolib/page_bundler_capture_test.go +++ b/hugolib/page_bundler_capture_test.go @@ -143,8 +143,9 @@ F: D: __bundle/en/work/base/_index.md/resources/en/work/base/_1.png __bundle/en/work/base/a/b/index.md/resources/en/work/base/a/b/ab1.md -__bundle/en/work/base/b/index.md/resources/en/work/base/b/1.md|en/work/base/b/2.md|en/work/base/b/c/logo.png|en/work/base/b/custom-mime.bep|en/work/base/b/sunset1.jpg|en/work/base/b/sunset2.jpg -__bundle/en/work/base/c/index.md/resources/en/work/base/c/logo-은행.png +__bundle/en/work/base/b/my-bundle/index.md/resources/en/work/base/b/my-bundle/1.md|en/work/base/b/my-bundle/2.md|en/work/base/b/my-bundle/c/logo.png|en/work/base/b/my-bundle/custom-mime.bep|en/work/base/b/my-bundle/sunset1.jpg|en/work/base/b/my-bundle/sunset2.jpg +__bundle/en/work/base/c/bundle/index.md/resources/en/work/base/c/bundle/logo-은행.png +__bundle/en/work/base/root/index.md/resources/en/work/base/root/1.md|en/work/base/root/c/logo.png C: /work/base/assets/pic1.png /work/base/assets/pic2.png diff --git a/hugolib/page_bundler_test.go b/hugolib/page_bundler_test.go index cef1e0239..0344cf024 100644 --- a/hugolib/page_bundler_test.go +++ b/hugolib/page_bundler_test.go @@ -52,6 +52,7 @@ func TestPageBundlerSite(t *testing.T) { "a": ":sections/:filename", "b": ":year/:slug/", "c": ":sections/:slug", + "": ":filename/", }) cfg.Set("outputFormats", map[string]interface{}{ @@ -74,8 +75,7 @@ func TestPageBundlerSite(t *testing.T) { th := testHelper{s.Cfg, s.Fs, t} - // Singles (2), Below home (1), Bundle (1) - assert.Len(s.RegularPages, 7) + assert.Len(s.RegularPages, 8) singlePage := s.getPage(KindPage, "a/1.md") @@ -99,33 +99,47 @@ func TestPageBundlerSite(t *testing.T) { // This should be just copied to destination. th.assertFileContent(filepath.FromSlash("/work/public/assets/pic1.png"), "content") - leafBundle1 := s.getPage(KindPage, "b/index.md") + leafBundle1 := s.getPage(KindPage, "b/my-bundle/index.md") assert.NotNil(leafBundle1) + assert.Equal("b", leafBundle1.Section()) + assert.NotNil(s.getPage(KindSection, "b")) + + // This is a root bundle and should live in the "home section" + // See https://github.com/gohugoio/hugo/issues/4332 + rootBundle := s.getPage(KindPage, "root") + assert.NotNil(rootBundle) + assert.True(rootBundle.Parent().IsHome()) + if ugly { + assert.Equal("/root.html", rootBundle.RelPermalink()) + } else { + assert.Equal("/root/", rootBundle.RelPermalink()) + } + leafBundle2 := s.getPage(KindPage, "a/b/index.md") assert.NotNil(leafBundle2) - unicodeBundle := s.getPage(KindPage, "c/index.md") + unicodeBundle := s.getPage(KindPage, "c/bundle/index.md") assert.NotNil(unicodeBundle) pageResources := leafBundle1.Resources.ByType(pageResourceType) assert.Len(pageResources, 2) firstPage := pageResources[0].(*Page) secondPage := pageResources[1].(*Page) - assert.Equal(filepath.FromSlash("b/1.md"), firstPage.pathOrTitle(), secondPage.pathOrTitle()) + assert.Equal(filepath.FromSlash("b/my-bundle/1.md"), firstPage.pathOrTitle(), secondPage.pathOrTitle()) assert.Contains(firstPage.Content, "TheContent") - assert.Len(leafBundle1.Resources, 6) // 2 pages 3 images 1 custom mime type + assert.Equal(6, len(leafBundle1.Resources)) assert.Equal(firstPage, pageResources.GetByPrefix("1")) assert.Equal(secondPage, pageResources.GetByPrefix("2")) assert.Nil(pageResources.GetByPrefix("doesnotexist")) imageResources := leafBundle1.Resources.ByType("image") - assert.Len(imageResources, 3) + assert.Equal(3, len(imageResources)) image := imageResources[0] altFormat := leafBundle1.OutputFormats().Get("CUSTOMO") assert.NotNil(altFormat) - assert.Equal(filepath.FromSlash("/work/base/b/c/logo.png"), image.(resource.Source).AbsSourceFilename()) + assert.Equal(filepath.FromSlash("/work/base/b/my-bundle/c/logo.png"), image.(resource.Source).AbsSourceFilename()) assert.Equal("https://example.com/2017/pageslug/c/logo.png", image.Permalink()) th.assertFileContent(filepath.FromSlash("/work/public/2017/pageslug/c/logo.png"), "content") th.assertFileContent(filepath.FromSlash("/work/public/cpath/2017/pageslug/c/logo.png"), "content") @@ -161,6 +175,8 @@ func TestPageBundlerSite(t *testing.T) { assert.Equal("/2017/pageslug/", leafBundle1.RelPermalink()) th.assertFileContent(filepath.FromSlash("/work/public/2017/pageslug/index.html"), "TheContent") th.assertFileContent(filepath.FromSlash("/work/public/cpath/2017/pageslug/cindex.html"), "TheContent") + th.assertFileContent(filepath.FromSlash("/work/public/2017/pageslug/index.html"), "Single Title") + th.assertFileContent(filepath.FromSlash("/work/public/root/index.html"), "Single Title") assert.Equal("/a/b/", leafBundle2.RelPermalink()) @@ -193,8 +209,8 @@ func TestPageBundlerSiteMultilingual(t *testing.T) { s := sites.Sites[0] assert.Equal(8, len(s.RegularPages)) - assert.Equal(18, len(s.Pages)) - assert.Equal(35, len(s.AllPages)) + assert.Equal(16, len(s.Pages)) + assert.Equal(31, len(s.AllPages)) bundleWithSubPath := s.getPage(KindPage, "lb/index") assert.NotNil(bundleWithSubPath) @@ -269,9 +285,9 @@ func TestMultilingualDisableLanguage(t *testing.T) { s := sites.Sites[0] assert.Equal(8, len(s.RegularPages)) - assert.Equal(18, len(s.Pages)) + assert.Equal(16, len(s.Pages)) // No nn pages - assert.Equal(18, len(s.AllPages)) + assert.Equal(16, len(s.AllPages)) for _, p := range s.rawAllPages { assert.True(p.Lang() != "nn") } @@ -431,7 +447,7 @@ TheContent. ` singleLayout := ` -Title: {{ .Title }} +Single Title: {{ .Title }} Content: {{ .Content }} {{ $sunset := .Resources.GetByPrefix "my-sunset-1" }} {{ with $sunset }} @@ -482,15 +498,15 @@ Short Thumb Width: {{ $thumb.Width }} writeSource(t, fs, filepath.Join(workDir, "base", "assets", "pages", "mypage.md"), pageContent) // Bundle - writeSource(t, fs, filepath.Join(workDir, "base", "b", "index.md"), pageWithImageShortcodeAndResourceMetadataContent) - writeSource(t, fs, filepath.Join(workDir, "base", "b", "1.md"), pageContent) - writeSource(t, fs, filepath.Join(workDir, "base", "b", "2.md"), pageContent) - writeSource(t, fs, filepath.Join(workDir, "base", "b", "custom-mime.bep"), "bepsays") - writeSource(t, fs, filepath.Join(workDir, "base", "b", "c", "logo.png"), "content") + writeSource(t, fs, filepath.Join(workDir, "base", "b", "my-bundle", "index.md"), pageWithImageShortcodeAndResourceMetadataContent) + writeSource(t, fs, filepath.Join(workDir, "base", "b", "my-bundle", "1.md"), pageContent) + writeSource(t, fs, filepath.Join(workDir, "base", "b", "my-bundle", "2.md"), pageContent) + writeSource(t, fs, filepath.Join(workDir, "base", "b", "my-bundle", "custom-mime.bep"), "bepsays") + writeSource(t, fs, filepath.Join(workDir, "base", "b", "my-bundle", "c", "logo.png"), "content") // Bundle with 은행 slug // See https://github.com/gohugoio/hugo/issues/4241 - writeSource(t, fs, filepath.Join(workDir, "base", "c", "index.md"), `--- + writeSource(t, fs, filepath.Join(workDir, "base", "c", "bundle", "index.md"), `--- title: "은행 은행" slug: 은행 date: 2017-10-09 @@ -498,16 +514,22 @@ date: 2017-10-09 Content for 은행. `) - writeSource(t, fs, filepath.Join(workDir, "base", "c", "logo-은행.png"), "은행 PNG") + + // Bundle in root + writeSource(t, fs, filepath.Join(workDir, "base", "root", "index.md"), pageWithImageShortcodeAndResourceMetadataContent) + writeSource(t, fs, filepath.Join(workDir, "base", "root", "1.md"), pageContent) + writeSource(t, fs, filepath.Join(workDir, "base", "root", "c", "logo.png"), "content") + + writeSource(t, fs, filepath.Join(workDir, "base", "c", "bundle", "logo-은행.png"), "은행 PNG") // Write a real image into one of the bundle above. src, err := os.Open("testdata/sunset.jpg") assert.NoError(err) // We need 2 to test https://github.com/gohugoio/hugo/issues/4202 - out, err := fs.Source.Create(filepath.Join(workDir, "base", "b", "sunset1.jpg")) + out, err := fs.Source.Create(filepath.Join(workDir, "base", "b", "my-bundle", "sunset1.jpg")) assert.NoError(err) - out2, err := fs.Source.Create(filepath.Join(workDir, "base", "b", "sunset2.jpg")) + out2, err := fs.Source.Create(filepath.Join(workDir, "base", "b", "my-bundle", "sunset2.jpg")) assert.NoError(err) _, err = io.Copy(out, src) diff --git a/source/fileInfo.go b/source/fileInfo.go index a20ba27e5..eb7015aa1 100644 --- a/source/fileInfo.go +++ b/source/fileInfo.go @@ -54,6 +54,7 @@ type File interface { LogicalName() string // Section is first directory below the content root. + // For page bundles in root, the Section will be empty. Section() string // BaseFileName is a filename without extension. @@ -99,6 +100,7 @@ type FileInfo struct { baseName string translationBaseName string section string + isLeafBundle bool uniqueID string @@ -142,16 +144,12 @@ func (fi *FileInfo) String() string { return fi.BaseFileName() } // in some cases that is slightly expensive to construct. func (fi *FileInfo) init() { fi.lazyInit.Do(func() { - parts := strings.Split(fi.relDir, helpers.FilePathSeparator) + relDir := strings.Trim(fi.relDir, helpers.FilePathSeparator) + parts := strings.Split(relDir, helpers.FilePathSeparator) + var section string - if len(parts) == 1 { + if (!fi.isLeafBundle && len(parts) == 1) || len(parts) > 1 { section = parts[0] - } else if len(parts) > 1 { - if parts[0] == "" { - section = parts[1] - } else { - section = parts[0] - } } fi.section = section @@ -161,7 +159,7 @@ func (fi *FileInfo) init() { }) } -func (sp *SourceSpec) NewFileInfo(baseDir, filename string, fi os.FileInfo) *FileInfo { +func (sp *SourceSpec) NewFileInfo(baseDir, filename string, isLeafBundle bool, fi os.FileInfo) *FileInfo { dir, name := filepath.Split(filename) if !strings.HasSuffix(dir, helpers.FilePathSeparator) { @@ -204,6 +202,7 @@ func (sp *SourceSpec) NewFileInfo(baseDir, filename string, fi os.FileInfo) *Fil name: name, baseName: baseName, translationBaseName: translationBaseName, + isLeafBundle: isLeafBundle, } return f diff --git a/source/fileInfo_test.go b/source/fileInfo_test.go index 8ce8c16ef..1b9b130e4 100644 --- a/source/fileInfo_test.go +++ b/source/fileInfo_test.go @@ -34,10 +34,15 @@ func TestFileInfo(t *testing.T) { assert.Equal(filepath.FromSlash("/a/b/page.md"), f.Filename()) assert.Equal(filepath.FromSlash("b/"), f.Dir()) assert.Equal(filepath.FromSlash("b/page.md"), f.Path()) + assert.Equal("b", f.Section()) + + }}, + {filepath.FromSlash("/a/"), filepath.FromSlash("/a/b/c/d/page.md"), func(f *FileInfo) { + assert.Equal("b", f.Section()) }}, } { - f := s.NewFileInfo(this.base, this.filename, nil) + f := s.NewFileInfo(this.base, this.filename, false, nil) this.assert(f) } diff --git a/source/filesystem.go b/source/filesystem.go index a5f2988e9..db004d3a1 100644 --- a/source/filesystem.go +++ b/source/filesystem.go @@ -57,7 +57,7 @@ func (f *Filesystem) add(name string, fi os.FileInfo) (err error) { name = norm.NFC.String(name) } - file = f.SourceSpec.NewFileInfo(f.Base, name, fi) + file = f.SourceSpec.NewFileInfo(f.Base, name, false, fi) f.files = append(f.files, file) return err