How to Open Link in New Tab with Hugo's new Goldmark Markdown Renderer in v0.62.0

In v0.62.0, Hugo has switched to the new Goldmark Markdown Renderer by default, instead of the Blackfriday renderer used previously. Goldmark also introduces a new way to add Markdown Render Hooks to control custom behaviour, e.g. image processing or opening links in new tabs by adding target="_blank" attribute to the links.

I’ve written an article detailing the Goldmark changes as well as how to configure Markdown Render Hooks here: https://agrimprasad.com/post/hugo-goldmark-markdown/

TLDR of the article is that if you just want to be able to open links in new tab for your Hugo site, create a file at layouts/_default/_markup/render-link.html with the following content:

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

Thanks, it was helpful. However, using it in my blog, I have found out it could be improved even more:

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

{{ .Text | safeUrl }} handles a corner case where you render link which is marked as code, e.g. [`hrefTargetBlank`](http://example.com/hugo-docs) doesn't work. Without | safeHTML the link text it is rendered verbatim as <code>hrefTargetBlank</code> instead of being styled as code.

See the related merged PR to the Hugo documentation.

1 Like

I found this really helpful @szpak.

Just to not that your line has a small type-o in it where your second fuction call uses safeUrl not the correct capitalisation (safeURL).

Making the corrected line:

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

Thanks @briggySmalls. In fact there is a difference even in comparison to my linked PR :).

However, as it is a text context and can contain different elements it would be even better to use safeHTML instead of safeURL. Unfortunately, I’m no longer able to edit that post. Therefore, the updated line here, again:

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

And, for security /performance reasons, add rel="noreferrer noopener":

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

@h-enk Sounds reasonable. You might consider propose that change to the Hugo documentation.

1 Like

Hey @szpak, good point. I just did that.

This seems not to work for plain URL links?
I tried the method, but no target="_blank" is added at any href …

Just what I was looking for. Thanks. I tried a few things but could not figure out how to also make this work with mailto links. I duplicated the line and changed http to mailto and that made duplicate links.

I tried a new render-mailto.html file which did nothing. I guess some type of if statement in the render-link.html so it picks up either http or mailto … I know that this is a minor edge case using gmail but inquiring minds and all.

you have to use render-link! Here my implementation:

{{ if strings.HasPrefix .Destination "mailto" -}}Send mail to {{end}}
<a href={{ .Destination | safeURL }}
    {{ if strings.HasPrefix .Destination "http" -}} target=_blank rel="noopener noreferrer" {{- end }}
>{{ .PlainText | htmlEscape }}</a>
2 Likes

this worked for me. it opens either mailto or http or https links from markdown files in a new tab. Thanks for your help

<a href={{ .Destination | safeURL }}
    {{ if strings.HasPrefix .Destination "mailto" -}} target=_blank {{end}}
    {{ if strings.HasPrefix .Destination "http" -}} target=_blank rel="noopener noreferrer" {{- end }}
>{{ .PlainText | htmlEscape }}</a>
1 Like

In my theme, navbar menus are handled by HTML templates, without being processed by Goldmark. I had to do more to apply it to links in the navbar.

I copied header.html from the theme:

mkdir -p layouts/partials/
cp themes/airspace_theme/layouts/partials/header.html layouts/partials/

and modified it to conditionally add target="_blank", just as the OP does in his solution:

<li><a href="{{ .URL | relLangURL }}"{{ if strings.HasPrefix .URL "http" }} target="_blank"{{ end }}>{{ .Name }}</a></li>

With this and the OP’s solution implemented, absolute links in the content and the navbar menus are opened in a new browser tab.

So I’m using this line from the top post:

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

Can it be adapted that it opens .pdf documents from my site also in a new tab?
I’m not familiar with the functions, but it seems if strings.HasPrefix .Destination “http” seems to verify that the destination starts with http. Unfortunately I haven’t found a HasPostfix function. So I don’t have any idea how to achieve this.

See:

https://gohugo.io/functions/strings.hassuffix/#readout

Thanks. I was a bit confused on the page of the functions that HasPrefix is listed without strings. before it, while HasSuffix has it:

Maybe that could be improved in the manual.

Anyway, thanks for the help, this line works:

<a href="{{ .Destination | safeURL }}"{{ with .Title}} title="{{ . }}"{{ end }}{{ if or (strings.HasPrefix .Destination "http") (strings.HasSuffix .Destination ".pdf") }} target="_blank"{{ end }}>{{ .Text }}</a>

This topic was automatically closed after 33 hours. New replies are no longer allowed.