Насторил работу блога через Backend

This commit is contained in:
Web-serfer 2026-04-15 02:12:25 +05:00
parent 014439d565
commit edd730b438
33 changed files with 1019 additions and 200 deletions

View file

@ -4,16 +4,10 @@ import { SITE_URL } from '@constants';
import PostCommentForm from '@components/blog/PostCommentForm.astro';
import RelatedPosts from '@components/blog/RelatedPosts.astro';
import ArticleTableOfContents from '@components/blog/ArticleTableOfContents.astro';
import { getCollection, getEntry, render } from 'astro:content';
import { getPostBySlug, getPosts } from '@lib/pb';
import { marked } from 'marked';
export const prerender = true;
export async function getStaticPaths() {
const posts = await getCollection('blog') as { id: string; data: Record<string, any> }[];
return posts.map((post: { id: string }) => ({
params: { slug: post.id },
}));
}
export const prerender = false;
const slug = Astro.params.slug;
@ -21,87 +15,77 @@ if (!slug) {
return Astro.redirect('/blog');
}
const post = await getEntry('blog', slug);
const post = await getPostBySlug(slug);
if (!post) {
return Astro.redirect('/blog');
}
const { Content } = await render(post);
// Конвертируем markdown в HTML
const contentHtml = marked(post.content || '');
// Извлекаем заголовки из MDX тела для оглавления
const body = post.body || '';
// Извлекаем заголовки для оглавления
const headingRegex = /^(#{2,3})\s+(.+)$/gm;
const tocItems: { id: string; text: string; level: number }[] = [];
const body = post.content || '';
let match;
let headingIndex = 0;
while ((match = headingRegex.exec(body)) !== null) {
const level = match[1].length;
const text = match[2].trim();
// Генерируем ID из текста заголовка
const id = text.toLowerCase()
.replace(/[^\w\s-]/g, '')
.replace(/\s+/g, '-');
tocItems.push({ level, id: `heading-${headingIndex++}`, text });
}
console.log('=== TOC ITEMS ===', tocItems);
// Форматируем дату
const formatDate = (date: Date) => {
return date.toLocaleDateString('ru-RU', {
const formatDate = (date: string) => {
return new Date(date).toLocaleDateString('ru-RU', {
day: 'numeric',
month: 'long',
year: 'numeric'
});
};
// Логика авторизации (пока статичная переменная)
const isAuthorized = false;
// Для related posts берем те же категории
const { posts: relatedPosts } = await getPosts({ perPage: 4, category: post.category });
const filteredRelated = relatedPosts.filter(p => p.slug !== slug).slice(0, 3);
// URL текущей страницы
const currentUrl = `${SITE_URL}/blog/${post.id}`;
// Получаем все посты для блока "Читайте также"
const allPosts = await getCollection('blog');
const currentUrl = `${SITE_URL}/blog/${slug}`;
---
<ArticleLayout
title={`${post.data.title} — автоюрист в Сургуте`}
description={post.data.description}
canonicalLink={`${SITE_URL}/blog/${post.id}`}
title={`${post.title} — автоюрист в Сургуте`}
description={post.description}
canonicalLink={`${SITE_URL}/blog/${slug}`}
breadcrumbs={[
{ label: 'Главная', href: '/' },
{ label: 'Блог', href: '/blog' },
{ label: post.data.title }
{ label: post.title }
]}
heroImage={post.data.imageUrl}
heroAlt={post.data.title}
category={post.data.category}
postTitle={post.data.title}
date={formatDate(post.data.date)}
author={post.data.author}
readTime={post.data.readTime}
heroImage={post.imageUrl}
heroAlt={post.title}
category={post.category}
postTitle={post.title}
date={formatDate(post.date)}
author={post.author}
readTime={post.readTime}
postId={post.id}
postUrl={currentUrl}
initialLikes={12}
initialDislikes={2}
>
<!-- Содержимое статьи -->
<div class="post-content">
<Content />
</div>
<div class="post-content" set:html={contentHtml} />
<!-- Форма комментариев -->
<PostCommentForm
postId={post.id}
isAuthorized={isAuthorized}
isAuthorized={false}
/>
<!-- Похожие статьи -->
<RelatedPosts
posts={allPosts}
currentSlug={post.id}
posts={filteredRelated}
currentSlug={slug}
/>
<!-- Оглавление в сайдбаре -->
@ -168,4 +152,4 @@ const allPosts = await getCollection('blog');
font-size: 1.25rem;
}
}
</style>
</style>