--- import BaseLayout from './BaseLayout.astro'; import Header from '../components/Header.astro'; import Footer from '../components/Footer.astro'; // import MiniKnowledgeGraph from '../components/MiniKnowledgeGraph.astro'; // Keep if needed elsewhere, but remove from main content import MiniGraph from '../components/MiniGraph.astro'; // Add import for MiniGraph import { getCollection } from 'astro:content'; interface Props { frontmatter: { title: string; description?: string; pubDate: Date; updatedDate?: Date; heroImage?: string; category?: string; tags?: string[]; readTime?: string; draft?: boolean; author?: string; // Field for explicitly related posts related_posts?: string[]; }, slug: string // Add slug to props } const { frontmatter, slug } = Astro.props; // Get all posts for finding related content const allPosts = await getCollection('posts'); // Create a currentPost object that matches the structure expected by MiniKnowledgeGraph const currentPost = { slug: slug, data: frontmatter }; // Find related posts - first from explicitly defined related_posts const explicitRelatedPosts = frontmatter.related_posts ? allPosts.filter(post => frontmatter.related_posts?.includes(post.slug) && post.slug !== slug ) : []; // Then find posts with shared tags (if we need more related posts) const MAX_RELATED_POSTS = 3; let relatedPostsByTags = []; if (explicitRelatedPosts.length < MAX_RELATED_POSTS && frontmatter.tags && frontmatter.tags.length > 0) { // Create a map of posts by tags for efficient lookup const postsByTag = new Map(); frontmatter.tags.forEach(tag => { postsByTag.set(tag, allPosts.filter(post => post.slug !== slug && post.data.tags?.includes(tag) && !explicitRelatedPosts.some(p => p.slug === post.slug) )); }); // Score posts by number of shared tags const scoredPosts = new Map(); postsByTag.forEach((posts, tag) => { posts.forEach(post => { const currentScore = scoredPosts.get(post.slug) || 0; scoredPosts.set(post.slug, currentScore + 1); }); }); // Convert to array, sort by score, and take what we need relatedPostsByTags = Array.from(scoredPosts.entries()) .sort((a, b) => b[1] - a[1]) .slice(0, MAX_RELATED_POSTS - explicitRelatedPosts.length) .map(([slug]) => allPosts.find(post => post.slug === slug)) .filter(Boolean); // Remove any undefined entries } // Combine explicit and tag-based related posts const relatedPosts = [...explicitRelatedPosts, ...relatedPostsByTags]; // Format date const formattedPubDate = frontmatter.pubDate ? new Date(frontmatter.pubDate).toLocaleDateString('en-us', { year: 'numeric', month: 'long', day: 'numeric', }) : 'N/A'; const formattedUpdatedDate = frontmatter.updatedDate ? new Date(frontmatter.updatedDate).toLocaleDateString('en-us', { year: 'numeric', month: 'long', day: 'numeric', }) : null; // Default image if heroImage is missing const displayImage = frontmatter.heroImage || '/images/placeholders/default.jpg'; ---
{/* Display Draft Badge if needed */} {frontmatter.draft && DRAFT} {/* Title */}

{frontmatter.title}

{/* Description */} {frontmatter.description &&

{frontmatter.description}

} {/* Metadata (Date, Read Time) */} {/* Tags */} {frontmatter.tags && frontmatter.tags.length > 0 && ( )}
{/* Display Hero Image */} {displayImage && (
{frontmatter.title}
)} {/* Content Connections - Removed MiniKnowledgeGraph from here */} {/*

Post Connections

*/} {/* Main Content Area */}
{/* Renders the actual markdown content */}
{/* Related Posts Section */} {relatedPosts.length > 0 && ( )}
{/* Sidebar */}