import { imageMetadata } from '@/helpers/images'; import { urlJoin } from '@/helpers/tools'; import options from '@/options'; import { defineCollection, z } from 'astro:content'; export const defaultCover = '/images/default-cover.jpg'; // Copied and modified from https://github.com/zce/velite/blob/main/src/schemas/slug.ts // The slug is internally supported by Astro with 'content' type. // We add the slug here for validating the YAML configuration. const slug = () => z .string() .min(3) .max(200) .regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/i, 'Invalid slug'); const image = (fallbackImage: string) => z .string() .optional() .default(fallbackImage) .transform(async (arg) => await imageMetadata(arg)); // Categories Collection const categoriesCollection = defineCollection({ type: 'data', schema: z.object({ name: z.string().max(20), slug: slug(), cover: image(defaultCover), description: z.string().max(999).optional(), }), }); // Friends Collection const friendsCollection = defineCollection({ type: 'data', schema: z.array( z .object({ website: z.string().max(40), description: z.string().optional(), homepage: z.string().url(), poster: z .string() .transform((poster) => (poster.startsWith('/') ? urlJoin(options.assetsPrefix(), poster) : poster)), favicon: z.string().optional(), }) .transform((data) => { if (data.favicon === undefined) { data.favicon = `${data.homepage}/favicon.ico`; } return data; }), ), }); // Posts Collection const postsCollection = defineCollection({ type: 'content', schema: z.object({ title: z.string().max(99), date: z.date(), updated: z.date().optional(), comments: z.boolean().optional().default(true), tags: z.array(z.string()).optional().default([]), category: z.string(), summary: z.string().optional().default(''), cover: image(defaultCover), published: z.boolean().optional().default(true), }), }); // Pages Collection const pagesCollection = defineCollection({ type: 'content', schema: z.object({ title: z.string().max(99), date: z.date(), updated: z.date().optional(), comments: z.boolean().optional().default(true), cover: image(defaultCover), published: z.boolean().optional().default(true), friend: z.boolean().optional().default(false), }), }); // Tags Collection const tagsCollection = defineCollection({ type: 'data', schema: z.array( z.object({ name: z.string().max(20), slug: slug(), }), ), }); export const collections = { categories: categoriesCollection, friends: friendsCollection, pages: pagesCollection, posts: postsCollection, tags: tagsCollection, };