iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
📄

3 Ways to Control Table of Contents Display in Hugo

に公開

Hugo changed its default Markdown parser from "Blackfriday" to "Goldmark" starting with v0.6.0. [1] This allows you to customize the Markdown output format by leveraging Goldmark's flexibility.

On the other hand, it is also true that the output of the table of contents (.TableOfContents) has become somewhat subtle in its behavior.

With Blackfriday, you can control the display based on the presence of headings by using the with syntax. This is because the value of .TableOfContents is empty when there are no headings.

{{/* Automatically display TOC in Blackfriday */}}

{{- with .TableOfContents -}}
  {{- . -}}
{{- end -}}

However, the new Markdown parser does not work that way. With the code above, the following HTML will always be inserted:

<nav id="TableOfContents"></nav>

When using the TOC output feature, you likely wouldn't use it as-is, but rather customize it by wrapping the TOC in HTML or applying CSS. Especially if you have turned the TOC into an accordion, it ends up looking a bit silly if nothing happens when clicked because it is empty.

As seen by the addition of the Markdown output customization feature mentioned earlier, Hugo's intention seems to be to fully push Goldmark. Therefore, let's consider how to display the TOC based on the presence of headings even with Goldmark.

Option 1: CSS

The quickest way is to apply CSS. As shown earlier, an empty TOC generates an empty <nav> element with the ID TableOfContents. Therefore, you can easily hide it by combining it with the :empty selector.

#TableOfContents:empty {
  display: none !important;
}

Pros

  • Easy to implement.
  • Particularly useful when applying CSS directly to #TableOfContents.

Cons

  • The parent element of #TableOfContents cannot be hidden.
  • The HTML code itself remains in the source.

Option 2: Front matter

Another option is to set a parameter for the table of contents display in the front matter.

---
toc: true # Display table of contents
---

# Heading

Text
{{/* Display TOC if the toc value in front matter is true */}}

{{- with .Page.Params.toc -}}
  {{- $.TableOfContents -}}
{{- end -}}

Pros

  • Same processing as with Blackfriday is possible.
  • As a side effect, you can choose to output the TOC optionally (even if headings exist, you can intentionally hide it).

Cons

  • Controlling the TOC becomes manual and is tedious.
  • You need to add this to the front matter of all Markdown files.

Option 3: String comparison

The following code is a way to determine whether the value of .TableOfContents matches its value when there are no headings. In short, it will only output the table of contents if they do not match.

{{- $TOC_EMPTY := "<nav id=\"TableOfContents\"></nav>" -}}

{{- if ne .TableOfContents $TOC_EMPTY -}}
    {{- .TableOfContents -}}
{{- end -}}

Pros

  • Although the syntax is different, it performs exactly the same processing as with Blackfriday.
  • It automatically outputs the table of contents based on the presence of headings.

Cons

  • None in particular.

Conclusion

I have introduced three methods for controlling the display of the table of contents in Hugo. Each has its own characteristics, but I personally recommend the last method. As far as I have researched, I haven't found any pages mentioning this approach, but I believe it is the best way.

脚注
  1. The latest version as of March 18, 2021, is v0.81.0. ↩︎

GitHubで編集を提案

Discussion