Move catalog indexes to Markdown front matter

This commit is contained in:
2026-08-22 12:42:11 +03:00
parent 188d9f2b18
commit aa8deee35a
65 changed files with 819 additions and 707 deletions
+47
View File
@@ -0,0 +1,47 @@
import { readFile } from "node:fs/promises";
import { parseDocument } from "yaml";
export type CatalogIndex<T> = {
description: string;
metadata: T;
};
export function parseCatalogIndex<T>(source: string, indexPath: string): CatalogIndex<T> {
const lines = source.split(/\r?\n/);
if (lines[0] !== "---") {
throw new Error(`${indexPath}: YAML Front Matter must start with ---`);
}
const closingDelimiter = lines.indexOf("---", 1);
if (closingDelimiter === -1) {
throw new Error(`${indexPath}: YAML Front Matter is missing its closing ---`);
}
const document = parseDocument(lines.slice(1, closingDelimiter).join("\n"), {
prettyErrors: true,
});
if (document.errors.length > 0) {
throw new Error(
`${indexPath}: ${document.errors.map((error) => error.message).join("; ")}`,
);
}
const metadata = document.toJS() as unknown;
if (typeof metadata !== "object" || metadata === null || Array.isArray(metadata)) {
throw new Error(`${indexPath}: YAML Front Matter must contain an object`);
}
if (Object.hasOwn(metadata, "description")) {
throw new Error(`${indexPath}: description must be the Markdown body`);
}
const description = lines.slice(closingDelimiter + 1).join("\n").trim();
if (description.length === 0) {
throw new Error(`${indexPath}: Markdown description is missing`);
}
return { metadata: metadata as T, description };
}
export async function readCatalogIndex<T>(indexPath: string): Promise<CatalogIndex<T>> {
return parseCatalogIndex<T>(await readFile(indexPath, "utf8"), indexPath);
}