Improve type support in resources.Concat
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Thu, 12 Jul 2018 09:26:51 +0000 (11:26 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Thu, 12 Jul 2018 11:43:27 +0000 (13:43 +0200)
This allows the result of `.Resources.Match` and similar to be concatenated.

Fixes #4934

hugolib/resource_chain_test.go
resource/bundler/bundler.go
tpl/resources/resources.go

index b836ef0b7b4644e1e538ba942a0ba8da6e251d50..b49e1ee72572de8d7086aa9bd78a27f556f087b9 100644 (file)
@@ -80,14 +80,21 @@ Min HTML: {{ ( resources.Get "mydata/html1.html" | resources.Minify ).Content |
 {{ $a := "A" | resources.FromString "a.txt"}}
 {{ $b := "B" | resources.FromString "b.txt"}}
 {{ $c := "C" | resources.FromString "c.txt"}}
+{{ $textResources := .Resources.Match "*.txt" }}
 {{ $combined := slice $a $b $c | resources.Concat "bundle/concat.txt" }}
-T: Content: {{ $combined.Content }}|RelPermalink: {{ $combined.RelPermalink }}|Permalink: {{ $combined.Permalink }}|MediaType: {{ $combined.MediaType.Type }}
+T1: Content: {{ $combined.Content }}|RelPermalink: {{ $combined.RelPermalink }}|Permalink: {{ $combined.Permalink }}|MediaType: {{ $combined.MediaType.Type }}
+{{ with $textResources }}
+{{ $combinedText := . | resources.Concat "bundle/concattxt.txt" }}
+T2: Content: {{ $combinedText.Content }}|{{ $combinedText.RelPermalink }}
+{{ end }}
 `)
                }, func(b *sitesBuilder) {
-                       b.AssertFileContent("public/index.html", `T: Content: ABC|RelPermalink: /bundle/concat.txt|Permalink: http://example.com/bundle/concat.txt|MediaType: text/plain`)
+                       b.AssertFileContent("public/index.html", `T1: Content: ABC|RelPermalink: /bundle/concat.txt|Permalink: http://example.com/bundle/concat.txt|MediaType: text/plain`)
                        b.AssertFileContent("public/bundle/concat.txt", "ABC")
-               }},
 
+                       b.AssertFileContent("public/index.html", `T2: Content: t1t|t2t|`)
+                       b.AssertFileContent("public/bundle/concattxt.txt", "t1t|t2t|")
+               }},
                {"fromstring", func() bool { return true }, func(b *sitesBuilder) {
                        b.WithTemplates("home.html", `
 {{ $r := "Hugo Rocks!" | resources.FromString "rocks/hugo.txt" }}
@@ -137,12 +144,31 @@ T3: {{ $resultMD5.Content }}|{{ $resultMD5.RelPermalink}}|{{$resultMD5.MediaType
 
                b := newTestSitesBuilder(t).WithLogger(loggers.NewWarningLogger())
                b.WithSimpleConfigFile()
-               b.WithContent("page.md", `
+               b.WithContent("_index.md", `
 ---
-title: Hello
+title: Home
 ---
 
-`)
+Home.
+
+`,
+                       "page1.md", `
+---
+title: Hello1
+---
+
+Hello1
+`,
+                       "page2.md", `
+---
+title: Hello2
+---
+
+Hello2
+`,
+                       "t1.txt", "t1t|",
+                       "t2.txt", "t2t|",
+               )
 
                b.WithSourceFile(filepath.Join("assets", "css", "styles1.css"), `
 h1 {
index a86b39efa0e66d2aefc75516be460e3b673b700a..b9cd718dbe058187176f9fc5ba7af1b6518417be 100644 (file)
@@ -62,7 +62,7 @@ func (r *multiReadSeekCloser) Close() error {
 }
 
 // Concat concatenates the list of Resource objects.
-func (c *Client) Concat(targetPath string, resources []resource.Resource) (resource.Resource, error) {
+func (c *Client) Concat(targetPath string, resources resource.Resources) (resource.Resource, error) {
        // The CACHE_OTHER will make sure this will be re-created and published on rebuilds.
        return c.rs.ResourceCache.GetOrCreate(resource.CACHE_OTHER, targetPath, func() (resource.Resource, error) {
                var resolvedm media.Type
index 5d4f6e3156b9b01ae08a54fab4f150a1b090df08..c9d3275e5966ba1214acf1ccb535c91afb9ad88c 100644 (file)
@@ -79,19 +79,38 @@ func (ns *Namespace) Get(filename interface{}) (resource.Resource, error) {
 
 // Concat concatenates a slice of Resource objects. These resources must
 // (currently) be of the same Media Type.
-func (ns *Namespace) Concat(targetPathIn interface{}, r []interface{}) (resource.Resource, error) {
+func (ns *Namespace) Concat(targetPathIn interface{}, r interface{}) (resource.Resource, error) {
        targetPath, err := cast.ToStringE(targetPathIn)
        if err != nil {
                return nil, err
        }
-       rr := make([]resource.Resource, len(r))
-       for i := 0; i < len(r); i++ {
-               rv, ok := r[i].(resource.Resource)
-               if !ok {
-                       return nil, fmt.Errorf("cannot concat type %T", rv)
+
+       var rr resource.Resources
+
+       switch v := r.(type) {
+       // This is what we get from the slice func.
+       case []interface{}:
+               rr = make([]resource.Resource, len(v))
+               for i := 0; i < len(v); i++ {
+                       rv, ok := v[i].(resource.Resource)
+                       if !ok {
+                               return nil, fmt.Errorf("cannot concat type %T", v[i])
+                       }
+                       rr[i] = rv
                }
-               rr[i] = rv
+       // This is what we get from .Resources.Match etc.
+       case resource.Resources:
+               rr = v
+       default:
+               // We may support Page collections at one point, but we need to think about ...
+               // what to acutually concatenate.
+               return nil, fmt.Errorf("slice %T not supported in concat", r)
        }
+
+       if len(rr) == 0 {
+               return nil, errors.New("must provide one or more Resource objects to concat")
+       }
+
        return ns.bundlerClient.Concat(targetPath, rr)
 }