www-new/lib/organized-content.ts

65 lines
1.7 KiB
TypeScript

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<T>(setA: Set<T>, setB: Set<T>): boolean {
const aContainsB = [...setB].every((b) => setA.has(b));
const bContainsA = [...setA].every((a) => setB.has(a));
return aContainsB && bContainsA;
}