Files

63 lines
1.4 KiB
TypeScript
Raw Permalink Normal View History

2026-02-07 20:17:46 -05:00
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
const postsDirectory = path.join(process.cwd(), 'content/posts');
export type PostMetadata = {
title: string;
date: string;
description: string;
slug: string;
tags?: string[];
};
export type Post = {
metadata: PostMetadata;
content: string;
};
export function getPostSlugs() {
if (!fs.existsSync(postsDirectory)) {
return [];
}
return fs.readdirSync(postsDirectory);
}
export function getPostBySlug(slug: string): Post {
const realSlug = slug.replace(/\.mdx$/, '');
2026-02-08 23:18:21 -05:00
if (/[\/\\]|\.\./.test(realSlug)) {
throw new Error(`Invalid slug: ${realSlug}`);
}
2026-02-07 20:17:46 -05:00
const fullPath = path.join(postsDirectory, `${realSlug}.mdx`);
2026-02-08 23:18:21 -05:00
let fileContents: string;
try {
fileContents = fs.readFileSync(fullPath, 'utf8');
} catch {
throw new Error(`Post not found: ${realSlug}`);
}
2026-02-07 20:17:46 -05:00
const { data, content } = matter(fileContents);
return {
metadata: {
...data,
slug: realSlug,
} as PostMetadata,
content,
};
}
export function getAllPosts(): PostMetadata[] {
const slugs = getPostSlugs();
const posts = slugs
.filter((slug) => slug.endsWith('.mdx'))
.map((slug) => getPostBySlug(slug).metadata)
// Sort posts by date in descending order
.sort((post1, post2) => (post1.date > post2.date ? -1 : 1));
return posts;
}