Finish adding blog posts
This commit is contained in:
parent
4a3ee88f77
commit
cf180442c3
21 changed files with 178 additions and 40 deletions
|
|
@ -2,7 +2,6 @@
|
|||
import { Image } from "astro:assets";
|
||||
import { getCollection, getEntries, type CollectionEntry } from "astro:content";
|
||||
import GalleryLayout from "../layouts/GalleryLayout.astro";
|
||||
import { t } from "../i18n";
|
||||
import UserComponent from "../components/UserComponent.astro";
|
||||
import { markdownToPlaintext } from "../utils/markdown_to_plaintext";
|
||||
|
||||
|
|
@ -34,13 +33,13 @@ const posts = await Promise.all(
|
|||
data-tooltip
|
||||
>
|
||||
{post.data.thumbnail ? (
|
||||
<div class="flex aspect-[630/500] max-w-[288px] justify-center">
|
||||
<div class="flex aspect-square max-w-[288px] justify-center">
|
||||
<Image
|
||||
loading={i < 10 ? "eager" : "lazy"}
|
||||
class="u-photo m-auto"
|
||||
src={post.data.thumbnail}
|
||||
alt={`Thumbnail for ${post.data.title}`}
|
||||
width={288}
|
||||
width={192}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import type { GetStaticPaths } from "astro";
|
||||
import { type CollectionEntry, getCollection } from "astro:content";
|
||||
import { PUBLISH_DRAFTS } from "astro:env/server";
|
||||
import BlogLayout from "../../layouts/BlogLayout.astro";
|
||||
import BlogPostLayout from "../../layouts/BlogPostLayout.astro";
|
||||
|
||||
type Props = CollectionEntry<"blog">;
|
||||
|
||||
|
|
@ -24,6 +24,6 @@ const post = Astro.props;
|
|||
const { Content } = await post.render();
|
||||
---
|
||||
|
||||
<BlogLayout {...post.data}>
|
||||
<BlogPostLayout {...post.data}>
|
||||
<Content />
|
||||
</BlogLayout>
|
||||
</BlogPostLayout>
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ const games = await Promise.all(
|
|||
data-tooltip
|
||||
>
|
||||
{game.data.thumbnail ? (
|
||||
<div class="flex aspect-[630/500] max-w-[288px] justify-center">
|
||||
<div class="flex aspect-square max-w-[288px] justify-center">
|
||||
<Image
|
||||
loading={i < 10 ? "eager" : "lazy"}
|
||||
class="u-photo m-auto"
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ const latestItems: LatestItemsEntry[] = await Promise.all(
|
|||
date: post.data.pubDate,
|
||||
fn: async () =>
|
||||
({
|
||||
type: "Game",
|
||||
type: "Blog post",
|
||||
thumbnail: post.data.thumbnail,
|
||||
href: `/blog/${post.slug}`,
|
||||
title: post.data.title,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ const { badTag } = Astro.props;
|
|||
<meta content="No." property="og:description" />
|
||||
<meta name="robots" content="noindex" />
|
||||
</Fragment>
|
||||
<h1 class="m-2 text-2xl font-semibold text-stone-800 dark:text-stone-100">Works tagged "{badTag}"</h1>
|
||||
<h1 class="p-name m-2 text-3xl font-semibold text-stone-800 dark:text-stone-100">Works tagged "{badTag}"</h1>
|
||||
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" />
|
||||
<p class="my-4">No.</p>
|
||||
</GalleryLayout>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import Prose from "../../components/Prose.astro";
|
|||
import { t, DEFAULT_LANG } from "../../i18n";
|
||||
import { qualifyLocalURLsInMarkdown } from "../../utils/qualify_local_urls_in_markdown";
|
||||
import UserComponent from "../../components/UserComponent.astro";
|
||||
import { markdownToPlaintext } from "../../utils/markdown_to_plaintext";
|
||||
|
||||
type EntryWithPubDate<C extends CollectionKey> = CollectionEntry<C> & { data: { pubDate: Date } };
|
||||
|
||||
|
|
@ -18,6 +19,7 @@ type Props = {
|
|||
related?: string[];
|
||||
stories: (EntryWithPubDate<"stories"> & { authors: CollectionEntry<"users">[] })[];
|
||||
games: (EntryWithPubDate<"games"> & { authors: CollectionEntry<"users">[] })[];
|
||||
blogPosts: (EntryWithPubDate<"blog"> & { authors: CollectionEntry<"users">[] })[];
|
||||
};
|
||||
|
||||
type Params = {
|
||||
|
|
@ -25,24 +27,22 @@ type Params = {
|
|||
};
|
||||
|
||||
export const getStaticPaths: GetStaticPaths = async () => {
|
||||
const [stories, games, series, tagCategories] = await Promise.all([
|
||||
const [stories, games, blogPosts, series, tagCategories] = await Promise.all([
|
||||
getCollection("stories"),
|
||||
getCollection("games"),
|
||||
getCollection("blog"),
|
||||
getCollection("series"),
|
||||
getCollection("tag-categories"),
|
||||
]);
|
||||
const seriesTags = new Set(series.map((s) => s.data.name));
|
||||
const tags = new Set<string>();
|
||||
stories.forEach((story) => {
|
||||
story.data.tags.forEach((tag) => {
|
||||
tags.add(tag);
|
||||
});
|
||||
});
|
||||
games.forEach((game) => {
|
||||
game.data.tags.forEach((tag) => {
|
||||
tags.add(tag);
|
||||
});
|
||||
});
|
||||
[stories, games, blogPosts].forEach((collection) =>
|
||||
collection.forEach((content) => {
|
||||
content.data.tags.forEach((tag) => {
|
||||
tags.add(tag);
|
||||
});
|
||||
}),
|
||||
);
|
||||
const tagDescriptions = tagCategories.reduce(
|
||||
(acc, category) => {
|
||||
category.data.tags.forEach(({ name, description, related }) => {
|
||||
|
|
@ -100,6 +100,18 @@ export const getStaticPaths: GetStaticPaths = async () => {
|
|||
authors: await getEntries(game.data.authors),
|
||||
})),
|
||||
),
|
||||
blogPosts: await Promise.all(
|
||||
(
|
||||
blogPosts.filter(
|
||||
(post) => !post.data.isDraft && post.data.pubDate && post.data.tags.includes(tag),
|
||||
) as EntryWithPubDate<"blog">[]
|
||||
)
|
||||
.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime())
|
||||
.map(async (post) => ({
|
||||
...post,
|
||||
authors: await getEntries(post.data.authors),
|
||||
})),
|
||||
),
|
||||
} satisfies Props,
|
||||
})),
|
||||
);
|
||||
|
|
@ -116,12 +128,14 @@ const totalWorksWithTag = t(
|
|||
props.tag,
|
||||
props.stories.length,
|
||||
props.games.length,
|
||||
props.blogPosts.length,
|
||||
);
|
||||
---
|
||||
|
||||
<GalleryLayout pageTitle={`Works tagged "${props.tag}"`}>
|
||||
<meta slot="head" content={`Bad Manners || ${totalWorksWithTag || props.tag}`} property="og:description" />
|
||||
<h1 class="m-2 text-2xl font-semibold text-stone-800 dark:text-stone-100">Works tagged "{props.tag}"</h1>
|
||||
<h1 class="p-name m-2 text-3xl font-semibold text-stone-800 dark:text-stone-100">Works tagged "{props.tag}"</h1>
|
||||
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" />
|
||||
<div class="my-4">
|
||||
<Prose>
|
||||
{description ? <Markdown of={description} /> : null}
|
||||
|
|
@ -148,6 +162,7 @@ const totalWorksWithTag = t(
|
|||
class="u-url text-link hover:underline focus:underline"
|
||||
href={`/stories/${story.slug}`}
|
||||
title={t(story.data.lang, "story/warnings", story.data.wordCount, story.data.contentWarning)}
|
||||
data-tooltip
|
||||
>
|
||||
{story.data.thumbnail ? (
|
||||
<div class="flex aspect-square max-w-[192px] justify-center">
|
||||
|
|
@ -210,9 +225,10 @@ const totalWorksWithTag = t(
|
|||
class="u-url text-link hover:underline focus:underline"
|
||||
href={`/games/${game.slug}`}
|
||||
title={t(game.data.lang, "game/warnings", game.data.platforms, game.data.contentWarning)}
|
||||
data-tooltip
|
||||
>
|
||||
{game.data.thumbnail ? (
|
||||
<div class="flex aspect-[630/500] max-w-[192px] justify-center">
|
||||
<div class="flex aspect-square max-w-[192px] justify-center">
|
||||
<Image
|
||||
class="u-photo m-auto"
|
||||
src={game.data.thumbnail}
|
||||
|
|
@ -255,4 +271,63 @@ const totalWorksWithTag = t(
|
|||
</section>
|
||||
)
|
||||
}
|
||||
{
|
||||
props.blogPosts.length > 0 && (
|
||||
<section class="my-2" aria-labelledby="content-blogPosts">
|
||||
<h2 id="content-blogPosts" class="p-2 text-xl font-semibold text-stone-800 dark:text-stone-100">
|
||||
Blog posts
|
||||
</h2>
|
||||
<ul class="flex flex-wrap items-start justify-center gap-4 text-center md:justify-normal">
|
||||
{props.blogPosts.map((post) => (
|
||||
<li class="h-entry break-inside-avoid" lang={post.data.lang}>
|
||||
<a
|
||||
class="u-url text-link hover:underline focus:underline"
|
||||
href={`/blog/${post.slug}`}
|
||||
title={markdownToPlaintext(post.data.description)}
|
||||
data-tooltip
|
||||
>
|
||||
{post.data.thumbnail ? (
|
||||
<div class="flex aspect-square max-w-[192px] justify-center">
|
||||
<Image
|
||||
class="u-photo m-auto"
|
||||
src={post.data.thumbnail}
|
||||
alt={`Thumbnail for ${post.data.title}`}
|
||||
width={192}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
<div class="max-w-[192px] text-sm">
|
||||
<span class="p-name" aria-label="Title">
|
||||
{post.data.title}
|
||||
</span>
|
||||
<br />
|
||||
<time
|
||||
class="dt-published italic"
|
||||
datetime={post.data.pubDate.toISOString().slice(0, 10)}
|
||||
aria-label="Publish date"
|
||||
>
|
||||
{post.data.pubDate.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })}
|
||||
</time>
|
||||
</div>
|
||||
</a>
|
||||
<div class="sr-only select-none">
|
||||
<p class="p-category" aria-label="Category">
|
||||
Blog post
|
||||
</p>
|
||||
<p class="p-summary" aria-label="Summary">
|
||||
{post.data.description}
|
||||
</p>
|
||||
<div aria-label="Authors">
|
||||
<span>{post.authors.length == 1 ? "Author:" : "Authors:"}</span>
|
||||
{post.authors.map((author) => (
|
||||
<UserComponent rel="author" class="p-author" user={author} lang={post.data.lang} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
</GalleryLayout>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue