Серия знает о себе всё
«Часть 2 из 3» в кикере, оглавление серии слева, мост со шкалой внизу и «осталось ~5 мин» — ничего из этого не набрано руками. Разберём арифметику серий: она проще, чем выглядит, и вся происходит на сборке.
#Оглавление руками
Наивная модель: серия — это когда в конце каждой статьи стоит список ссылок на остальные. Работает ровно до второго изменения. Добавил четвёртую часть — иди обнови три старых статьи. Переставил части местами — «часть 3 из 7» в заголовках теперь врёт, и хорошо, если ты вспомнил про все семь. Оглавление, размазанное по статьям, устаревает в момент любой правки — потому что источников правды столько же, сколько частей.
Хуже того: половина серийной механики вообще не выражается ссылками руками. «Осталось ~9 минут до конца серии» — это арифметика по всем частям сразу; ни одна статья в одиночку такого про себя не знает.
#Папка, а не поле
Здесь у серии один источник правды. Часть почти ничего о себе не объявляет — она просто лежит в папке серии, под-секции рубрики:
content/inside/ — папка этой самой серииcontent/inside/
anatomy/ ← серия
_index.md ← метаданные серии: title, description, порядок
guide-is-a-bundle/ ← часть, weight: 10
series-knows-itself/ ← часть, weight: 20 — ты здесь
palette-is-a-file/ ← часть, weight: 30Это папка статьи, которую ты сейчас читаешь, — можешь сверить с кикером над заголовком. Членство — это расположение; единственное, что часть несёт сама, — weight во front matter, её порядок среди частей. Всё остальное вычисляется на сборке: части сортируются по weight, номер «N» — позиция в отсортированном списке, «M» — его длина. Заметь: порядок задаёт вес, а не даты публикации — переставить части местами можно, не переписывая историю ленты.
Из того же отсортированного списка собирается всё серийное на странице. Кикер склеивается из трёх независимых источников: метка рубрики (front matter секции), заголовок серии (front matter её _index.md) и вычисленное «часть N из M». Панель слева — оглавление с отметкой текущей части. Мост внизу — соседи prev/next плюс шкала прогресса. Один список — четыре потребителя.
Вот как выглядит наша серия глазами сборки:
Подсвеченная ячейка — статья, внутри которой ты находишься. Наведи на соседние: у каждой в тултипе её вес и минуты.
Заголовок серии, описание и порядок на странице рубрики — тоже не магия: это front matter _index.md её папки — здесь это content/inside/anatomy/_index.md (каркас создаётся командой hugo new content inside/anatomy/_index.md --kind series). Тот же файл даёт серии лендинг по адресу /inside/anatomy/: заголовок с тэглайном, описание, тело самого файла как эпиграф, список частей и кнопку «начать серию». Ссылки «вся серия» в панели и мосте ведут именно туда; на странице рубрики та же серия стоит блоком с якорем. А серия, анонсированная _index.md без единой части, — не ошибка: рубрика покажет её тизером «готовится», а лендинг отрендерит анонс.
Контекст серии разрешает хелпер-партиал article/series-ctx.html: серия — это просто .CurrentSection страницы, когда та лежит глубже своей рубрики, а части — обычные страницы этой секции, по возрастанию weight — дефолтная сортировка Hugo. Мост берёт оттуда позицию: prev/next — соседи по списку, шкала — flex-grow: mins каждой части, «осталось ~N мин» — сумма mins частей после текущей.
#Проверь арифметику
Формула моста настолько короткая, что её можно пересчитать прямо здесь. Виджет ниже гоняет ту же логику по числам этой самой серии:
Заметь: числа в виджете совпадают с диаграммой выше и с настоящим мостом внизу страницы. Так и задумано — источник у всех трёх один.
А что со статьями вне серий? У них тот же кикер, только вместо «часть N из M» — «разбор», а панель слева наполняется из поля related во front matter: три-пять ссылок на близкие гайды. Серия — не обязанность, а опция.
Теперь ты можешь собрать серию из любых гайдов, сложив их в одну папку, — и переставлять части, меняя один weight, а не N статей.
#Что дальше
Мост внизу уже посчитал, что осталась одна часть. В ней — про цвет: почему все семь палитр этой страницы живут в data-файлах и как добавить свою, не тронув ни строчки темы.