Hugo: оглавление
Мастерим оглавление для статьи на сайте, собранном на hugo

Однажды приходит понимание того, что нашим замечательным страницам с объемным контентом и множеством заголовков и подзаголовков чего-то не хватает, а именно - оглавления.
Конечно, hugo умеет автоматически создавать оглавление страницы, собирая заголовки из области контента {{.Content}}
. Для этого достаточно добавить в шаблон страницы со статьей блок {{.TableOfContents}}
.
Можно даже добавить щепотку логики в такое решение: например, выводить оглавления только в случаях, когда объем контентного содержимого превышает определенное количество слов (в нашем примере - 400).
Для этого нужно создать файл шаблона оглавления:
layouts/partials/toc.html
со следующим кодом:
{{ if and (gt .WordCount 400 ) (.Params.toc) }}
<aside>
<header>
<h2>{{.Title}}</h2>
</header>
{{.TableOfContents}}
</aside>
{{ end }}
Но что делать, если Мы хотим сохранить полный контроль над контентом и выводить оглавление строго по своему желанию. В такой ситуации на помощь приходят шорткоды.
Что же, создадим файл с шорткодом для вывода оглавления:
layouts/shortcodes/toc.html
со следующим кодом:
<h3>Содержание</h3>
{{.Page.TableOfContents}} <!-- Правильно -->
в данном случае использование конструкции:
{{.TableOfContents}} <!-- Так делать не стоит -->
будет неверным и неминуемо приведет к ошибке при сборке сайта.
Теперь для вызова оглавления достаточно создать шорткод:
{{< toc >}}
Казалось бы все замечательно. Но есть и ложка дегтя. Предложенное решение не позволяет назначать тег заголовка h1...h6
для первого уровня вложенности оглавления. В оглавлении отсчет всегда ведется от h1
. Так как для контента стартовыми заголовками обычно являются теги h2
или h3
, мы получаем непрезентабельный внешний вид страницы и лишние уровни вложенность списков <ul><li><ul><li>
в HTML-коде.
На помощь приходит функция replaceRE
, позволяющая заменить все вхождения регулярного выражения необходимым блоком кода. К сожалению, в настоящее время, это решение не работает в шаблоне шорткода, но отлично справляется со своими функциями в шаблоне страницы сайта с контентным содержимым.
В случае, если стартовым заголовком для статьи является тег уровня h3
, достаточно заменить:
{{.Content}}
на код:
{{ .Content | replaceRE `<nav id="TableOfContents">\s*<ul>\s*<li>\s*<ul>\s*<li>\s*<ul>` `<nav id="TableOfContents"><ul>` | replaceRE `</ul>\s*</li>\s*</ul>\s*</li>\s*</ul>\s*</nav>` `</ul></nav>` | safeHTML}}
и мы получим великолепное оглавление для страницы.
Спасибо за внимание.