I recently tried to percent-encode (or URL-encode) strings in Hugo. Percent-encoding is used to encode data in query strings of URLs because they must only contain ASCII characters. There is a Hugo built-in querify
function to transform key-value pairs to query strings. But my requirement was to URL-encode a single string value and not build a query string from key-value pairs.
My goal is to allow users of the Hugo theme to add social media sharing buttons through the site configuration like this:
[params]
[[params.socialShare]]
formatString = "https://www.facebook.com/sharer.php?u={url}"
[[params.socialShare]]
formatString = "https://reddit.com/submit?url={url}&title={title}"
The formatString
contains {url}
and {title}
placeholders. The following is a simplified sharing button implementation using the format strings where placeholders are substituted with page-level variable values during Hugo build-time:
{{ $href := .formatString }}
{{ $href := replace $href "{url}" .Permalink }}
{{ $href := replace $href "{title}" .Title }}
<a href="{{ $href | safeURL }}">Share Me!</a>
The issue here is that .Permalink
and .Title
must be percent-encoded. As I’ve searched the web on how to do this with Hugo, I only found unsolved forum posts:
- About htmlEscape: transform https into https%3A%2F%2F
- URL encoding (percent encoding) with Hugo?
- Is there a url encoder function in Hugo?
I couldn’t believe this was an unsolved mystery and assumed I was just too dumb to read the docs. Hugo was written in Go, so I looked into how to do percent-encoding in Go: with the url.QueryEscape()
function from the net/url
package.
Searching the Hugo code base for url.QueryEscape
leads to exactly one result. It turns out I discovered an undocumented, built-in Hugo function called urlquery
. The following:
{{ urlquery "https://schnerring.net" }}
…returns the result: https%3A%2F%2Fschnerring.net
. Here is the fixed version of the sharing button:
{{ $href := .formatString }}
{{ $href := replace $href "{url}" (urlquery .Permalink) }}
{{ $href := replace $href "{title}" (urlquery .Title) }}
<a href="{{ $href | safeURL }}">Share Me!</a>
The full social sharing button implementation is available on my GitHub.