Add blog support
This commit is contained in:
61
src/pages/blog/[...page].astro
Normal file
61
src/pages/blog/[...page].astro
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
---
|
||||||
|
import Layout from "~/layouts/PageLayout.astro";
|
||||||
|
|
||||||
|
import { SITE } from "~/config.mjs";
|
||||||
|
import { getAllPosts } from "~/utils/getAllPosts";
|
||||||
|
import BlogPostCard from "~/components/widgets/BlogPostCard.astro";
|
||||||
|
import Pagination from "~/components/widgets/Pagination.astro";
|
||||||
|
|
||||||
|
export async function getStaticPaths({ paginate }) {
|
||||||
|
const posts = await getAllPosts();
|
||||||
|
|
||||||
|
return paginate(posts, {
|
||||||
|
pageSize: SITE.postsPerPage,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { page } = Astro.props;
|
||||||
|
|
||||||
|
const currentPage = page.currentPage ?? 1;
|
||||||
|
|
||||||
|
const title = `Blog ${currentPage > 1 ? `— Page ${currentPage} ` : ""}— ${
|
||||||
|
SITE.name
|
||||||
|
}`;
|
||||||
|
const description = "News and step-by-step guides about AstroWind";
|
||||||
|
const canonical = new URL(page.url.current, Astro.site);
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout meta={{ title, description, canonical }}>
|
||||||
|
<main class="mt-20">
|
||||||
|
<section class="px-4 sm:px-6 py-8 sm:py-16 lg:py-20 mx-auto max-w-3xl">
|
||||||
|
<header>
|
||||||
|
<h1
|
||||||
|
class="text-center text-5xl md:text-[3.50rem] font-bold leading-tighter tracking-tighter mb-8 md:mb-16"
|
||||||
|
style="
|
||||||
|
"
|
||||||
|
>
|
||||||
|
News and step-by-step guides about
|
||||||
|
<span
|
||||||
|
class="bg-clip-text text-transparent bg-gradient-to-r from-blue-500 to-pink-500"
|
||||||
|
>AstroWind
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
</header>
|
||||||
|
<ul>
|
||||||
|
{
|
||||||
|
page.data.map((post) => (
|
||||||
|
<li class="mb-10 md:mb-16">
|
||||||
|
<BlogPostCard post={post} />
|
||||||
|
</li>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{
|
||||||
|
(page.url.prev || page.url.next) && (
|
||||||
|
<Pagination prevUrl={page.url.prev} nextUrl={page.url.next} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</Layout>
|
79
src/pages/blog/[slug].astro
Normal file
79
src/pages/blog/[slug].astro
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
---
|
||||||
|
import Layout from "~/layouts/PageLayout.astro";
|
||||||
|
import Picture from "~/components/core/Picture.astro";
|
||||||
|
|
||||||
|
import { SITE } from "~/config.mjs";
|
||||||
|
import { getAllPosts } from "~/utils/getAllPosts";
|
||||||
|
|
||||||
|
export async function getStaticPaths() {
|
||||||
|
const posts = await getAllPosts();
|
||||||
|
|
||||||
|
return posts.map((post) => ({
|
||||||
|
params: { slug: post.slug },
|
||||||
|
props: { post },
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
const { post } = Astro.props;
|
||||||
|
|
||||||
|
const title = `${post.title} — ${SITE.name}`;
|
||||||
|
const description = post.description;
|
||||||
|
const canonical = new URL(`blog/${post.slug}/`, Astro.site);
|
||||||
|
|
||||||
|
const images = import.meta.glob("../../assets/images/*");
|
||||||
|
|
||||||
|
const imageSrc =
|
||||||
|
typeof images[post.image] === "function"
|
||||||
|
? (await images[post.image]())["default"]
|
||||||
|
: typeof post.image === "string"
|
||||||
|
? post.image
|
||||||
|
: null;
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout
|
||||||
|
meta={{
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
canonical,
|
||||||
|
image: imageSrc,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<main class="mt-20">
|
||||||
|
<section class="py-8 sm:py-16 lg:py-20 mx-auto">
|
||||||
|
<article>
|
||||||
|
<header>
|
||||||
|
<p class="max-w-3xl mx-auto text-center">
|
||||||
|
<time datetime={post.pubDate}>
|
||||||
|
{
|
||||||
|
new Date(post.pubDate).toLocaleDateString("en-us", {
|
||||||
|
year: "numeric",
|
||||||
|
month: "short",
|
||||||
|
day: "numeric",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</time> ~ {Math.ceil(post.readingTime)} min
|
||||||
|
</p>
|
||||||
|
<h1
|
||||||
|
class="px-4 sm:px-6 max-w-3xl mx-auto text-center text-5xl md:text-[3.50rem] font-bold leading-tighter tracking-tighter mb-6 md:mb-8"
|
||||||
|
>
|
||||||
|
{post.title}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<Picture
|
||||||
|
src={imageSrc}
|
||||||
|
class="max-w-full lg:max-w-6xl mx-auto mt-4 mb-6 sm:rounded-md bg-gray-400 dark:bg-slate-700"
|
||||||
|
widths={[400, 768, 900]}
|
||||||
|
sizes="(max-width: 767px) 400px, (max-width: 900px) 768px, 900px"
|
||||||
|
alt={post.description}
|
||||||
|
aspectRatio="16:9"
|
||||||
|
/>
|
||||||
|
</header>
|
||||||
|
<div
|
||||||
|
class="container mx-auto px-4 sm:px-6 max-w-3xl prose prose-lg lg:prose-xl dark:prose-invert dark:prose-headings:text-slate-300 prose-md prose-headings:leading-tighter prose-headings:tracking-tighter prose-headings:font-bold prose-a:text-blue-600 dark:prose-a:text-blue-400 prose-img:rounded-md prose-img:shadow-lg mt-8"
|
||||||
|
>
|
||||||
|
<Fragment set:html={post.body} />
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</Layout>
|
Reference in New Issue
Block a user