From cdb982874fd13c3244b60328202e642b32c7ba86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Tue, 14 May 2024 09:03:43 +0200 Subject: [PATCH] Fix mixed case resource paths --- hugolib/content_map.go | 14 ++++++----- hugolib/page__meta.go | 2 +- .../pagesfromgotmpl_integration_test.go | 19 ++++++++------- resources/page/pagemeta/page_frontmatter.go | 24 +++++++++++++++++-- .../page/pagemeta/page_frontmatter_test.go | 2 +- resources/resource_spec.go | 2 +- 6 files changed, 44 insertions(+), 19 deletions(-) diff --git a/hugolib/content_map.go b/hugolib/content_map.go index d68b0068bac..b75ccdbcb7d 100644 --- a/hugolib/content_map.go +++ b/hugolib/content_map.go @@ -314,9 +314,7 @@ func (m *pageMap) addPagesFromGoTmplFi(fi hugofs.FileMetaInfo, buildConfig *Buil Watching: s.Conf.Watching(), HandlePage: func(pt *pagesfromdata.PagesFromTemplate, pc *pagemeta.PageConfig) error { s := pt.Site.(*Site) - pc.Path = path.Join(pt.GoTmplFi.Meta().PathInfo.Base(), pc.Path) - // TODO1 validate. - if err := pc.Compile(true, "", s.Log, s.conf.MediaTypes.Config); err != nil { + if err := pc.Compile(pt.GoTmplFi.Meta().PathInfo.Base(), true, "", s.Log, s.conf.MediaTypes.Config); err != nil { return err } @@ -352,13 +350,17 @@ func (m *pageMap) addPagesFromGoTmplFi(fi hugofs.FileMetaInfo, buildConfig *Buil }, HandleResource: func(pt *pagesfromdata.PagesFromTemplate, rc *pagemeta.ResourceConfig) error { s := pt.Site.(*Site) - rc.Path = path.Join(pt.GoTmplFi.Meta().PathInfo.Base(), rc.Path) - if err := rc.Compile(s.Conf.PathParser(), s.conf.MediaTypes.Config); err != nil { + if err := rc.Compile( + pt.GoTmplFi.Meta().PathInfo.Base(), + s.Conf.PathParser(), + s.conf.MediaTypes.Config, + ); err != nil { return err } + rs := &resourceSource{path: rc.PathInfo, rc: rc, opener: nil, fi: nil, langIndex: s.languagei} - _, n, replaced := s.pageMap.treeResources.InsertIntoValuesDimensionWithLock(rc.Path, rs) + _, n, replaced := s.pageMap.treeResources.InsertIntoValuesDimensionWithLock(rc.PathInfo.Base(), rs) if h.isRebuild() && replaced { pt.AddChange(n.GetIdentity()) diff --git a/hugolib/page__meta.go b/hugolib/page__meta.go index e28b013a240..fbc1a8aa1d1 100644 --- a/hugolib/page__meta.go +++ b/hugolib/page__meta.go @@ -688,7 +688,7 @@ params: return err } - if err := pcfg.Compile(false, ext, p.s.Log, p.s.conf.MediaTypes.Config); err != nil { + if err := pcfg.Compile("", false, ext, p.s.Log, p.s.conf.MediaTypes.Config); err != nil { return err } diff --git a/hugolib/pagesfromdata/pagesfromgotmpl_integration_test.go b/hugolib/pagesfromdata/pagesfromgotmpl_integration_test.go index b0aff3aa68c..60930321a56 100644 --- a/hugolib/pagesfromdata/pagesfromgotmpl_integration_test.go +++ b/hugolib/pagesfromdata/pagesfromgotmpl_integration_test.go @@ -71,7 +71,7 @@ Pfile Content {{ $contentMarkdown := dict "value" "**Hello World**" "mediaType" "text/markdown" }} {{ $contentMarkdownDefault := dict "value" "**Hello World Default**" }} {{ $contentHTML := dict "value" "Hello World! No **markdown** here." "mediaType" "text/html" }} -{{ $.AddPage (dict "kind" "page" "path" "p1" "title" $title "dates" $dates "content" $contentMarkdown "params" (dict "param1" "param1v" ) ) }} +{{ $.AddPage (dict "kind" "page" "path" "P1" "title" $title "dates" $dates "content" $contentMarkdown "params" (dict "param1" "param1v" ) ) }} {{ $.AddPage (dict "kind" "page" "path" "p2" "title" "p2title" "dates" $dates "content" $contentHTML ) }} {{ $.AddPage (dict "kind" "page" "path" "p3" "title" "p3title" "dates" $dates "content" $contentMarkdownDefault "draft" false ) }} {{ $.AddPage (dict "kind" "page" "path" "p4" "title" "p4title" "dates" $dates "content" $contentMarkdownDefault "draft" $data.draft ) }} @@ -81,15 +81,22 @@ Pfile Content {{ $.AddResource (dict "path" "p1/data1.yaml" "content" $resourceContent) }} {{ $.AddResource (dict "path" "p1/mytext.txt" "content" (dict "value" "some text") "name" "textresource" "title" "My Text Resource" "params" (dict "param1" "param1v") )}} {{ $.AddResource (dict "path" "p1/sub/mytex2.txt" "content" (dict "value" "some text") "title" "My Text Sub Resource" ) }} +{{ $.AddResource (dict "path" "P1/Sub/MyMixCaseText2.txt" "content" (dict "value" "some text") "title" "My Text Sub Mixed Case Path Resource" ) }} {{ $.AddResource (dict "path" "p1/sub/data1.yaml" "content" $resourceContent "title" "Sub data") }} {{ $resourceParams := dict "data2ParaM1" "data2Param1v" }} {{ $.AddResource (dict "path" "p1/data2.yaml" "name" "data2.yaml" "title" "My data 2" "params" $resourceParams "content" $resourceContent) }} {{ $.AddResource (dict "path" "p1/featuredimage.png" "name" "featured.png" "title" "My Featured Image" "params" $resourceParams "content" (dict "value" $pixel ))}} ` -func TestPagesFromGoTmplBasic(t *testing.T) { +func TestPagesFromGoTmplMisc(t *testing.T) { t.Parallel() b := hugolib.Test(t, filesPagesFromDataTempleBasic) + b.AssertPublishDir(` +docs/p1/mytext.txt +docs/p1/sub/mytex2.tx +docs/p1/sub/mymixcasetext2.txt + `) + // Page from markdown file. b.AssertFileContent("public/docs/pfile/index.html", "Dates: Date: 2023-03-01|Lastmod: 2023-03-01|PublishDate: 2023-03-01|ExpiryDate: 0001-01-01|") // Pages from gotmpl. @@ -98,11 +105,12 @@ func TestPagesFromGoTmplBasic(t *testing.T) { "Path: /docs/p1|", "Hello World", "Params: param1v|", - "Len Resources: 6", + "Len Resources: 7", "RelPermalink: /mydata.yaml|Name: data1.yaml|Title: data1.yaml|Params: map[]|", "RelPermalink: /mydata.yaml|Name: data2.yaml|Title: My data 2|Params: map[data2param1:data2Param1v]|", "RelPermalink: /a/pixel.png|Name: featured.png|Title: My Featured Image|Params: map[data2param1:data2Param1v]|", "RelPermalink: /docs/p1/sub/mytex2.txt|Name: sub/mytex2.txt|", + "RelPermalink: /docs/p1/sub/mymixcasetext2.txt|Name: sub/mymixcasetext2.txt|", "RelPermalink: /mydata.yaml|Name: sub/data1.yaml|Title: Sub data|Params: map[]|", "Featured Image: /a/pixel.png|featured.png|", "Resized Featured Image: /a/pixel_hu8aa3346827e49d756ff4e630147c42b5_70_10x10_resize_box_3.png|10|", @@ -113,11 +121,6 @@ func TestPagesFromGoTmplBasic(t *testing.T) { ) b.AssertFileContent("public/docs/p2/index.html", "Single: p2title|", "Hello World! No **markdown** here.") b.AssertFileContent("public/docs/p3/index.html", "Hello World Default") - - b.AssertPublishDir(` - docs/p1/mytext.txt - docs/p1/sub/mytex2.tx - `) } func TestPagesFromGoTmplAsciidocAndSimilar(t *testing.T) { diff --git a/resources/page/pagemeta/page_frontmatter.go b/resources/page/pagemeta/page_frontmatter.go index 8ec61aed0c8..6bf3b8b2ed1 100644 --- a/resources/page/pagemeta/page_frontmatter.go +++ b/resources/page/pagemeta/page_frontmatter.go @@ -16,6 +16,7 @@ package pagemeta import ( "errors" "fmt" + "path" "strings" "time" @@ -147,7 +148,20 @@ func (p *PageConfig) Validate(pagesFromData bool) error { } // Compile sets up the page configuration after all fields have been set. -func (p *PageConfig) Compile(pagesFromData bool, ext string, logger loggers.Logger, mediaTypes media.Types) error { +func (p *PageConfig) Compile(basePath string, pagesFromData bool, ext string, logger loggers.Logger, mediaTypes media.Types) error { + // In content adapters, we always get relative paths. + if basePath != "" { + p.Path = path.Join(basePath, p.Path) + } + + if pagesFromData { + // Note that NormalizePathStringBasic will make sure that we don't preserve the unnormalized path. + // We do that when we create pages from the file system; mostly for backward compatibility, + // but also because people tend to use use the filename to name their resources (with spaces and all), + // and this isn't relevant when creating resources from an API where it's easy to add textual meta data. + p.Path = paths.NormalizePathStringBasic(p.Path) + } + if p.Content.Markup == "" && p.Content.MediaType == "" { if ext == "" { ext = "md" @@ -219,10 +233,16 @@ func (rc *ResourceConfig) Validate() error { return nil } -func (rc *ResourceConfig) Compile(pathParser *paths.PathParser, mediaTypes media.Types) error { +func (rc *ResourceConfig) Compile(basePath string, pathParser *paths.PathParser, mediaTypes media.Types) error { if rc.Params != nil { maps.PrepareParams(rc.Params) } + + // Note that NormalizePathStringBasic will make sure that we don't preserve the unnormalized path. + // We do that when we create resources from the file system; mostly for backward compatibility, + // but also because people tend to use use the filename to name their resources (with spaces and all), + // and this isn't relevant when creating resources from an API where it's easy to add textual meta data. + rc.Path = paths.NormalizePathStringBasic(path.Join(basePath, rc.Path)) rc.PathInfo = pathParser.Parse(files.ComponentFolderContent, rc.Path) if rc.Content.MediaType != "" { var found bool diff --git a/resources/page/pagemeta/page_frontmatter_test.go b/resources/page/pagemeta/page_frontmatter_test.go index c3f5cbd7098..18f9e5aa177 100644 --- a/resources/page/pagemeta/page_frontmatter_test.go +++ b/resources/page/pagemeta/page_frontmatter_test.go @@ -175,7 +175,7 @@ func TestContentMediaTypeFromMarkup(t *testing.T) { } { var pc pagemeta.PageConfig pc.Content.Markup = test.in - c.Assert(pc.Compile(true, "", logger, media.DefaultTypes), qt.IsNil) + c.Assert(pc.Compile("", true, "", logger, media.DefaultTypes), qt.IsNil) c.Assert(pc.ContentMediaType.Type, qt.Equals, test.expected) } } diff --git a/resources/resource_spec.go b/resources/resource_spec.go index 08d405e5587..4ec8f21d570 100644 --- a/resources/resource_spec.go +++ b/resources/resource_spec.go @@ -151,7 +151,7 @@ func (r *Spec) NewResourceWrapperFromResourceConfig(rc *pagemeta.ResourceConfig) case resource.Resource: return cloneWithMetadataFromResourceConfigIfNeeded(rc, r), nil default: - return nil, fmt.Errorf("failed to create resource for path %q, expected a resource.Resource, got %T", rc.Path, content.Value) + return nil, fmt.Errorf("failed to create resource for path %q, expected a resource.Resource, got %T", rc.PathInfo.Path(), content.Value) } }