Handle external links with Render Hook Templates

Just wanted to share how to handle external links thanks to Render Hook Templates.

Put the following:

<a href="{{ .Destination | safeURL }}"{{ if ne true (in (urls.Parse .Destination).Host (urls.Parse .Site.BaseURL).Host) }} target="_blank"{{ end }}>{{ .Text }}</a>

Inside:

layouts
└── _default
    └── _markup
        └── render-link.html

Notice: from a UX point of view, it is not really recommended to force external links to open in new tabs. You may add an “external link” icon after the link text instead.

I created a PR in case one wants to include this example in the docs.

2 Likes

I think I would go for the simpler:

{{ if strings.HasPrefix .Destination “http” }} target=“_blank”{{ end }}

5 Likes

I guess you mean that with canonifyURLs: false (default) ?

No, I mean exactly what I wrote. Nothing more or less.

Then I don’t understand, because we can have internal links begining with “http”, and ultimately all links begin with “http”.

(Also I noticed I had to reload the Hugo server sometimes for the changes in render-link.html to take effect)

It seems render-link is processed before URLs are canonified, so @bep’s code works perfectly even though I have canonifyURLs set to true. :+1:

But links like [a link](http://mydomain.com/blog) will be treated as external, no? That’s why I chose (urls.Parse .Destination).Host, to be sure to treat links correctly even if the content editor puts a “full” internal URL. Bep’s code assume that all internal links are written without “http” in front of them, right?

Yes. But if this was my blog, I would write every relative URLs in markdown like this:

[a link](/blog/mypost.md)

And every link out to the world like this:

[a link out on the internet](https://example.org/some-external-link)

Note that I have kept the link as a filename (mypost.md); that way I guess the links will also work when browsed on github.com.

I would probably also write variants of the above like this:

[a link](../blog/mypost.md)

And then use .Page.GetPage in the hook template for every non-external link.

If you do this and then use .Permalink for all your linking, there should be no need for canonifyURLs (I think…)

3 Likes

Ok!

I’d rather not depend on conventions for content editors to write URLs.
And I canonify links for mixed content, assets resolving and SEO reasons.