Final touches to the facelift
This commit is contained in:
parent
379287af36
commit
a2fbf908aa
19 changed files with 194 additions and 87 deletions
package-lock.jsonpackage.jsontailwind.config.mjs
scripts
src
components
content
i18n
layouts
pages
styles
utils
98
package-lock.json
generated
98
package-lock.json
generated
|
@ -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": {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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!");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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">
|
||||
{
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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",
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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: {
|
||||
|
|
Loading…
Add table
Reference in a new issue