Add blog utilities and tag pages
Introduce formatBlogDate, slugifyTag and getTagHref in src/lib/blog.ts and a reading time helper getReadingTime in src/lib/readingTime.ts. Update blog index and post pages to display ISO dates, reading times and link tags to /blog/tag/<slug>. Add a tag listing page at src/pages/blog/tag/[tag].astro with styles and static paths generation
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
---
|
||||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
import { getCollection, type CollectionEntry } from "astro:content";
|
||||
import { formatBlogDate, getTagHref } from "../../lib/blog";
|
||||
import { getReadingTime } from "../../lib/readingTime";
|
||||
|
||||
type BlogPost = CollectionEntry<"blog">;
|
||||
|
||||
@@ -69,10 +71,7 @@ const {
|
||||
};
|
||||
|
||||
const { Content } = await post.render();
|
||||
|
||||
function formatDate(date: Date) {
|
||||
return date.toISOString().split("T")[0];
|
||||
}
|
||||
const readingTime = getReadingTime(post.body);
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
@@ -92,7 +91,16 @@ function formatDate(date: Date) {
|
||||
)
|
||||
}
|
||||
<h1 class="title">{post.data.title}</h1>
|
||||
<p class="date">{formatDate(post.data.pubDate)}</p>
|
||||
<div class="meta-row">
|
||||
<time
|
||||
class="date"
|
||||
datetime={formatBlogDate(post.data.pubDate)}
|
||||
>
|
||||
{formatBlogDate(post.data.pubDate)}
|
||||
</time>
|
||||
<span class="meta-sep" aria-hidden="true">·</span>
|
||||
<span class="reading-time">{readingTime.text}</span>
|
||||
</div>
|
||||
{
|
||||
post.data.tags.length > 0 && (
|
||||
<div
|
||||
@@ -100,7 +108,9 @@ function formatDate(date: Date) {
|
||||
aria-label={`${post.data.title} tags`}
|
||||
>
|
||||
{post.data.tags.map((tag) => (
|
||||
<span class="tag">{tag}</span>
|
||||
<a class="tag" href={getTagHref(tag)}>
|
||||
{tag}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
@@ -185,11 +195,26 @@ function formatDate(date: Date) {
|
||||
href={`/blog/${relatedPost.slug}`}
|
||||
class="related-card"
|
||||
>
|
||||
<span class="related-date">
|
||||
{formatDate(
|
||||
relatedPost.data.pubDate,
|
||||
)}
|
||||
</span>
|
||||
<div class="related-meta">
|
||||
<span class="related-date">
|
||||
{formatBlogDate(
|
||||
relatedPost.data.pubDate,
|
||||
)}
|
||||
</span>
|
||||
<span
|
||||
class="related-sep"
|
||||
aria-hidden="true"
|
||||
>
|
||||
·
|
||||
</span>
|
||||
<span class="related-reading-time">
|
||||
{
|
||||
getReadingTime(
|
||||
relatedPost.body,
|
||||
).text
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
<h3>{relatedPost.data.title}</h3>
|
||||
<p>{relatedPost.data.description}</p>
|
||||
</a>
|
||||
@@ -283,6 +308,22 @@ function formatDate(date: Date) {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.meta-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
color: var(--color-text-dim);
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.meta-sep {
|
||||
color: var(--color-surface);
|
||||
}
|
||||
|
||||
.reading-time {
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.tag-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -296,6 +337,12 @@ function formatDate(date: Date) {
|
||||
border: 1px solid var(--color-surface);
|
||||
padding: 1px 6px;
|
||||
border-radius: 999px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.tag:hover {
|
||||
color: var(--color-accent-bright);
|
||||
border-color: color-mix(in srgb, var(--color-accent) 45%, transparent);
|
||||
}
|
||||
|
||||
.content {
|
||||
@@ -547,12 +594,26 @@ function formatDate(date: Date) {
|
||||
}
|
||||
|
||||
.related-date {
|
||||
display: inline-block;
|
||||
color: var(--color-text-dim);
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.related-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
margin-bottom: var(--space-xs);
|
||||
}
|
||||
|
||||
.related-sep {
|
||||
color: var(--color-surface);
|
||||
}
|
||||
|
||||
.related-reading-time {
|
||||
color: var(--color-accent);
|
||||
font-size: 0.78rem;
|
||||
}
|
||||
|
||||
.related-card h3 {
|
||||
font-size: 1rem;
|
||||
color: var(--color-accent-bright);
|
||||
@@ -625,6 +686,11 @@ function formatDate(date: Date) {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.meta-row,
|
||||
.related-meta {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
|
||||
Reference in New Issue
Block a user