Создание списка подарков для Hugo блога Link to heading

Иногда хочется иметь возможность делиться с друзьями списком желаний или подарков (wishlist), которые бы хотелось получить. В этом посте я покажу, как создать такую функцию для блога на движке Hugo.

Что мы будем создавать? Link to heading

Мы создадим отдельную страницу в блоге, на которой будут отображаться товары из JSON файла с возможностью отслеживать статус заказа (заказан/не заказан), изображениями и ссылками для покупки.

Реализация Link to heading

Шаг 1: Создание файла данных Link to heading

Сначала создадим директорию data в корне проекта Hugo и файл wishlist.json:

mkdir -p data

Файл data/wishlist.json будет содержать информацию о товарах:

[
  {
    "id": 1,
    "name": "Retroid Pocket5",
    "image": "/images/products/pocket.webp",
    "link": "https://www.ozon.ru/product/igrovaya-konsol-retroid-pocket5-rp5-vysokoproizvoditelnaya-portativnaya-igrovaya-konsol-android-2342879320/",
    "ordered": false,
    "price": "18509₽",
    "notes": "Игровая консоль"
  },
  {
    "id": 2,
    "name": "AULA F99",
    "image": "/images/products/AULAF99.webp",
    "link": "https://www.ozon.ru/product/aula-klaviatura-igrovaya-klaviatura-besprovodnaya-igrovaya-klaviatura-besprovodnaya-aula-2261788753/",
    "ordered": false,
    "price": "5510₽",
    "notes": "Механическая клавиатура AULA F99"
  }
]

Каждый товар имеет следующие поля:

  • id: уникальный идентификатор
  • name: название товара
  • image: путь к изображению
  • link: ссылка для покупки
  • ordered: статус заказа (true/false)
  • price: цена
  • notes: примечания

Шаг 2: Создание шаблона для отображения Link to heading

Теперь создадим шаблон для отображения списка подарков. Создайте директорию для шаблонов:

mkdir -p layouts/wishlist

Создайте файл layouts/wishlist/list.html:

{{ define "title" }}
  {{ .Title }} · {{ .Site.Title }}
{{ end }}

{{ define "content" }}
  <section class="container list">
    <header>
      <h1 class="title">
        <a class="title-link" href="{{ .Permalink | safeURL }}">
          {{ .Title }}
        </a>
      </h1>
    </header>
    {{ .Content }}
    
    <!-- Вставляем содержимое Wishlist -->
    {{ partial "wishlist-content" . }}
  </section>
{{ end }}

Шаг 3: Создание partial для содержимого Link to heading

Создайте директорию для partials:

mkdir -p layouts/partials

Создайте файл layouts/partials/wishlist-content.html:

