Add "Woofer Exploration" and improve drafting
This commit is contained in:
parent
a9d5a88d0e
commit
405ad38f5d
25 changed files with 300 additions and 189 deletions
|
|
@ -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>© 2024 | </span>
|
||||
<span>© {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">
|
||||
|
|
|
|||
|
|
@ -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
|
||||
>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue