The same content can be relevant in several places.

Here is how to include one file in multiple pages using Hugo Shortcodes.

Requirements

Here is what I’ve been searching for:

  • The solution must support content written both in Markdown and HTML
  • The Front Matter from the included file should not be displayed
  • Optional: do not display included files on the homepage

Solution

Create a file called layouts/shortcodes/include.html with this content:

{{ $file := .Get 0 }}
{{ (printf "%s%s" .Page.File.Dir $file) | readFile | replaceRE "^---[\\s\\S]+?---" "" | safeHTML }}

Usage

    {{% include "included-file-name.md" %}}

Results

  • Works fine!
  • Markdown content is properly rendered.
  • The filename is enough (no fullpath is required)
  • HTML is rendered, at least with unsafe: true in the config file.
  • The Front Matter of the included file is properly hidden. Thanks to @shafiemukhre.
  • Using draft: true is used to hide included files from the homepage.

Caveats

  • When editing the included file, the page including this file is not automatically updated. Restarting the server is required.
  • Does not work if the included file starts with <div>: Hugo crashed with an error “plain HTML documents not supported”

Roadmap

Archives

Before finding the right solution, I’ve been testing the following methods:

Iteration #1

Create the following file in layouts/shortcodes/include.html:

{{ $file := .Get 0 }}
{{ $file | readFile | safeHTML }}

Call with {{% include "/content/article/included-file-name.md" %}}

Results:

  • Markdown content is properly rendered.
  • HTML is rendered, at least with unsafe: true. Note that Hugo must be restarted to see the HTML modifications
  • Does not work if the included file starts with <div>: Hugo crashed with an error “plain HTML documents not supported”

Source

Iteration #2

Same as above but the relative filepath is enough (no full path)

Usage: {{% include "included-file-name.md" %}}

Code:

{{ $file := .Get 0 }}
{{ (printf "%s%s" .Page.File.Dir $file) | readFile | safeHTML }}

Results:

Same as Iteration #1. Relative file path is now enough.

Source

Iteration #3

Still in layouts/shortcodes/include.html:

{{ $base_path := $.Page.Dir }}
{{ $file_path := .Get 0 }}
{{ $full_file_path := (path.Join $base_path $file_path) }}
{{ readFile $full_file_path | markdownify | safeHTML }}

Call with {{< include "included-file-name.md" >}}

(Note that we switch from {{% %}} to {{< >}})

Results:

Same as Iteration #2

Source

Iteration #4

    {{ (site.GetPage $file).RawContent }}

    {{ $filepath := printf "%s%s" .Page.File.Dir $file }}


    {{ (site.GetPage $filepath).RawContent }}

    {{- with $.Page.Resources.GetMatch $file -}}
      {{- .Content -}}
    {{- end -}}

    {{ with site.GetPage $filepath}}
      {{ .RawContent }}
    {{ end }}

    {{ with .Site.GetPage $filepath }}{{.Content}}{{end}}

Other methods untested so far

References