feat: new blog layout and props

This commit is contained in:
KazooTTT
2025-02-05 15:27:29 +08:00
parent ea645368e9
commit fea129eb98
12 changed files with 36 additions and 50 deletions

Binary file not shown.

View File

@ -37,14 +37,14 @@ const dateTimeOptions: Intl.DateTimeFormatOptions = {
</h1> </h1>
<div class="flex flex-wrap items-center gap-x-3 gap-y-2"> <div class="flex flex-wrap items-center gap-x-3 gap-y-2">
<p class="font-semibold"> <p class="font-semibold">
<FormattedDate date={data.publishDate} dateTimeOptions={dateTimeOptions} /> /{" "} <FormattedDate date={data.date} dateTimeOptions={dateTimeOptions} /> /{" "}
{readingTime} {readingTime}
</p> </p>
{ {
data.updatedDate && ( data.date_modified && (
<span class="bg-quote/5 text-quote rounded-lg px-2 py-1"> <span class="bg-quote/5 text-quote rounded-lg px-2 py-1">
Updated: Updated:
<FormattedDate class="ms-1" date={data.updatedDate} dateTimeOptions={dateTimeOptions} /> <FormattedDate class="ms-1" date={data.date_modified} dateTimeOptions={dateTimeOptions} />
</span> </span>
) )
} }

View File

@ -13,7 +13,7 @@ const { as: Tag = "div", post, withDesc = false } = Astro.props;
<FormattedDate <FormattedDate
class="min-w-30 font-semibold text-gray-600 dark:text-gray-400" class="min-w-30 font-semibold text-gray-600 dark:text-gray-400"
date={post.data.publishDate} date={post.data.date}
/> />
<Tag> <Tag>
{post.data.draft && <span class="text-red-500">(Draft) </span>} {post.data.draft && <span class="text-red-500">(Draft) </span>}

View File

@ -14,7 +14,8 @@ const { Content } = await render(note);
<article <article
class:list={[ class:list={[
isPreview && "inline-grid rounded-md bg-[rgb(240,240,240)] px-4 py-3 dark:bg-[rgb(33,35,38)]", isPreview &&
"inline-grid w-full rounded-md bg-[rgb(240,240,240)] px-4 py-3 dark:bg-[rgb(33,35,38)]",
]} ]}
data-pagefind-body={isPreview ? false : true} data-pagefind-body={isPreview ? false : true}
> >
@ -37,7 +38,7 @@ const { Content } = await render(note);
month: "2-digit", month: "2-digit",
day: "2-digit", day: "2-digit",
}} }}
date={note.data.publishDate} date={note.data.date}
/> />
<div <div
class="prose prose-sm prose-cactus mt-4 max-w-none [&>p:last-of-type]:mb-0" class="prose prose-sm prose-cactus mt-4 max-w-none [&>p:last-of-type]:mb-0"

View File

@ -6,43 +6,30 @@ function removeDupsAndLowerCase(array: string[]) {
} }
const baseSchema = z.object({ const baseSchema = z.object({
title: z.string().max(60), title: z.string()
}); });
const post = defineCollection({ const post = defineCollection({
loader: glob({ base: "./src/content/post", pattern: "**/*.{md,mdx}" }), loader: glob({ base: "./src/content/post", pattern: "**/*.{md,mdx}" }),
schema: ({ image }) => schema: () =>
baseSchema.extend({ baseSchema.extend({
description: z.string(), description: z.string().optional().nullable(),
coverImage: z
.object({
alt: z.string(),
src: image(),
})
.optional(),
draft: z.boolean().default(false), draft: z.boolean().default(false),
ogImage: z.string().optional(), banner: z.string().optional(),
tags: z.array(z.string()).default([]).transform(removeDupsAndLowerCase), tags: z.array(z.string()).default([]).transform(removeDupsAndLowerCase),
publishDate: z categories: z.array(z.string()).default([]).transform(removeDupsAndLowerCase),
.string() date: z.union([z.string(), z.date()]).transform((val) => new Date(val)),
.or(z.date()) date_modified: z.date().optional(),
.transform((val) => new Date(val)),
updatedDate: z
.string()
.optional()
.transform((str) => (str ? new Date(str) : undefined)),
}), }),
}); });
const note = defineCollection({ const note = defineCollection({
loader: glob({ base: "./src/content/note", pattern: "**/*.{md,mdx}" }), loader: glob({ base: "./src/content/note", pattern: "**/*.{md,mdx}" }),
schema: baseSchema.extend({ schema: baseSchema.extend({
description: z.string().optional(), description: z.string().optional().nullable(),
publishDate: z date: z.union([z.string(), z.date()]).transform((val) => new Date(val)),
.string()
.datetime({ offset: true }) // Ensures ISO 8601 format with offsets allowed (e.g. "2024-01-01T00:00:00Z" and "2024-01-01T00:00:00+02:00")
.transform((val) => new Date(val)),
}), }),
}); });
export const collections = { post, note }; export const collections = { post, note };

