resource: Start Resources :counter first time they're used
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sat, 27 Jan 2018 09:22:42 +0000 (10:22 +0100)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sat, 27 Jan 2018 09:22:42 +0000 (10:22 +0100)
This is less surprising and more flexible than the original implementation.

Given:

```toml
[[resources]]
  src = "documents/photo_specs.pdf"
  title = "Photo Specifications"
[[resources]]
  src = "**.pdf"
  name = "pdf-file-:counter"
```

Every `pdf` in the bundle will have an unique counter, but the `photo_specs.pdf` is still allowed to have its specific `title`.

If you change the above example to:

```toml
[[resources]]
  src = "documents/*specs.pdf"
  title = "Photo Specifications #:conter"
[[resources]]
  src = "**.pdf"
  name = "pdf-file-:counter"
```

We are talking about two different groups of documents, each with its own counters starting at 1.

Fixes #4335

resource/resource.go
resource/resource_test.go

index 2e5c8011af280ed8e21e26d8a8903a2a4bc31084..dfda1ae7a901cb5a63959ed3722755cedc0ce317 100644 (file)
@@ -447,6 +447,8 @@ func (l *genericResource) Publish() error {
        return helpers.WriteToDisk(target, f, l.spec.Fs.Destination)
 }
 
+const counterPlaceHolder = ":counter"
+
 // AssignMetadata assigns the given metadata to those resources that supports updates
 // and matching by wildcard given in `src` using `filepath.Match` with lower cased values.
 // This assignment is additive, but the most specific match needs to be first.
@@ -464,6 +466,7 @@ func AssignMetadata(metadata []map[string]interface{}, resources ...Resource) er
                var (
                        nameSet, titleSet bool
                        currentCounter    = 0
+                       counterFound      bool
                        resourceSrcKey    = strings.ToLower(r.Name())
                )
 
@@ -487,12 +490,16 @@ func AssignMetadata(metadata []map[string]interface{}, resources ...Resource) er
                                if !nameSet {
                                        name, found := meta["name"]
                                        if found {
-                                               if currentCounter == 0 {
+                                               name := cast.ToString(name)
+                                               if !counterFound {
+                                                       counterFound = strings.Contains(name, counterPlaceHolder)
+                                               }
+                                               if counterFound && currentCounter == 0 {
                                                        currentCounter = counters[srcKey] + 1
                                                        counters[srcKey] = currentCounter
                                                }
 
-                                               ma.setName(replaceResourcePlaceholders(cast.ToString(name), currentCounter))
+                                               ma.setName(replaceResourcePlaceholders(name, currentCounter))
                                                nameSet = true
                                        }
                                }
@@ -500,11 +507,15 @@ func AssignMetadata(metadata []map[string]interface{}, resources ...Resource) er
                                if !titleSet {
                                        title, found := meta["title"]
                                        if found {
-                                               if currentCounter == 0 {
+                                               title := cast.ToString(title)
+                                               if !counterFound {
+                                                       counterFound = strings.Contains(title, counterPlaceHolder)
+                                               }
+                                               if counterFound && currentCounter == 0 {
                                                        currentCounter = counters[srcKey] + 1
                                                        counters[srcKey] = currentCounter
                                                }
-                                               ma.setTitle((replaceResourcePlaceholders(cast.ToString(title), currentCounter)))
+                                               ma.setTitle((replaceResourcePlaceholders(title, currentCounter)))
                                                titleSet = true
                                        }
                                }
@@ -524,7 +535,7 @@ func AssignMetadata(metadata []map[string]interface{}, resources ...Resource) er
 }
 
 func replaceResourcePlaceholders(in string, counter int) string {
-       return strings.Replace(in, ":counter", strconv.Itoa(counter), -1)
+       return strings.Replace(in, counterPlaceHolder, strconv.Itoa(counter), -1)
 }
 
 func (l *genericResource) target() string {
index 54d200c1c58eff572a7984c3a16239548de89014..fc6416e6aad43c9afa12342bf5a60ae0c766df1c 100644 (file)
@@ -311,6 +311,48 @@ func TestAssignMetadata(t *testing.T) {
                        assert.Equal("Other Logo #2", logo1.Title())
                        assert.Equal("Name #2", logo1.Name())
 
+               }},
+               // Start counting first time :counter is used
+               // See https://github.com/gohugoio/hugo/issues/4335
+               {[]map[string]interface{}{
+                       map[string]interface{}{
+                               "title": "Third Logo",
+                               "src":   "logo3.png",
+                       },
+                       map[string]interface{}{
+                               "title": "Other Logo #:counter",
+                               "name":  "Name #:counter",
+                               "src":   "logo*",
+                       },
+               }, func(err error) {
+                       assert.NoError(err)
+                       assert.Equal("Third Logo", logo3.Title())
+                       assert.Equal("Name #3", logo3.Name())
+                       assert.Equal("Other Logo #1", logo2.Title())
+                       assert.Equal("Name #1", logo2.Name())
+                       assert.Equal("Other Logo #2", logo1.Title())
+                       assert.Equal("Name #2", logo1.Name())
+
+               }},
+               {[]map[string]interface{}{
+                       map[string]interface{}{
+                               "name": "third-logo",
+                               "src":  "logo3.png",
+                       },
+                       map[string]interface{}{
+                               "title": "Logo #:counter",
+                               "name":  "Name #:counter",
+                               "src":   "logo*",
+                       },
+               }, func(err error) {
+                       assert.NoError(err)
+                       assert.Equal("Logo #3", logo3.Title())
+                       assert.Equal("third-logo", logo3.Name())
+                       assert.Equal("Logo #1", logo2.Title())
+                       assert.Equal("Name #1", logo2.Name())
+                       assert.Equal("Logo #2", logo1.Title())
+                       assert.Equal("Name #2", logo1.Name())
+
                }},
                {[]map[string]interface{}{
                        map[string]interface{}{