mirror of
https://github.com/10h30/blog-balodeplao.git
synced 2026-05-12 15:21:15 +09:00
123 lines
3.2 KiB
Plaintext
123 lines
3.2 KiB
Plaintext
---
|
|
import BaseLayout from "@/layouts/BaseLayout.astro";
|
|
import Schema from "@/components/seo/Schema.astro";
|
|
import Tags from "@/components/ui/Tags.astro";
|
|
import Categories from "@/components/ui/Categories.astro";
|
|
import Destinations from "@/components/ui/Destinations.astro";
|
|
import { toR2Url } from "@/utils/r2";
|
|
import Picture from "@/components/ui/Picture.astro";
|
|
|
|
import { getCollection, render, type CollectionEntry } from "astro:content";
|
|
|
|
interface Props {
|
|
post: CollectionEntry<"blog">;
|
|
}
|
|
|
|
export async function getStaticPaths() {
|
|
const blog = await getCollection("blog");
|
|
return blog.map((post) => ({
|
|
params: { slug: post.id },
|
|
props: { post },
|
|
}));
|
|
}
|
|
|
|
const { post } = Astro.props as Props;
|
|
const { Content, remarkPluginFrontmatter } = await render(post);
|
|
const {
|
|
title,
|
|
description,
|
|
pubDate,
|
|
author,
|
|
image,
|
|
categories,
|
|
tags,
|
|
destination,
|
|
} = post.data;
|
|
const coverImage = toR2Url(image);
|
|
|
|
const formattedDate = pubDate.toLocaleDateString("vi-VN", {
|
|
year: "numeric",
|
|
month: "long",
|
|
day: "numeric",
|
|
});
|
|
|
|
const readingTime = remarkPluginFrontmatter?.minutesRead
|
|
? `${Math.ceil(remarkPluginFrontmatter.minutesRead)} phút đọc`
|
|
: "";
|
|
|
|
const metadata = {
|
|
title: title,
|
|
description: description,
|
|
ogImage: coverImage,
|
|
};
|
|
---
|
|
|
|
<BaseLayout metadata={metadata}>
|
|
<Schema
|
|
type="BlogPosting"
|
|
data={{
|
|
title,
|
|
description,
|
|
image,
|
|
pubDate,
|
|
author,
|
|
url: Astro.url.href,
|
|
}}
|
|
/>
|
|
<section class="relative px-4 py-8 sm:px-6 lg:px-8 md:py-12">
|
|
<div class="relative mx-auto max-w-3xl">
|
|
<div class="reveal mb-10 text-center">
|
|
{
|
|
categories && categories.length > 0 && (
|
|
<div class="mb-3 flex flex-wrap justify-center gap-2">
|
|
<Categories categories={categories} />
|
|
</div>
|
|
)
|
|
}
|
|
<p class="text-sm font-semibold tracking-wide text-primary uppercase">
|
|
{formattedDate} • {author}
|
|
{readingTime && ` • ${readingTime}`}
|
|
</p>
|
|
<h1
|
|
class="font-heading mt-2 text-3xl font-bold leading-tight tracking-tighter text-foreground sm:text-4xl md:text-5xl"
|
|
>
|
|
{title}
|
|
</h1>
|
|
{
|
|
destination && destination.length > 0 && (
|
|
<div class="flex flex-wrap justify-center gap-2 mt-4">
|
|
<Destinations destinations={destination} />
|
|
</div>
|
|
)
|
|
}
|
|
</div>
|
|
|
|
{
|
|
coverImage && (
|
|
<div class="reveal relative mb-8 h-96 w-full overflow-hidden rounded-xl shadow-lg">
|
|
<Picture
|
|
src={coverImage}
|
|
alt={title}
|
|
class="h-full w-full object-cover"
|
|
fetchpriority="high"
|
|
/>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
<div
|
|
class="reveal prose prose-lg dark:prose-invert mx-auto prose-headings:text-foreground prose-a:text-primary hover:prose-a:underline prose-p:text-muted-foreground prose-strong:text-foreground prose-li:text-muted-foreground prose-code:text-primary"
|
|
>
|
|
<Content />
|
|
</div>
|
|
{
|
|
tags && tags.length > 0 && (
|
|
<div class="mt-4 relative z-20">
|
|
<Tags tags={tags} />
|
|
</div>
|
|
)
|
|
}
|
|
</div>
|
|
</section>
|
|
</BaseLayout>
|