Retouch all pages and add 'Engaged in Reality'

This commit is contained in:
Bad Manners 2024-11-01 19:44:34 -03:00
parent 1dda4c9af8
commit b03aca87e7
No known key found for this signature in database
GPG key ID: 8C88292CCB075609
37 changed files with 1701 additions and 553 deletions

View file

@ -5,6 +5,6 @@ import GalleryLayout from "@layouts/GalleryLayout.astro";
<GalleryLayout pageTitle="404">
<meta slot="head" property="og:description" content="Not found" />
<h1 class="m-2 text-3xl font-semibold text-stone-800 dark:text-stone-100">404 &ndash; Not Found</h1>
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" />
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" aria-hidden />
<p class="my-4">The requested link could not be found. Make sure that the URL is correct.</p>
</GalleryLayout>

View file

@ -21,9 +21,9 @@ const posts = await Promise.all(
<GalleryLayout pageTitle="Blog" class="h-feed">
<meta slot="head" property="og:description" content="Bad Manners || A game that I've gone and done." />
<h1 class="p-name m-2 text-3xl font-semibold text-stone-800 dark:text-stone-100">Blog</h1>
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" />
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" aria-hidden />
<div class="my-4 flex w-full">
<p class="p-summary grow">Posts on whatever has been rattling in my head as of late.</p>
<p class="p-summary grow">Whatever has been rattling in my head as of late.</p>
<a class="u-url text-link ml-2 p-1 md:mr-5" href="/blog/feed.xml" rel="alternate" title="RSS feed" data-tooltip>
<IconSquareRSS width="2rem" height="2rem" />
<span class="sr-only">RSS feed</span>

View file

@ -21,7 +21,7 @@ const games = await Promise.all(
<GalleryLayout pageTitle="Games" class="h-feed">
<meta slot="head" property="og:description" content="Bad Manners || A game that I've gone and done." />
<h1 class="p-name m-2 text-3xl font-semibold text-stone-800 dark:text-stone-100">Games</h1>
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" />
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" aria-hidden />
<div class="my-4 flex w-full">
<p class="p-summary grow">A game that I've gone and done.</p>
<a class="u-url text-link ml-2 p-1 md:mr-5" href="/games/feed.xml" rel="alternate" title="RSS feed" data-tooltip>

View file

@ -6,9 +6,10 @@ import GalleryLayout from "@layouts/GalleryLayout.astro";
import { t, type Lang } from "@i18n";
import UserComponent from "@components/UserComponent.astro";
import { markdownToPlaintext } from "@utils/markdown_to_plaintext";
import { IconNoOneUnder18, IconSquareRSS } from "@components/icons";
import { IconNoOneUnder18, IconSparkles, IconSquareRSS } from "@components/icons";
const MAX_ITEMS = 10;
const MAX_FEATURED_ITEMS = 4;
const MAX_LATEST_ITEMS = 10;
interface LatestItemsEntry {
type: string;
@ -24,90 +25,146 @@ interface LatestItemsEntry {
type EntryWithPubDate<C extends CollectionKey> = CollectionEntry<C> & { data: { pubDate: Date } };
const stories = (
const latestStories = (
(await getCollection(
"stories",
(story) => !story.data.isDraft && story.data.pubDate,
)) as EntryWithPubDate<"stories">[]
)
.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime())
.slice(0, MAX_ITEMS);
const games = (
.slice(0, MAX_LATEST_ITEMS);
const latestGames = (
(await getCollection("games", (game) => !game.data.isDraft && game.data.pubDate)) as EntryWithPubDate<"games">[]
)
.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime())
.slice(0, MAX_ITEMS);
const posts = (
.slice(0, MAX_LATEST_ITEMS);
const latestPosts = (
(await getCollection("blog", (post) => !post.data.isDraft && post.data.pubDate)) as EntryWithPubDate<"blog">[]
)
.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime())
.slice(0, MAX_ITEMS);
.slice(0, MAX_LATEST_ITEMS);
const featuredStories = (
(await getCollection(
"stories",
(story) => !story.data.isDraft && story.data.pubDate && story.data.isFeatured,
)) as EntryWithPubDate<"stories">[]
).sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime());
const featuredGames = (
(await getCollection(
"games",
(game) => !game.data.isDraft && game.data.pubDate && game.data.isFeatured,
)) as EntryWithPubDate<"games">[]
).sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime());
const featuredPosts = (
(await getCollection(
"blog",
(post) => !post.data.isDraft && post.data.pubDate && post.data.isFeatured,
)) as EntryWithPubDate<"blog">[]
).sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime());
async function storyEntry(story: EntryWithPubDate<"stories">): Promise<LatestItemsEntry> {
return {
type: "Story",
isAgeRestricted: story.data.isAgeRestricted,
thumbnail: story.data.thumbnail,
href: `/stories/${story.slug}`,
title: story.data.title,
authors: await getEntries(story.data.authors),
lang: story.data.lang,
altText: t(story.data.lang, "story/warnings", story.data.wordCount, story.data.contentWarning),
pubDate: story.data.pubDate,
} satisfies LatestItemsEntry;
}
async function gameEntry(game: EntryWithPubDate<"games">): Promise<LatestItemsEntry> {
return {
type: "Game",
isAgeRestricted: game.data.isAgeRestricted,
thumbnail: game.data.thumbnail,
href: `/games/${game.slug}`,
title: game.data.title,
authors: await getEntries(game.data.authors),
lang: game.data.lang,
altText: t(game.data.lang, "game/warnings", game.data.platforms, game.data.contentWarning),
pubDate: game.data.pubDate,
} satisfies LatestItemsEntry;
}
async function blogEntry(post: EntryWithPubDate<"blog">): Promise<LatestItemsEntry> {
return {
type: "Blog post",
isAgeRestricted: post.data.isAgeRestricted,
thumbnail: post.data.thumbnail,
href: `/blog/${post.slug}`,
title: post.data.title,
authors: await getEntries(post.data.authors),
lang: post.data.lang,
altText: markdownToPlaintext(post.data.description),
pubDate: post.data.pubDate,
} satisfies LatestItemsEntry;
}
const latestItems: LatestItemsEntry[] = await Promise.all(
[
stories.map((story) => ({
latestStories.map((story) => ({
date: story.data.pubDate,
fn: async () =>
({
type: "Story",
isAgeRestricted: story.data.isAgeRestricted,
thumbnail: story.data.thumbnail,
href: `/stories/${story.slug}`,
title: story.data.title,
authors: await getEntries(story.data.authors),
lang: story.data.lang,
altText: t(story.data.lang, "story/warnings", story.data.wordCount, story.data.contentWarning),
pubDate: story.data.pubDate,
}) satisfies LatestItemsEntry,
fn: async () => await storyEntry(story),
})),
games.map((game) => ({
latestGames.map((game) => ({
date: game.data.pubDate,
fn: async () =>
({
type: "Game",
isAgeRestricted: game.data.isAgeRestricted,
thumbnail: game.data.thumbnail,
href: `/games/${game.slug}`,
title: game.data.title,
authors: await getEntries(game.data.authors),
lang: game.data.lang,
altText: t(game.data.lang, "game/warnings", game.data.platforms, game.data.contentWarning),
pubDate: game.data.pubDate,
}) satisfies LatestItemsEntry,
fn: async () => await gameEntry(game),
})),
posts.map((post) => ({
latestPosts.map((post) => ({
date: post.data.pubDate,
fn: async () =>
({
type: "Blog post",
isAgeRestricted: post.data.isAgeRestricted,
thumbnail: post.data.thumbnail,
href: `/blog/${post.slug}`,
title: post.data.title,
authors: await getEntries(post.data.authors),
lang: post.data.lang,
altText: markdownToPlaintext(post.data.description),
pubDate: post.data.pubDate,
}) satisfies LatestItemsEntry,
fn: async () => await blogEntry(post),
})),
]
.flat()
.sort((a, b) => b.date.getTime() - a.date.getTime())
.slice(0, MAX_ITEMS)
.slice(0, MAX_LATEST_ITEMS)
.map(async (entry) => await entry.fn()),
);
const featuredItems: LatestItemsEntry[] = await Promise.all(
[
featuredStories.map((story) => ({
date: story.data.pubDate,
fn: async () => await storyEntry(story),
})),
featuredGames.map((game) => ({
date: game.data.pubDate,
fn: async () => await gameEntry(game),
})),
featuredPosts.map((post) => ({
date: post.data.pubDate,
fn: async () => await blogEntry(post),
})),
]
.flat()
.sort((a, b) => b.date.getTime() - a.date.getTime())
.map(async (entry) => await entry.fn()),
);
if (featuredItems.length > MAX_FEATURED_ITEMS) {
throw new Error(`Cannot have more than ${MAX_FEATURED_ITEMS} featured items (found ${featuredItems.length} items)`);
}
---
<GalleryLayout pageTitle="Gallery" class="h-feed">
<meta slot="head" property="og:description" content="Bad Manners || Welcome to my gallery!" />
<h1 class="p-name m-2 text-3xl font-semibold text-stone-800 dark:text-stone-100">Gallery</h1>
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" />
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" aria-hidden />
<div class="p-summary">
<div class="my-4 flex">
<p class="grow">
Hey there, welcome to my corner of the Internet! This is where I'll share all of the safe vore and endosoma
content that I'll make. You can check the latest uploads below, or use the navigation bar to dig through all of
my content.
Welcome to my corner of the Internet! If you're looking for my main page, <a
class="u-url text-link underline"
href="https://badmanners.xyz"
x-data={JSON.stringify({ href: "https://badmanners.xyz", suffix: "?ageVerified=true" })}
x-bind:href="ageVerified ? href + suffix : href"
rel="me">click here</a
>.
</p>
<a class="u-url text-link ml-2 p-1 md:mr-5" href="/feed.xml" rel="alternate" title="RSS feed" data-tooltip>
<IconSquareRSS width="2rem" height="2rem" />
@ -115,12 +172,86 @@ const latestItems: LatestItemsEntry[] = await Promise.all(
</a>
</div>
</div>
<section class="my-2" aria-labelledby="latest-uploads">
<h2 id="latest-uploads" class="p-2 text-xl font-semibold text-stone-800 dark:text-stone-100">Latest uploads</h2>
<section
class="my-2 max-w-max rounded-lg bg-stone-50 px-4 pb-8 pt-4 md:-ml-2 md:pb-10 dark:bg-stone-700"
aria-labelledby="featured-uploads"
>
<h2 id="featured-uploads" class="mb-4 p-2 text-xl font-semibold text-stone-900 dark:text-stone-50">
<span class="inline-block align-middle">
<IconSparkles width="1.25rem" height="1.25rem" />
</span>
<span>Featured</span>
</h2>
<ul class="flex flex-wrap items-start justify-center gap-4 text-center md:justify-normal">
{
featuredItems.map((entry) => (
<li class="h-entry break-inside-avoid" lang={entry.lang} aria-label={entry.title}>
<a
class="u-url text-link hover:underline focus:underline"
href={entry.href}
title={entry.altText}
data-tooltip
>
{entry.thumbnail ? (
<div class="flex aspect-square max-w-[192px] justify-center">
<Image
loading="eager"
class="u-photo m-auto"
src={entry.thumbnail}
alt={`Thumbnail for ${entry.title}`}
width={192}
/>
</div>
) : null}
<div class="max-w-[192px] text-sm">
<span class="p-name" aria-label="Title">
{entry.title}
</span>
<br />
<span class="italic">
{entry.isAgeRestricted ? (
<span class="inline-block align-middle" aria-label="Age restricted">
<IconNoOneUnder18 width="1.25rem" height="1.25rem" />
</span>
) : null}
<span class="p-category" aria-label="Category">
{entry.type}
</span>{" "}
&ndash;{" "}
<time
class="dt-published"
datetime={entry.pubDate.toISOString().slice(0, 10)}
aria-label="Publish date"
>
{entry.pubDate.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })}
</time>
</span>
</div>
</a>
<div class="sr-only select-none">
<p class="p-summary" aria-label="Summary">
{entry.altText}
</p>
<div aria-label="Authors">
<span>{entry.authors.length == 1 ? "Author:" : "Authors:"}</span>
{entry.authors.map((author) => (
<UserComponent rel="author" class="p-author" user={author} lang={entry.lang} />
))}
</div>
</div>
</li>
))
}
</ul>
</section>
<section class="mb-2 mt-12" aria-labelledby="latest-uploads">
<h2 id="latest-uploads" class="mb-4 p-2 text-xl font-semibold text-stone-800 dark:text-stone-100">
Latest uploads
</h2>
<ul class="flex flex-wrap items-start justify-center gap-4 text-center md:justify-normal">
{
latestItems.map((entry) => (
<li class="h-entry break-inside-avoid" lang={entry.lang}>
<li class="h-entry break-inside-avoid" lang={entry.lang} aria-label={entry.title}>
<a
class="u-url text-link hover:underline focus:underline"
href={entry.href}

View file

@ -11,6 +11,6 @@ import GalleryLayout from "@layouts/GalleryLayout.astro";
<GalleryLayout pageTitle="Search">
<meta slot="head" property="og:description" content="Bad Manners || Search" />
<h1 class="m-2 text-3xl font-semibold text-stone-800 dark:text-stone-100">Search</h1>
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" />
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" aria-hidden />
<SearchComponent id="search" className="pagefind-ui my-4" />
</GalleryLayout>

View file

@ -32,7 +32,7 @@ const totalPages = Math.ceil(page.total / page.size);
<GalleryLayout pageTitle="Stories" class="h-feed">
<meta slot="head" property="og:description" content={`Bad Manners || ${page.total} stories.`} />
<h1 class="p-name m-2 grow text-3xl font-semibold text-stone-800 dark:text-stone-100">Stories</h1>
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" />
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" aria-hidden />
<div class="my-4 flex">
<p class="p-summary grow">The bulk of my content!</p>
<a class="u-url text-link ml-2 p-1 md:mr-5" href="/stories/feed.xml" rel="alternate" title="RSS feed" data-tooltip>
@ -70,7 +70,7 @@ const totalPages = Math.ceil(page.total / page.size);
) : (
<a
class="text-link border-r border-stone-400 px-2 py-1 underline dark:border-stone-500"
href={p === 1 ? "/stories/" : `/stories/${p}`}
href={p === 1 ? "/stories" : `/stories/${p}`}
>
{p}
</a>
@ -166,7 +166,7 @@ const totalPages = Math.ceil(page.total / page.size);
) : (
<a
class="text-link border-r border-stone-400 px-2 py-1 underline dark:border-stone-500"
href={p === 1 ? "/stories/" : `/stories/${p}`}
href={p === 1 ? "/stories" : `/stories/${p}`}
>
{p}
</a>

View file

@ -3,6 +3,7 @@ import { getCollection, getEntry, type CollectionEntry } from "astro:content";
import { Image } from "astro:assets";
import GalleryLayout from "@layouts/GalleryLayout.astro";
import mapImage from "@assets/images/tlotm_map.jpg";
import { IconNoOneUnder18 } from "@components/icons";
type StoryWithPubDate = CollectionEntry<"stories"> & { data: { pubDate: Date } };
@ -27,7 +28,7 @@ const mainChaptersWithSummaries = mainChapters.filter((story) => story.data.summ
content="The Lost of the Marshes || The story of Quince, Nikili, and Suu."
/>
<h1 class="p-name m-2 text-3xl font-semibold text-stone-800 dark:text-stone-100">{series.data.name}</h1>
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" />
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" aria-hidden />
<p class="p-summary my-4">
This is the main hub for the story of Quince, Nikili, and Suu, as well as all bonus content.
</p>
@ -79,6 +80,11 @@ const mainChaptersWithSummaries = mainChapters.filter((story) => story.data.summ
<div class="max-w-48 text-sm">
<span class="p-name">{story.data.title}</span>
<br />
{story.data.isAgeRestricted ? (
<span class="inline-block align-middle" aria-label="Age restricted">
<IconNoOneUnder18 width="1.25rem" height="1.25rem" />
</span>
) : null}
<time class="dt-published italic" datetime={story.data.pubDate.toISOString().slice(0, 10)}>
{story.data.pubDate.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })}
</time>
@ -108,6 +114,11 @@ const mainChaptersWithSummaries = mainChapters.filter((story) => story.data.summ
<div class="max-w-48 text-sm">
<span class="p-name">{story.data.title}</span>
<br />
{story.data.isAgeRestricted ? (
<span class="inline-block align-middle" aria-label="Age restricted">
<IconNoOneUnder18 width="1.25rem" height="1.25rem" />
</span>
) : null}
<time class="dt-published italic" datetime={story.data.pubDate.toISOString().slice(0, 10)}>
{story.data.pubDate.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })}
</time>

View file

@ -78,8 +78,7 @@ if (uncategorizedTagsSet.size > 0) {
<GalleryLayout pageTitle="Tags">
<meta property="og:description" slot="head" content="Bad Manners || Find all content with a specific tag." />
<h1 class="m-2 text-3xl font-semibold text-stone-800 dark:text-stone-100">All available tags</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">You can find all content with a specific tag by selecting it below from the appropriate category.</p>
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" aria-hidden />
<section class="my-2" aria-labelledby="category-series">
<h2 id="category-series" class="p-2 text-xl font-semibold text-stone-800 dark:text-stone-100">Series</h2>
<ul class="list-disc pl-8">
@ -105,7 +104,7 @@ if (uncategorizedTagsSet.size > 0) {
{tagList.map(({ id, name, description }) => (
<li>
<a
class="rounded-full bg-bm-300 px-3 py-1 text-sm text-black shadow-sm hover:underline focus:underline dark:bg-bm-600 dark:text-white"
class="rounded-full bg-bm-300 px-3 py-1 text-sm text-black shadow-sm hover:underline focus:underline dark:bg-green-700 dark:text-white"
href={`/tags/${id}`}
title={description}
data-tooltip

View file

@ -27,6 +27,6 @@ const { badTag } = Astro.props;
<meta name="robots" content="noindex" />
</Fragment>
<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" />
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" aria-hidden />
<p class="my-4">No.</p>
</GalleryLayout>

View file

@ -139,7 +139,7 @@ const totalWorksWithTag = t(
<GalleryLayout pageTitle={`Works tagged "${props.tag}"`}>
<meta slot="head" content={`Bad Manners || ${totalWorksWithTag || props.tag}`} property="og:description" />
<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" />
<hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" aria-hidden />
<div class="my-4">
<Prose>
{description ? <Markdown of={description} /> : null}