Создаем отдельную страницу архивов на Hugo
Hugo — один из самых популярных генераторов статических сайтов. Он написан на языке Go, что дает ему удивительную скорость и гибкость. Тем не менее сейчас Hugo имеет версию v0.79.1, а значит это не финальная его версия и API еще будет меняться. Соответственно, на данный момент, имеются некоторые недоработки. Одна их них - это отсутствие страницы архивов из коробки. Тем не менее, благодаря очень гибкой системе шаблонов и таксономий, эту функциональность очень легко реализовать в теме.
Данный сайт изначально был создан на hexo. Hexo неплохой генератор, но по некоторым причинам мною было принято решение перенести его на hugo. Для hexo существует плагин hexo-generator-archive, который генерирует прикольную страницу со списком всех статей, разбитых по году публикации (пример). И мне очень хотелось оставить эту страницу и на hugo. Причем так, чтобы это не выглядело как костыль.
Как оказалось, это давольно просто, но очень не очевидно. Довольно быстро в официальной документации находится страница про группировку контента. Далее один из примеров почти полностью подходит под наши нужды:
<!-- Groups content by month according to the "date" field in front matter -->
{{ range .Pages.GroupByDate "2006-01" }}
<h3>{{ .Key }}</h3>
<ul>
{{ range .Pages }}
<li>
<a href="{{ .Permalink }}">{{ .Title }}</a>
<div class="meta">{{ .Date.Format "Mon, Jan 2, 2006" }}</div>
</li>
{{ end }}
</ul>
{{ end }}
Для тех кто не сталкивался с Go: "2006-01"
это не просто дата для примера. Go в строке указания формата даты использует конкретное время, а именно: Mon Jan 2 15:04:05 MST 2006
. А значит, что данная строка будет аналогом YYYY-MM
для большинства других языков.
Итак, теперь осталось только понять, где расположить этот код. Если бы мы хотели создать виджет в боковой колонке, то все было бы просто. Но вот с отдельной страницей нет простых и понятных решений. Самый популярный и рабочий вариант: предлагается все записи добавлять в категорию archive, и использовать /categories/archive
в качестве страницы архивов. Данный подход мне очень не нравится, в первую очередь тем, что необходимо вручную добавлять статьи в категорию.
Как оказалось, создать отдельную страницу под какую-то свою логику очень просто. Поможет нам в этом система таксономий.
Первое, что необходимо: добавить новую таксономию в файле конфигурации:
baseURL: "https://devstory.xyz/"
title: DevStory
# ....
taxonomies:
tag: tags
archives: archives # тут мы можем указать url нашего архива
# ....
После чего на нашем сайте появиться новая страница по адресу /archives
:
Теперь создадим отдельный шаблон списка archives/list.html
для этой таксономии в папке вашей темы.
Зачем вставим код слегка отредактировав html (подробнее об используемых конструкциях можно узнать здесь)
{{ define "main" }}
<div class="archive">
{{ range .Pages.GroupByDate "2006" }}
<h2 class="archive-year">{{ .Key }}</h2>
{{ range .Pages }}
<div class="post-item">
{{ partial "partials/post/post-info-short" . }}
<a href="{{ .RelPermalink }}" class="post-title-link">{{ .Title }}</a>
</div>
{{ end }}
{{ end }}
</div>
{{ end }}
Но наша страница не изменится, и все еще будет пуста. Это связано с тем, что в свойстве Pages будет пусто, так как у нас нет страниц, связанных с таксономией archives
. А значит, и выведено ничего не будет. Не стоит сразу же бежать и всем записям проставлять archives: true
.
Обратившись к документации, мы можем найти два интересных свойства: .Site.Pages
и .Site.RegularPages
. .Site.Pages
- это коллекция всех объектов сайта: страниц, разделов, таксономий и т.д. Его можно использовать, чтобы вывести, скажем, теги и категории, созданные в течение выбранного года. А для фильтрации нужных типов можно использовать функцию where. Но как по мне, более логично использовать записи из свойства .Site.RegularPages
, в котором уже заранее отфильтрованы только страницы (нужно обратить внимание, что будут включены все страницы из папки content
, а не только записи из папки content/posts
). И так, итоговый код будет выглядеть вот так:
{{ define "main" }}
<div class="archive">
{{ range .Site.RegularPages.GroupByDate "2006" }}
<h2 class="archive-year">{{ .Key }}</h2>
{{ range .Pages }}
<div class="post-item">
{{ partial "partials/post/post-info-short" . }}
<a href="{{ .RelPermalink }}" class="post-title-link">{{ .Title }}</a>
</div>
{{ end }}
{{ end }}
</div>
{{ end }}
И мы увидим все статьи сайта, именно, так как мы хотели:
Если мы сгенерируем сайт и посмотрим содержимое папки public/archives
, то увидим там только файлы index.html
и index.xml
.
Так как нет записей с таксономией archives
, hugo сгенерирует только “пустой” список страниц и больше ничего. Это означает, что на сайте не будет случайных “мусорных” страниц. А в index.html
будет содержаться сгенерированный нами список страниц, разбитый по годом, без пагинации.