From 3decf4a327157e98d3da3502b6d777de63437c39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Mon, 23 Apr 2018 08:09:56 +0200 Subject: [PATCH] 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 --- hugolib/shortcode.go | 21 +++++++++++++++------ hugolib/shortcode_test.go | 27 +++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/hugolib/shortcode.go b/hugolib/shortcode.go index 933bbe44e..4792b7f61 100644 --- a/hugolib/shortcode.go +++ b/hugolib/shortcode.go @@ -40,7 +40,11 @@ type ShortcodeWithPage struct { 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 @@ type shortcode struct { name string inner []interface{} // string or nested shortcode params interface{} // map or array + ordinal int err error doMarkup bool } @@ -287,7 +292,7 @@ func renderShortcode( 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 @@ var errShortCodeIllegalState = errors.New("Illegal shortcode state") // 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 @@ Loop: 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 @@ func (s *shortcodeHandler) extractShortcodes(stringToParse string, p *PageWithou // … it's safe to keep some "global" state var currItem item var currShortcode shortcode + var ordinal int Loop: for { @@ -605,7 +613,7 @@ Loop: // 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 @@ Loop: placeHolder := s.createShortcodePlaceholder() result.WriteString(placeHolder) + ordinal++ s.shortcodes.Add(placeHolder, currShortcode) case tEOF: break Loop diff --git a/hugolib/shortcode_test.go b/hugolib/shortcode_test.go index 3e8a952e6..b380a5b36 100644 --- a/hugolib/shortcode_test.go +++ b/hugolib/shortcode_test.go @@ -894,17 +894,28 @@ weight: %d --- # 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 @@ weight: %d 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()) }