diff --git a/src/content/pages/inye-otrazheniya-amber-yantarnoe-korolevstvo.md b/src/content/pages/inye-otrazheniya-amber-yantarnoe-korolevstvo.md index 489df48..9dbaf5d 100644 --- a/src/content/pages/inye-otrazheniya-amber-yantarnoe-korolevstvo.md +++ b/src/content/pages/inye-otrazheniya-amber-yantarnoe-korolevstvo.md @@ -5,6 +5,7 @@ legacyId: "132" menuOrder: "4" pubDate: "2011-05-18T00:40:47+03:00" updatedDate: "2014-07-14T00:12:19+03:00" +description: "Игровая вселенная по «Хроникам Амбера» Роджера Желязны: Истинный мир, его Отражения и принцы крови с непростой семейной историей." --- Тест diff --git a/src/content/pages/inye-otrazheniya-kindret-krovnye-bratya.md b/src/content/pages/inye-otrazheniya-kindret-krovnye-bratya.md index 7d63ccb..75804d5 100644 --- a/src/content/pages/inye-otrazheniya-kindret-krovnye-bratya.md +++ b/src/content/pages/inye-otrazheniya-kindret-krovnye-bratya.md @@ -5,6 +5,7 @@ legacyId: "130" menuOrder: "5" pubDate: "2011-05-18T00:39:40+03:00" updatedDate: "2014-07-14T00:12:27+03:00" +description: "Ролевая игра по циклу «Киндрэт» Алексея Пехова, Елены Бычковой и Натальи Турчаниновой: вампирские кланы ночной Столицы и их теневая политика." --- «Киндрэт. Кровные братья» — первая книга цикла Киндрэт известных российских писателей Алексея Пехова, Елены Бычковой и Натальи Турчаниновой, рассказывающая о жизни кланов вампиров. В цикл романов по миру ночной Столицы вошли 4 книги: «Кровные братья», «Колдун из клана смерти», «Основатель», «Новые боги». diff --git a/src/content/pages/inye-otrazheniya-sumerki-dozorov.md b/src/content/pages/inye-otrazheniya-sumerki-dozorov.md index a27a673..15affa3 100644 --- a/src/content/pages/inye-otrazheniya-sumerki-dozorov.md +++ b/src/content/pages/inye-otrazheniya-sumerki-dozorov.md @@ -5,6 +5,7 @@ legacyId: "124" menuOrder: "3" pubDate: "2011-05-18T00:27:35+03:00" updatedDate: "2014-07-14T00:12:09+03:00" +description: "Главная ролевая игра «Иных Отражений» по миру «Дозоров» Сергея Лукьяненко и Владимира Васильева: Иные, Свет и Тьма, древний Договор." --- **Иные Отражения: Сумерки Дозоров** diff --git a/src/content/pages/nashi-druzya.md b/src/content/pages/nashi-druzya.md index 34f4db1..79d3e86 100644 --- a/src/content/pages/nashi-druzya.md +++ b/src/content/pages/nashi-druzya.md @@ -5,6 +5,7 @@ legacyId: "339" menuOrder: "2" pubDate: "2013-07-09T13:29:47+03:00" updatedDate: "2025-06-07T02:31:08+03:00" +description: "Партнёры и друзья ролевой группы «Иные Отражения»: ООО «АйТи Решения» (hhivp.com) — IT-услуги для бизнеса в Москве и области." --- [ООО "АйТи Решения"](https://hhivp.com) предоставляет полный спектр IT услуг на территории Москвы и Московской области, как частным лицам, так и представителям бизнеса. Мы способствуем развитию Вашего бизнеса и достижению самых смелых результатов! diff --git a/src/content/pages/o-nas.md b/src/content/pages/o-nas.md index 1452048..0acc108 100644 --- a/src/content/pages/o-nas.md +++ b/src/content/pages/o-nas.md @@ -5,6 +5,7 @@ legacyId: "137" menuOrder: "1" pubDate: "2011-05-18T00:50:11+03:00" updatedDate: "2014-07-14T00:10:31+03:00" +description: "История ролевой группы «Иные Отражения»: основана в 2006 году как «Иные Миры», в 2007-м объединилась с проектом «Отражения»." --- **Ролевая группа "Иные Отражения"** diff --git a/src/content/pages/renessans.md b/src/content/pages/renessans.md index d585a70..2a4beb2 100644 --- a/src/content/pages/renessans.md +++ b/src/content/pages/renessans.md @@ -5,6 +5,7 @@ legacyId: "378" menuOrder: "6" pubDate: "2013-10-06T02:59:22+03:00" updatedDate: "2014-07-14T00:12:33+03:00" +description: "«Ренессанс» — ролевая игра по миру «Дозоров» Сергея Лукьяненко: Иные, Сумрак и древний Договор в декорациях эпохи Возрождения." --- **Иные Отражения: Ренессанс** diff --git a/src/pages/[slug].astro b/src/pages/[slug].astro index 057b44e..fe8be9e 100644 --- a/src/pages/[slug].astro +++ b/src/pages/[slug].astro @@ -6,13 +6,27 @@ import { CATEGORY_COLORS } from '../consts'; export async function getStaticPaths() { const posts = await getCollection('posts'); const pages = await getCollection('pages'); + + // Считаем сколько постов с одинаковым {title, year} — если >1, в SEO-title + // подставим полную дату, иначе только год. + const titleYearCount = new Map(); + for (const p of posts) { + const key = `${p.data.title}|${p.data.pubDate.getFullYear()}`; + titleYearCount.set(key, (titleYearCount.get(key) ?? 0) + 1); + } + return [ - ...posts.map((p) => ({ params: { slug: p.data.slug }, props: { entry: p, kind: 'post' as const } })), - ...pages.map((p) => ({ params: { slug: p.data.slug }, props: { entry: p, kind: 'page' as const } })), + ...posts.map((p) => { + const year = p.data.pubDate.getFullYear(); + const key = `${p.data.title}|${year}`; + const sameYearDup = (titleYearCount.get(key) ?? 1) > 1; + return { params: { slug: p.data.slug }, props: { entry: p, kind: 'post' as const, sameYearDup } }; + }), + ...pages.map((p) => ({ params: { slug: p.data.slug }, props: { entry: p, kind: 'page' as const, sameYearDup: false } })), ]; } -const { entry, kind } = Astro.props; +const { entry, kind, sameYearDup } = Astro.props; const { Content } = await render(entry); // Буквица — только для постов с телом длиннее короткого порога. const bodyLen = entry.body?.length ?? 0; @@ -20,10 +34,18 @@ const useDropCap = kind === 'post' && bodyLen > 240; const fmtDate = (d: Date) => d.toLocaleDateString('ru-RU', { year: 'numeric', month: 'long', day: 'numeric' }); + +// Короткая дата без "г." для SEO-title постов с одинаковым названием в одном году. +const fmtDateForTitle = (d: Date) => + d.toLocaleDateString('ru-RU', { year: 'numeric', month: 'long', day: 'numeric' }).replace(/\sг\.?$/, ''); + +const seoTitle = kind === 'post' + ? `${entry.data.title} (${sameYearDup ? fmtDateForTitle(entry.data.pubDate) : entry.data.pubDate.getFullYear()})` + : entry.data.title; ---
diff --git a/src/pages/category/[slug].astro b/src/pages/category/[slug].astro index acc4517..27faa6e 100644 --- a/src/pages/category/[slug].astro +++ b/src/pages/category/[slug].astro @@ -27,8 +27,18 @@ const sorted = posts.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.va const fmtDate = (d: Date) => d.toLocaleDateString('ru-RU', { year: 'numeric', month: 'long', day: 'numeric' }); + +const yearsRange = (() => { + if (!sorted.length) return ''; + const years = sorted.map((p) => p.data.pubDate.getFullYear()); + const min = Math.min(...years); + const max = Math.max(...years); + return min === max ? `${min}` : `${min}–${max}`; +})(); +const pubWord = plural(sorted.length, ['публикация', 'публикации', 'публикаций']); +const catDescription = `${name} — ${sorted.length} ${pubWord}${yearsRange ? ` (${yearsRange})` : ''} в архиве ролевой группы «Иные Отражения».`; --- - +
Категория

{name}

diff --git a/src/pages/index.astro b/src/pages/index.astro index 16eb7c8..50f7f01 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -13,7 +13,7 @@ const oldestYear = posts.length ? posts[posts.length - 1].data.pubDate.getFullYe const fmtDate = (d: Date) => d.toLocaleDateString('ru-RU', { year: 'numeric', month: 'long', day: 'numeric' }); --- - +
Ролевой проект · с {SITE_FOUNDED} года

Иные
Отражения