69 lines
2.0 KiB
TypeScript
69 lines
2.0 KiB
TypeScript
import fs from 'fs';
|
|
import path from 'path';
|
|
import { bundleMDX } from 'mdx-bundler';
|
|
import remarkGfm from 'remark-gfm';
|
|
import rehypeSlug from 'rehype-slug';
|
|
|
|
export interface Frontmatter {
|
|
title: string;
|
|
date: string;
|
|
excerpt?: string;
|
|
teaser?: string;
|
|
tags?: string[];
|
|
icon?: string;
|
|
image?: string;
|
|
video?: string;
|
|
}
|
|
|
|
export interface Post {
|
|
slug: string;
|
|
frontmatter: Frontmatter;
|
|
code: string;
|
|
}
|
|
|
|
const contentDirectory = path.join(process.cwd(), 'content');
|
|
const datePrefixRegex = /^\d{4}-\d{2}-\d{2}-/;
|
|
|
|
export function getPostSlugs(type: 'projects' | 'research' | 'teaching' | 'experience') {
|
|
const typeDirectory = path.join(contentDirectory, type);
|
|
if (!fs.existsSync(typeDirectory)) return [];
|
|
return fs.readdirSync(typeDirectory).map(file =>
|
|
file.replace(datePrefixRegex, '').replace(/\.mdx$/, '')
|
|
);
|
|
}
|
|
|
|
export async function getPostBySlug(type: 'projects' | 'research' | 'teaching' | 'experience', slug: string): Promise<Post | null> {
|
|
const typeDirectory = path.join(contentDirectory, type);
|
|
|
|
const allFiles = fs.readdirSync(typeDirectory);
|
|
const fileName = allFiles.find(file =>
|
|
file.replace(datePrefixRegex, '').replace(/\.mdx$/, '') === slug
|
|
);
|
|
|
|
if (!fileName) {
|
|
console.error(`[MDX] Could not find a file for slug: ${slug} in ${typeDirectory}`);
|
|
return null;
|
|
}
|
|
|
|
const fullPath = path.join(typeDirectory, fileName);
|
|
const fileContents = fs.readFileSync(fullPath, 'utf8');
|
|
|
|
const dateMatch = fileName.match(/^\d{4}-\d{2}-\d{2}/);
|
|
const dateFromFilename = dateMatch ? dateMatch[0] : new Date().toISOString();
|
|
|
|
const { code, frontmatter } = await bundleMDX({
|
|
source: fileContents,
|
|
mdxOptions(options) {
|
|
options.remarkPlugins = [...(options.remarkPlugins ?? []), remarkGfm];
|
|
options.rehypePlugins = [...(options.rehypePlugins ?? []), rehypeSlug];
|
|
return options;
|
|
},
|
|
});
|
|
|
|
return {
|
|
slug,
|
|
frontmatter: { ...frontmatter, date: dateFromFilename } as Frontmatter,
|
|
code,
|
|
};
|
|
}
|