Add Mastodon comments and remove date-fns dependency
This commit is contained in:
parent
00fa1fb164
commit
3e8bcbcf43
19 changed files with 393 additions and 142 deletions
|
|
@ -1,7 +1,6 @@
|
|||
import rss, { type RSSFeedItem } from "@astrojs/rss";
|
||||
import type { APIRoute } from "astro";
|
||||
import { getCollection } from "astro:content";
|
||||
import { getUnixTime, addMinutes } from "date-fns";
|
||||
|
||||
type FeedItem = RSSFeedItem & {
|
||||
pubDate: Date;
|
||||
|
|
@ -9,9 +8,19 @@ type FeedItem = RSSFeedItem & {
|
|||
|
||||
const MAX_ITEMS = 10;
|
||||
|
||||
function toNoonUTCDate(date: Date) {
|
||||
const adjustedDate = new Date(date);
|
||||
adjustedDate.setUTCHours(12);
|
||||
return adjustedDate;
|
||||
}
|
||||
|
||||
export const GET: APIRoute = async ({ site }) => {
|
||||
const stories = (await getCollection("stories", (story) => !story.data.isDraft)).sort((a, b) => getUnixTime(b.data.pubDate) - getUnixTime(a.data.pubDate)).slice(0, MAX_ITEMS);
|
||||
const games = (await getCollection("games", (game) => !game.data.isDraft)).sort((a, b) => getUnixTime(b.data.pubDate) - getUnixTime(a.data.pubDate)).slice(0, MAX_ITEMS);
|
||||
const stories = (await getCollection("stories", (story) => !story.data.isDraft))
|
||||
.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime())
|
||||
.slice(0, MAX_ITEMS);
|
||||
const games = (await getCollection("games", (game) => !game.data.isDraft))
|
||||
.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime())
|
||||
.slice(0, MAX_ITEMS);
|
||||
return rss({
|
||||
title: "Gallery | Bad Manners",
|
||||
description: "Stories, games, and (possibly) more by Bad Manners",
|
||||
|
|
@ -19,7 +28,7 @@ export const GET: APIRoute = async ({ site }) => {
|
|||
items: [
|
||||
stories.map<FeedItem>((story) => ({
|
||||
title: `New story! "${story.data.title}"`,
|
||||
pubDate: addMinutes(story.data.pubDate, 12 * 60 - story.data.pubDate.getTimezoneOffset()),
|
||||
pubDate: toNoonUTCDate(story.data.pubDate),
|
||||
link: `/stories/${story.slug}`,
|
||||
description:
|
||||
`Word count: ${story.data.wordCount}. ${story.data.contentWarning} ${story.data.descriptionPlaintext || story.data.description}`
|
||||
|
|
@ -29,7 +38,7 @@ export const GET: APIRoute = async ({ site }) => {
|
|||
})),
|
||||
games.map<FeedItem>((game) => ({
|
||||
title: `New game! "${game.data.title}"`,
|
||||
pubDate: addMinutes(game.data.pubDate, 12 * 60 - game.data.pubDate.getTimezoneOffset()),
|
||||
pubDate: toNoonUTCDate(game.data.pubDate),
|
||||
link: `/games/${game.slug}`,
|
||||
description: `${game.data.contentWarning} ${game.data.descriptionPlaintext || game.data.description}`
|
||||
.replaceAll(/[\n ]+/g, " ")
|
||||
|
|
@ -38,7 +47,7 @@ export const GET: APIRoute = async ({ site }) => {
|
|||
})),
|
||||
]
|
||||
.flat()
|
||||
.sort((a, b) => getUnixTime(b.pubDate) - getUnixTime(a.pubDate))
|
||||
.sort((a, b) => b.pubDate.getTime() - a.pubDate.getTime())
|
||||
.slice(0, MAX_ITEMS),
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
---
|
||||
import { Image } from "astro:assets";
|
||||
import { getCollection } from "astro:content";
|
||||
import { getUnixTime, format as formatDate } from "date-fns";
|
||||
import { enUS as enUSLocale } from "date-fns/locale/en-US";
|
||||
import GalleryLayout from "../layouts/GalleryLayout.astro";
|
||||
|
||||
const games = (await getCollection("games", (game) => !game.data.isDraft)).sort(
|
||||
(a, b) => getUnixTime(b.data.pubDate) - getUnixTime(a.data.pubDate),
|
||||
(a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime(),
|
||||
);
|
||||
---
|
||||
|
||||
|
|
@ -14,26 +12,23 @@ const games = (await getCollection("games", (game) => !game.data.isDraft)).sort(
|
|||
<meta slot="head-description" content="Bad Manners || A game that I've gone and done." property="og:description" />
|
||||
<h1 class="m-2 text-2xl font-semibold text-stone-800 dark:text-stone-100">Games</h1>
|
||||
<p class="my-4">A game that I've gone and done.</p>
|
||||
<ul class="my-6 flex flex-wrap justify-center gap-4 text-center md:justify-normal items-start">
|
||||
<ul class="my-6 flex flex-wrap items-start justify-center gap-4 text-center md:justify-normal">
|
||||
{
|
||||
games.map((game) => (
|
||||
<li>
|
||||
<a class="text-link hover:underline focus:underline" href={`/games/${game.slug}`}>
|
||||
{game.data.thumbnail ? (
|
||||
<div class="max-w-[288px] aspect-[630/500] flex justify-center">
|
||||
<Image
|
||||
class="m-auto"
|
||||
src={game.data.thumbnail}
|
||||
alt={`Thumbnail for ${game.data.title}`}
|
||||
width={288}
|
||||
/>
|
||||
<div class="flex aspect-[630/500] max-w-[288px] justify-center">
|
||||
<Image class="m-auto" src={game.data.thumbnail} alt={`Thumbnail for ${game.data.title}`} width={288} />
|
||||
</div>
|
||||
) : null}
|
||||
<div class="max-w-[288px] text-sm">
|
||||
<>
|
||||
<span>{game.data.title}</span>
|
||||
<br />
|
||||
<span class="italic">{formatDate(game.data.pubDate, "MMM d, yyyy", { locale: enUSLocale })}</span>
|
||||
<span class="italic">
|
||||
{game.data.pubDate.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })}
|
||||
</span>
|
||||
</>
|
||||
</div>
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
---
|
||||
import { type CollectionEntry, getCollection } from "astro:content";
|
||||
import { Image } from "astro:assets";
|
||||
import { getUnixTime, format as formatDate } from "date-fns";
|
||||
import { enUS as enUSLocale } from "date-fns/locale/en-US";
|
||||
import GalleryLayout from "../layouts/GalleryLayout.astro";
|
||||
|
||||
const MAX_ITEMS = 5;
|
||||
|
|
@ -15,25 +13,32 @@ interface LatestItemsEntry {
|
|||
pubDate: Date;
|
||||
}
|
||||
|
||||
const stories = (await getCollection("stories", (story) => !story.data.isDraft)).sort((a, b) => getUnixTime(b.data.pubDate) - getUnixTime(a.data.pubDate)).slice(0, MAX_ITEMS);
|
||||
const games = (await getCollection("games", (game) => !game.data.isDraft)).sort((a, b) => getUnixTime(b.data.pubDate) - getUnixTime(a.data.pubDate)).slice(0, MAX_ITEMS);
|
||||
const stories = (await getCollection("stories", (story) => !story.data.isDraft))
|
||||
.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime())
|
||||
.slice(0, MAX_ITEMS);
|
||||
const games = (await getCollection("games", (game) => !game.data.isDraft))
|
||||
.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime())
|
||||
.slice(0, MAX_ITEMS);
|
||||
|
||||
const latestItems: LatestItemsEntry[] = [
|
||||
stories.map<LatestItemsEntry>(story => ({
|
||||
stories.map<LatestItemsEntry>((story) => ({
|
||||
type: "Story",
|
||||
thumbnail: story.data.thumbnail,
|
||||
href: `/stories/${story.slug}`,
|
||||
title: story.data.title,
|
||||
pubDate: story.data.pubDate,
|
||||
})),
|
||||
games.map<LatestItemsEntry>(game => ({
|
||||
games.map<LatestItemsEntry>((game) => ({
|
||||
type: "Game",
|
||||
thumbnail: game.data.thumbnail,
|
||||
href: `/games/${game.slug}`,
|
||||
title: game.data.title,
|
||||
pubDate: game.data.pubDate,
|
||||
})),
|
||||
].flat().sort((a, b) => getUnixTime(b.pubDate) - getUnixTime(a.pubDate)).slice(0, MAX_ITEMS);
|
||||
]
|
||||
.flat()
|
||||
.sort((a, b) => b.pubDate.getTime() - a.pubDate.getTime())
|
||||
.slice(0, MAX_ITEMS);
|
||||
---
|
||||
|
||||
<GalleryLayout pageTitle="Gallery">
|
||||
|
|
@ -54,25 +59,23 @@ const latestItems: LatestItemsEntry[] = [
|
|||
</p>
|
||||
<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>
|
||||
<ul class="flex flex-wrap justify-center gap-4 text-center md:justify-normal items-start">
|
||||
<ul class="flex flex-wrap items-start justify-center gap-4 text-center md:justify-normal">
|
||||
{
|
||||
latestItems.map((entry) => (
|
||||
<li class="break-inside-avoid">
|
||||
<a class="text-link hover:underline focus:underline" href={entry.href}>
|
||||
{entry.thumbnail ? (
|
||||
<div class="max-w-[192px] aspect-square flex justify-center">
|
||||
<Image
|
||||
class="m-auto"
|
||||
src={entry.thumbnail}
|
||||
alt={`Thumbnail for ${entry.title}`}
|
||||
width={192}
|
||||
/>
|
||||
<div class="flex aspect-square max-w-[192px] justify-center">
|
||||
<Image class="m-auto" src={entry.thumbnail} alt={`Thumbnail for ${entry.title}`} width={192} />
|
||||
</div>
|
||||
) : null}
|
||||
<div class="max-w-[192px] text-sm">
|
||||
<span>{entry.title}</span>
|
||||
<br />
|
||||
<span class="italic">{entry.type} – {formatDate(entry.pubDate, "MMM d, yyyy", { locale: enUSLocale })}</span>
|
||||
<span class="italic">
|
||||
{entry.type} –{" "}
|
||||
{entry.pubDate.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })}
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -2,14 +2,12 @@
|
|||
import type { GetStaticPaths, Page } from "astro";
|
||||
import { Image } from "astro:assets";
|
||||
import { getCollection } from "astro:content";
|
||||
import { getUnixTime, format as formatDate } from "date-fns";
|
||||
import { enUS as enUSLocale } from "date-fns/locale/en-US";
|
||||
import GalleryLayout from "../../layouts/GalleryLayout.astro";
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
|
||||
export const getStaticPaths: GetStaticPaths = async ({ paginate }) => {
|
||||
const stories = (await getCollection("stories", (story) => !story.data.isDraft)).sort(
|
||||
(a, b) => getUnixTime(b.data.pubDate) - getUnixTime(a.data.pubDate),
|
||||
(a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime(),
|
||||
);
|
||||
return paginate(stories, { pageSize: 30 });
|
||||
};
|
||||
|
|
@ -62,13 +60,13 @@ const totalPages = Math.ceil(page.total / page.size);
|
|||
)
|
||||
}
|
||||
</div>
|
||||
<ul class="flex flex-wrap justify-center gap-4 text-center md:justify-normal items-start">
|
||||
<ul class="flex flex-wrap items-start justify-center gap-4 text-center md:justify-normal">
|
||||
{
|
||||
page.data.map((story) => (
|
||||
<li class="break-inside-avoid">
|
||||
<a class="text-link hover:underline focus:underline" href={`/stories/${story.slug}`}>
|
||||
{story.data.thumbnail ? (
|
||||
<div class="max-w-[192px] aspect-square flex justify-center">
|
||||
<div class="flex aspect-square max-w-[192px] justify-center">
|
||||
<Image
|
||||
class="m-auto"
|
||||
src={story.data.thumbnail}
|
||||
|
|
@ -80,7 +78,9 @@ const totalPages = Math.ceil(page.total / page.size);
|
|||
<div class="max-w-[192px] text-sm">
|
||||
<span>{story.data.title}</span>
|
||||
<br />
|
||||
<span class="italic">{formatDate(story.data.pubDate, "MMM d, yyyy", { locale: enUSLocale })}</span>
|
||||
<span class="italic">
|
||||
{story.data.pubDate.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })}
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { type APIRoute, type GetStaticPaths } from "astro";
|
||||
import { getCollection, getEntry, type CollectionEntry, getEntries } from "astro:content";
|
||||
import { marked, type RendererApi } from "marked";
|
||||
import he from "he";
|
||||
import { decode as tinyDecode } from "tiny-decode";
|
||||
import { type Website } from "../../../../../content/config";
|
||||
|
||||
const WEBSITE_LIST = ["eka", "furaffinity", "inkbunny", "sofurry", "weasyl"] as const satisfies Website[];
|
||||
|
|
@ -269,7 +269,7 @@ export const GET: APIRoute<Props, Params> = async ({ props: { story }, params: {
|
|||
const markdownExport: ReadonlyArray<ExportWebsite> = ["weasyl"] as const;
|
||||
// BBCode exports
|
||||
if (bbcodeExports.includes(website)) {
|
||||
storyDescription = he.decode(await marked.use({ renderer: bbcodeRenderer }).parse(storyDescription));
|
||||
storyDescription = tinyDecode(await marked.use({ renderer: bbcodeRenderer }).parse(storyDescription));
|
||||
headers["Content-Type"] = "text/plain; charset=utf-8";
|
||||
// Markdown exports (no-op)
|
||||
} else if (!markdownExport.includes(website)) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
import { getCollection, getEntry } from "astro:content";
|
||||
import { Image } from "astro:assets";
|
||||
import { getUnixTime } from "date-fns";
|
||||
import GalleryLayout from "../../layouts/GalleryLayout.astro";
|
||||
import mapImage from "../../assets/images/tlotm_map.jpg";
|
||||
|
||||
|
|
@ -9,10 +8,10 @@ const series = await getEntry("series", "the-lost-of-the-marshes");
|
|||
const stories = await getCollection("stories", (story) => !story.data.isDraft && story.data.series?.id === series.id);
|
||||
const mainChapters = stories
|
||||
.filter((story) => story.slug.startsWith("the-lost-of-the-marshes/chapter-"))
|
||||
.sort((a, b) => getUnixTime(a.data.pubDate) - getUnixTime(b.data.pubDate));
|
||||
.sort((a, b) => a.data.pubDate.getTime() - b.data.pubDate.getTime());
|
||||
const bonusChapters = stories
|
||||
.filter((story) => story.slug.startsWith("the-lost-of-the-marshes/bonus-"))
|
||||
.sort((a, b) => getUnixTime(a.data.pubDate) - getUnixTime(b.data.pubDate));
|
||||
.sort((a, b) => a.data.pubDate.getTime() - b.data.pubDate.getTime());
|
||||
const mainChaptersWithSummaries = mainChapters.filter((story) => story.data.summary);
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import type { GetStaticPaths } from "astro";
|
|||
import { Image } from "astro:assets";
|
||||
import { type CollectionEntry, getCollection } from "astro:content";
|
||||
import { slug } from "github-slugger";
|
||||
import { getUnixTime } from "date-fns";
|
||||
import GalleryLayout from "../../layouts/GalleryLayout.astro";
|
||||
|
||||
export const getStaticPaths: GetStaticPaths = async () => {
|
||||
|
|
@ -27,10 +26,10 @@ export const getStaticPaths: GetStaticPaths = async () => {
|
|||
tag,
|
||||
stories: stories
|
||||
.filter((story) => !story.data.isDraft && story.data.tags.includes(tag))
|
||||
.sort((a, b) => getUnixTime(b.data.pubDate!) - getUnixTime(a.data.pubDate!)),
|
||||
.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime()),
|
||||
games: games
|
||||
.filter((game) => !game.data.isDraft && game.data.tags.includes(tag))
|
||||
.sort((a, b) => getUnixTime(b.data.pubDate) - getUnixTime(a.data.pubDate)),
|
||||
.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime()),
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
|
@ -69,12 +68,12 @@ if (count == 1) {
|
|||
<h2 id="content-stories" class="p-2 text-xl font-semibold text-stone-800 dark:text-stone-100">
|
||||
Stories
|
||||
</h2>
|
||||
<ul class="flex flex-wrap justify-center gap-4 text-center md:justify-normal items-start">
|
||||
<ul class="flex flex-wrap items-start justify-center gap-4 text-center md:justify-normal">
|
||||
{stories.map((story) => (
|
||||
<li class="break-inside-avoid">
|
||||
<a class="text-link hover:underline focus:underline" href={`/stories/${story.slug}`}>
|
||||
{story.data.thumbnail ? (
|
||||
<div class="max-w-[192px] aspect-square flex justify-center">
|
||||
<div class="flex aspect-square max-w-[192px] justify-center">
|
||||
<Image
|
||||
class="m-auto"
|
||||
src={story.data.thumbnail}
|
||||
|
|
@ -97,19 +96,19 @@ if (count == 1) {
|
|||
<h2 id="content-games" class="p-2 text-xl font-semibold text-stone-800 dark:text-stone-100">
|
||||
Games
|
||||
</h2>
|
||||
<ul class="flex flex-wrap justify-center gap-4 text-center md:justify-normal items-start">
|
||||
<ul class="flex flex-wrap items-start justify-center gap-4 text-center md:justify-normal">
|
||||
{games.map((game) => (
|
||||
<li class="break-inside-avoid">
|
||||
<a class="text-link hover:underline focus:underline" href={`/games/${game.slug}`}>
|
||||
{game.data.thumbnail ? (
|
||||
<div class="max-w-[192px] aspect-[630/500] flex justify-center">
|
||||
<Image
|
||||
class="m-auto"
|
||||
src={game.data.thumbnail}
|
||||
alt={`Thumbnail for ${game.data.title}`}
|
||||
width={192}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex aspect-[630/500] max-w-[192px] justify-center">
|
||||
<Image
|
||||
class="m-auto"
|
||||
src={game.data.thumbnail}
|
||||
alt={`Thumbnail for ${game.data.title}`}
|
||||
width={192}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
<div class="max-w-48 text-sm">{game.data.title}</div>
|
||||
</a>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue