Deprecate descriptionPlaintext field
This commit is contained in:
parent
a713adc1ec
commit
688f9b982d
27 changed files with 64 additions and 121 deletions
examples
package-lock.jsonpackage.jsonsrc
content
config.ts
games
stories
birdroom.mdbladder-filler.mdbottom-of-the-food-chain.mddelicacy-s-dare.mdflavorful-favor.mdpart-of-the-show.mdruffling-some-feathers.mdteam-building.md
the-lost-of-the-marshes
tiny-accident.mdtag-categories
layouts
pages
utils
|
@ -10,8 +10,6 @@ contentWarning: >
|
|||
# thumbnail: /src/assets/thumbnails/game_thumbnail.png
|
||||
description: |
|
||||
Some funny text.
|
||||
# descriptionPlaintext: >
|
||||
# Some funny text.
|
||||
platforms: [web, windows, linux, macos, android, ios]
|
||||
# posts:
|
||||
# mastodon: https://meow.social/@BadManners/133742069
|
||||
|
|
|
@ -11,8 +11,6 @@ contentWarning: >
|
|||
# thumbnail: /src/assets/thumbnails/story_thumbnail.png
|
||||
description: |
|
||||
Some funny text.
|
||||
# descriptionPlaintext: >
|
||||
# Some funny text.
|
||||
# posts:
|
||||
# mastodon: https://meow.social/@BadManners/133742069
|
||||
tags: []
|
||||
|
|
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "gallery-badmanners-xyz",
|
||||
"version": "1.5.1",
|
||||
"version": "1.5.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "gallery-badmanners-xyz",
|
||||
"version": "1.5.1",
|
||||
"version": "1.5.2",
|
||||
"dependencies": {
|
||||
"@astrojs/check": "^0.5.10",
|
||||
"@astrojs/rss": "^4.0.5",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "gallery-badmanners-xyz",
|
||||
"type": "module",
|
||||
"version": "1.5.1",
|
||||
"version": "1.5.2",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
|
|
|
@ -80,7 +80,6 @@ const storiesCollection = defineCollection({
|
|||
.union([reference("users"), z.array(reference("users"))])
|
||||
.default("bad-manners")
|
||||
.refine(refineAuthors, `"authors" cannot be empty`),
|
||||
descriptionPlaintext: z.string().optional(),
|
||||
summary: z.string().optional(),
|
||||
thumbnail: image().optional(),
|
||||
thumbnailWidth: z.number().int().optional(),
|
||||
|
@ -123,7 +122,6 @@ const gamesCollection = defineCollection({
|
|||
.union([reference("users"), z.array(reference("users"))])
|
||||
.default("bad-manners")
|
||||
.refine(refineAuthors, `"authors" cannot be empty`),
|
||||
descriptionPlaintext: z.string().optional(),
|
||||
thumbnail: image().optional(),
|
||||
thumbnailWidth: z.number().int().optional(),
|
||||
thumbnailHeight: z.number().int().optional(),
|
||||
|
|
|
@ -16,16 +16,6 @@ description: |
|
|||
* An original soundtrack with 9 exclusive songs.
|
||||
* A challenging physics-based fishing minigame with scaling difficulty.
|
||||
* And a special cutscene...
|
||||
descriptionPlaintext: >
|
||||
Crossing Over is the story of a soul and their journey towards the Hereafter. With the help of Marco, a soul ferrier, they will remember their past and fish unexpected objects out of the ethereal river.
|
||||
|
||||
This game was created all by myself on February 2024, as an entry for Strawberry Jam 8.
|
||||
|
||||
Features:
|
||||
An hour-long linear narrative with branching dialogues;
|
||||
An original soundtrack with 9 exclusive songs;
|
||||
A challenging physics-based fishing minigame with scaling difficulty;
|
||||
And a special cutscene...
|
||||
platforms:
|
||||
- web
|
||||
- windows
|
||||
|
|
|
@ -12,10 +12,6 @@ description: |
|
|||
This silly short was inspired by [a wonderful commission](https://booru.badmanners.xyz/index.php?q=post/view/4) that I got from [Eli-Eternity](https://www.furaffinity.net/user/eli-eternity) and was supposed to go along with it, but this story doesn't even come close to doing it justice. Seriously, check out his piece if you haven't! It's turned out amazing, and he's done an incredible job, and I love it so much!
|
||||
|
||||
Why are you still reading this instead of clicking the link above?!
|
||||
descriptionPlaintext: >
|
||||
Beetle finds an odd-shaped friend deep in his work, and does what he does best: be a messy distraction.
|
||||
|
||||
This silly short was inspired by a wonderful commission that I got from Eli-Eternity and was supposed to go along with it, but this story doesn't even come close to doing it justice. Seriously, check out his piece if you haven't! It's turned out amazing, and he's done an incredible job, and I love it so much!
|
||||
posts:
|
||||
eka: https://aryion.com/g4/view/893560
|
||||
furaffinity: https://www.furaffinity.net/view/52187011/
|
||||
|
|
|
@ -11,12 +11,6 @@ description: |
|
|||
|
||||
The return of Beetle! Swallowing multiple creatures, through multiple holes – [myself included!](/stories/birdroom) –, has done little to quell his unusual appetites. But this time, he's set his eyes on you! Yes, you – a small dragon, who has been itching to try some bladder vore. An unusual request, but hey, I won't judge you!
|
||||
|
||||
...In all seriousness, I wanted to do something more daring for a PoV story. With a dragon, instead of a generic anthro, this time. And not to mention bladder vore, which is also a first for me. I'll still stick to third person narration for most of my stories, but let me know if PoV is something that you want to see more of.
|
||||
descriptionPlaintext: >
|
||||
Always watch what you wish for... Blather the right thing to the right gryphon, and you might wash up in a bladder!
|
||||
|
||||
The return of Beetle! Swallowing multiple creatures, through multiple holes – myself included! –, has done little to quell his unusual appetites. But this time, he's set his eyes on you! Yes, you – a small dragon, who has been itching to try some bladder vore. An unusual request, but hey, I won't judge you!
|
||||
|
||||
...In all seriousness, I wanted to do something more daring for a PoV story. With a dragon, instead of a generic anthro, this time. And not to mention bladder vore, which is also a first for me. I'll still stick to third person narration for most of my stories, but let me know if PoV is something that you want to see more of.
|
||||
posts:
|
||||
eka: https://aryion.com/g4/view/951990
|
||||
|
|
|
@ -10,10 +10,6 @@ description: |
|
|||
A unique opportunity falls onto Muno's coils, but he's not too pleased about it...
|
||||
|
||||
I know everyone is already thinking about October and Halloween, but I still have a Snektember addition to share! This story follows Muno the snake after the events of ["Ruffling Some Feathers"](/stories/ruffling-some-feathers), although you don't need to read that story to enjoy this one.
|
||||
descriptionPlaintext: >
|
||||
A unique opportunity falls onto Muno's coils, but he's not too pleased about it...
|
||||
|
||||
I know everyone is already thinking about October and Halloween, but I still have a Snektember addition to share! This story follows Muno the snake after the events of "Ruffling Some Feathers", although you don't need to read that story to enjoy this one.
|
||||
posts:
|
||||
eka: https://aryion.com/g4/view/937236
|
||||
furaffinity: https://www.furaffinity.net/view/53834643/
|
||||
|
|
|
@ -10,10 +10,6 @@ description: |
|
|||
Alqpra is willing to get his hands dirty in order to settle a score with Sonos... And a lot more than just his hands.
|
||||
|
||||
I was inspired by a certain dragon's writings, and wanted to try my hand at a few messier themes! Check out [destinyisbad1](https://www.furaffinity.net/user/destinyisbad1)'s gallery if you enjoy stories like this.
|
||||
descriptionPlaintext: >
|
||||
Alqpra is willing to get his hands dirty in order to settle a score with Sonos... And a lot more than just his hands.
|
||||
|
||||
I was inspired by a certain dragon's writings, and wanted to try my hand at a few messier themes! Check out destinyisbad1's gallery if you enjoy stories like this.
|
||||
posts:
|
||||
eka: https://aryion.com/g4/view/856561
|
||||
furaffinity: https://www.furaffinity.net/view/50557193/
|
||||
|
|
|
@ -10,10 +10,6 @@ description: |
|
|||
One, fearful and furry; one, formidable and feathery; and one, fired-up for the follow-up. A threesome fatefully forced into a fantastical face-to-face.
|
||||
|
||||
So many ideas that I want to write...! I just haven't found a lot of motivation to write as much as before. But I'm still working, and haven't gone anywhere. At least I finally managed to churn out this one, featuring Beetle, one of my OCs! You might recognize him from [one of the few things](https://booru.badmanners.xyz/index.php?q=post/view/3) I actually uploaded this last month. Quite a fun personality to play with, along with my sona Sam and another OC, Muno - someone might remember that last name from one of my previous stories. All of my characters featured in stories are fun really, with a few that I wanna revisit or new ones that I make for each new setting. Just wish I had a better writing rhythm to put all those ideas to life like I used to, though! Managing to finish this story is a start, I guess.
|
||||
descriptionPlaintext: >
|
||||
One, fearful and furry; one, formidable and feathery; and one, fired-up for the follow-up. A threesome fatefully forced into a fantastical face-to-face.
|
||||
|
||||
So many ideas that I want to write...! I just haven't found a lot of motivation to write as much as before. But I'm still working, and haven't gone anywhere. At least I finally managed to churn out this one, featuring Beetle, one of my OCs! You might recognize him from one of the few things I actually uploaded this last month. Quite a fun personality to play with, along with my sona Sam and another OC, Muno - someone might remember that last name from one of my previous stories. All of my characters featured in stories are fun really, with a few that I wanna revisit or new ones that I make for each new setting. Just wish I had a better writing rhythm to put all those ideas to life like I used to, though! Managing to finish this story is a start, I guess.
|
||||
posts:
|
||||
eka: https://aryion.com/g4/view/884215
|
||||
furaffinity: https://www.furaffinity.net/view/51778522/
|
||||
|
|
|
@ -10,10 +10,6 @@ description: |
|
|||
You attend a show, unaware of how personal it can turn out...
|
||||
|
||||
This is a story based off of a YCH that I got from [Helkumurrr](https://www.furaffinity.net/user/helkumurrr) which [you should definitely check out](https://booru.badmanners.xyz/index.php?q=post/view/5). First piece with myself as pred, to complement my previous commission where I was prey – and also with a short (and hopefully fun) story to go along with it!
|
||||
descriptionPlaintext: >
|
||||
You attend a show, unaware of how personal it can turn out...
|
||||
|
||||
This is a story based off of a YCH that I got from Helkumurrr which you should definitely check out. First piece with myself as pred, to complement my previous commission where I was prey – and also with a short (and hopefully fun) story to go along with it!
|
||||
posts:
|
||||
eka: https://aryion.com/g4/view/902197
|
||||
furaffinity: https://www.furaffinity.net/view/52509501/
|
||||
|
|
|
@ -10,10 +10,6 @@ description: |
|
|||
A sneaky snake switches to sudden snack, since he stopped Sovinne's sleep.
|
||||
|
||||
I'd created Muno for a different purpose, but since I wanted a story with snake prey, I thought, "why not just use him instead of making a new OC"? Also, I blame [Mr.Arcaneus](https://www.furaffinity.net/user/mr.arcaneus)'s artwork for putting me in a bird/snake mood!
|
||||
descriptionPlaintext: >
|
||||
A sneaky snake switches to sudden snack, since he stopped Sovinne's sleep.
|
||||
|
||||
I'd created Muno for a different purpose, but since I wanted a story with snake prey, I thought, "why not just use him instead of making a new OC"? Also, I blame Mr.Arcaneus's artwork for putting me in a bird/snake mood!
|
||||
posts:
|
||||
eka: https://aryion.com/g4/view/867781
|
||||
furaffinity: https://www.furaffinity.net/view/51060636/
|
||||
|
|
|
@ -10,10 +10,6 @@ description: |
|
|||
After another semester in college, Yolk finds new opportunities to surpass his limits and grow closer to his friends than ever.
|
||||
|
||||
This commission is a sequel to the raffle request, [Team Effort](/stories/team-effort)!
|
||||
descriptionPlaintext: >
|
||||
After another semester in college, Yolk finds new opportunities to surpass his limits and grow closer to his friends than ever.
|
||||
|
||||
This commission is a sequel to the raffle request, Team Effort!
|
||||
posts:
|
||||
eka: https://aryion.com/g4/view/970583
|
||||
furaffinity: https://www.furaffinity.net/view/55080578/
|
||||
|
|
|
@ -10,10 +10,6 @@ thumbnail: /src/assets/thumbnails/tlotm_bonus_1.png
|
|||
description: |
|
||||
This is a bonus chapter of The Lost of the Marshes, set between [Chapter 4 – Change](/stories/the-lost-of-the-marshes/chapter-4) and [Chapter 5 – Intersection](/stories/the-lost-of-the-marshes/chapter-5).
|
||||
|
||||
I had this idea while working on the next chapter, and wanted to try something a bit more experimental involving these characters. It's self-indulgent and loose canon, and something of a departure from my usual stories! I don't even know how to describe it... Well, whatever it is, it's certainly a mash of different thoughts and ideas that had been boiling in my head, and simmering them down into something legible was an interesting exercise. Hope it's an enjoyable read too!
|
||||
descriptionPlaintext: >
|
||||
This is a bonus chapter of The Lost of the Marshes, set between Chapter 4 – Change and Chapter 5 – Intersection.
|
||||
|
||||
I had this idea while working on the next chapter, and wanted to try something a bit more experimental involving these characters. It's self-indulgent and loose canon, and something of a departure from my usual stories! I don't even know how to describe it... Well, whatever it is, it's certainly a mash of different thoughts and ideas that had been boiling in my head, and simmering them down into something legible was an interesting exercise. Hope it's an enjoyable read too!
|
||||
posts:
|
||||
eka: https://aryion.com/g4/view/858815
|
||||
|
|
|
@ -13,10 +13,6 @@ description: |
|
|||
This chapter took a lot longer to churn out than any other so far. It was still a bunch of fun to write, but each chapter so far has been a lot more work than the last... So before chapter 5 comes out (and don't worry, it will – there are plenty more chapters with these three still planned!), I might put out a few separate standalone stories that focus more on "hot sauce" and less on world-building, just so I can have a more regular posting schedule.
|
||||
|
||||
[BONUS CHAPTER! Quince's Fantasy, set **after** this one.](/stories/the-lost-of-the-marshes/bonus-1-quince-s-fantasy)
|
||||
descriptionPlaintext: >
|
||||
How hard is it to sneak a giant dragon into a village? Quince and Nikili might learn the answer sooner rather than later...
|
||||
|
||||
This chapter took a lot longer to churn out than any other so far. It was still a bunch of fun to write, but each chapter so far has been a lot more work than the last... So before chapter 5 comes out (and don't worry, it will – there are plenty more chapters with these three still planned!), I might put out a few separate standalone stories that focus more on "hot sauce" and less on world-building, just so I can have a more regular posting schedule.
|
||||
posts:
|
||||
eka: https://aryion.com/g4/view/802298
|
||||
furaffinity: https://www.furaffinity.net/view/48067054/
|
||||
|
|
|
@ -13,10 +13,6 @@ description: |
|
|||
This chapter turned out pretty heavy, both dialogue- and theme-wise... Regardless, I hope you enjoy it. I want to work on something short for the 8/8, and next will be chapter 6, which should hopefully be more positive and have more emphasis on vore.
|
||||
|
||||
[BONUS CHAPTER! Quince's Fantasy, set **before** this one.](/stories/the-lost-of-the-marshes/bonus-1-quince-s-fantasy)
|
||||
descriptionPlaintext: >
|
||||
In a distant place full of passing faces, our protagonists are forced to face their demons, both without and within.
|
||||
|
||||
This chapter turned out pretty heavy, both dialogue- and theme-wise... Regardless, I hope you enjoy it. I want to work on something short for the 8/8, and next will be chapter 6, which should hopefully be more positive and have more emphasis on vore.
|
||||
posts:
|
||||
eka: https://aryion.com/g4/view/808898
|
||||
furaffinity: https://www.furaffinity.net/view/48412505/
|
||||
|
|
|
@ -10,10 +10,6 @@ description: |
|
|||
Kolo's day at the airship is nearly over, but a tiny stalker will unwittingly make his evening quite eventful...
|
||||
|
||||
Finally got around to finishing a story ever since I worked on [Crossing Over](/games/crossing-over)! I wanna get back into writing more stuff again, and this short story has finally broken my writer's block. My goal is to go back to working on commissions, but I feel I'm not quite in the headspace to tackle them just yet... Nevertheless, I hope you enjoy this!
|
||||
descriptionPlaintext: >
|
||||
Kolo's day at the airship is nearly over, but a tiny stalker will unwittingly make his evening quite eventful...
|
||||
|
||||
Finally got around to finishing a story ever since I worked on Crossing Over! I wanna get back into writing more stuff again, and this short story has finally broken my writer's block. My goal is to go back to working on commissions, but I feel I'm not quite in the headspace to tackle them just yet... Nevertheless, I hope you enjoy this!
|
||||
posts:
|
||||
eka: https://aryion.com/g4/view/994229
|
||||
furaffinity: https://www.furaffinity.net/view/56026627/
|
||||
|
|
|
@ -2,7 +2,7 @@ name: Type of content
|
|||
index: 8
|
||||
tags:
|
||||
- name: request
|
||||
description: Stories made as part of someone else's request as a gift.
|
||||
description: Stories made by someone else's request, as a gift.
|
||||
- name: commission
|
||||
description: Stories made as part of a commission to someone else.
|
||||
- name: { eng: flash fiction, tok: lipu lili }
|
||||
|
|
|
@ -182,9 +182,9 @@ const thumbnail =
|
|||
year: "numeric",
|
||||
})}
|
||||
data-pagefind-index-attrs="aria-description"
|
||||
data-pagefind-meta={`date:${props.pubDate.toISOString().slice(undefined, 10)}`}
|
||||
data-pagefind-meta={`date:${props.pubDate.toISOString().slice(0, 10)}`}
|
||||
>
|
||||
{t(props.lang, "story/publish_date", props.pubDate.toISOString().slice(undefined, 10))}
|
||||
{t(props.lang, "story/publish_date", props.pubDate.toISOString().slice(0, 10))}
|
||||
</p>
|
||||
) : null
|
||||
}
|
||||
|
|
|
@ -244,9 +244,9 @@ const wordCount = props.wordCount ? `${props.wordCount}` : "???";
|
|||
year: "numeric",
|
||||
})}
|
||||
data-pagefind-index-attrs="aria-description"
|
||||
data-pagefind-meta={`date:${props.pubDate.toISOString().slice(undefined, 10)}`}
|
||||
data-pagefind-meta={`date:${props.pubDate.toISOString().slice(0, 10)}`}
|
||||
>
|
||||
{t(props.lang, "story/publish_date", props.pubDate.toISOString().slice(undefined, 10))}
|
||||
{t(props.lang, "story/publish_date", props.pubDate.toISOString().slice(0, 10))}
|
||||
</p>
|
||||
) : null
|
||||
}
|
||||
|
|
|
@ -215,13 +215,18 @@ export const GET: APIRoute<Props, Params> = async ({ props: { story }, site }) =
|
|||
(_, group1, group2) => `[${group1}](${new URL(group2, site).toString()})`,
|
||||
);
|
||||
if (exportFormat === "bbcode") {
|
||||
return [website, markdownToBbcode(storyDescription).replaceAll(/\n\n\n+/g, "\n\n").trim()];
|
||||
return [
|
||||
website,
|
||||
markdownToBbcode(storyDescription)
|
||||
.replaceAll(/\n\n\n+/g, "\n\n")
|
||||
.trim(),
|
||||
];
|
||||
} else if (exportFormat === "markdown") {
|
||||
return [website, storyDescription.replaceAll(/\n\n\n+/g, "\n\n").trim()];
|
||||
} else {
|
||||
throw new Error(`Unhandled export format "${exportFormat}"`);
|
||||
}
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
const storyHeader =
|
||||
|
|
|
@ -2,10 +2,10 @@ import rss, { type RSSFeedItem } from "@astrojs/rss";
|
|||
import type { APIRoute } from "astro";
|
||||
import { getCollection, type CollectionEntry } from "astro:content";
|
||||
import sanitizeHtml from "sanitize-html";
|
||||
import { marked } from "marked";
|
||||
import { decode as tinyDecode } from "tiny-decode";
|
||||
import { t } from "../i18n";
|
||||
import type { Lang } from "../content/config";
|
||||
import { markdownToHtml } from "../utils/markdown_to_html";
|
||||
import { markdownToPlaintext } from "../utils/markdown_to_plaintext";
|
||||
|
||||
type FeedItem = RSSFeedItem & {
|
||||
pubDate: Date;
|
||||
|
@ -48,7 +48,7 @@ export const GET: APIRoute = async ({ site }) => {
|
|||
pubDate: toNoonUTCDate(data.pubDate!),
|
||||
link: `/stories/${slug}`,
|
||||
description:
|
||||
`${t(data.lang, "story/warnings", data.wordCount, data.contentWarning.trim())} ${data.descriptionPlaintext || data.description}`
|
||||
`${t(data.lang, "story/warnings", data.wordCount, data.contentWarning.trim())}\n\n${markdownToPlaintext(data.description)}`
|
||||
.replaceAll(/[\n ]+/g, " ")
|
||||
.trim(),
|
||||
categories: ["story"],
|
||||
|
@ -73,8 +73,8 @@ export const GET: APIRoute = async ({ site }) => {
|
|||
? `<p>${t(data.lang, "export_story/commissioned_by", getLinkForUser(users.find((user) => user.id === data.commissioner!.id)!, data.lang))}</p>`
|
||||
: "") +
|
||||
`<hr><p><em>${t(data.lang, "story/warnings", data.wordCount, data.contentWarning.trim())}</em></p>` +
|
||||
`<hr>${tinyDecode(await marked(body))}` +
|
||||
`<hr>${tinyDecode(await marked(data.description))}`,
|
||||
`<hr>${markdownToHtml(body)}` +
|
||||
`<hr>${markdownToHtml(data.description)}`,
|
||||
),
|
||||
})),
|
||||
),
|
||||
|
@ -84,7 +84,7 @@ export const GET: APIRoute = async ({ site }) => {
|
|||
pubDate: toNoonUTCDate(data.pubDate!),
|
||||
link: `/games/${slug}`,
|
||||
description:
|
||||
`${t(data.lang, "game/warnings", data.platforms, data.contentWarning)} ${data.descriptionPlaintext || data.description}`
|
||||
`${t(data.lang, "game/warnings", data.platforms, data.contentWarning)}\n\n${markdownToPlaintext(data.description)}`
|
||||
.replaceAll(/[\n ]+/g, " ")
|
||||
.trim(),
|
||||
categories: ["game"],
|
||||
|
@ -104,8 +104,8 @@ export const GET: APIRoute = async ({ site }) => {
|
|||
)}</p>` +
|
||||
`<hr><p>${t(data.lang, "game/platforms", data.platforms)}</p>` +
|
||||
`<hr><p><em>${data.contentWarning.trim()}</em></p>` +
|
||||
`<hr>${tinyDecode(marked.parse(body) as string)}` +
|
||||
`<hr>${tinyDecode(marked.parse(data.description) as string)}`,
|
||||
`<hr>${markdownToHtml(body)}` +
|
||||
`<hr>${markdownToHtml(data.description)}`,
|
||||
),
|
||||
})),
|
||||
),
|
||||
|
|
|
@ -31,38 +31,36 @@ const seriesCollection = await getCollection("series");
|
|||
});
|
||||
|
||||
const uncategorizedTagsSet = new Set(tagsSet);
|
||||
const categorizedTags: Array<[string, string, [string, string | undefined][]]> = await Promise.all(
|
||||
tagCategories
|
||||
.sort((a, b) => a.data.index - b.data.index)
|
||||
.map(async (category) => {
|
||||
const tagList = category.data.tags.map(({ name, description }) => {
|
||||
description = description && markdownToPlaintext(description).replaceAll(/\n+/g, " ").trim();
|
||||
return (typeof name === "string" ? [name, description] : [name["eng"]!, description]) as [
|
||||
string,
|
||||
string | undefined,
|
||||
];
|
||||
});
|
||||
tagList.forEach(([tag, _], index) => {
|
||||
if (index !== tagList.findLastIndex(([otherTag, _]) => tag == otherTag)) {
|
||||
throw new Error(`Duplicated tag "${tag}" found in multiple tag-categories lists`);
|
||||
const categorizedTags = tagCategories
|
||||
.sort((a, b) => a.data.index - b.data.index)
|
||||
.map((category) => {
|
||||
const tagList = category.data.tags.map(({ name, description }) => {
|
||||
description = description && markdownToPlaintext(description).replaceAll(/\n+/g, " ").trim();
|
||||
return (typeof name === "string" ? { name, description } : { name: name["eng"]!, description }) as {
|
||||
name: string;
|
||||
description?: string;
|
||||
};
|
||||
});
|
||||
tagList.forEach(({ name }, index) => {
|
||||
if (index !== tagList.findLastIndex(({ name: otherTag }) => name == otherTag)) {
|
||||
throw new Error(`Duplicated tag "${name}" found in multiple tag-categories lists`);
|
||||
}
|
||||
});
|
||||
return [
|
||||
category.data.name,
|
||||
category.id,
|
||||
tagList.filter(({ name }) => {
|
||||
if (draftOnlyTagsSet.has(name)) {
|
||||
console.log(`Omitting draft-only tag "${name}"`);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return [
|
||||
category.data.name,
|
||||
category.id,
|
||||
tagList.filter(([tag, _]) => {
|
||||
if (draftOnlyTagsSet.has(tag)) {
|
||||
console.log(`Omitting draft-only tag "${tag}"`);
|
||||
return false;
|
||||
}
|
||||
if (tagsSet.has(tag)) {
|
||||
uncategorizedTagsSet.delete(tag);
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
];
|
||||
}),
|
||||
);
|
||||
if (tagsSet.has(name)) {
|
||||
uncategorizedTagsSet.delete(name);
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
] as [string, string, { name: string; description?: string }[]];
|
||||
});
|
||||
|
||||
if (uncategorizedTagsSet.size > 0) {
|
||||
const tagList = [...uncategorizedTagsSet];
|
||||
|
@ -101,10 +99,10 @@ if (uncategorizedTagsSet.size > 0) {
|
|||
{category}
|
||||
</h2>
|
||||
<ul class="flex max-w-3xl flex-wrap gap-x-2 gap-y-2 px-2">
|
||||
{tagList.map(([tag, description]) => (
|
||||
{tagList.map(({ name, description }) => (
|
||||
<li class="rounded-full bg-bm-300 px-3 py-1 text-sm text-black shadow-sm dark:bg-bm-600 dark:text-white">
|
||||
<a class="hover:underline focus:underline" href={`/tags/${slug(tag)}`} title={description}>
|
||||
{tag}
|
||||
<a class="hover:underline focus:underline" href={`/tags/${slug(name)}`} title={description}>
|
||||
{name}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
|
|
|
@ -61,7 +61,7 @@ export const getStaticPaths: GetStaticPaths = async () => {
|
|||
);
|
||||
return acc;
|
||||
},
|
||||
[] as [string, { description: string | undefined; related: string[] | undefined }][],
|
||||
[] as [string, { description?: string; related?: string[] }][],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
4
src/utils/markdown_to_html.ts
Normal file
4
src/utils/markdown_to_html.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
import { marked } from "marked";
|
||||
import { decode } from "tiny-decode";
|
||||
|
||||
export const markdownToHtml = (text: string) => decode((marked.parse(text) as string).trim());
|
|
@ -4,7 +4,6 @@ import { decode } from "tiny-decode";
|
|||
const renderer: RendererApi = {
|
||||
strong: (text) => text,
|
||||
em: (text) => `_${text}_`,
|
||||
del: (text) => text,
|
||||
codespan: (code) => code,
|
||||
br: () => `\n\n`,
|
||||
link: (_href, _title, text) => text,
|
||||
|
@ -14,11 +13,14 @@ const renderer: RendererApi = {
|
|||
listitem: (text) => `- ${text}\n`,
|
||||
blockquote: (quote) => `\n> ${quote}\n`,
|
||||
code: (code) => `\n${code}\n`,
|
||||
heading: (heading) => `\n${heading}\n`,
|
||||
heading: (heading) => `\n== ${heading} ==\n`,
|
||||
table: (header, body) => `\n${header}\n---\n${body}\n`,
|
||||
tablerow: (content) => `${content.slice(0, -3)}\n`,
|
||||
tablecell: (content) => `${content} | `,
|
||||
hr: () => `\n***\n`,
|
||||
del: () => {
|
||||
throw new Error("Not supported by plaintext: del");
|
||||
},
|
||||
image: () => {
|
||||
throw new Error("Not supported by plaintext: img");
|
||||
},
|
||||
|
|
Loading…
Add table
Reference in a new issue