Add qualifyLocalURLsInMarkdown()
This will handle special links in the description and similar fields
This commit is contained in:
parent
c38275e2f2
commit
cd67f6a5c5
20 changed files with 982 additions and 296 deletions
|
|
@ -6,6 +6,7 @@ import sanitizeHtml from "sanitize-html";
|
|||
import { t, type Lang } from "../i18n";
|
||||
import { markdownToPlaintext } from "../utils/markdown_to_plaintext";
|
||||
import { getUsernameForLang } from "../utils/get_username_for_lang";
|
||||
import { qualifyLocalURLsInMarkdown } from "../utils/qualify_local_urls_in_markdown";
|
||||
|
||||
type FeedItem = RSSFeedItem &
|
||||
Required<Pick<RSSFeedItem, "title" | "pubDate" | "link" | "description" | "categories" | "content">>;
|
||||
|
|
@ -28,6 +29,81 @@ const getLinkForUser = (user: CollectionEntry<"users">, lang: Lang) => {
|
|||
return userName;
|
||||
};
|
||||
|
||||
async function storyFeedItem(
|
||||
site: URL | undefined,
|
||||
data: EntryWithPubDate<"stories">["data"],
|
||||
slug: CollectionEntry<"stories">["slug"],
|
||||
body: string,
|
||||
): Promise<FeedItem> {
|
||||
return {
|
||||
title: `New story! "${data.title}"`,
|
||||
pubDate: toNoonUTCDate(data.pubDate),
|
||||
link: `/stories/${slug}`,
|
||||
description:
|
||||
`${t(data.lang, "story/warnings", data.wordCount, data.contentWarning)}\n\n${markdownToPlaintext(await qualifyLocalURLsInMarkdown(data.description, data.lang, site))}`.replaceAll(
|
||||
/[\n ]+/g,
|
||||
" ",
|
||||
),
|
||||
categories: ["story"],
|
||||
content: sanitizeHtml(
|
||||
`<h1>${data.title}</h1>` +
|
||||
`<p>${t(
|
||||
data.lang,
|
||||
"story/authors",
|
||||
(await getEntries(data.authors)).map((author) => getLinkForUser(author, data.lang)),
|
||||
)}</p>` +
|
||||
(data.requester
|
||||
? `<p>${t(
|
||||
data.lang,
|
||||
"story/requested_by",
|
||||
(await getEntries(data.requester)).map((requester) => getLinkForUser(requester, data.lang)),
|
||||
)}</p>`
|
||||
: "") +
|
||||
(data.commissioner
|
||||
? `<p>${t(
|
||||
data.lang,
|
||||
"story/commissioned_by",
|
||||
(await getEntries(data.commissioner)).map((commissioner) => getLinkForUser(commissioner, data.lang)),
|
||||
)}</p>`
|
||||
: "") +
|
||||
`<hr><p><em>${t(data.lang, "story/warnings", data.wordCount, data.contentWarning)}</em></p>` +
|
||||
`<hr>${await markdown(body)}` +
|
||||
`<hr>${await markdown(await qualifyLocalURLsInMarkdown(data.description, data.lang, site))}`,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
async function gameFeedItem(
|
||||
site: URL | undefined,
|
||||
data: EntryWithPubDate<"games">["data"],
|
||||
slug: CollectionEntry<"games">["slug"],
|
||||
body: string,
|
||||
): Promise<FeedItem> {
|
||||
return {
|
||||
title: `New game! "${data.title}"`,
|
||||
pubDate: toNoonUTCDate(data.pubDate),
|
||||
link: `/games/${slug}`,
|
||||
description:
|
||||
`${t(data.lang, "game/warnings", data.platforms, data.contentWarning)}\n\n${markdownToPlaintext(await qualifyLocalURLsInMarkdown(data.description, data.lang, site))}`.replaceAll(
|
||||
/[\n ]+/g,
|
||||
" ",
|
||||
),
|
||||
categories: ["game"],
|
||||
content: sanitizeHtml(
|
||||
`<h1>${data.title}</h1>` +
|
||||
`<p>${t(
|
||||
data.lang,
|
||||
"story/authors",
|
||||
(await getEntries(data.authors)).map((author) => getLinkForUser(author, data.lang)),
|
||||
)}</p>` +
|
||||
`<hr><p>${t(data.lang, "game/platforms", data.platforms)}</p>` +
|
||||
`<hr><p><em>${data.contentWarning}</em></p>` +
|
||||
`<hr>${await markdown(body)}` +
|
||||
`<hr>${await markdown(await qualifyLocalURLsInMarkdown(data.description, data.lang, site))}`,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
export const GET: APIRoute = async ({ site }) => {
|
||||
const stories = (
|
||||
(await getCollection(
|
||||
|
|
@ -47,75 +123,21 @@ export const GET: APIRoute = async ({ site }) => {
|
|||
title: "Gallery | Bad Manners",
|
||||
description: "Stories, games, and (possibly) more by Bad Manners",
|
||||
site: site!,
|
||||
items: [
|
||||
await Promise.all(
|
||||
stories.map<Promise<FeedItem>>(async ({ data, slug, body }) => ({
|
||||
title: `New story! "${data.title}"`,
|
||||
pubDate: toNoonUTCDate(data.pubDate),
|
||||
link: `/stories/${slug}`,
|
||||
description:
|
||||
`${t(data.lang, "story/warnings", data.wordCount, data.contentWarning)}\n\n${markdownToPlaintext(data.description)}`.replaceAll(
|
||||
/[\n ]+/g,
|
||||
" ",
|
||||
),
|
||||
categories: ["story"],
|
||||
content: sanitizeHtml(
|
||||
`<h1>${data.title}</h1>` +
|
||||
`<p>${t(
|
||||
data.lang,
|
||||
"story/authors",
|
||||
(await getEntries(data.authors)).map((author) => getLinkForUser(author, data.lang)),
|
||||
)}</p>` +
|
||||
(data.requester
|
||||
? `<p>${t(
|
||||
data.lang,
|
||||
"story/requested_by",
|
||||
(await getEntries(data.requester)).map((requester) => getLinkForUser(requester, data.lang)),
|
||||
)}</p>`
|
||||
: "") +
|
||||
(data.commissioner
|
||||
? `<p>${t(
|
||||
data.lang,
|
||||
"story/commissioned_by",
|
||||
(await getEntries(data.commissioner)).map((commissioner) =>
|
||||
getLinkForUser(commissioner, data.lang),
|
||||
),
|
||||
)}</p>`
|
||||
: "") +
|
||||
`<hr><p><em>${t(data.lang, "story/warnings", data.wordCount, data.contentWarning)}</em></p>` +
|
||||
`<hr>${await markdown(body)}` +
|
||||
`<hr>${await markdown(data.description)}`,
|
||||
),
|
||||
items: await Promise.all(
|
||||
[
|
||||
stories.map(({ data, slug, body }) => ({
|
||||
date: data.pubDate,
|
||||
fn: () => storyFeedItem(site, data, slug, body),
|
||||
})),
|
||||
),
|
||||
await Promise.all(
|
||||
games.map<Promise<FeedItem>>(async ({ data, slug, body }) => ({
|
||||
title: `New game! "${data.title}"`,
|
||||
pubDate: toNoonUTCDate(data.pubDate),
|
||||
link: `/games/${slug}`,
|
||||
description:
|
||||
`${t(data.lang, "game/warnings", data.platforms, data.contentWarning)}\n\n${markdownToPlaintext(data.description)}`.replaceAll(
|
||||
/[\n ]+/g,
|
||||
" ",
|
||||
),
|
||||
categories: ["game"],
|
||||
content: sanitizeHtml(
|
||||
`<h1>${data.title}</h1>` +
|
||||
`<p>${t(
|
||||
data.lang,
|
||||
"story/authors",
|
||||
(await getEntries(data.authors)).map((author) => getLinkForUser(author, data.lang)),
|
||||
)}</p>` +
|
||||
`<hr><p>${t(data.lang, "game/platforms", data.platforms)}</p>` +
|
||||
`<hr><p><em>${data.contentWarning}</em></p>` +
|
||||
`<hr>${await markdown(body)}` +
|
||||
`<hr>${await markdown(data.description)}`,
|
||||
),
|
||||
games.map(({ data, slug, body }) => ({
|
||||
date: data.pubDate,
|
||||
fn: () => gameFeedItem(site, data, slug, body),
|
||||
})),
|
||||
),
|
||||
]
|
||||
.flat()
|
||||
.sort((a, b) => b.pubDate.getTime() - a.pubDate.getTime())
|
||||
.slice(0, MAX_ITEMS),
|
||||
]
|
||||
.flat()
|
||||
.sort((a, b) => b.date.getTime() - a.date.getTime())
|
||||
.slice(0, MAX_ITEMS)
|
||||
.map((value) => value.fn()),
|
||||
),
|
||||
});
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue