Новые изменения в компоенты

This commit is contained in:
Web-serfer 2026-04-26 22:45:19 +05:00
parent a14c18542e
commit faf02848ed
3 changed files with 33 additions and 19 deletions

View file

@ -27,7 +27,7 @@ const { items } = Astro.props;
</aside>
)}
<style>
<style is:global>
.toc-container { width: 100%; }
.toc-nav {
background: #ffffff;
@ -43,6 +43,7 @@ const { items } = Astro.props;
margin: 0 0 1.25rem;
padding-bottom: 0.75rem;
border-bottom: 2px solid #eac26e;
text-align: center;
}
.toc-list {
@ -55,10 +56,19 @@ const { items } = Astro.props;
gap: 0.25rem;
}
/* ЧЕРНАЯ НУМЕРАЦИЯ */
.toc-item.level-2 { counter-reset: toc-h3; counter-increment: toc-h2; }
/* Поддержка level=1 (из HTML h2) и level=2/3 */
.toc-item.level-1, .toc-item.level-2 { counter-reset: toc-h3; counter-increment: toc-h2; }
.toc-item.level-3 { counter-increment: toc-h3; padding-left: 1.25rem; }
/* h2 = level 1 в HTML */
.toc-item.level-1, .toc-item.level-2 {
font-weight: 600;
}
.toc-item.level-1 .toc-link, .toc-item.level-2 .toc-link {
font-size: 0.95rem;
padding: 0.6rem 0.75rem;
}
.toc-link {
display: flex;
padding: 0.5rem 0.75rem;
@ -70,19 +80,21 @@ const { items } = Astro.props;
transition: all 0.2s ease;
}
/* Номера в оглавлении */
.toc-link::before {
content: "";
display: inline-block;
width: 1.5rem;
color: #1e3050;
font-weight: 700;
margin-right: 0.6rem;
flex-shrink: 0;
text-align: center;
}
.level-2 .toc-link::before { content: counter(toc-h2) "."; }
.level-3 .toc-link::before { content: counter(toc-h2) "." counter(toc-h3) "."; font-size: 0.85em; opacity: 0.7; }
.toc-item.level-1 .toc-link::before, .toc-item.level-2 .toc-link::before { content: counter(toc-h2) "."; }
.toc-item.level-3 .toc-link::before { content: counter(toc-h2) "." counter(toc-h3) "."; font-size: 0.85em; opacity: 0.7; }
.toc-link:hover { color: #1e3050; background: #f1f5f9; }
/* АКТИВНЫЙ ПУНКТ (При скролле) */
.toc-item.active .toc-link {
color: #eac26e;
font-weight: 700;

View file

@ -147,14 +147,17 @@ export async function getPostBySlug(slug: string): Promise<Post | null> {
return result.items[0] as unknown as Post;
}
export async function getAllCategories(): Promise<string[]> {
const result = await pb.collection('posts').getFullList({
filter: 'draft = false',
fields: 'category',
});
export const FIXED_BLOG_CATEGORIES = [
'ДТП',
'Лишение прав',
'Страховые споры',
'Штрафы ГИБДД',
'Возмещение ущерба',
'Судебные дела',
];
const categories = (result || []).map((post) => post.category as string).filter(Boolean);
return ['Все', ...new Set(categories)];
export async function getAllCategories(): Promise<string[]> {
return ['Все', ...FIXED_BLOG_CATEGORIES];
}
export function getPostImageUrl(post: { image?: string }): string {

View file

@ -26,18 +26,17 @@ const { likes = 0, dislikes = 0 } = await getPostVotesStats(post.id).catch(() =>
// Конвертируем markdown в HTML
const contentHtml = marked(post.content || '');
// Извлекаем заголовки для оглавления
const headingRegex = /^(#{2,3})\s+(.+)$/gm;
// Извлекаем заголовки для оглавления (поддержка HTML и Markdown)
const headingRegex = /<h([2-3])[^>]*>([^<]+)<\/?h[2-3]>/gi;
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 level = parseInt(match[1]); // Теперь 2 или 3
const text = match[2].trim();
tocItems.push({ level, id: `heading-${headingIndex++}`, text });
}
console.log('[DEBUG] tocItems:', JSON.stringify(tocItems));
const formatDate = (date: string) => {
const d = new Date(date);
const day = d.getDate().toString().padStart(2, '0');
@ -90,7 +89,7 @@ const heroImage = getPostImageUrl(post);
<RelatedPosts posts={filteredRelated} currentSlug={slug} />
*/}
<!-- Оглавление - пробуем без slot -->
<!-- Оглавление -->
<div slot="sidebar">
<ArticleTableOfContents items={tocItems} />
</div>