Render-Link Functionality Not Working

Hi all,

I have the following in my layouts/_default/_markup/render-link.html file:

{{ $url := .Destination | safeURL }}
{{ $findThis := "/redirect/" }}
{{ $hasIt := in $url $findThis }}
{{ $hasItPrefix := strings.HasPrefix $url $findThis }}
{{ $url }}<br />
{{ $hasIt }}<br />
{{ $hasItPrefix }}

This produces the following output on a page with an anchor link:

/redirect/external-site/
false
false

I would have expected true for both boolean lines, any ideas on what I’m missing?

I’m currently using Hugo v0.72.0.

Thank you for any help!

1 Like

I tried this as a partial (first line becomes

{{ $url := .Get 0 | safeURL }}

). The call

{{< xx "/redirect/external-site/" >}}

yields the url plus two times true.

Maybe your .Destination looks like a string but isn’t?

Thank you for the suggestions.

When I change the first line to:

{{ $url := .Get 0 | safeURL }}

I get an error:

/layouts/_default/_markup/render-link.html:1:11": execute of template failed: template: 
_default/_markup/render-link.html:1:11: executing "_default/_markup/render-link.html" at <.Get>: can't evaluate field Get in type goldmark.linkCon /layouts/_default/_markup/render-link.html:1:11": execute of template failed: template: _default/_markup/render-link.html:1:11: 
executing "_default/_markup/render-link.html" at <.Get>: can't evaluate field Get in type goldmark.linkContext

/layouts/_default/_markup/render-link.html:1:11": 
execute of template failed: template: _default/_markup/render-link.html:1:11: 
executing "_default/_markup/render-link.html" at <.Get>: 
can't evaluate field Get in type goldmark.linkContext /layouts/_default/_markup/render-link.html:1:11": 
execute of template failed: template: _default/_markup/render-link.html:1:11: 
executing "_default/_markup/render-link.html" at <.Get>: can't evaluate field Get in type goldmark.linkContext

So it doesn’t appear to work, if I add the following type check to the bottom of my code I get string as the result:

{{ printf "%T" .Destination }}

If I do the following, it’s template.URL:

{{ printf "%T" (.Destination | safeURL) }}

The change .Get 0 is when you use it as a shortcode.

Ok, I’d like to try to get everything to work in the render-link.html file first. When I remove the safeURL from my first line in the original code it still produces the same result.

Try this: Create layouts/shortcodes/xx.html:

{{ $url := .Get 0 | safeURL }}
{{ $findThis := "/redirect/" }}
{{ $hasIt := in $url $findThis }}
{{ $hasItPrefix := strings.HasPrefix $url $findThis }}
{{ $url }}<br />
{{ $hasIt }}<br />
{{ $hasItPrefix }}

From your content (either .md or .html):

{{< xx "/redirect/external-site/" >}}

This should yield:

/redirect/external-site/
true
true

This would be much simpler and more efficient to troubleshoot if you were to post a link to a public repository for your site.

Great idea, here’s the basics:

This is a bug. I’ll post a follow-up shortly.

In your markdown do this:

[This is a link]({{% relref "/redirect/external-site.md" %}})

instead of this:

[This is a link]({{< relref "/redirect/external-site.md" >}})
1 Like

Thanks Joe, I can confirm that the change has rectified the problem.

Out of curiosity now - what’s the difference between {{< and {{%?

Thanks again.

I wish this were a trivial question. It is not. The behavior changed in version 0.55, and again in 0.60.

Version Shortcode Markdown HTML
0.54 {{ .Inner }} {{< foo >}}**bold**{{< /foo >}} **bold**
0.54 {{ .Inner }} {{% foo %}}**bold**{{% /foo %}} <strong>bold</strong>
0.54 <p>{{ .Inner }}</p> {{< foo >}}**bold**{{< /foo >}} <p>**bold**</p>
0.54 <p>{{ .Inner }}</p> {{% foo %}}**bold**{{% /foo %}} <p><strong>bold</strong></p>
 
0.55 {{ .Inner }} {{< foo >}}**bold**{{< /foo >}} **bold**
0.55 {{ .Inner }} {{% foo %}}**bold**{{% /foo %}} <p><strong>bold</strong></p>
0.55 <p>{{ .Inner }}</p> {{< foo >}}**bold**{{< /foo >}} <p>**bold**</p>
0.55 <p>{{ .Inner }}</p> {{% foo %}}**bold**{{% /foo %}} <p>**bold**</p>
 
0.60 {{ .Inner }} {{< foo >}}**bold**{{< /foo >}} **bold**
0.60 {{ .Inner }} {{% foo %}}**bold**{{% /foo %}} <p><strong>bold</strong></p>
0.60 <p>{{ .Inner }}</p> {{< foo >}}**bold**{{< /foo >}} <p>**bold**</p>
0.60 <p>{{ .Inner }}</p> {{% foo %}}**bold**{{% /foo %}} <!-- raw HTML omitted -->

Look at the last line.

The <!-- raw HTML omitted --> comment is rendered, without warning during the build, due to the security model introduced in Hugo 0.60. In this example, to get the desired output…

Shortcode:

<p>{{ .Inner | markdownify }}</p>

And then call it with:

{{< foo >}}**bold**{{< /foo >}}

So now we’re in the habit of coding our shortcodes templates this way, and always calling them with the {{< foo >}} notation. But there’s another big difference between the two notation styles, introduced in Hugo 0.55. From the release notes:

Shortcodes using the {{% %}} as the outer-most delimiter will now be fully rendered when sent to the content renderer (e.g. Blackfriday for Markdown), meaning they can be part of the generated table of contents, footnotes, etc.

I think this change is what makes it possible to do what you originally asked about: using the output of a shortcode within a render hook.

Comments:

  1. Prior to deployment we always grep the public directory for <!-- raw HTML omitted --> and ZgotmplZ to find problems that Hugo doesn’t warn us about during build.

  2. With Hugo 0.62 and later .RenderString is preferable to markdownify:

    {{ .Inner | .Page.RenderString }}

  3. The version 0.60 examples assume default settings (i.e., you have not overridden default security settings in config.toml).

  4. If you find this confusing you are not alone. The existing documentation is insufficient, but I’m not sure anyone understands the functionality/cases well enough to rewrite it.

8 Likes

Thank you !! I almost went crazy many times (and i think i understand reasonably the hugo philosophy). So when @jmooring says that, it is good for my mental health :crazy_face:

This is the best explanation so far I ever saw. You should put that at minimum in the tip/trick section too.