Skip to content

Commit

Permalink
resources: Create a ResourceFinder interface
Browse files Browse the repository at this point in the history
And make both .Resources and resources implement it.

Fixes gohugoio#8653
  • Loading branch information
bep committed Oct 20, 2021
1 parent 471ed91 commit 2fe4d97
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 18 deletions.
6 changes: 4 additions & 2 deletions hugolib/hugo_sites_build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,9 @@ func doTestMultiSitesBuild(t *testing.T, configTemplate, configSuffix string) {
bundleFr := frSite.getPage(page.KindPage, "bundles/b1/index.md")
c.Assert(bundleFr, qt.Not(qt.IsNil))
c.Assert(len(bundleFr.Resources()), qt.Equals, 1)
logoFr := bundleFr.Resources().GetMatch("logo*")
logoFr, _ := bundleFr.Resources().GetMatch("logo*")
logoFrGet, _ := bundleFr.Resources().Get("logo.png")
c.Assert(logoFrGet, qt.Equals, logoFr)
c.Assert(logoFr, qt.Not(qt.IsNil))
b.AssertFileContent("public/fr/bundles/b1/index.html", "Resources: image/png: /blog/fr/bundles/b1/logo.png")
b.AssertFileContent("public/fr/bundles/b1/logo.png", "PNG Data")
Expand All @@ -405,7 +407,7 @@ func doTestMultiSitesBuild(t *testing.T, configTemplate, configSuffix string) {
c.Assert(bundleEn, qt.Not(qt.IsNil))
b.AssertFileContent("public/en/bundles/b1/index.html", "RelPermalink: /blog/en/bundles/b1/|")
c.Assert(len(bundleEn.Resources()), qt.Equals, 1)
logoEn := bundleEn.Resources().GetMatch("logo*")
logoEn, _ := bundleEn.Resources().GetMatch("logo*")
c.Assert(logoEn, qt.Not(qt.IsNil))
b.AssertFileContent("public/en/bundles/b1/index.html", "Resources: image/png: /blog/en/bundles/b1/logo.png")
b.AssertFileContent("public/en/bundles/b1/logo.png", "PNG Data")
Expand Down
25 changes: 18 additions & 7 deletions hugolib/pagebundler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import (
"strings"
"testing"

"github.com/gohugoio/hugo/resources/resource"

"github.com/gohugoio/hugo/config"

"github.com/gohugoio/hugo/hugofs/files"
Expand Down Expand Up @@ -184,9 +186,17 @@ func TestPageBundlerSiteRegular(t *testing.T) {
c.Assert(firstPage.Parent(), qt.Equals, leafBundle1)
c.Assert(secondPage.Parent(), qt.Equals, leafBundle1)

c.Assert(pageResources.GetMatch("1*"), qt.Equals, firstPage)
c.Assert(pageResources.GetMatch("2*"), qt.Equals, secondPage)
c.Assert(pageResources.GetMatch("doesnotexist*"), qt.IsNil)
mustGetMatch := func(r resource.Resources, pattern string) resource.Resource {
res, err := r.GetMatch(pattern)
if err != nil {
panic(err)
}
return res
}

c.Assert(mustGetMatch(pageResources, "1*"), qt.Equals, firstPage)
c.Assert(mustGetMatch(pageResources, "2*"), qt.Equals, secondPage)
c.Assert(mustGetMatch(pageResources, "doesnotexist*"), qt.IsNil)

imageResources := leafBundle1.Resources().ByType("image")
c.Assert(len(imageResources), qt.Equals, 3)
Expand Down Expand Up @@ -327,9 +337,9 @@ func TestPageBundlerSiteMultilingual(t *testing.T) {

// See https://github.com/gohugoio/hugo/issues/4295
// Every resource should have its Name prefixed with its base folder.
cBundleResources := bundleWithSubPath.Resources().Match("c/**")
cBundleResources, _ := bundleWithSubPath.Resources().Match("c/**")
c.Assert(len(cBundleResources), qt.Equals, 4)
bundlePage := bundleWithSubPath.Resources().GetMatch("c/page*")
bundlePage, _ := bundleWithSubPath.Resources().GetMatch("c/page*")
c.Assert(bundlePage, qt.Not(qt.IsNil))

bcBundleNN, _ := nnSite.getPageNew(nil, "bc")
Expand Down Expand Up @@ -553,8 +563,9 @@ HEADLESS {{< myShort >}}

headlessResources := headless.Resources()
c.Assert(len(headlessResources), qt.Equals, 3)
c.Assert(len(headlessResources.Match("l*")), qt.Equals, 2)
pageResource := headlessResources.GetMatch("p*")
res, _ := headlessResources.Match("l*")
c.Assert(len(res), qt.Equals, 2)
pageResource, _ := headlessResources.GetMatch("p*")
c.Assert(pageResource, qt.Not(qt.IsNil))
p := pageResource.(page.Page)
c.Assert(content(p), qt.Contains, "SHORTCODE")
Expand Down
79 changes: 70 additions & 9 deletions resources/resource/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,16 @@ import (
"strings"

"github.com/gohugoio/hugo/hugofs/glob"
"github.com/spf13/cast"
)

var _ ResourceFinder = (*Resources)(nil)

// Resources represents a slice of resources, which can be a mix of different types.
// I.e. both pages and images etc.
type Resources []Resource

// var _ resource.ResourceFinder = (*Namespace)(nil)
// ResourcesConverter converts a given slice of Resource objects to Resources.
type ResourcesConverter interface {
ToResources() Resources
Expand All @@ -41,21 +45,42 @@ func (r Resources) ByType(tp string) Resources {
return filtered
}

// Get locates the name given in Resources.
// The search is case insensitive.
func (r Resources) Get(name interface{}) (Resource, error) {
namestr, err := cast.ToStringE(name)
if err != nil {
return nil, err
}
namestr = strings.ToLower(namestr)
for _, resource := range r {
if strings.EqualFold(namestr, resource.Name()) {
return resource, nil
}
}
return nil, nil
}

// GetMatch finds the first Resource matching the given pattern, or nil if none found.
// See Match for a more complete explanation about the rules used.
func (r Resources) GetMatch(pattern string) Resource {
g, err := glob.GetGlob(pattern)
func (r Resources) GetMatch(pattern interface{}) (Resource, error) {
patternstr, err := cast.ToStringE(pattern)
if err != nil {
return nil
return nil, err
}

g, err := glob.GetGlob(patternstr)
if err != nil {
return nil, err
}

for _, resource := range r {
if g.Match(strings.ToLower(resource.Name())) {
return resource
return resource, nil
}
}

return nil
return nil, nil
}

// Match gets all resources matching the given base filename prefix, e.g
Expand All @@ -67,10 +92,15 @@ func (r Resources) GetMatch(pattern string) Resource {
// Match matches by using the value of Resource.Name, which, by default, is a filename with
// path relative to the bundle root with Unix style slashes (/) and no leading slash, e.g. "images/logo.png".
// See https://github.com/gobwas/glob for the full rules set.
func (r Resources) Match(pattern string) Resources {
g, err := glob.GetGlob(pattern)
func (r Resources) Match(pattern interface{}) (Resources, error) {
patternstr, err := cast.ToStringE(pattern)
if err != nil {
return nil, err
}

g, err := glob.GetGlob(patternstr)
if err != nil {
return nil
return nil, err
}

var matches Resources
Expand All @@ -79,7 +109,7 @@ func (r Resources) Match(pattern string) Resources {
matches = append(matches, resource)
}
}
return matches
return matches, nil
}

type translatedResource interface {
Expand Down Expand Up @@ -121,3 +151,34 @@ func (r Resources) MergeByLanguageInterface(in interface{}) (interface{}, error)
type Source interface {
Publish() error
}

// ResourceFinder provides method to find Resources.
type ResourceFinder interface {

// Get locates the filename given in Hugo's assets filesystem
// and creates a Resource object that can be used for further transformations.
Get(filename interface{}) (Resource, error)

// GetMatch finds the first Resource matching the given pattern, or nil if none found.
//
// See Match for a more complete explanation about the rules used.
GetMatch(pattern interface{}) (Resource, error)

// Match gets all resources matching the given base path prefix, e.g
// "*.png" will match all png files. The "*" does not match path delimiters (/),
// so if you organize your resources in sub-folders, you need to be explicit about it, e.g.:
// "images/*.png". To match any PNG image anywhere in the bundle you can do "**.png", and
// to match all PNG images below the images folder, use "images/**.jpg".
//
// The matching is case insensitive.
//
// Match matches by using a relative pathwith Unix style slashes (/) and no
// leading slash, e.g. "images/logo.png".
//
// See https://github.com/gobwas/glob for the full rules set.
//
// It looks for files in the assets file system.
//
// See Match for a more complete explanation about the rules used.
Match(pattern interface{}) (Resources, error)
}
2 changes: 2 additions & 0 deletions tpl/resources/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ func New(deps *deps.Deps) (*Namespace, error) {
}, nil
}

var _ resource.ResourceFinder = (*Namespace)(nil)

// Namespace provides template functions for the "resources" namespace.
type Namespace struct {
deps *deps.Deps
Expand Down

0 comments on commit 2fe4d97

Please sign in to comment.