Files
Raphael Salaja b0c89649b1 feat: new article animate presence (#7)
* feat: add AnimatePresence article with interactive playground

* feat: add playground

* feat: ƒix basic demo

* feat: ap article start

* chore: cleanup

* chore: pre-commit

* feat: update article

* refactor: improve code formatting and readability in demo and script files

* refactor: enhance formatting for improved readability in slideshow demo

* chore: generate open graph rather than dynamically

* chore: add @clack/prompts dependency and enhance icon/image generation scripts with improved logging

* refactor: generators

* chore: cleanup

* feat: refactor generator

* feat: second draft

* docs: final draft

* chore: final draft again

* chore: update publication date and enhance text-to-speech generator with alignment data
2026-01-25 22:41:51 +00:00

71 lines
1.6 KiB
TypeScript

/**
* Content source - Fumadocs loader and page formatting
*/
import { docs } from "fumadocs/server";
import { type InferPageType, loader } from "fumadocs-core/source";
import { type Author, getAuthorById } from "./authors";
export const source = loader({
baseUrl: "/",
source: docs.toFumadocsSource(),
});
export function getPageImage(page: InferPageType<typeof source>) {
const segments = [...page.slugs, "image.png"];
return {
segments,
url: `/open-graph/${page.slugs.join("/")}/image.png`,
};
}
/**
* A full page object from Fumadocs source.
*/
export type Page = NonNullable<ReturnType<typeof source.getPage>>;
/**
* A formatted page with resolved author data and formatted dates.
*/
export interface FormattedPage {
url: string;
title: string;
description: string;
author: Author;
coauthors: Author[];
icon?: "motion" | "code" | "writing";
date: string;
}
function formatData(data: Page["data"]) {
if (!data.author) {
throw new Error("Author id is required.");
}
return {
title: data.title,
description: data.description,
author: getAuthorById(data.author),
coauthors: (data.coauthors ?? []).map(getAuthorById),
icon: data.icon,
date: data.date,
};
}
/**
* Formats page data with resolved authors and formatted dates.
*/
export function formatPageData(data: Page["data"]): Omit<FormattedPage, "url"> {
return formatData(data);
}
/**
* Formats an array of Page objects.
*/
export function formatPages(pages: Page[]): FormattedPage[] {
return pages.map((page) => ({
url: page.url,
...formatData(page.data),
}));
}