221 lines
6.0 KiB
TypeScript
221 lines
6.0 KiB
TypeScript
import { z } from 'astro/zod';
|
|
|
|
const isProd = (): boolean => import.meta.env.MODE === 'production' || process.env.NODE_ENV === 'production';
|
|
|
|
// The type of the options, use zod for better validation.
|
|
const Options = z
|
|
.object({
|
|
local: z
|
|
.object({
|
|
port: z.number(),
|
|
})
|
|
.transform((local) => ({ ...local, website: `http://localhost:${local.port}` })),
|
|
title: z.string().max(40),
|
|
website: z
|
|
.string()
|
|
.url()
|
|
.refine((u) => !u.endsWith('/'))
|
|
.readonly(),
|
|
description: z.string().max(100),
|
|
keywords: z.array(z.string()),
|
|
author: z.object({ name: z.string(), email: z.string().email(), url: z.string().url() }),
|
|
navigation: z.array(z.object({ text: z.string().trim(), link: z.string(), target: z.string().optional() })),
|
|
socials: z.array(
|
|
z.object({
|
|
name: z.string(),
|
|
icon: z.string(),
|
|
type: z.enum(['link', 'qrcode']),
|
|
title: z.string().optional(),
|
|
link: z.string().url(),
|
|
}),
|
|
),
|
|
settings: z.object({
|
|
footer: z.object({
|
|
initialYear: z.number().max(2024),
|
|
icpNo: z.string().optional(),
|
|
moeIcpNo: z.string().optional(),
|
|
astroBadge: z.boolean().default(true),
|
|
}),
|
|
locale: z.string().optional().default('zh-CN'),
|
|
timeZone: z.string().optional().default('Asia/Shanghai'),
|
|
timeFormat: z.string().optional().default('yyyy-MM-dd HH:mm:ss'),
|
|
twitter: z.string(),
|
|
assetPrefix: z
|
|
.string()
|
|
.url()
|
|
.refine((u) => !u.endsWith('/'))
|
|
.readonly(),
|
|
post: z.object({
|
|
sort: z.enum(['asc', 'desc']),
|
|
feature: z.array(z.string()).min(3).optional(),
|
|
}),
|
|
pagination: z.object({
|
|
posts: z.number().optional().default(5),
|
|
category: z.number().optional().default(7),
|
|
tags: z.number().optional().default(7),
|
|
search: z.number().optional().default(7),
|
|
}),
|
|
feed: z.object({
|
|
full: z.boolean().optional().default(true),
|
|
size: z.number().optional().default(20),
|
|
}),
|
|
sidebar: z.object({
|
|
search: z.boolean().default(false),
|
|
post: z.number().default(6),
|
|
comment: z.number().default(0),
|
|
tag: z.number().default(20),
|
|
calendar: z.boolean().default(false),
|
|
}),
|
|
comments: z.object({
|
|
enable: z.boolean().optional().default(true),
|
|
size: z.number().default(10).readonly(),
|
|
avatar: z.object({
|
|
mirror: z.string().url().readonly(),
|
|
size: z.number(),
|
|
}),
|
|
}),
|
|
toc: z.object({
|
|
minHeadingLevel: z.number().optional().default(2),
|
|
maxHeadingLevel: z.number().optional().default(3),
|
|
}),
|
|
}),
|
|
thumbnail: z
|
|
.function()
|
|
.args(z.object({ src: z.string().min(1), width: z.number().or(z.string()), height: z.number().or(z.string()) }))
|
|
.returns(z.string()),
|
|
})
|
|
.transform((opts) => {
|
|
const assetsPrefix = (): string => (isProd() ? opts.settings.assetPrefix : opts.local.website);
|
|
return {
|
|
...opts,
|
|
// Monkey patch for the issue https://github.com/withastro/astro/issues/11282
|
|
// No need to fallback to the import.meta.env.PROD I think.
|
|
isProd,
|
|
// Given that the import.meta.env.ASSETS_PREFIX has two types.
|
|
// I have to use this uniform method instead.
|
|
assetsPrefix,
|
|
defaultOpenGraph: (): string => `${assetsPrefix()}/images/open-graph.png`,
|
|
};
|
|
})
|
|
.refine(
|
|
(options) => options.settings.toc.minHeadingLevel <= options.settings.toc.maxHeadingLevel,
|
|
'Invalid toc setting, the minHeadingLevel should bellow the maxHeadingLevel',
|
|
);
|
|
|
|
const options: z.input<typeof Options> = {
|
|
local: {
|
|
port: 4321,
|
|
},
|
|
title: '且听书吟',
|
|
website: 'https://yufan.me',
|
|
description: '诗与梦想的远方',
|
|
keywords: ['雨帆', '且听书吟', 'syhily', 'amehochan', 'yufan'],
|
|
author: {
|
|
name: '雨帆',
|
|
email: 'syhily@gmail.com',
|
|
url: 'https://yufan.me',
|
|
},
|
|
navigation: [
|
|
{
|
|
text: '首页',
|
|
link: '/',
|
|
},
|
|
{
|
|
text: '分类',
|
|
link: '/categories',
|
|
},
|
|
{
|
|
text: '关于',
|
|
link: '/about',
|
|
},
|
|
{
|
|
text: '留言',
|
|
link: '/guestbook',
|
|
},
|
|
{
|
|
text: '友链',
|
|
link: '/links',
|
|
},
|
|
],
|
|
socials: [
|
|
{
|
|
name: 'GitHub',
|
|
icon: 'icon-github-fill',
|
|
type: 'link',
|
|
link: 'https://github.com/syhily',
|
|
},
|
|
{
|
|
name: '知乎',
|
|
icon: 'icon-zhihu-square-fill',
|
|
type: 'link',
|
|
link: 'https://www.zhihu.com/people/syhily',
|
|
},
|
|
{
|
|
name: '微信',
|
|
icon: 'icon-wechat',
|
|
type: 'qrcode',
|
|
title: '扫码加我微信好友',
|
|
link: 'https://u.wechat.com/EBpmuKmrVz4YVFnoCJdnruA',
|
|
},
|
|
],
|
|
settings: {
|
|
footer: {
|
|
initialYear: 2011,
|
|
icpNo: '皖ICP备2021002315号-2',
|
|
moeIcpNo: '萌ICP备20200318号',
|
|
astroBadge: true,
|
|
},
|
|
locale: 'zh-CN',
|
|
timeZone: 'Asia/Shanghai',
|
|
timeFormat: 'yyyy-MM-dd',
|
|
twitter: 'amehochan',
|
|
assetPrefix: 'https://cat.yufan.me',
|
|
post: {
|
|
sort: 'desc',
|
|
},
|
|
pagination: {
|
|
posts: 6,
|
|
category: 7,
|
|
tags: 7,
|
|
search: 7,
|
|
},
|
|
feed: {
|
|
full: true,
|
|
size: 10,
|
|
},
|
|
sidebar: {
|
|
search: true,
|
|
post: 5,
|
|
comment: 5,
|
|
tag: 10,
|
|
calendar: true,
|
|
},
|
|
comments: {
|
|
enable: true,
|
|
size: 10,
|
|
avatar: {
|
|
mirror: 'https://weavatar.com/avatar',
|
|
size: 120,
|
|
},
|
|
},
|
|
toc: {
|
|
minHeadingLevel: 2,
|
|
maxHeadingLevel: 3,
|
|
},
|
|
},
|
|
thumbnail: ({ src, width, height }) => {
|
|
if (src.endsWith('.svg')) {
|
|
return src;
|
|
}
|
|
if (isProd()) {
|
|
// Add upyun thumbnail support.
|
|
return `${src}!upyun520/both/${width}x${height}/format/webp/quality/100/unsharp/true/progressive/true`;
|
|
}
|
|
// See https://docs.astro.build/en/reference/image-service-reference/#local-services
|
|
// Remember to add the localhost to you image service settings.
|
|
return `http://localhost:4321/_image?href=${src}&w=${width}&h=${height}&f=webp&q=100`;
|
|
},
|
|
};
|
|
|
|
export default Options.parse(options);
|