import { promises as fs } from 'fs' import path from 'path' import frontmatter from 'front-matter' export interface PostMeta { slug: string, date: Date, title: string, subtitle?: string, unlisted: boolean, filePath: string, resources?: string[] } export interface Post extends Omit { body: string, } type Attributes = { [key: string]: any } const POST_FILE_PATTERN = /^(?[0-9]{4}-[0-9]{2}-[0-9]{2}(-[0-9]{1,2})?)_(?[^\.]+)\.md$/ export async function getPostSlugs(): Promise { const postsDir = path.join(process.cwd(), 'posts') const postPaths = await fs.readdir(postsDir) return postPaths.map(getSlugFromFilePath).filter(slug => slug !== null) as string[] } export function getSlugFromFilePath(postPath: string): string | null { const regexResult = POST_FILE_PATTERN.exec(postPath) if (!regexResult?.groups) return null return regexResult.groups.slug } export async function loadPageMetada(slug: string): Promise { const postsDir = path.join(process.cwd(), 'posts') const postPaths = await fs.readdir(postsDir) const postMatch: RegExpExecArray | null | undefined = postPaths .map((postFile: string) => POST_FILE_PATTERN.exec(postFile)) .filter((regexResult: RegExpExecArray | null) => regexResult !== null) .find((regexResult: RegExpExecArray) => regexResult.groups?.slug === slug) if (!postMatch) return null const fileName = `${postMatch.groups?.date}_${postMatch.groups?.slug}.md` const filePath = path.join(process.cwd(), 'posts', fileName) const fileContents = (await fs.readFile(filePath)).toString('utf8') const { attributes } = frontmatter(fileContents) const data: Attributes = attributes as Attributes if (!data.title) return null const [year, month, day] = postMatch.groups?.date.split('-') || [] const date = new Date(Date.UTC(parseInt(year), parseInt(month) - 1, parseInt(day))) return { date, filePath, slug: postMatch.groups?.slug || '', title: data.title, subtitle: data.subtitle, unlisted: typeof data.unlisted === 'boolean' ? data.unlisted : false, resources: data.resources } } export async function loadSinglePage(slug: string): Promise { const postMeta = await loadPageMetada(slug) if (!postMeta) return null const fileContents = (await fs.readFile(postMeta.filePath)).toString('utf8') const { body } = frontmatter(fileContents) const { filePath, ...otherMeta } = postMeta return { ...otherMeta, body } }