I was looking for a way to include HTML snippets into Hugo posts. The magic formula includes shortcode templates and readFile
.
Hugo’s shortcode templates are a very neat way to bring custom, reusable pieces of HTML into your posts.
It’s as simple as adding a file into the layouts/shortcodes
folder.
The full file structure of this example looks like this:
┌─ content
│ └─ posts
│ └─ example
│ ├─ index.md ◄- Post where we want to include snippet.html
│ └─ snippet.html ◄- HTML snippet that we want to be included
├─ data
├─ layouts
│ └─ shortcodes
│ └─ include-html.html ◄- Shortcode template
└─ config.toml
Let’s start at the bottom with the shortcode:
A shortcode is a reusable HTML template that can include executable code.
The name of the file is also the name of the shortcode.
Our include-html.html
looks like this:
{{ $file := .Get 0 }}
{{ $file | readFile | safeHTML }}
(original source is this discussion)
What happens here is that .Get 0
reads the first parameter of the shortcode and stores it in the $file
variable.
In the next line, $file
is piped into readFile
which reads the content of the file.
The content is then piped into safeHTML
which declares the content as “safe” HTML and therefore avoids further escaping by Go templates.
In our post index.md
we can now include the file snippet.html
by using the include-html
shortcode:
{{< include-html "content/posts/example/snippet.html" >}}
The rendered page should now include the content of snippet.html
.
Having to declare the full path can be cumbersome and error prone. It would be nicer to only specify the relative path to snippet.html
from the page that includes it.
We can achieve that by a slight modification of include-html.html
:
{{ $file := .Get 0 }}
{{ (printf "%s%s" .Page.File.Dir $file) | readFile | safeHTML }}
(printf "%s%s" .Page.File.Dir $file)
concatenates .Page.File.Dir
(the folder of the current page) and $file
. The rest works as before. Now we can include the snippet simply like this:
{{< include-html "snippet.html" >}}
Done!
Markdown
It’s also possible to include Markdown files instead of HTML files in a very similar way. I suggest to create another shortcode named include-md
:
{{ $file := .Get 0 }}
{{ $file | readFile | markdownify }}
That’s it!