Migrate to LFTP deployment and improve templates

- Add `deploy-lftp` command
- Add 404 page
- Change relative links to absolute links
- Fix pagination links
- Remove drafts from Pagefind indexing
- Fix OpenGraph descriptions for i18n
- Add Commissioners and Requesters components
- Add consistent type-checking for getStaticPaths
This commit is contained in:
Bad Manners 2024-06-16 19:24:25 -03:00
parent 837433364d
commit a9d5a88d0e
26 changed files with 254 additions and 70 deletions

9
src/pages/404.astro Normal file
View file

@ -0,0 +1,9 @@
---
import GalleryLayout from "../layouts/GalleryLayout.astro";
---
<GalleryLayout pageTitle="Gallery">
<meta slot="head-description" property="og:description" content="Not found" />
<h1 class="m-2 text-2xl font-semibold text-stone-800 dark:text-stone-100">404 &ndash; Not Found</h1>
<p class="my-4">The requested link couldn't be found. Make sure that the URL is correct.</p>
</GalleryLayout>

View file

@ -1,8 +1,8 @@
import { type APIRoute, type GetStaticPaths } from "astro";
import type { APIRoute, GetStaticPaths } from "astro";
import { getCollection, getEntry, type CollectionEntry, getEntries } from "astro:content";
import { marked, type RendererApi } from "marked";
import { decode as tinyDecode } from "tiny-decode";
import { type Lang, type Website } from "../../../content/config";
import type { Lang, Website } from "../../../content/config";
import { t } from "../../../i18n";
type ExportFormat = "bbcode" | "markdown";
@ -252,9 +252,9 @@ export const GET: APIRoute<Props, Params> = async ({ props: { story }, site }) =
)
.join("\n\n")
.replaceAll(
/\[([^\]]+)\]\((\.[^\)]+)\)/g,
/\[([^\]]+)\]\((\/[^\)]+)\)/g,
(_, group1, group2) =>
`[${group1}](${new URL(group2, new URL(`/stories/${story.slug}`, site)).toString()})`,
`[${group1}](${new URL(group2, site).toString()})`,
);
if (exportFormat === "bbcode") {
return [

View file

@ -3,14 +3,19 @@ import type { GetStaticPaths } from "astro";
import { type CollectionEntry, getCollection } from "astro:content";
import GameLayout from "../../layouts/GameLayout.astro";
type Props = CollectionEntry<"games">;
type Params = {
slug: CollectionEntry<"games">["slug"];
};
export const getStaticPaths: GetStaticPaths = async () => {
const games = await getCollection("games");
return games.map((game) => ({
params: { slug: game.slug },
props: game,
params: { slug: game.slug } satisfies Params,
props: game satisfies Props,
}));
};
type Props = CollectionEntry<"games">;
const game = Astro.props;
const { Content } = await game.render();

View file

@ -3,14 +3,19 @@ import type { GetStaticPaths } from "astro";
import { type CollectionEntry, getCollection } from "astro:content";
import StoryLayout from "../../layouts/StoryLayout.astro";
type Props = CollectionEntry<"stories">;
type Params = {
slug: CollectionEntry<"stories">["slug"];
};
export const getStaticPaths: GetStaticPaths = async () => {
const stories = await getCollection("stories");
return stories.map((story) => ({
params: { slug: story.slug },
props: story,
params: { slug: story.slug } satisfies Params,
props: story satisfies Props,
}));
};
type Props = CollectionEntry<"stories">;
const story = Astro.props;
const { Content } = await story.render();

View file

@ -5,15 +5,15 @@ import { getCollection } from "astro:content";
import GalleryLayout from "../../layouts/GalleryLayout.astro";
import type { CollectionEntry } from "astro:content";
type Props = {
page: Page<CollectionEntry<"stories">>;
};
export const getStaticPaths: GetStaticPaths = async ({ paginate }) => {
const stories = (await getCollection("stories", (story) => !story.data.isDraft)).sort(
(a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime(),
);
return paginate(stories, { pageSize: 30 });
};
type Props = {
page: Page<CollectionEntry<"stories">>;
return paginate(stories, { pageSize: 30 }) satisfies { props: Props }[];
};
const { page } = Astro.props;
@ -46,7 +46,10 @@ const totalPages = Math.ceil(page.total / page.size);
{p + 1}
</span>
) : (
<a class="text-link border-r border-stone-400 px-2 py-1 underline dark:border-stone-500" href={`./${p + 1}`}>
<a
class="text-link border-r border-stone-400 px-2 py-1 underline dark:border-stone-500"
href={page.url.current.replace(`/${page.currentPage}`, `/${p + 1}`)}
>
{p + 1}
</a>
),
@ -102,7 +105,10 @@ const totalPages = Math.ceil(page.total / page.size);
{p + 1}
</span>
) : (
<a class="text-link border-r border-stone-400 px-2 py-1 underline dark:border-stone-500" href={`./${p + 1}`}>
<a
class="text-link border-r border-stone-400 px-2 py-1 underline dark:border-stone-500"
href={page.url.current.replace(`/${page.currentPage}`, `/${p + 1}`)}
>
{p + 1}
</a>
),

View file

@ -5,6 +5,16 @@ import { type CollectionEntry, getCollection } from "astro:content";
import { slug } from "github-slugger";
import GalleryLayout from "../../layouts/GalleryLayout.astro";
type Props = {
tag: string;
stories: CollectionEntry<"stories">[];
games: CollectionEntry<"games">[];
};
type Params = {
slug: string;
};
export const getStaticPaths: GetStaticPaths = async () => {
const [stories, games] = await Promise.all([getCollection("stories"), getCollection("games")]);
const tags = new Set<string>();
@ -21,7 +31,7 @@ export const getStaticPaths: GetStaticPaths = async () => {
return [...tags]
.filter((tag) => !["The Lost of the Marshes"].includes(tag))
.map((tag) => ({
params: { slug: slug(tag) },
params: { slug: slug(tag) } satisfies Params,
props: {
tag,
stories: stories
@ -30,16 +40,10 @@ export const getStaticPaths: GetStaticPaths = async () => {
games: games
.filter((game) => !game.data.isDraft && game.data.tags.includes(tag))
.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime()),
},
} satisfies Props,
}));
};
type Props = {
tag: string;
stories: CollectionEntry<"stories">[];
games: CollectionEntry<"games">[];
};
const { tag, stories, games } = Astro.props;
const count = stories.length + games.length;
let tagDescription: string = "";