39 lines
1.2 KiB
TypeScript
39 lines
1.2 KiB
TypeScript
/* Mirrors BlogPost / GalleryImage in portfolio/data/content.ts. Keep in sync:
|
|
* the portfolio type-checks blog-posts.json against its own copy at build. */
|
|
|
|
export type GalleryImage = string | {
|
|
src: string;
|
|
/** Used as the image's alt text and tooltip. */
|
|
description?: string;
|
|
};
|
|
|
|
export type BlogPost = {
|
|
id: number;
|
|
slug: string; // kebab-case, URL-safe
|
|
title: string;
|
|
description: string; // 1-2 sentence excerpt shown on cards
|
|
date: string; // ISO date, e.g. "2026-09-14"
|
|
category: string; // slug, e.g. "meta" — one category per post
|
|
tags: string[];
|
|
images?: GalleryImage[]; // optional; first image is the card cover
|
|
details: string; // markdown body
|
|
};
|
|
|
|
/** A post as submitted by the editor: everything but the server-assigned id. */
|
|
export type PostInput = Omit<BlogPost, "id">;
|
|
|
|
export type ImageFile = {
|
|
name: string;
|
|
/** Path as stored in BlogPost.images (no leading slash). */
|
|
src: string;
|
|
size: number;
|
|
};
|
|
|
|
export function imageSrc(image: GalleryImage): string {
|
|
return typeof image === "string" ? image : image.src;
|
|
}
|
|
|
|
export function imageDescription(image: GalleryImage): string | undefined {
|
|
return typeof image === "string" ? undefined : image.description;
|
|
}
|