Prevent recursion in a shortcode

Hi, i have written a simple shortcode for Article count, word count and reading-time, in a section:

{{ $docs := (where .Site.RegularPages "Section" "==" "docs") }}
{{ $docsCount := len $docs }}

{{ $scratch_Docs := newScratch }}
{{ range (where .Site.RegularPages "Section" "==" "docs") }}
{{ $scratch_Docs.Add "wordcount" .WordCount }}
{{ $scratch_Docs.Add "readingtime" .ReadingTime }}
{{ end }}

{{ $docsCount }} with
{{ lang.NumFmt 0 ($scratch_Docs.Get "wordcount") "- ." | lang.NumFmt 0 }} Words. Reading Time {{ lang.NumFmt 0 ($scratch_Docs.Get "readingtime") "- ." | lang.NumFmt 0 }} Minutes {{ lang.NumFmt 0   ( mul ($scratch_Docs.Get "readingtime") 0.0166)  "- ." | lang.NumFmt 0 }} Hours.

If I call the the shortcode in a document within the section docs it comes to a recursive with an error message… how can I prevent this?

If I use the shortcode outside the docs section it works fine.

As written you cannot.

See https://gohugo.io/troubleshooting/faq/#which-page-methods-trigger-content-rendering.

The following methods on a Page object trigger content rendering: Content , FuzzyWordCount , Len , Plain , PlainWords , ReadingTime , Summary , Truncated , and WordCount .

You are trying to render content, which contains the shortcode, which tries to render content, which contains the shortcode, etc.

:chicken: :egg: :chicken: :egg: :chicken: :egg: :chicken: :egg:


You could move this stuff into a partial (but you cannot call the partial from a shortcode or you’d be right back where you started).

1 Like

Hmmm, that makes sense. Would there be a possibility to save the data determined in the shortcode (e.g. in a json file, as Data Template ) for later use?

Why does this need to be in a shortcode instead of in a single page template? Something like…

layouts/_default/single.html

{{ define "main" }}
  <h1>{{ .Title }}</h1>
  <div>{{ .Date | time.Format ":date_medium" }}</div>

  {{ if eq .Section "docs" }}
    <div>
      <div>Word count: {{ .WordCount }}</div>
      <div>Reading time: {{ .ReadingTime }}</div>
    </div>
  {{ end }}

  {{ .Content }}
{{ end }}

Because I build up a total reading-time and a total word-count from a whole section (over all documents in it). Only the first document (the preface) should display the values.

Then, in the preface template, or within a conditional block scoped to the preface, range through the relevant pages and calculate the totals.

1 Like