2026-01-20 02:31:21 +03:00
|
|
|
|
import { getPostData, getAllPostSlugs } from '@/lib/posts';
|
|
|
|
|
|
import { notFound } from 'next/navigation';
|
|
|
|
|
|
import Link from 'next/link';
|
2026-01-20 04:17:03 +03:00
|
|
|
|
import "@/app/markdown.css";
|
2026-01-20 02:31:21 +03:00
|
|
|
|
|
|
|
|
|
|
interface PostPageProps {
|
|
|
|
|
|
params: Promise<{ slug: string }>;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export async function generateStaticParams() {
|
|
|
|
|
|
const slugs = getAllPostSlugs();
|
|
|
|
|
|
console.log('Генерация статических путей для slugs:', slugs);
|
|
|
|
|
|
|
|
|
|
|
|
return slugs.map((slug) => ({
|
|
|
|
|
|
slug,
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export async function generateMetadata({ params }: PostPageProps) {
|
|
|
|
|
|
const { slug } = await params;
|
|
|
|
|
|
const post = await getPostData(slug);
|
|
|
|
|
|
|
|
|
|
|
|
if (!post) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
title: 'Пост не найден',
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
title: post.title,
|
|
|
|
|
|
description: post.description,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export default async function PostPage({ params }: PostPageProps) {
|
|
|
|
|
|
const { slug } = await params;
|
|
|
|
|
|
const post = await getPostData(slug);
|
|
|
|
|
|
|
|
|
|
|
|
console.log(`Загрузка поста: ${slug}, результат:`, post ? 'найден' : 'не найден');
|
|
|
|
|
|
|
|
|
|
|
|
if (!post) {
|
|
|
|
|
|
notFound();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const formatDate = (dateStr: string) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const date = new Date(dateStr);
|
|
|
|
|
|
return new Intl.DateTimeFormat('ru-RU', {
|
|
|
|
|
|
weekday: 'long',
|
|
|
|
|
|
year: 'numeric',
|
|
|
|
|
|
month: 'long',
|
|
|
|
|
|
day: 'numeric',
|
|
|
|
|
|
}).format(date);
|
|
|
|
|
|
} catch {
|
|
|
|
|
|
return dateStr;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<>
|
|
|
|
|
|
<main className="flex flex-col gap-[32px] row-start-2 items-center">
|
2026-02-05 12:39:59 +03:00
|
|
|
|
<section className="space-y-1 text-center max-w-4xl w-full px-4 mt-2 pt-[1em]">
|
2026-01-20 02:31:21 +03:00
|
|
|
|
<dl className="space-y-10">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<dt className="sr-only">Опубликовано</dt>
|
|
|
|
|
|
<dd className="text-base leading-6 font-medium text-gray-500 dark:text-gray-400">
|
|
|
|
|
|
{formatDate(post.date)}
|
|
|
|
|
|
</dd>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</dl>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<h1 className="text-3xl leading-9 font-extrabold tracking-tight text-gray-900 sm:text-4xl sm:leading-10 md:text-5xl md:leading-14 dark:text-gray-100">
|
|
|
|
|
|
{post.title}
|
|
|
|
|
|
</h1>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
{post.tags.length > 0 && (
|
|
|
|
|
|
<div className="flex flex-wrap justify-center gap-2 mt-4">
|
|
|
|
|
|
{post.tags.map((tag) => (
|
|
|
|
|
|
<Link
|
|
|
|
|
|
key={tag}
|
|
|
|
|
|
href={`/tags/${tag}`}
|
|
|
|
|
|
className="inline-block border border-slate-400 px-3 py-1 rounded-full text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
|
|
|
|
|
|
>
|
|
|
|
|
|
{tag}
|
|
|
|
|
|
</Link>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</section>
|
|
|
|
|
|
<section className="mx-auto px-4 pb-[4em] w-full px-[3em]">
|
|
|
|
|
|
<article
|
2026-01-20 03:11:12 +03:00
|
|
|
|
className="markdown"
|
2026-01-20 02:31:21 +03:00
|
|
|
|
dangerouslySetInnerHTML={{ __html: post.contentHtml }}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
</main>
|
|
|
|
|
|
</>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|