shithub: hugo

Download patch

ref: 3decf4a327157e98d3da3502b6d777de63437c39
parent: 24c662ce6bea029b0b24160376eaceaed1481d1c
author: Bjørn Erik Pedersen <[email protected]>
date: Mon Apr 23 04:09:56 EDT 2018

hugolib: Add zero-based Ordinal to shortcode

The count starts at 0 relative to the shortcode's parent: Either the page or the surrounding shortcode.

Access it in a shortcode like this:

```bash
Ordinal is {{ .Ordinal }}
```

Note that this is a shared ordinal for all shortcodes in the relevant context, so, as an example, you have this in a content page:

```markdown
This is a shortcode:

{{< hello >}}

This is another shortcode:

{{< hugo >}}

The `.Ordinal` you get in the two shortcodes above is 0 and 1.
```

See #3359

--- a/hugolib/shortcode.go
+++ b/hugolib/shortcode.go
@@ -40,7 +40,11 @@
 	Page          *PageWithoutContent
 	Parent        *ShortcodeWithPage
 	IsNamedParams bool
-	scratch       *Scratch
+
+	// Zero-based oridinal in relation to its parent.
+	Ordinal int
+
+	scratch *Scratch
 }
 
 // Site returns information about the current site.
@@ -122,6 +126,7 @@
 	name     string
 	inner    []interface{} // string or nested shortcode
 	params   interface{}   // map or array
+	ordinal  int
 	err      error
 	doMarkup bool
 }
@@ -287,7 +292,7 @@
 		return ""
 	}
 
-	data := &ShortcodeWithPage{Params: sc.params, Page: p, Parent: parent}
+	data := &ShortcodeWithPage{Ordinal: sc.ordinal, Params: sc.params, Page: p, Parent: parent}
 	if sc.params != nil {
 		data.IsNamedParams = reflect.TypeOf(sc.params).Kind() == reflect.Map
 	}
@@ -449,12 +454,13 @@
 // pageTokens state:
 // - before: positioned just before the shortcode start
 // - after: shortcode(s) consumed (plural when they are nested)
-func (s *shortcodeHandler) extractShortcode(pt *pageTokens, p *PageWithoutContent) (*shortcode, error) {
-	sc := &shortcode{}
+func (s *shortcodeHandler) extractShortcode(ordinal int, pt *pageTokens, p *PageWithoutContent) (*shortcode, error) {
+	sc := &shortcode{ordinal: ordinal}
 	var isInner = false
 
 	var currItem item
 	var cnt = 0
+	var nestedOrdinal = 0
 
 Loop:
 	for {
@@ -470,7 +476,8 @@
 			if cnt > 0 {
 				// nested shortcode; append it to inner content
 				pt.backup3(currItem, next)
-				nested, err := s.extractShortcode(pt, p)
+				nested, err := s.extractShortcode(nestedOrdinal, pt, p)
+				nestedOrdinal++
 				if nested.name != "" {
 					s.nameSet[nested.name] = true
 				}
@@ -593,6 +600,7 @@
 	// … it's safe to keep some "global" state
 	var currItem item
 	var currShortcode shortcode
+	var ordinal int
 
 Loop:
 	for {
@@ -605,7 +613,7 @@
 			// let extractShortcode handle left delim (will do so recursively)
 			pt.backup()
 
-			currShortcode, err := s.extractShortcode(pt, p)
+			currShortcode, err := s.extractShortcode(ordinal, pt, p)
 
 			if currShortcode.name != "" {
 				s.nameSet[currShortcode.name] = true
@@ -621,6 +629,7 @@
 
 			placeHolder := s.createShortcodePlaceholder()
 			result.WriteString(placeHolder)
+			ordinal++
 			s.shortcodes.Add(placeHolder, currShortcode)
 		case tEOF:
 			break Loop
--- a/hugolib/shortcode_test.go
+++ b/hugolib/shortcode_test.go
@@ -894,17 +894,28 @@
 ---
 # doc
 
-{{< increment >}}{{< s1 >}}{{< increment >}}{{< s2 >}}{{< increment >}}{{< s3 >}}{{< increment >}}{{< s4 >}}{{< increment >}}{{< s5 >}}
+{{< s1 >}}{{< s2 >}}{{< s3 >}}{{< s4 >}}{{< s5 >}}
 
+{{< nested >}}
+{{< ordinal >}}
+{{< ordinal >}}
+{{< ordinal >}}
+{{< /nested >}}
 
+
 `
 
-	shortCodeTemplate := `v%d: {{ .Page.Scratch.Get "v" }}|`
+	ordinalShortcodeTemplate := `ordinal: {{ .Ordinal }}`
 
+	nestedShortcode := `outer ordinal: {{ .Ordinal }} inner: {{ .Inner }}`
+
+	shortCodeTemplate := `v%d: {{ .Ordinal }}|`
+
 	var shortcodes []string
 	var content []string
 
-	shortcodes = append(shortcodes, []string{"shortcodes/increment.html", `{{ .Page.Scratch.Add "v" 1}}`}...)
+	shortcodes = append(shortcodes, []string{"shortcodes/nested.html", nestedShortcode}...)
+	shortcodes = append(shortcodes, []string{"shortcodes/ordinal.html", ordinalShortcodeTemplate}...)
 
 	for i := 1; i <= 5; i++ {
 		shortcodes = append(shortcodes, []string{fmt.Sprintf("shortcodes/s%d.html", i), fmt.Sprintf(shortCodeTemplate, i)}...)
@@ -923,7 +934,15 @@
 
 	p1 := s.RegularPages[0]
 
-	if !strings.Contains(string(p1.content()), `v1: 1|v2: 2|v3: 3|v4: 4|v5: 5`) {
+	if !strings.Contains(string(p1.content()), `v1: 0|v2: 1|v3: 2|v4: 3|v5: 4|`) {
+		t.Fatal(p1.content())
+	}
+
+	// Check nested behaviour
+	if !strings.Contains(string(p1.content()), `outer ordinal: 5 inner: 
+ordinal: 0
+ordinal: 1
+ordinal: 2`) {
 		t.Fatal(p1.content())
 	}