Hugo: Add Table of Contents Anywhere in Markdown File

Hugo: Add Table of Contents Anywhere in Markdown File

Hugo provides a built-in module named {{ .TableOfContents }} to generate table of contents. It is pretty handy because it generates the table of content without help of any JavaScript or CSS code. But there is a problem with it, you need to put it inside templates. You can’t render it inside the contents of the markdown file. Means you will be able to render it either at top, or at the bottom of your contents.

Usually I prefer to have a small introduction and rest of the contents, have a table of content in between them(like this article).Now we are going to see how to do that using custom shortcodes.

What is shortcodes

Shortcodes is like a tag which can be used inside a markdown file. It will allow you to use built-in or custom templates. You can also pass arguments through shortcode and render them in template. There are some built-in shortcodes like figure, gist etc. But we are going to build our own shortcodes.

Create custom shortcodes

First we need to create the shortcodes file named table_of_contents.html then put it inside layouts/shortcodes directory. The folder structure will look like this:

├── contents
├── layouts
│   ├── partials
│   └── shortcodes
│       └── table_of_contents.html
├── static
├── themes
└── config.toml

then inside the html file, we need to write the following code:

<div class="toc">
  {{ .Page.TableOfContents }}

Cool. Our shortcode is ready to use.


We need to use the shortcodes by putting {{< table_of_contents >}} inside markdown files. For example:

## Your content

Some lines

{{< table_of_contents >}}

More lines

Replace {{ .Page.TableOfContents }} with the following code:

{{ .Page.TableOfContents | replaceRE "<ul>[[:space:]]*<li>[[:space:]]*<ul>" "<ul>" | replaceRE "</ul>[[:space:]]*</li>[[:space:]]*</ul>" "</ul>" |  safeHTML }}

It will generate table of contents with hyperlinks to each header.

In conclusion

Shortcodes are pretty awesome and you can use it in many ways like given here. It allows you to have a cleaner implementation and reusability. But one downside is that, you need to put this shortcode in every markdown file to render the table of contents inside them.

I hope this article helps. If you have any questions, please share in the comment section below.

Last updated: Jul 13, 2024

← Previous
Reduce Build Time for Images with Data Science Packages

How to build a docker image faster containing packages like Numpy, SciPy, Pandas etc.

Next →
Progressive Web App in Hugo using GitHub Actions

Implement a Progressive Web App in your Hugo based static site using GitHub Actions.

Share Your Thoughts
M↓ Markdown