mirror of
https://github.com/KazooTTT/kazoottt-blog-v2.git
synced 2025-06-20 17:27:34 +08:00
feat: new blog layout and props
This commit is contained in:
BIN
src/assets/ZCOOLXiaoWei-Regular.ttf
Normal file
BIN
src/assets/ZCOOLXiaoWei-Regular.ttf
Normal file
Binary file not shown.
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -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>}
|
||||||
|
@ -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"
|
||||||
|
@ -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 };
|
||||||
|
@ -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] = [];
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
---
|
---
|
||||||
|
@ -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}/`,
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
|
@ -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,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
@ -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}/`,
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user