import fs from "node:fs"; import path from "node:path"; import matter from "gray-matter"; export type DevblogPost = { slug: string; title: string; date: string; excerpt: string; author?: string; tags?: string[]; game?: string; content: string; }; const POSTS_DIR = path.join(process.cwd(), "content", "devblog"); function ensureDir() { if (!fs.existsSync(POSTS_DIR)) { fs.mkdirSync(POSTS_DIR, { recursive: true }); } } export function getAllPosts(): DevblogPost[] { ensureDir(); const files = fs .readdirSync(POSTS_DIR) .filter((f) => f.endsWith(".mdx") || f.endsWith(".md")); const posts = files.map((file) => { const slug = file.replace(/\.(mdx|md)$/, ""); const raw = fs.readFileSync(path.join(POSTS_DIR, file), "utf8"); const { data, content } = matter(raw); return { slug, title: data.title ?? slug, date: data.date ?? new Date().toISOString().slice(0, 10), excerpt: data.excerpt ?? "", author: data.author, tags: data.tags ?? [], game: data.game, content, } as DevblogPost; }); return posts.sort((a, b) => (a.date < b.date ? 1 : -1)); } export function getPost(slug: string): DevblogPost | undefined { return getAllPosts().find((p) => p.slug === slug); } export function getPostsByGame(gameSlug: string): DevblogPost[] { return getAllPosts().filter( (p) => p.game === gameSlug || p.tags?.includes(gameSlug), ); } export function getAdjacentPosts(slug: string): { newer?: DevblogPost; older?: DevblogPost; } { const posts = getAllPosts(); const idx = posts.findIndex((p) => p.slug === slug); if (idx === -1) return {}; return { newer: idx > 0 ? posts[idx - 1] : undefined, older: idx < posts.length - 1 ? posts[idx + 1] : undefined, }; }