110 lines
2.8 KiB
Plaintext
110 lines
2.8 KiB
Plaintext
|
|
---
|
||
|
|
|
||
|
|
import { getProfileArticleById } from '@api/posts.js';
|
||
|
|
|
||
|
|
import MainLayout from '@layouts/MainLayout.astro';
|
||
|
|
|
||
|
|
export const prerender = false; // динамический роутинг
|
||
|
|
const { category, slug } = Astro.params;
|
||
|
|
|
||
|
|
// ищем ID поста
|
||
|
|
function findPostId(slug) {
|
||
|
|
|
||
|
|
const lastItem = Array.isArray(slug) ? slug[slug.length - 1] : slug;
|
||
|
|
|
||
|
|
// Находим последний дефис
|
||
|
|
const dashIndex = lastItem.lastIndexOf('-');
|
||
|
|
if (dashIndex === -1) return null;
|
||
|
|
|
||
|
|
// Берем всё после дефиса
|
||
|
|
const idStr = lastItem.substring(dashIndex + 1);
|
||
|
|
|
||
|
|
// Преобразуем в число
|
||
|
|
const id = Number(idStr);
|
||
|
|
return Number.isInteger(id) ? id : null;
|
||
|
|
}
|
||
|
|
|
||
|
|
const postId = findPostId(slug);
|
||
|
|
|
||
|
|
let article;
|
||
|
|
|
||
|
|
try {
|
||
|
|
article = await getProfileArticleById(postId);
|
||
|
|
} catch (error) {
|
||
|
|
return Astro.redirect('/404');
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!article) {
|
||
|
|
return Astro.redirect('/404');
|
||
|
|
}
|
||
|
|
|
||
|
|
// Валидация: проверяем категорию
|
||
|
|
const articleCategory = article.categories?.nodes?.[0]?.slug;
|
||
|
|
|
||
|
|
|
||
|
|
// Если категория не совпадает, делаем редирект
|
||
|
|
if (articleCategory && category !== articleCategory) {
|
||
|
|
debugLog(`Редирект: категория не совпадает (${category} != ${articleCategory})`);
|
||
|
|
|
||
|
|
// Строим правильный URL
|
||
|
|
const correctUri = article.uri
|
||
|
|
.replace(/^\//, '')
|
||
|
|
.replace(/\/$/, '');
|
||
|
|
|
||
|
|
return Astro.redirect(`/${correctUri}/`, 301);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Валидация: проверяем полный путь
|
||
|
|
const currentPath = `${category}/${Array.isArray(slug) ? slug.join('/') : slug}`;
|
||
|
|
const correctPath = article.uri
|
||
|
|
.replace(/^\//, '')
|
||
|
|
.replace(/\/$/, '');
|
||
|
|
|
||
|
|
if (currentPath !== correctPath) {
|
||
|
|
debugLog(`Редирект: путь не совпадает (${currentPath} != ${correctPath})`);
|
||
|
|
return Astro.redirect(`/${correctPath}/`, 301);
|
||
|
|
}
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
|
||
|
|
<MainLayout
|
||
|
|
title={article.title}
|
||
|
|
description="Информационное агентство Деловой журнал Профиль"
|
||
|
|
>
|
||
|
|
|
||
|
|
<h1 class="article-title">{article.title}</h1>
|
||
|
|
|
||
|
|
{article.tags?.nodes?.length > 0 && (
|
||
|
|
<div class="tags-list">
|
||
|
|
<strong>Метки:</strong>
|
||
|
|
{article.tags.nodes.map(tag => (
|
||
|
|
<a href={tag.uri} class="tag" key={tag.id}>{tag.name}</a>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
|
||
|
|
{article.featuredImage?.node?.sourceUrl && (
|
||
|
|
<figure class="featured-image">
|
||
|
|
<img
|
||
|
|
src={article.featuredImage.node.sourceUrl}
|
||
|
|
alt={article.featuredImage.node.altText || article.title}
|
||
|
|
loading="eager"
|
||
|
|
class="article-image"
|
||
|
|
/>
|
||
|
|
{article.featuredImage.node.caption && (
|
||
|
|
<figcaption class="image-caption" set:html={article.featuredImage.node.caption} />
|
||
|
|
)}
|
||
|
|
</figure>
|
||
|
|
)}
|
||
|
|
|
||
|
|
<div class="article-content" set:html={article.content} />
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
</MainLayout>
|
||
|
|
|
||
|
|
|