Eleventy з коробки вміє групувати статті за тегами, але справжніх категорій, та ще й вкладених (як на цьому блозі: «Софт» → «Windows», «Linux», «Android»), у ньому немає. Колись я зробив їх досить «криворуким» способом: окремий файл для кожної категорії, окрема колекція, вручну прописаний список посилань. Тоді я попросив у читачів підказати, як зробити розумніше. З часом спосіб знайшовся сам, і він набагато простіший.
Нижче покажу, як зробити в Eleventy категорії з ієрархією, автоматичні сторінки категорій з посторінковою навігацією і посилання на категорію в кожній статті. Якщо ти тільки починаєш, спершу прочитай, як створити статичний сайт на Eleventy.
Ідея: категорія – це тека
Eleventy сам перетворює структуру тек на адреси сторінок, тому найлогічніше, щоб тека статті і була її категорією:
web/
php-html-css/
php-html-css.json
my-first-post/index.md
wordpress/
wordpress.json
theme-from-scratch/index.md
soft/
linux/
linux.json
best-distro/index.md
Стаття web/wordpress/theme-from-scratch/index.md відкриватиметься за адресою /web/wordpress/theme-from-scratch/, і вже з адреси видно, що вона в категорії «WordPress», яка вкладена у «Веб».
Крок 1. Назви категорій в одному місці
Усі категорії з їхніми назвами опиши в одному глобальному файлі даних _data/categories.json. Ключ – шлях теки, значення – назва, яку бачитиме відвідувач:
{
"web": "Веб",
"web/php-html-css": "PHP, HTML, CSS",
"web/wordpress": "WordPress",
"soft": "Софт",
"soft/linux": "Linux"
}
Це єдиний список, який доведеться доповнювати вручну, і він же стане основою для меню категорій.
Крок 2. Файл даних теки
В Eleventy є зручна штука – файл даних теки. Якщо покласти в теку JSON-файл з тією самою назвою, що й тека, його дані отримають усі сторінки в ній і в усіх підтеках. Тому в web/wordpress/wordpress.json пишемо:
{
"tags": "posts",
"categorySlug": "web/wordpress"
}
Тепер кожна стаття з цієї теки автоматично знає свою категорію і потрапляє в загальну колекцію posts, а у front matter самих статей нічого про категорію писати не треба.
Крок 3. Колекція сторінок категорій
Найхитріше місце. Сторінка категорії має показувати статті не тільки свої, а й з дочірніх категорій, і ділити їх на сторінки по 12 штук. Вбудована пагінація Eleventy вміє розбивати лише один список, тож заздалегідь підготуємо у файлі eleventy.config.js колекцію, де кожен елемент – це одна готова сторінка якоїсь категорії:
export default function (eleventyConfig) {
eleventyConfig.addCollection("categoryPages", function (collectionApi) {
const perPage = 12;
const byCategory = {};
// найновіші статті першими
for (const post of collectionApi.getFilteredByTag("posts").reverse()) {
// стаття потрапляє у свою категорію і в усі батьківські
const parts = post.data.categorySlug.split("/");
parts.forEach((part, i) => {
const slug = parts.slice(0, i + 1).join("/");
(byCategory[slug] ??= []).push(post);
});
}
const pages = [];
for (const [slug, posts] of Object.entries(byCategory)) {
const total = Math.ceil(posts.length / perPage);
for (let n = 1; n <= total; n++) {
pages.push({ slug, n, total, posts: posts.slice((n - 1) * perPage, n * perPage) });
}
}
return pages;
});
}
Якщо в «WordPress» 30 статей, у колекції з'являться три елементи для цієї категорії (12 + 12 + 6), а ці ж 30 статей потраплять і на сторінки батьківської категорії «Веб». Нова категорія підхоплюється автоматично, щойно в ній з'являється перша стаття.
Крок 4. Один шаблон для всіх категорій
Тепер створи в корені проєкту файл category.njk. Завдяки пагінації по одному елементу з нього згенерується окрема сторінка для кожного елемента колекції:
---
layout: base.njk
pagination:
data: collections.categoryPages
size: 1
alias: cat
permalink: "/category/{{ cat.slug }}/{% if cat.n > 1 %}page/{{ cat.n }}/{% endif %}"
eleventyComputed:
title: "{{ categories[cat.slug] }}"
---
<h1>{{ categories[cat.slug] }}</h1>
{% for post in cat.posts %}
<article>
<h2><a href="{{ post.url }}">{{ post.data.title }}</a></h2>
{% if post.data.description %}<p>{{ post.data.description }}</p>{% endif %}
</article>
{% endfor %}
{% if cat.total > 1 %}
<nav class="pagination">
{% if cat.n > 1 %}
<a href="/category/{{ cat.slug }}/{% if cat.n > 2 %}page/{{ cat.n - 1 }}/{% endif %}">← Новіші</a>
{% endif %}
<span>Сторінка {{ cat.n }} з {{ cat.total }}</span>
{% if cat.n < cat.total %}
<a href="/category/{{ cat.slug }}/page/{{ cat.n + 1 }}/">Старіші →</a>
{% endif %}
</nav>
{% endif %}
У результаті з'являться сторінки /category/web/, /category/web/wordpress/, /category/web/wordpress/page/2/ і так далі – без жодного окремого файлу для кожної категорії. Саме цього бракувало моєму старому способу: тоді для посторінкової навігації доводилося створювати окремий шаблон і окрему колекцію на кожну категорію.
Крок 5. Посилання на категорію в статті
Раніше це була найбільша морока: я тримав окремий список категорій з посиланнями і перебирав його циклом. Тепер у кожної статті вже є categorySlug, а назва лежить у categories, тож у шаблоні статті достатньо одного рядка:
<a href="/category/{{ categorySlug }}/">{{ categories[categorySlug] }}</a>
У списку статей на сторінці блогу дані кожної статті лежать у post.data:
<a href="/category/{{ post.data.categorySlug }}/">{{ categories[post.data.categorySlug] }}</a>
Крок 6. Меню категорій
Меню будуємо з того самого _data/categories.json. Рівень вкладеності легко визначити за кількістю частин у шляху, а далі вже справа CSS – наприклад, дати дочірнім пунктам відступ:
<nav class="categories">
{% for slug, title in categories %}
<a class="level-{{ slug.split('/').length }}" href="/category/{{ slug }}/">{{ title }}</a>
{% endfor %}
</nav>
Якщо ж хочеш справжнє вкладене меню з підсвіткою активного пункту, скористайся плагіном, про який я писав у статті меню в Eleventy через eleventy-navigation.
Як додати нову категорію
Скажімо, у «Веб» з'являється нова категорія «Drupal». Тепер це три кроки:
- Створити теку
web/drupalі писати в ній статті. - Покласти в неї файл
drupal.jsonз"tags": "posts"і"categorySlug": "web/drupal". - Додати рядок
"web/drupal": "Drupal"у_data/categories.json.
Сторінка категорії, посторінкова навігація і посилання в статтях з'являться самі.
Ще більше можливостей Eleventy, наприклад власні шорткоди і фільтри, зібрані за позначкою Eleventy, а інші генератори – за позначкою Статичні сайти.
А як ти організовуєш статті на своєму статичному сайті – тегами чи категоріями? Пиши в коментарях 🙂

Прокоментувати
На сайті відображається лише твоє ім'я та коментар. Електронна пошта зберігається виключно для зв'язку з тобою за потреби та в жодному разі не передається стороннім особам.