* style: better reply button. * feat: add astro badge. * chore: drop useless styles. * feat: use new options.ts for global configuration. * fix: the invalid import.meta.env.PROD in astro build. * feat: move og to new assert prefix. * chore: add better og description. * chore: make sure all the images link could be correctly replaced. * feat: add upyun uploader.
107 lines
2.7 KiB
TypeScript
107 lines
2.7 KiB
TypeScript
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,
|
|
};
|