{{ if $.Site.Data.wishlist }}
  <div class="wishlist-container">
    <div class="wishlist-grid">
      {{ range $.Site.Data.wishlist }}
        <div class="wishlist-item {{ if .ordered }}ordered{{ else }}not-ordered{{ end }}">
          <div class="wishlist-image">
            <a href="{{ .link }}" target="_blank">
              <img src="{{ .image }}" alt="{{ .name }}" onerror="this.onerror=null; this.src='data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\' width=\'200\' height=\'200\' viewBox=\'0 0 24 24\' fill=\'none\' stroke=\'%23ccc\' stroke-width=\'2\' stroke-linecap=\'round\' stroke-linejoin=\'round\'><rect x=\'3\' y=\'3\' width=\'18\' height=\'18\' rx=\'2\' ry=\'2\'></rect><circle cx=\'8.5\' cy=\'8.5\' r=\'1.5\'></circle><polyline points=\'21 15 16 10 5 21\'></polyline></svg>;'/>
            </a>
          </div>
          <div class="wishlist-details">
            <h3 class="wishlist-name">
              <a href="{{ .link }}" target="_blank">{{ .name }}</a>
            </h3>
            <p class="wishlist-price">{{ .price }}</p>
            <p class="wishlist-notes">{{ .notes }}</p>
            <div class="wishlist-status">
              Статус: 
              <span class="status-badge {{ if .ordered }}ordered{{ else }}not-ordered{{ end }}">
                {{ if .ordered }}Заказано{{ else }}Не заказано{{ end }}
              </span>
            </div>
          </div>
        </div>
      {{ else }}
        <p>Список желаний пуст или данные не загружены.</p>
      {{ end }}
    </div>
  </div>

  <style>
    .wishlist-container {
      margin-top: 2rem;
    }

    .wishlist-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
      gap: 1.5rem;
      margin-top: 1rem;
    }

    .wishlist-item {
      border: 1px solid #ddd;
      border-radius: 8px;
      padding: 1rem;
      background-color: #f9f9f9;
      transition: box-shadow 0.3s ease;
      box-shadow: 0 2px 4px rgba(0,0,0,0.05);
    }

    .wishlist-item:hover {
      box-shadow: 0 4px 8px rgba(0,0,0,0.1);
    }

    .wishlist-item.ordered {
      border-left: 4px solid #4caf50;
      background-color: #f1f8e9;
    }

    .wishlist-item.not-ordered {
      border-left: 4px solid #ff9800;
      background-color: #fff8e1;
    }

    .wishlist-image {
      text-align: center;
      margin-bottom: 1rem;
    }

    .wishlist-image img {
      max-width: 100%;
      height: auto;
      border-radius: 4px;
      object-fit: cover;
      aspect-ratio: 1/1;
    }

    .wishlist-name {
      margin: 0 0 0.5rem 0;
    }

    .wishlist-name a {
      text-decoration: none;
      color: #333;
    }

    .wishlist-name a:hover {
      color: #4285f4;
    }

    .wishlist-price {
      font-weight: bold;
      color: #e91e63;
      margin: 0.5rem 0;
    }

    .wishlist-notes {
      color: #666;
      margin: 0.5rem 0;
      font-size: 0.9em;
    }

    .wishlist-status {
      margin-top: 1rem;
      font-weight: bold;
    }

    .status-badge {
      padding: 0.25rem 0.5rem;
      border-radius: 4px;
      font-size: 0.9em;
    }

    .status-badge.ordered {
      background-color: #e8f5e9;
      color: #4caf50;
    }

    .status-badge.not-ordered {
      background-color: #fff3e0;
      color: #ff9800;
    }
  </style>
{{ else }}
  <p>Данные не найдены в $.Site.Data.wishlist</p>
{{ end }}

Шаг 4: Создание страницы для списка подарков Link to heading

Теперь создадим файл содержимого для раздела. Создайте директорию:

mkdir -p content/wishlist

Создайте файл content/wishlist/_index.md:

---
title: "Whishlist"
date: 2026-01-19T14:00:00+03:00
draft: false
---

Вот мой личный список подарков. Товары, помеченные как "Заказано", уже были куплены.

Шаг 5: Обновление меню Link to heading

Добавим ссылку на страницу списка подарков в меню сайта, обновив файл hugo.toml:

[[menu.main]]
name = "Wishlist"
weight = 6
url = "wishlist/"

Использование Link to heading

После создания всех необходимых файлов, список подарков будет доступен по адресу /wishlist/. Для добавления новых товаров достаточно обновить файл data/wishlist.json.

Для каждого товара можно указать следующие поля в файле data/wishlist.json:

  • id: уникальный идентификатор товара (число)
  • name: название товара (строка)
  • image: путь к изображению товара (строка) - это поле используется для указания изображения
  • link: ссылка для покупки товара (строка) - это поле содержит URL для перехода к покупке
  • ordered: статус заказа (булевое значение true/false) - это поле определяет, заказан товар или нет
  • price: цена товара (строка) - это поле отображает стоимость
  • notes: примечания о товаре (строка) - это поле содержит дополнительную информацию

Особенности реализации Link to heading

  • Использование раздела (section) позволяет создать отдельную страницу с собственным шаблоном
  • Адаптивная сетка для отображения товаров
  • Разные стили для заказанных и не заказанных товаров
  • Автоматическая подстановка резервного изображения при отсутствии оригинала
  • Использование partial позволяет повторно использовать код отображения

Заключение Link to heading

Теперь у вас есть полнофункциональный список подарков на вашем Hugo сайте.