Using shortcode inside render-hook

While playing with render hooks and shortcodes, I was trying to distinguish between several image sources within a render hook for a markdown link.

The link looks like this

[{{< image src="myimage.jpg" >}}](http://myurl)

The image shortcode is quite simple and consists of just two lines:

{{ $src := $.Get "src" }}
<img src="{{ $src }}" />

Last but not least the render hook, taken from the documentation

<a href="{{ .Destination | safeURL }}"{{ with .Title}} title="{{ . }}"{{ end }}{{ if strings.HasPrefix .Destination "http" }} target="_blank" rel="noopener"{{ end }}>{{ .Text | safeHTML }}</a>

Within the render hook (located in render-link.html) I was trying to check if there’s an image (= the image shortcode) embedded, checking “.Text” or “.PlainText” for containing the string “img” or “image”.

To my surprise, neither “.Text” nor “.PlainText” contained any of these strings.

While investigating further using

<p>Length: {{ len .PlainText }}</p>
<p>Substr 1: {{ substr .PlainText 0 13 }}</p>
<p>Substr 2: {{ substr .PlainText 13 12 }}</p>

within “render-link.html”, I got the result

Length: 25
Substr 1: HAHAHUGOSHORT
Substr 2: CODE-s0-HBHB

Which translates to:

HAHAHUGOSHORTCODE-s0-HBHB

If I don’t split the string and leave “.PlainText” intact, the image is displayed instead of what should be “.PlainText”.

Conclusion: While running a render-hook, shortcodes are translated to an internal format and it’s impossible to check either for the original shortcode tag or the rendered tag.

Question: Is there a way to get either the original shortcode-string or the rendered output from within render-link.html?

Change this:

{{< image src="myimage.jpg" >}}

To this:

{{% image src="myimage.jpg" %}}

And you’ll need this in your site configuration:

[markup.goldmark.renderer]
unsafe = true

It’s not unsafe if you are in control of the content.

@jmooring
Thanks, this really does the trick.

Do you have some additional documentation on how you came across this solution?
I tired Configure Markup |Hugo but wasn’t able to figure it out by myself.

When you call a shortcode using the {{< foo >}} notation, we do not render the shortcode before:

  1. Sending the page content to the markdown renderer (Goldmark), or
  2. Hooking into links, images, and headings

Instead, we send a placeholder, effectively something like this:

HAHAHUGOSHORTCODE-UNIQUE-ID

When we get this back from Goldmark, we replace the placeholder with the rendered shortcode.

But you can also force your shortcode to be rendered before we send the page content to Goldmark (and before we hook into links, images, and headings) by using this notation:

{{% div %}}  

But, by default, Goldmark considers HTML in markdown unsafe, so it replaces the HTML with this HTML comment:

<!-- raw HTML omitted -->

To tell Goldmark that HTML in markdown is safe in your situation:

[markup.goldmark.renderer]
unsafe = true
3 Likes

Thanks a lot for the explanation!

1 Like

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