20b67f11e0
TOC:
- renderMarkdownWithToc: парсит h2/h3, генерит транслит-якоря для кириллицы, возвращает {html, toc}
- TableOfContents компонент: sticky на десктопе, раскрывающийся блок на мобиле
- IntersectionObserver-free подсветка активной секции через scroll listener
- Двухколоночный layout статьи на lg+: 240px TOC + контент
SVG-обложки:
- ArticleCoverSVG: процедурно сгенерированная композиция (curve/circle/arc/rect) по seed = id статьи
- 6 палитр на выбор (emerald/teal/yellow/blue/purple/orange), seed детерминированный
- Используется в ArticleCard как fallback когда cover_url пусто
- На странице статьи тоже SVG если обложки нет
- Тег статьи отображается лейблом в углу
Архив:
- /archive: все статьи сгруппированы по месяцам, компактный список
- В Header добавлен пункт Архив (desktop+mobile)
- В Footer ссылки на Архив, Заметки, О проекте
- В sitemap.xml включён /archive
42 lines
1.4 KiB
JavaScript
42 lines
1.4 KiB
JavaScript
import { listArticles, listTags, listSeries } from '@/lib/engine';
|
|
|
|
const SITE = 'https://zeropost.ru';
|
|
|
|
export default async function sitemap() {
|
|
const [articles, tags, series] = await Promise.all([
|
|
listArticles({ limit: 200 }).catch(() => []),
|
|
listTags().catch(() => []),
|
|
listSeries().catch(() => []),
|
|
]);
|
|
|
|
const staticPages = [
|
|
{ url: `${SITE}/`, lastModified: new Date(), changeFrequency: 'daily', priority: 1 },
|
|
{ url: `${SITE}/about`, lastModified: new Date(), changeFrequency: 'monthly', priority: 0.5 },
|
|
{ url: `${SITE}/notes`, lastModified: new Date(), changeFrequency: 'daily', priority: 0.6 },
|
|
{ url: `${SITE}/archive`, lastModified: new Date(), changeFrequency: 'daily', priority: 0.7 },
|
|
];
|
|
|
|
const articlePages = articles.map(a => ({
|
|
url: `${SITE}/blog/${a.slug}`,
|
|
lastModified: a.published_at ? new Date(a.published_at) : new Date(),
|
|
changeFrequency: 'monthly',
|
|
priority: 0.8,
|
|
}));
|
|
|
|
const tagPages = tags.map(t => ({
|
|
url: `${SITE}/tag/${encodeURIComponent(t.tag)}`,
|
|
lastModified: new Date(),
|
|
changeFrequency: 'weekly',
|
|
priority: 0.6,
|
|
}));
|
|
|
|
const seriesPages = series.map(s => ({
|
|
url: `${SITE}/series/${s.slug}`,
|
|
lastModified: s.updated_at ? new Date(s.updated_at) : new Date(),
|
|
changeFrequency: 'weekly',
|
|
priority: 0.7,
|
|
}));
|
|
|
|
return [...staticPages, ...articlePages, ...seriesPages, ...tagPages];
|
|
}
|