import fs from "fs/promises"; import path from "path"; import matter from "gray-matter"; import { serialize } from "next-mdx-remote/serialize"; const BASE_PATH = "content"; const ORDER_FILE = "ORDER.json"; export async function getSectionNamesForPage(page: string) { const sectionDir = path.join(BASE_PATH, page); return (await fs.readdir(sectionDir)) .filter((name) => name.endsWith(".md")) .map((name) => name.slice(0, -".md".length)); } export async function getSectionsForPage(page: string) { const names = await getSectionNamesForPage(page); const order = await getSectionOrder(page); if (!isEquivalent(new Set(names), new Set(order))) { throw new Error( `${ORDER_FILE} must contain all sections defined for page ${page}` ); } const sections = names .sort((a, b) => order.indexOf(a) - order.indexOf(b)) .map(async (name) => ({ name, data: await getSectionForPage(page, name), })); return await Promise.all(sections); } async function getSectionForPage(page: string, section: string) { const raw = await fs.readFile( path.join(BASE_PATH, page, `${section}.md`), "utf-8" ); const { content, data } = matter(raw); return { content: await serialize(content), title: data.title as string, }; } async function getSectionOrder(page: string) { const raw = await fs.readFile( path.join(BASE_PATH, page, ORDER_FILE), "utf-8" ); return JSON.parse(raw) as string[]; } function isEquivalent(setA: Set, setB: Set): boolean { const aContainsB = [...setB].every((b) => setA.has(b)); const bContainsA = [...setA].every((a) => setB.has(a)); return aContainsB && bContainsA; }