How can you pass in a variable as a shortcode's argument value?

I have (2) shortcodes, one is called info and the other is called course-link.

These info calls can be anywhere inside of a Markdown content file. Imagine having an arbitrary call to action that may or may not exist in a blog post at any point. It’s important that this is callable inside of a specific post. It’s not a layout worthy item.

I’d like to be able to render the course-link’s value as the value to the info’s buttonURL argument like this:

{{ $buttonURL := (course-link "example.com") }}
{{< info
  header="Update: A New Course is Available"
  buttonURL=$buttonURL
  buttonLabel= "Example course"
>}}

When I do this, I literally get back $buttonURL as the value. If I try to inline that shortcode call into the info shortcode’s buttonURL then I get a Go panic with:

web-1  | panic: html/template: cannot Clone "" after it has executed
web-1  |
web-1  | goroutine 22 [running]:
web-1  | github.com/gohugoio/hugo/tpl/internal/go_templates/htmltemplate.Must(...)
web-1  |        /root/project/hugo/tpl/internal/go_templates/htmltemplate/template.go:369
web-1  | github.com/gohugoio/hugo/tpl/tplimpl.(*templateNamespace).createPrototypes(0xc00a282cf0)
web-1  |        /root/project/hugo/tpl/tplimpl/template.go:1006 +0xa9
web-1  | github.com/gohugoio/hugo/tpl/tplimpl.(*templateExec).MarkReady.func1()
web-1  |        /root/project/hugo/tpl/tplimpl/template.go:320 +0x3c
web-1  | sync.(*Once).doSlow(0x40f37f?, 0x2587e00?)
web-1  |        /usr/local/go/src/sync/once.go:74 +0xc2
web-1  | sync.(*Once).Do(...)
web-1  |        /usr/local/go/src/sync/once.go:65
web-1  | github.com/gohugoio/hugo/tpl/tplimpl.(*templateExec).MarkReady(0x53854b0?)
web-1  |        /root/project/hugo/tpl/tplimpl/template.go:317 +0x59
web-1  | github.com/gohugoio/hugo/hugolib.newHugoSites.func3({0x0?, 0xc009c883c0?})
web-1  |        /root/project/hugo/hugolib/site_new.go:366 +0xab
web-1  | github.com/gohugoio/hugo/lazy.(*Init).Do.func1()
web-1  |        /root/project/hugo/lazy/init.go:107 +0xe2
web-1  | github.com/gohugoio/hugo/lazy.(*onceMore).Do(0x5?, 0x2ab7f90?)
web-1  |        /root/project/hugo/lazy/once.go:53 +0x129
web-1  | github.com/gohugoio/hugo/lazy.(*Init).Do(0xc000aff6c0, {0x3feac88?, 0x547f4a0?})
web-1  |        /root/project/hugo/lazy/init.go:88 +0x65
web-1  | github.com/gohugoio/hugo/lazy.(*Init).Do.func1()
web-1  |        /root/project/hugo/lazy/init.go:112 +0x18a
web-1  | github.com/gohugoio/hugo/lazy.(*onceMore).Do(0xc001a235a0?, 0xc009629f80?)
web-1  |        /root/project/hugo/lazy/once.go:53 +0x129
web-1  | github.com/gohugoio/hugo/lazy.(*Init).Do(0xc000afecb0, {0x3feac88?, 0x547f4a0?})
web-1  |        /root/project/hugo/lazy/init.go:88 +0x65
web-1  | github.com/gohugoio/hugo/hugolib.(*HugoSites).process(0xc000a01680, {0x3feac88, 0x547f4a0}, {0x3ff3c30?, 0xc0001f53e0?}, 0xc008331ec0, 0xc001a236e0, {0xc001a27740, 0x5, 0x8})
web-1  |        /root/project/hugo/hugolib/hugo_sites_build.go:253 +0x125
web-1  | github.com/gohugoio/hugo/hugolib.(*HugoSites).Build.func4()
web-1  |        /root/project/hugo/hugolib/hugo_sites_build.go:148 +0xbd
web-1  | github.com/gohugoio/hugo/hugolib.(*HugoSites).Build(0xc000a01680, {0x0, 0x0, 0x0, 0x1, 0xc000034510, 0x0, 0x1, 0x0}, {0xc001a27740, ...})
web-1  |        /root/project/hugo/hugolib/hugo_sites_build.go:159 +0x6f8
web-1  | github.com/gohugoio/hugo/commands.(*hugoBuilder).rebuildSites(0xc000a50700, {0xc009629260, 0x4, 0x4})
web-1  |        /root/project/hugo/commands/hugobuilder.go:1064 +0x188
web-1  | github.com/gohugoio/hugo/commands.(*hugoBuilder).handleEvents.func6(0xc000a50700, 0xc00be3eb28)
web-1  |        /root/project/hugo/commands/hugobuilder.go:886 +0x8b
web-1  | github.com/gohugoio/hugo/commands.(*hugoBuilder).handleEvents(0xc000a50700, 0xc000794870, 0xc000125db8, {0xc0096291a0, 0x4, 0x4}, 0xc0007953b0)
web-1  |        /root/project/hugo/commands/hugobuilder.go:889 +0x13dd
web-1  | github.com/gohugoio/hugo/commands.(*hugoBuilder).newWatcher.func2()
web-1  |        /root/project/hugo/commands/hugobuilder.go:374 +0x2e8
web-1  | created by github.com/gohugoio/hugo/commands.(*hugoBuilder).newWatcher in goroutine 1
web-1  |        /root/project/hugo/commands/hugobuilder.go:344 +0x4c5

Things are in /root because I’m running Hugo instead of Docker btw.

I don’t exactly understand what you are trying to do …

Maybe passing the result of one shortcode to another on at different locations on the same page…

  • I suppose you enabled inline shortcodes in your config.

  • Your first line is not valid in a markdown file.

    • it is tempale code
    • you cannot create a variable in markdown
    • course-link is not a function

General things:

  • shortcode can call partials
    So you could pass the string to the info shortcode and evaluate it there

  • you can nest shortcodes
    Shortcodes | Hugo

  • look at page scratch and store methods
    This enables you to create “variables” on page level that can be set and get from different shortcodes, partials…

  • this one seems pretty close at least get an idea Use front matter defined variables as argument in custom shortcode

1 Like

No, that’s not possible, but having lots of template logic in your content files is probably not where you want to go anyway. So in my head, passing

{{< info
  header="Update: A New Course is Available"
  buttonURL="example.com"
  buttonLabel= "Example course"
>}}

Would make it both simpler and easier to use.

Thanks, I was able to get it working with .Inner. Although when passing the URL from the shortcode to partial I kept getting #ZgotmplZ as the output. I had to | safeURL it. For reference that would have been near impossible to debug without StackOverflow. It would be nice if Hugo could emit a warning there with a description on what went wrong.

example.com” in this case could come from relref or another shortcode. Without it coming from relref then I’m going to lose the ability to check if the link is valid and have Hugo handle converting “/hello” into ugly URLs or not.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.