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 I required 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:

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.