Declarations, types and generics.
import { readFile } from "node:fs/promises";
/** Frontmatter as it appears at the top of a content file. */
export interface Entry {
readonly slug: string;
title: string;
date: `${number}-${number}-${number}`;
draft?: boolean;
}
export const enum Collection {
TechNotes = "tech-notes",
Work = "work",
}
type Loader<T> = (path: string) => Promise<T | undefined>;
const SLUG = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
const RETRIES = 3;
const TIMEOUT_MS = 1_500;
Functions, control flow and template literals.
export const load: Loader<Entry> = async (path) => {
if (!SLUG.test(path)) {
throw new Error(`"${path}" is not a valid slug.`);
}
for (let attempt = 0; attempt < RETRIES; attempt += 1) {
try {
const source = await readFile(`content/${path}.mdx`, "utf8");
const { title, date, draft = false } = JSON.parse(source) as Entry;
return { slug: path, title, date, draft };
} catch (cause) {
if (attempt === RETRIES - 1) {
console.warn("Giving up on %s after %d tries", path, RETRIES, cause);
}
}
}
return undefined;
};
TSX, with attributes and embedded expressions.
function EntryList({
entries,
onSelect,
}: {
entries: Array<Entry>;
onSelect?: (slug: string) => void;
}) {
return (
<ul className="entryList" aria-label="Entries">
{entries.map(({ slug, title, date }) => (
<li key={slug} data-date={date}>
<button type="button" onClick={() => onSelect?.(slug)}>
{title}
</button>
</li>
))}
</ul>
);
}