View File

@ -12,7 +12,7 @@ export async function getAllPosts(): Promise<CollectionEntry<"post">[]> {
*/ */
export function groupPostsByYear(posts: CollectionEntry<"post">[]) { export function groupPostsByYear(posts: CollectionEntry<"post">[]) {
return posts.reduce<Record<string, CollectionEntry<"post">[]>>((acc, post) => { return posts.reduce<Record<string, CollectionEntry<"post">[]>>((acc, post) => {
const year = post.data.publishDate.getFullYear(); const year = post.data.date.getFullYear();
if (!acc[year]) { if (!acc[year]) {
acc[year] = []; acc[year] = [];
} }

View File

@ -12,7 +12,13 @@ interface Props {
} }
const { post } = Astro.props; const { post } = Astro.props;
const { ogImage, title, description, updatedDate, publishDate } = post.data; const {
banner: ogImage,
title,
description,
date_modified: updatedDate,
date: publishDate,
} = post.data;
const socialImage = ogImage ?? `/og-image/${post.id}.png`; const socialImage = ogImage ?? `/og-image/${post.id}.png`;
const articleDate = updatedDate?.toISOString() ?? publishDate.toISOString(); const articleDate = updatedDate?.toISOString() ?? publishDate.toISOString();
const { headings, remarkPluginFrontmatter } = await render(post); const { headings, remarkPluginFrontmatter } = await render(post);

View File

@ -20,8 +20,7 @@ const { note } = Astro.props;
const meta = { const meta = {
description: description:
note.data.description || note.data.description || `Read about my note posted on: ${note.data.date.toLocaleDateString()}`,
`Read about my note posted on: ${note.data.publishDate.toLocaleDateString()}`,
title: note.data.title, title: note.data.title,
}; };
--- ---

View File

@ -11,7 +11,7 @@ export const GET = async () => {
site: import.meta.env.SITE, site: import.meta.env.SITE,
items: notes.map((note) => ({ items: notes.map((note) => ({
title: note.data.title, title: note.data.title,
pubDate: note.data.publishDate, pubDate: note.data.date,
link: `notes/${note.id}/`, link: `notes/${note.id}/`,
})), })),
}); });

View File

@ -1,5 +1,4 @@
import RobotoMonoBold from "@/assets/roboto-mono-700.ttf"; import ZCOOLXiaoWei from "@/assets/ZCOOLXiaoWei-Regular.ttf";
import RobotoMono from "@/assets/roboto-mono-regular.ttf";
import { getAllPosts } from "@/data/post"; import { getAllPosts } from "@/data/post";
import { siteConfig } from "@/site.config"; import { siteConfig } from "@/site.config";
import { getFormattedDate } from "@/utils/date"; import { getFormattedDate } from "@/utils/date";
@ -12,17 +11,11 @@ const ogOptions: SatoriOptions = {
// debug: true, // debug: true,
fonts: [ fonts: [
{ {
data: Buffer.from(RobotoMono), data: Buffer.from(ZCOOLXiaoWei),
name: "Roboto Mono", name: "ZCOOLXiaoWei",
style: "normal", style: "normal",
weight: 400, weight: 400,
}, }
{
data: Buffer.from(RobotoMonoBold),
name: "Roboto Mono",
style: "normal",
weight: 700,
},
], ],
height: 630, height: 630,
width: 1200, width: 1200,
@ -79,11 +72,11 @@ export async function GET(context: APIContext) {
export async function getStaticPaths() { export async function getStaticPaths() {
const posts = await getAllPosts(); const posts = await getAllPosts();
return posts return posts
.filter(({ data }) => !data.ogImage) .filter(({ data }) => !data.banner)
.map((post) => ({ .map((post) => ({
params: { slug: post.id }, params: { slug: post.id },
props: { props: {
pubDate: post.data.updatedDate ?? post.data.publishDate, pubDate: post.data.date ?? post.data.date_modified ,
title: post.data.title, title: post.data.title,
}, },
})); }));

View File

@ -11,8 +11,8 @@ export const GET = async () => {
site: import.meta.env.SITE, site: import.meta.env.SITE,
items: posts.map((post) => ({ items: posts.map((post) => ({
title: post.data.title, title: post.data.title,
description: post.data.description, description: post.data.description ?? "",
pubDate: post.data.publishDate, pubDate: post.data.date,
link: `posts/${post.id}/`, link: `posts/${post.id}/`,
})), })),
}); });

View File

@ -19,5 +19,5 @@ export function collectionDateSort(
a: CollectionEntry<"post" | "note">, a: CollectionEntry<"post" | "note">,
b: CollectionEntry<"post" | "note">, b: CollectionEntry<"post" | "note">,
) { ) {
return b.data.publishDate.getTime() - a.data.publishDate.getTime(); return b.data.date.getTime() - a.data.date.getTime();
} }