From a2fbf908aa044e9cbe34deac988ea28aa5c5fb83 Mon Sep 17 00:00:00 2001 From: Bad Manners <me@badmanners.xyz> Date: Sat, 7 Sep 2024 18:02:53 -0300 Subject: [PATCH] Final touches to the facelift --- package-lock.json | 98 ++++++++++++++----- package.json | 1 + scripts/export-story.ts | 14 ++- src/components/MastodonComments.astro | 6 +- src/content/config.ts | 1 + src/i18n/index.ts | 2 +- src/layouts/GalleryLayout.astro | 76 +++++++++----- src/layouts/PublishedContentLayout.astro | 20 ++-- src/pages/404.astro | 3 +- src/pages/games.astro | 3 +- src/pages/index.astro | 7 +- src/pages/search.astro | 3 +- src/pages/stories/[page].astro | 3 +- .../stories/the-lost-of-the-marshes.astro | 5 +- src/pages/tags.astro | 3 +- src/styles/base.css | 17 ++++ src/utils/format_copyrighted_characters.ts | 2 +- src/utils/parse_partial_html_tag.ts | 6 +- tailwind.config.mjs | 11 ++- 19 files changed, 194 insertions(+), 87 deletions(-) diff --git a/package-lock.json b/package-lock.json index a0b46b9..1a78914 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "astro-htaccess": "^0.1.2", "astro-pagefind": "^1.6.0", "clsx": "^2.1.1", + "fluid-tailwind": "^1.0.3", "github-slugger": "^2.0.0", "marked": "^14.0.0", "pagefind": "^1.1.0", @@ -1601,65 +1602,71 @@ } }, "node_modules/@pagefind/darwin-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.1.0.tgz", - "integrity": "sha512-SLsXNLtSilGZjvqis8sX42fBWsWAVkcDh1oerxwqbac84HbiwxpxOC2jm8hRwcR0Z55HPZPWO77XeRix/8GwTg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.1.1.tgz", + "integrity": "sha512-tZ9tysUmQpFs2EqWG2+E1gc+opDAhSyZSsgKmFzhnWfkK02YHZhvL5XJXEZDqYy3s1FAKhwjTg8XDxneuBlDZQ==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@pagefind/darwin-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.1.0.tgz", - "integrity": "sha512-QjQSE/L5oS1C8N8GdljGaWtjCBMgMtfrPAoiCmINTu9Y9dp0ggAyXvF8K7Qg3VyIMYJ6v8vg2PN7Z3b+AaAqUA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.1.1.tgz", + "integrity": "sha512-ChohLQ39dLwaxQv0jIQB/SavP3TM5K5ENfDTqIdzLkmfs3+JlzSDyQKcJFjTHYcCzQOZVeieeGq8PdqvLJxJxQ==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@pagefind/default-ui": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pagefind/default-ui/-/default-ui-1.1.0.tgz", - "integrity": "sha512-+XiAJAK++C64nQcD7s3Prdmd5S92lT05fwjOxm0L1jj80jbL+tmvcqkkFnPpoqhnicIPgcAX/Y5W0HRZnBt35w==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@pagefind/default-ui/-/default-ui-1.1.1.tgz", + "integrity": "sha512-ZM0zDatWDnac/VGHhQCiM7UgA4ca8jpjA+VfuTJyHJBaxGqZMQnm4WoTz9E0KFcue1Bh9kxpu7uWFZfwpZZk0A==", + "license": "MIT" }, "node_modules/@pagefind/linux-arm64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.1.0.tgz", - "integrity": "sha512-8zjYCa2BtNEL7KnXtysPtBELCyv5DSQ4yHeK/nsEq6w4ToAMTBl0K06khqxdSGgjMSwwrxvLzq3so0LC5Q14dA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.1.1.tgz", + "integrity": "sha512-H5P6wDoCoAbdsWp0Zx0DxnLUrwTGWGLu/VI1rcN2CyFdY2EGSvPQsbGBMrseKRNuIrJDFtxHHHyjZ7UbzaM9EA==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@pagefind/linux-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.1.0.tgz", - "integrity": "sha512-4lsg6VB7A6PWTwaP8oSmXV4O9H0IHX7AlwTDcfyT+YJo/sPXOVjqycD5cdBgqNLfUk8B9bkWcTDCRmJbHrKeCw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.1.1.tgz", + "integrity": "sha512-yJs7tTYbL2MI3HT+ngs9E1BfUbY9M4/YzA0yEM5xBo4Xl8Yu8Qg2xZTOQ1/F6gwvMrjCUFo8EoACs6LRDhtMrQ==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@pagefind/windows-x64": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.1.0.tgz", - "integrity": "sha512-OboCM76BcMKT9IoSfZuFhiqMRgTde8x4qDDvKulFmycgiJrlL5WnIqBHJLQxZq+o2KyZpoHF97iwsGAm8c32sQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.1.1.tgz", + "integrity": "sha512-b7/qPqgIl+lMzkQ8fJt51SfguB396xbIIR+VZ3YrL2tLuyifDJ1wL5mEm+ddmHxJ2Fki340paPcDan9en5OmAw==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -3370,6 +3377,18 @@ "node": ">=8" } }, + "node_modules/filter-obj": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-5.1.0.tgz", + "integrity": "sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -3413,6 +3432,20 @@ "node": ">=8" } }, + "node_modules/fluid-tailwind": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fluid-tailwind/-/fluid-tailwind-1.0.3.tgz", + "integrity": "sha512-JhSklHiXUcKnb/PIru1TbyorLD+k0rCIgeAbFwzu1QyQHYDKmKKsKzN7xPisSeGGr7FtYY9S63t+tzddUlxxrQ==", + "license": "MIT", + "dependencies": { + "filter-obj": "^5.1.0", + "map-obj": "^5.0.2", + "picocolors": "^1.0.0" + }, + "peerDependencies": { + "tailwindcss": "^3.2.0" + } + }, "node_modules/foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -4266,6 +4299,18 @@ "optional": true, "peer": true }, + "node_modules/map-obj": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-5.0.2.tgz", + "integrity": "sha512-K6K2NgKnTXimT3779/4KxSvobxOtMmx1LBZ3NwRxT/MDIR3Br/fQ4Q+WCX5QxjyUR8zg5+RV9Tbf2c5pAWTD2A==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/markdown-table": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", @@ -5361,18 +5406,19 @@ } }, "node_modules/pagefind": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.1.0.tgz", - "integrity": "sha512-1nmj0/vfYcMxNEQj0YDRp6bTVv9hI7HLdPhK/vBBYlrnwjATndQvHyicj5Y7pUHrpCFZpFnLVQXIF829tpFmaw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.1.1.tgz", + "integrity": "sha512-U2YR0dQN5B2fbIXrLtt/UXNS0yWSSYfePaad1KcBPTi0p+zRtsVjwmoPaMQgTks5DnHNbmDxyJUL5TGaLljK3A==", + "license": "MIT", "bin": { "pagefind": "lib/runner/bin.cjs" }, "optionalDependencies": { - "@pagefind/darwin-arm64": "1.1.0", - "@pagefind/darwin-x64": "1.1.0", - "@pagefind/linux-arm64": "1.1.0", - "@pagefind/linux-x64": "1.1.0", - "@pagefind/windows-x64": "1.1.0" + "@pagefind/darwin-arm64": "1.1.1", + "@pagefind/darwin-x64": "1.1.1", + "@pagefind/linux-arm64": "1.1.1", + "@pagefind/linux-x64": "1.1.1", + "@pagefind/windows-x64": "1.1.1" } }, "node_modules/parse-latin": { diff --git a/package.json b/package.json index 1b441c4..493010b 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "astro-htaccess": "^0.1.2", "astro-pagefind": "^1.6.0", "clsx": "^2.1.1", + "fluid-tailwind": "^1.0.3", "github-slugger": "^2.0.0", "marked": "^14.0.0", "pagefind": "^1.1.0", diff --git a/scripts/export-story.ts b/scripts/export-story.ts index c92174d..f98ba21 100644 --- a/scripts/export-story.ts +++ b/scripts/export-story.ts @@ -168,10 +168,16 @@ async function exportStory(slug: string, options: { outputDir: string }) { ); const rtfText = await readFile(join(tempDir, "temp.rtf"), "utf-8"); const rtfStyles = getRTFStyles(rtfText); - await writeFile( - join(outputDir, `${slug}.rtf`), - rtfText.replaceAll(rtfStyles["Preformatted Text"], rtfStyles["Normal"]), - ); + if (!rtfStyles["Preformatted Text"]) { + console.warn(`Missing RTF style "Preformatted Text"! Skipping RTF file generation.`); + } else if (!rtfStyles["Normal"]) { + console.warn(`Missing RTF style "Normal"! Skipping RTF file generation.`); + } else { + await writeFile( + join(outputDir, `${slug}.rtf`), + rtfText.replaceAll(rtfStyles["Preformatted Text"], rtfStyles["Normal"]), + ); + } })(), ]); console.log("Success!"); diff --git a/src/components/MastodonComments.astro b/src/components/MastodonComments.astro index b81d7b2..01d610e 100644 --- a/src/components/MastodonComments.astro +++ b/src/components/MastodonComments.astro @@ -254,11 +254,11 @@ const { link, instance, user, postId } = Astro.props; if (comment.in_reply_to_id === post.postId || !(comment.in_reply_to_id in commentMap)) { commentMap[comment.id] = commentsList.length; commentsList.push(commentBox); - } else { - const commentsIndex = commentMap[comment.in_reply_to_id]; + } else if (commentMap[comment.in_reply_to_id]) { + const commentsIndex = commentMap[comment.in_reply_to_id]!; commentMap[comment.id] = commentsIndex; const parentThreadDiv = - commentsList[commentsIndex].querySelector<HTMLElementTagNameMap["div"]>("div[data-comment-thread]")!; + commentsList[commentsIndex]!.querySelector<HTMLElementTagNameMap["div"]>("div[data-comment-thread]")!; parentThreadDiv.setAttribute("aria-hidden", "false"); parentThreadDiv.appendChild(commentBox); } diff --git a/src/content/config.ts b/src/content/config.ts index ed8b506..a3f4d34 100644 --- a/src/content/config.ts +++ b/src/content/config.ts @@ -222,6 +222,7 @@ export type GamePlatform = z.infer<typeof platform>; export type CopyrightedCharacters = z.infer<typeof copyrightedCharacters>; export type PublishedContent = z.infer<typeof publishedContent>; export type PostWebsite = keyof PublishedContent["posts"]; +export type Posts = PublishedContent["posts"]; // Content collections diff --git a/src/i18n/index.ts b/src/i18n/index.ts index ccc56cc..9456b57 100644 --- a/src/i18n/index.ts +++ b/src/i18n/index.ts @@ -13,7 +13,7 @@ const UI_STRINGS = { tok: (names: string[]) => names.join(" en "), }, "util/capitalize": { - en: (text: string) => (text.length > 0 ? `${text[0].toUpperCase()}${text.slice(1)}` : ""), + en: (text: string) => (text.length > 0 ? `${text[0]!.toUpperCase()}${text.slice(1)}` : ""), }, "util/enumerate": { en: (count: number, nounSingular: string, nounPlural?: string) => { diff --git a/src/layouts/GalleryLayout.astro b/src/layouts/GalleryLayout.astro index c82927f..6d90491 100644 --- a/src/layouts/GalleryLayout.astro +++ b/src/layouts/GalleryLayout.astro @@ -37,30 +37,30 @@ const isCurrentRoute = (path: string) => <slot name="head" /> </Fragment> <div - class="flex min-h-screen flex-col bg-stone-200 text-stone-800 md:flex-row dark:bg-stone-800 dark:text-stone-200 print:bg-none" + class="flex flex-col bg-stone-200 text-stone-800 md:flex-row dark:bg-stone-800 dark:text-stone-200 print:bg-none" > <nav - class="h-card static mb-4 flex flex-col items-center bg-bm-300 pb-10 pt-10 text-center text-stone-900 shadow-xl md:fixed md:inset-y-0 md:left-0 md:mb-0 md:w-60 md:pt-20 dark:bg-green-900 dark:text-stone-100 print:bg-none print:shadow-none" + class="h-card mb-4 flex shrink-0 flex-col items-center border-b-4 border-bm-400 bg-bm-300 pb-10 pt-10 text-center text-stone-900 shadow-xl md:left-0 md:mb-0 md:min-h-screen md:w-72 md:justify-self-stretch md:border-b-0 md:border-r-4 md:pt-20 dark:border-green-950 dark:bg-green-900 dark:text-stone-100 print:bg-none print:shadow-none" > <img loading="eager" src={logo.src} alt="A pixelated metal briefcase over a background with a green gradient." - class="u-logo my-4 w-full max-w-[192px] rounded-sm border-2 border-green-950 shadow-md" + class="u-logo my-4 w-full max-w-[192px] rounded-sm border-2 border-green-800 shadow-md dark:border-green-950" width={192} /> - <span class="p-name mb-4 mt-2 text-2xl font-semibold">Bad Manners</span> - <ul class="flex flex-col gap-y-2 pr-8 text-left sm:pr-2"> + <span class="p-name mb-6 mt-4 text-3xl font-semibold">Bad Manners</span> + <ul class="flex w-[80%] max-w-sm flex-col gap-y-2 px-4 pr-8 text-left sm:pr-2"> <li> <a class="u-url text-link group" href="https://badmanners.xyz/" data-age-restricted rel="me"> - <IconHome width="1.25rem" height="1.25rem" class="inline align-text-top" /> - <span class="group-hover:underline group-focus:underline">Main website</span> + <IconHome width="1.25rem" height="1.25rem" class="order-1 inline align-text-top" /> + <span class="order-3 group-hover:underline group-focus:underline">Main website</span> </a> </li> <li> <a class="u-url text-link group" href="/" aria-current={isCurrentRoute("/") ? "page" : undefined}> - <IconBriefcase width="1.25rem" height="1.25rem" class="inline align-text-top" /> - <span class="group-hover:underline group-focus:underline">Gallery</span> + <IconBriefcase width="1.25rem" height="1.25rem" class="order-1 inline align-text-top" /> + <span class="order-3 group-hover:underline group-focus:underline">Gallery</span> </a> </li> <li> @@ -69,20 +69,20 @@ const isCurrentRoute = (path: string) => href="/stories/1" aria-current={isCurrentRoute("/stories/1") ? "page" : undefined} > - <IconBook width="1.25rem" height="1.25rem" class="inline align-text-top" /> - <span class="group-hover:underline group-focus:underline">Stories</span> + <IconBook width="1.25rem" height="1.25rem" class="order-1 inline align-text-top" /> + <span class="order-3 group-hover:underline group-focus:underline">Stories</span> </a> </li> <li> <a class="u-url text-link group" href="/games" aria-current={isCurrentRoute("/games") ? "page" : undefined}> - <IconGamepad width="1.25rem" height="1.25rem" class="inline align-text-top" /> - <span class="group-hover:underline group-focus:underline">Games</span> + <IconGamepad width="1.25rem" height="1.25rem" class="order-1 inline align-text-top" /> + <span class="order-3 group-hover:underline group-focus:underline">Games</span> </a> </li> <li> <a class="u-url text-link group" href="/tags" aria-current={isCurrentRoute("/tags") ? "page" : undefined}> - <IconTags width="1.25rem" height="1.25rem" class="inline align-text-top" /> - <span class="group-hover:underline group-focus:underline">Tags</span> + <IconTags width="1.25rem" height="1.25rem" class="order-1 inline align-text-top" /> + <span class="order-3 group-hover:underline group-focus:underline">Tags</span> </a> </li> <li> @@ -92,27 +92,35 @@ const isCurrentRoute = (path: string) => rel="search" aria-current={isCurrentRoute("/search") ? "page" : undefined} > - <IconMagnifyingGlass width="1.25rem" height="1.25rem" class="inline align-text-top" /> - <span class="group-hover:underline group-focus:underline">Search</span> + <IconMagnifyingGlass width="1.25rem" height="1.25rem" class="order-1 inline align-text-top" /> + <span class="order-3 group-hover:underline group-focus:underline">Search</span> </a> </li> <li> <a class="u-url text-link group" href="/feed.xml"> - <IconSquareRSS width="1.25rem" height="1.25rem" class="inline align-text-top" /> - <span class="group-hover:underline group-focus:underline">RSS feed</span> + <IconSquareRSS width="1.25rem" height="1.25rem" class="order-1 inline align-text-top" /> + <span class="order-3 group-hover:underline group-focus:underline">RSS feed</span> </a> </li> <li> - <button data-dark-mode style={{ display: "none" }} class="text-link group"> - <IconSun width="1.25rem" height="1.25rem" class="hidden align-middle dark:inline" /> - <IconMoon width="1.25rem" height="1.25rem" class="inline align-text-top dark:hidden" /> - <span class="group-hover:underline group-focus:underline" - >{t("en", "published_content/toggle_dark_mode")}</span + <button + data-dark-mode + style={{ display: "none" }} + class="text-link group" + aria-label={t("en", "published_content/toggle_dark_mode")} + > + <IconSun width="1.25rem" height="1.25rem" class="order-1 hidden align-text-top dark:inline" /> + <IconMoon width="1.25rem" height="1.25rem" class="order-1 inline align-text-top dark:hidden" /> + <span class="order-3 hidden group-hover:underline group-focus:underline dark:block" aria-hidden="true" + >Light mode</span + > + <span class="order-3 block group-hover:underline group-focus:underline dark:hidden" aria-hidden="true" + >Dark mode</span > </button> </li> </ul> - <div class="pt-4 text-center text-xs text-black dark:text-white"> + <div class="py-6 text-center text-xs text-black dark:text-white"> <span >© { currentYear === "2024" ? ( @@ -128,10 +136,26 @@ const isCurrentRoute = (path: string) => </div> </nav> <main - class:list={[className, "ml-0 max-w-6xl px-2 pb-12 pt-4 md:ml-60 md:px-4 print:pb-0"]} + class:list={[className, "ml-0 max-w-6xl px-2 pb-28 pt-4 md:px-4 lg:px-8 print:pb-0"]} data-pagefind-body={enablePagefind ? "" : undefined} > <slot /> </main> </div> </BaseLayout> +<style> + nav ul li a, + nav ul li button { + @apply flex w-full items-baseline justify-between; + } + + nav ul li a::after, + nav ul li button::after { + @apply order-2 flex-grow self-end bg-bottom; + background: radial-gradient(circle, currentcolor 1px, transparent 1px); + background-size: 1ex 4.5px; + background-repeat: space no-repeat; + content: ""; + height: 1ex; + } +</style> diff --git a/src/layouts/PublishedContentLayout.astro b/src/layouts/PublishedContentLayout.astro index 8ef3593..edca29a 100644 --- a/src/layouts/PublishedContentLayout.astro +++ b/src/layouts/PublishedContentLayout.astro @@ -9,7 +9,7 @@ import BaseLayout from "./BaseLayout.astro"; import CopyrightedCharacters from "../components/CopyrightedCharacters.astro"; import Prose from "../components/Prose.astro"; import MastodonComments from "../components/MastodonComments.astro"; -import type { CopyrightedCharacters as CopyrightedCharactersType } from "../content/config"; +import type { CopyrightedCharacters as CopyrightedCharactersType, Posts } from "../content/config"; import { qualifyLocalURLsInMarkdown } from "../utils/qualify_local_urls_in_markdown"; import { IconSun, @@ -44,14 +44,7 @@ type Props = { next?: RelatedContent; relatedStories?: CollectionEntry<"stories">[]; relatedGames?: CollectionEntry<"games">[]; - posts: { - mastodon?: { - link: string; - instance: string; - user: string; - postId: string; - }; - }; + posts: Posts; /* Layout attributes */ publishedContentType: "story" | "game"; @@ -159,14 +152,14 @@ const thumbnail = </div> </div> <main - class="h-entry mx-auto max-w-5xl rounded-lg bg-stone-50 px-2 pb-10 pt-12 shadow-sm sm:px-6 md:px-20 lg:px-36 dark:bg-stone-900 print:max-w-full print:bg-none print:shadow-none" + class="h-entry mx-auto max-w-6xl rounded-lg bg-stone-50 px-2 pb-10 shadow-sm sm:px-6 md:px-32 lg:px-64 dark:bg-stone-900 print:max-w-full print:bg-none print:shadow-none" data-pagefind-body={props.isDraft ? undefined : ""} data-pagefind-meta={`type:${props.publishedContentType}`} > { props.prev || props.next ? ( <div class="print:hidden"> - <div id="nav-top" class="my-4 grid grid-cols-2 justify-items-stretch gap-2 text-lg font-light"> + <div id="nav-top" class="my-4 grid grid-cols-2 justify-items-stretch gap-2 pt-4 text-lg font-light"> {props.prev ? ( <a href={props.prev.link} @@ -196,7 +189,9 @@ const thumbnail = </div> <hr class="mx-auto mb-5 w-full max-w-2xl border-stone-400 dark:border-stone-600" /> </div> - ) : null + ) : ( + <div class="pt-5 sm:pt-7" aria-hidden="true" /> + ) } <h1 id="section-title" @@ -205,6 +200,7 @@ const thumbnail = > {props.title} </h1> + <hr class="mb-3 ml-[2px] mt-2 h-[4px] w-1/2 rounded-sm bg-stone-800 dark:bg-stone-100" /> <section id="section-information" class="p-summary mt-1 space-y-2 px-2 font-serif font-light italic text-stone-600 dark:text-stone-200" diff --git a/src/pages/404.astro b/src/pages/404.astro index 12a22ab..a21a43f 100644 --- a/src/pages/404.astro +++ b/src/pages/404.astro @@ -4,6 +4,7 @@ import GalleryLayout from "../layouts/GalleryLayout.astro"; <GalleryLayout pageTitle="404"> <meta slot="head" property="og:description" content="Not found" /> - <h1 class="m-2 text-2xl font-semibold text-stone-800 dark:text-stone-100">404 – Not Found</h1> + <h1 class="m-2 text-3xl font-semibold text-stone-800 dark:text-stone-100">404 – Not Found</h1> + <hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" /> <p class="my-4">The requested link could not be found. Make sure that the URL is correct.</p> </GalleryLayout> diff --git a/src/pages/games.astro b/src/pages/games.astro index bb766a0..39c0529 100644 --- a/src/pages/games.astro +++ b/src/pages/games.astro @@ -19,7 +19,8 @@ const games = await Promise.all( <GalleryLayout pageTitle="Games" class="h-feed"> <meta slot="head" property="og:description" content="Bad Manners || A game that I've gone and done." /> - <h1 class="p-name m-2 text-2xl font-semibold text-stone-800 dark:text-stone-100">Games</h1> + <h1 class="p-name m-2 text-3xl font-semibold text-stone-800 dark:text-stone-100">Games</h1> + <hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" /> <p class="p-summary my-4">A game that I've gone and done.</p> <ul class="my-6 flex flex-wrap items-start justify-center gap-4 text-center md:justify-normal"> { diff --git a/src/pages/index.astro b/src/pages/index.astro index e054bb5..a22865d 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -75,11 +75,12 @@ const latestItems: LatestItemsEntry[] = await Promise.all( <GalleryLayout pageTitle="Gallery" class="h-feed"> <meta slot="head" property="og:description" content="Bad Manners || Welcome to my gallery!" /> - <h1 class="p-name m-2 text-2xl font-semibold text-stone-800 dark:text-stone-100">My gallery</h1> + <h1 class="p-name m-2 text-3xl font-semibold text-stone-800 dark:text-stone-100">Welcome to my gallery!</h1> + <hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" /> <div class="p-summary"> <p class="my-4"> - Welcome to my gallery! You can expect lots of safe vore/endosoma ahead. Use the navigation menu to navigate - through my content. + Glad to see you here. You can expect lots of safe vore/endosoma ahead. Use the navigation menu to navigate through + my content. </p> <ul class="list-disc pl-8"> <li><a class="text-link underline" href="/stories/1">Read my stories!</a></li> diff --git a/src/pages/search.astro b/src/pages/search.astro index fd3f581..4253d51 100644 --- a/src/pages/search.astro +++ b/src/pages/search.astro @@ -10,6 +10,7 @@ import GalleryLayout from "../layouts/GalleryLayout.astro"; <GalleryLayout pageTitle="Search"> <meta slot="head" property="og:description" content="Bad Manners || Search" /> - <h1 class="m-2 text-2xl font-semibold text-stone-800 dark:text-stone-100">Search</h1> + <h1 class="m-2 text-3xl font-semibold text-stone-800 dark:text-stone-100">Search</h1> + <hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" /> <SearchComponent id="search" className="pagefind-ui my-4" /> </GalleryLayout> diff --git a/src/pages/stories/[page].astro b/src/pages/stories/[page].astro index b8910c3..618b49c 100644 --- a/src/pages/stories/[page].astro +++ b/src/pages/stories/[page].astro @@ -30,7 +30,8 @@ const totalPages = Math.ceil(page.total / page.size); <GalleryLayout pageTitle="Stories" class="h-feed"> <meta slot="head" property="og:description" content={`Bad Manners || ${page.total} stories.`} /> - <h1 class="p-name m-2 text-2xl font-semibold text-stone-800 dark:text-stone-100">Stories</h1> + <h1 class="p-name m-2 text-3xl font-semibold text-stone-800 dark:text-stone-100">Stories</h1> + <hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" /> <div class="p-summary"> <p class="my-4">The bulk of my content!</p> <p class="text-center font-light text-stone-950 dark:text-white"> diff --git a/src/pages/stories/the-lost-of-the-marshes.astro b/src/pages/stories/the-lost-of-the-marshes.astro index 12cb29e..313b6f5 100644 --- a/src/pages/stories/the-lost-of-the-marshes.astro +++ b/src/pages/stories/the-lost-of-the-marshes.astro @@ -26,7 +26,8 @@ const mainChaptersWithSummaries = mainChapters.filter((story) => story.data.summ property="og:description" content="The Lost of the Marshes || The story of Quince, Nikili, and Suu." /> - <h1 class="p-name m-2 text-2xl font-semibold text-stone-800 dark:text-stone-100">{series.data.name}</h1> + <h1 class="p-name m-2 text-3xl font-semibold text-stone-800 dark:text-stone-100">{series.data.name}</h1> + <hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" /> <p class="p-summary my-4"> This is the main hub for the story of Quince, Nikili, and Suu, as well as all bonus content. </p> @@ -43,7 +44,7 @@ const mainChaptersWithSummaries = mainChapters.filter((story) => story.data.summ > <summary class="rounded-lg bg-stone-200 px-2 py-1 dark:bg-stone-800"> Click to reveal spoilers up to { - mainChaptersWithSummaries[mainChaptersWithSummaries.length - 1].data.title.match(/Chapter \d+\b/)?.[0] + mainChaptersWithSummaries[mainChaptersWithSummaries.length - 1]!.data.title.match(/Chapter \d+\b/)?.[0] } </summary> <ul class="border-t border-stone-400 px-1 dark:border-stone-500"> diff --git a/src/pages/tags.astro b/src/pages/tags.astro index 93eb9df..58a2c89 100644 --- a/src/pages/tags.astro +++ b/src/pages/tags.astro @@ -71,7 +71,8 @@ if (uncategorizedTagsSet.size > 0) { <GalleryLayout pageTitle="Tags"> <meta property="og:description" slot="head" content="Bad Manners || Find all content with a specific tag." /> - <h1 class="m-2 text-2xl font-semibold text-stone-800 dark:text-stone-100">All available tags</h1> + <h1 class="m-2 text-3xl font-semibold text-stone-800 dark:text-stone-100">All available tags</h1> + <hr class="mb-3 ml-[2px] mt-2 h-[4px] max-w-xs rounded-sm bg-stone-800 dark:bg-stone-100" /> <p class="my-4">You can find all content with a specific tag by selecting it below from the appropriate category.</p> <section class="my-2" aria-labelledby="category-series"> <h2 id="category-series" class="p-2 text-xl font-semibold text-stone-800 dark:text-stone-100">Series</h2> diff --git a/src/styles/base.css b/src/styles/base.css index da6dd59..1676347 100644 --- a/src/styles/base.css +++ b/src/styles/base.css @@ -2,6 +2,23 @@ @tailwind components; @tailwind utilities; +/* Tippy tooltips */ +.tippy-box[data-theme~="bm"] { + @apply bg-stone-800 font-sans text-sm text-stone-50 dark:bg-zinc-900 dark:text-zinc-100; +} +.tippy-box[data-theme~="bm"][data-placement^="top"] > .tippy-arrow::before { + @apply border-t-stone-800 dark:border-t-zinc-900; +} +.tippy-box[data-theme~="bm"][data-placement^="bottom"] > .tippy-arrow::before { + @apply border-b-stone-800 dark:border-b-zinc-900; +} +.tippy-box[data-theme~="bm"][data-placement^="left"] > .tippy-arrow::before { + @apply border-l-stone-800 dark:border-l-zinc-900; +} +.tippy-box[data-theme~="bm"][data-placement^="right"] > .tippy-arrow::before { + @apply border-r-stone-800 dark:border-r-zinc-900; +} + @layer components { .text-link, .pagefind-ui .pagefind-ui__result-link { diff --git a/src/utils/format_copyrighted_characters.ts b/src/utils/format_copyrighted_characters.ts index 31a9bbf..f352a04 100644 --- a/src/utils/format_copyrighted_characters.ts +++ b/src/utils/format_copyrighted_characters.ts @@ -6,7 +6,7 @@ export async function formatCopyrightedCharacters(copyrightedCharacters: Copyrig Object.values( Object.keys(copyrightedCharacters).reduce( (acc, character) => { - const user = copyrightedCharacters[character]; + const user = copyrightedCharacters[character]!; if (user.id in acc) { acc[user.id][1].push(character); } else { diff --git a/src/utils/parse_partial_html_tag.ts b/src/utils/parse_partial_html_tag.ts index 7727190..04c9ac6 100644 --- a/src/utils/parse_partial_html_tag.ts +++ b/src/utils/parse_partial_html_tag.ts @@ -18,7 +18,7 @@ export function parsePartialHTMLTag(text: string): ParsedHTMLTag { const openTag = partialText.match(OPEN_TAG_START_REGEX); if (openTag) { const result: ParsedHTMLTag = { - tag: openTag[1], + tag: openTag[1]!, type: "open", }; partialText = partialText.slice(openTag[0].length); @@ -30,7 +30,7 @@ export function parsePartialHTMLTag(text: string): ParsedHTMLTag { if (!result.attributes) { result.attributes = {}; } - result.attributes[attribute[1]] = attribute[2] ? JSON.parse(attribute[2]) : null; + result.attributes[attribute[1]!] = attribute[2] ? JSON.parse(attribute[2]) : null; partialText = partialText.slice(attribute[0].length); } if (partialText.match(END_OPEN_REGEX)) { @@ -44,7 +44,7 @@ export function parsePartialHTMLTag(text: string): ParsedHTMLTag { const closeTag = partialText.match(CLOSE_TAG_REGEX); if (closeTag) { return { - tag: closeTag[1], + tag: closeTag[1]!, type: "close", }; } diff --git a/tailwind.config.mjs b/tailwind.config.mjs index 41dc640..9724321 100644 --- a/tailwind.config.mjs +++ b/tailwind.config.mjs @@ -1,9 +1,18 @@ import defaultTheme from "tailwindcss/defaultTheme"; +import typography from "@tailwindcss/typography"; /** @type {import('tailwindcss').Config} */ export default { darkMode: ["variant", "@media not print { .dark & }"], - content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"], + content: { + files: [ + "./src/components/**/*.astro", + "./src/content/games/**/*.{md,mdx}", + "./src/content/stories/**/*.{md,mdx}", + "./src/layouts/*.astro", + "./src/pages/**/*.{astro,ts}", + ], + }, theme: { extend: { fontFamily: {