Add "Woofer Exploration" and improve drafting

This commit is contained in:
Bad Manners 2024-06-23 18:24:59 -03:00
parent a9d5a88d0e
commit 405ad38f5d
25 changed files with 300 additions and 189 deletions

View file

@ -11,6 +11,8 @@ type Props = {
const { pageTitle, enablePagefind } = Astro.props;
const logo = await getImage({ src: logoBM, width: 192 });
const currentYear = new Date().getFullYear();
const copyrightYear = currentYear > 2014 ? `2024${currentYear}` : "2024";
---
<BaseLayout pageTitle={pageTitle}>
@ -38,7 +40,7 @@ const logo = await getImage({ src: logoBM, width: 192 });
<span class="my-2 text-2xl font-semibold">Bad Manners</span>
<Navigation />
<div class="pt-4 text-center text-xs text-black dark:text-white">
<span>&copy; 2024 | </span>
<span>&copy; {copyrightYear} | </span>
<a class="hover:underline focus:underline" href="/licenses.txt" target="_blank">Licenses</a>
</div>
<div class="mt-2 flex items-center gap-x-1 pb-10">

View file

@ -10,27 +10,14 @@ import CopyrightedCharacters from "../components/CopyrightedCharacters.astro";
import Prose from "../components/Prose.astro";
import MastodonComments from "../components/MastodonComments.astro";
import UserComponent from "../components/UserComponent.astro";
import { formatCopyrightedCharacters } from "../utils/format_copyrighted_characters";
type Props = CollectionEntry<"games">["data"];
const { props } = Astro;
const series = props.series && (await getEntry(props.series));
const authors = await getEntries([props.authors].flat());
const copyrightedCharacters = await Promise.all(
Object.values(
Object.keys(props.copyrightedCharacters).reduce(
(acc, character) => {
const user = props.copyrightedCharacters[character];
if (!(user.id in acc)) {
acc[user.id] = [getEntry(user), []];
}
acc[user.id][1].push(character);
return acc;
},
{} as Record<string, [Promise<CollectionEntry<"users">>, string[]]>,
),
).map(async ([userPromise, characters]) => [await userPromise, characters] as [CollectionEntry<"users">, string[]]),
);
const copyrightedCharacters = await formatCopyrightedCharacters(props.copyrightedCharacters);
// const relatedStories = (await getEntries(props.relatedStories)).filter((story) => !story.data.isDraft);
// const relatedGames = (await getEntries(props.relatedGames)).filter((game) => !game.data.isDraft);
const categorizedTags = Object.fromEntries(
@ -46,7 +33,7 @@ const categorizedTags = Object.fromEntries(
const tags = props.tags.map<[string, string]>((tag) => {
const tagSlug = slug(tag);
if (!(tag in categorizedTags)) {
console.log(`Tag "${tag}" doesn't have a category in tag-categories!`);
console.log(`Tag "${tag}" doesn't have a category in the "tag-categories" collection!`);
return [tagSlug, tag];
}
return [tagSlug, categorizedTags[tag]!];
@ -187,7 +174,7 @@ const thumbnail =
>
{t(props.lang, "story/draft_warning")}
</p>
) : (
) : props.pubDate ? (
<p
id="publish-date"
class="mt-2 px-2 text-center font-serif font-light text-stone-600 dark:text-stone-200"
@ -202,7 +189,7 @@ const thumbnail =
>
{t(props.lang, "story/publish_date", props.pubDate.toISOString().slice(undefined, 10))}
</p>
)
) : null
}
<section id="description" class="px-2 font-serif" aria-describedby="title-description">
<h2 id="title-description" class="py-2 font-serif text-xl font-semibold text-stone-800 dark:text-stone-100">
@ -222,28 +209,32 @@ const thumbnail =
><span>{t(props.lang, "story/to_top")}</span></a
>
</div>
<section id="tags" aria-describedby="title-tags" class="my-5">
<h2 id="title-tags" class="p-2 font-serif text-xl font-semibold text-stone-800 dark:text-stone-100">Tags</h2>
<ul class="flex flex-wrap gap-x-2 gap-y-2 px-2">
{
tags.map(([tagSlug, tagText]) => (
<li class="rounded-full bg-bm-300 px-3 py-1 text-sm text-black shadow-sm dark:bg-bm-600 dark:text-white print:bg-none">
<a class="hover:underline focus:underline" href={`/tags/${tagSlug}`}>
{tagText}
</a>
</li>
))
}
</ul>
</section>
{
tags.length > 0 ? (
<section id="tags" aria-describedby="title-tags" class="my-5">
<h2 id="title-tags" class="p-2 font-serif text-xl font-semibold text-stone-800 dark:text-stone-100">
Tags
</h2>
<ul class="flex flex-wrap gap-x-2 gap-y-2 px-2">
{tags.map(([tagSlug, tagText]) => (
<li class="rounded-full bg-bm-300 px-3 py-1 text-sm text-black shadow-sm dark:bg-bm-600 dark:text-white print:bg-none">
<a class="hover:underline focus:underline" href={`/tags/${tagSlug}`}>
{tagText}
</a>
</li>
))}
</ul>
</section>
) : null
}
<MastodonComments
instance={props.mastodonPost?.instance}
user={props.mastodonPost?.user}
postId={props.mastodonPost?.postId}
instance={props.posts.mastodon?.instance}
user={props.posts.mastodon?.user}
postId={props.posts.mastodon?.postId}
/>
</main>
<div class="pt-6 text-center text-xs text-black dark:text-white">
<span>{t(props.lang, "story/copyright_year", props.pubDate.getFullYear())} | </span>
<span>{t(props.lang, "story/copyright_year", (props.pubDate || new Date()).getFullYear())} | </span>
<a class="hover:underline focus:underline" href="/licenses.txt" target="_blank"
>{t(props.lang, "story/licenses")}</a
>

View file

@ -12,6 +12,7 @@ import UserComponent from "../components/UserComponent.astro";
import CopyrightedCharacters from "../components/CopyrightedCharacters.astro";
import Prose from "../components/Prose.astro";
import MastodonComments from "../components/MastodonComments.astro";
import { formatCopyrightedCharacters } from "../utils/format_copyrighted_characters";
type Props = CollectionEntry<"stories">["data"];
@ -28,21 +29,7 @@ const series = props.series && (await getEntry(props.series));
const authors = await getEntries([props.authors].flat());
const commissioner = props.commissioner && (await getEntry(props.commissioner));
const requester = props.requester && (await getEntry(props.requester));
const copyrightedCharacters = await Promise.all(
Object.values(
Object.keys(props.copyrightedCharacters).reduce(
(acc, character) => {
const user = props.copyrightedCharacters[character];
if (!(user.id in acc)) {
acc[user.id] = [getEntry(user), []];
}
acc[user.id][1].push(character);
return acc;
},
{} as Record<string, [Promise<CollectionEntry<"users">>, string[]]>,
),
).map(async ([userPromise, characters]) => [await userPromise, characters] as [CollectionEntry<"users">, string[]]),
);
const copyrightedCharacters = await formatCopyrightedCharacters(props.copyrightedCharacters);
const relatedStories = (await getEntries(props.relatedStories)).filter((story) => !story.data.isDraft);
// const relatedGames = (await getEntries(props.relatedGames)).filter((game) => !game.data.isDraft);
const categorizedTags = Object.fromEntries(
@ -58,7 +45,7 @@ const categorizedTags = Object.fromEntries(
const tags = props.tags.map<[string, string]>((tag) => {
const tagSlug = slug(tag);
if (!(tag in categorizedTags)) {
console.log(`Tag "${tag}" doesn't have a category in tag-categories!`);
console.log(`Tag "${tag}" doesn't have a category in the "tag-categories" collection!`);
return [tagSlug, tag];
}
return [tagSlug, categorizedTags[tag]!];
@ -66,15 +53,13 @@ const tags = props.tags.map<[string, string]>((tag) => {
const thumbnail =
props.thumbnail &&
(await getImage({ src: props.thumbnail, width: props.thumbnailWidth, height: props.thumbnailHeight }));
const wordCount = props.wordCount ? `${props.wordCount}` : "???";
---
<BaseLayout pageTitle={props.title}>
<Fragment slot="head">
<meta property="og:title" content={props.title} data-pagefind-meta="title[content]" />
<meta
property="og:description"
content={t(props.lang, "story/warnings", props.wordCount, props.contentWarning.trim())}
/>
<meta property="og:description" content={t(props.lang, "story/warnings", wordCount, props.contentWarning.trim())} />
<meta property="og:url" content={Astro.url} data-pagefind-meta="url[content]" />
{
thumbnail ? (
@ -217,7 +202,7 @@ const thumbnail =
}
<div id="content-warning">
<p>
{t(props.lang, "story/warnings", props.wordCount, props.contentWarning.trim())}
{t(props.lang, "story/warnings", wordCount, props.contentWarning.trim())}
</p>
</div>
</section>
@ -251,7 +236,7 @@ const thumbnail =
>
{t(props.lang, "story/draft_warning")}
</p>
) : (
) : props.pubDate ? (
<p
id="publish-date"
class="mt-2 px-2 text-center font-serif font-light text-stone-600 dark:text-stone-200"
@ -266,7 +251,7 @@ const thumbnail =
>
{t(props.lang, "story/publish_date", props.pubDate.toISOString().slice(undefined, 10))}
</p>
)
) : null
}
<section id="description" class="px-2 font-serif" aria-describedby="title-description">
<h2 id="title-description" class="py-2 font-serif text-xl font-semibold text-stone-800 dark:text-stone-100">
@ -359,30 +344,32 @@ const thumbnail =
</section>
) : null
}
<section id="tags" aria-describedby="title-tags" class="my-5">
<h2 id="title-tags" class="p-2 font-serif text-xl font-semibold text-stone-800 dark:text-stone-100">
{t(props.lang, "story/tags")}
</h2>
<ul class="flex flex-wrap gap-x-2 gap-y-2 px-2">
{
tags.map(([tagSlug, tagText]) => (
<li class="rounded-full bg-bm-300 px-3 py-1 text-sm text-black shadow-sm dark:bg-bm-600 dark:text-white print:bg-none">
<a class="hover:underline focus:underline" href={`/tags/${tagSlug}`}>
{tagText}
</a>
</li>
))
}
</ul>
</section>
{
tags.length > 0 ? (
<section id="tags" aria-describedby="title-tags" class="my-5">
<h2 id="title-tags" class="p-2 font-serif text-xl font-semibold text-stone-800 dark:text-stone-100">
{t(props.lang, "story/tags")}
</h2>
<ul class="flex flex-wrap gap-x-2 gap-y-2 px-2">
{tags.map(([tagSlug, tagText]) => (
<li class="rounded-full bg-bm-300 px-3 py-1 text-sm text-black shadow-sm dark:bg-bm-600 dark:text-white print:bg-none">
<a class="hover:underline focus:underline" href={`/tags/${tagSlug}`}>
{tagText}
</a>
</li>
))}
</ul>
</section>
) : null
}
<MastodonComments
instance={props.mastodonPost?.instance}
user={props.mastodonPost?.user}
postId={props.mastodonPost?.postId}
instance={props.posts.mastodon?.instance}
user={props.posts.mastodon?.user}
postId={props.posts.mastodon?.postId}
/>
</main>
<div class="pt-6 text-center text-xs text-black dark:text-white">
<span>{t(props.lang, "story/copyright_year", props.pubDate.getFullYear())} | </span>
<span>{t(props.lang, "story/copyright_year", (props.pubDate || new Date()).getFullYear())} | </span>
<a class="hover:underline focus:underline" href="/licenses.txt" target="_blank"
>{t(props.lang, "story/licenses")}</a
>