mirror of
https://github.com/10h30/blog-balodeplao.git
synced 2026-05-12 23:21:16 +09:00
feat: enhance blog structure with categories, tags, and localization updates
This commit is contained in:
@@ -1,77 +0,0 @@
|
||||
---
|
||||
import BaseLayout from "@/layouts/BaseLayout.astro";
|
||||
import Schema from "@/components/seo/Schema.astro";
|
||||
|
||||
import { getCollection, render } from "astro:content";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const blog = await getCollection("blog");
|
||||
return blog.map((post) => ({
|
||||
params: { slug: post.id },
|
||||
props: { post },
|
||||
}));
|
||||
}
|
||||
|
||||
const { post } = Astro.props;
|
||||
const { Content, remarkPluginFrontmatter } = await render(post);
|
||||
const { title, description, pubDate, author, image } = post.data;
|
||||
|
||||
const formattedDate = pubDate.toLocaleDateString("es-ES", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
});
|
||||
|
||||
const readingTime = remarkPluginFrontmatter?.minutesRead
|
||||
? `${Math.ceil(remarkPluginFrontmatter.minutesRead)} min de lectura`
|
||||
: "";
|
||||
|
||||
const metadata = {
|
||||
title: title,
|
||||
description: description,
|
||||
ogImage: image,
|
||||
};
|
||||
---
|
||||
|
||||
<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">
|
||||
<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>
|
||||
</div>
|
||||
|
||||
{
|
||||
image && (
|
||||
<div class="reveal relative mb-8 h-96 w-full overflow-hidden rounded-xl shadow-lg">
|
||||
<img src={image} alt={title} class="h-full w-full object-cover" />
|
||||
</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>
|
||||
</div>
|
||||
</section>
|
||||
</BaseLayout>
|
||||
@@ -1,65 +0,0 @@
|
||||
---
|
||||
import BaseLayout from "@/layouts/BaseLayout.astro";
|
||||
import { getCollection } from "astro:content";
|
||||
import Headline from "@/components/ui/Headline.astro";
|
||||
import PostItem from "@/components/blog/PostItem.astro";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const allPosts = await getCollection("blog");
|
||||
const posts = allPosts.filter((post) => post.data && post.data.pubDate); // Ensure published
|
||||
|
||||
const categories = new Set();
|
||||
posts.forEach((post) => {
|
||||
if (post.data.category) {
|
||||
categories.add(post.data.category);
|
||||
}
|
||||
});
|
||||
|
||||
return Array.from(categories).map((category) => {
|
||||
return {
|
||||
params: { category: category as string },
|
||||
props: {
|
||||
category,
|
||||
posts: posts.filter((post) => post.data.category === category),
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const { category, posts } = Astro.props;
|
||||
|
||||
const metadata = {
|
||||
title: `Category: ${category}`,
|
||||
description: `Articles in the ${category} category.`,
|
||||
};
|
||||
---
|
||||
|
||||
<BaseLayout metadata={metadata}>
|
||||
<section class="relative px-4 py-24 sm:px-6 lg:px-8 md:py-32">
|
||||
<div class="relative mx-auto max-w-5xl">
|
||||
<Headline
|
||||
tagline="Category"
|
||||
title={category}
|
||||
subtitle={`Showing ${posts.length} article${posts.length === 1 ? "" : "s"}.`}
|
||||
classes={{
|
||||
container: "mb-12 text-center",
|
||||
title:
|
||||
"font-heading mb-4 text-4xl font-bold tracking-tight text-foreground md:text-6xl capitalized",
|
||||
subtitle: "mx-auto max-w-3xl text-xl text-muted-foreground",
|
||||
}}
|
||||
/>
|
||||
|
||||
<div class="mb-8 text-center">
|
||||
<a href="/blog" class="text-primary hover:underline">← Back to blog</a>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
|
||||
{
|
||||
posts
|
||||
.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf())
|
||||
.map((post) => <PostItem post={post} />)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</BaseLayout>
|
||||
@@ -1,63 +0,0 @@
|
||||
---
|
||||
import BaseLayout from "@/layouts/BaseLayout.astro";
|
||||
import { getCollection } from "astro:content";
|
||||
import Headline from "@/components/ui/Headline.astro";
|
||||
import PostItem from "@/components/blog/PostItem.astro";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const allPosts = await getCollection("blog");
|
||||
const posts = allPosts.filter((post) => post.data && post.data.pubDate); // Ensure published
|
||||
|
||||
const tags = new Set();
|
||||
posts.forEach((post) => {
|
||||
post.data.tags?.forEach((tag) => tags.add(tag));
|
||||
});
|
||||
|
||||
return Array.from(tags).map((tag) => {
|
||||
return {
|
||||
params: { tag: tag as string },
|
||||
props: {
|
||||
tag,
|
||||
posts: posts.filter((post) => post.data.tags?.includes(tag as string)),
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const { tag, posts } = Astro.props;
|
||||
|
||||
const metadata = {
|
||||
title: `Posts tagged with '${tag}'`,
|
||||
description: `Explore our articles about ${tag}.`,
|
||||
};
|
||||
---
|
||||
|
||||
<BaseLayout metadata={metadata}>
|
||||
<section class="relative px-4 py-24 sm:px-6 lg:px-8 md:py-32">
|
||||
<div class="relative mx-auto max-w-5xl">
|
||||
<Headline
|
||||
tagline="Tag"
|
||||
title={`#${tag}`}
|
||||
subtitle={`Showing ${posts.length} article${posts.length === 1 ? "" : "s"}.`}
|
||||
classes={{
|
||||
container: "mb-12 text-center",
|
||||
title:
|
||||
"font-heading mb-4 text-4xl font-bold tracking-tight text-foreground md:text-6xl capitalized",
|
||||
subtitle: "mx-auto max-w-3xl text-xl text-muted-foreground",
|
||||
}}
|
||||
/>
|
||||
|
||||
<div class="mb-8 text-center">
|
||||
<a href="/blog" class="text-primary hover:underline">← Back to blog</a>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
|
||||
{
|
||||
posts
|
||||
.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf())
|
||||
.map((post) => <PostItem post={post} />)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</BaseLayout>
|
||||
Reference in New Issue
Block a user