Add GitGud and astro-htaccess integration
This commit is contained in:
parent
4829af9f55
commit
37fba2f602
11 changed files with 260 additions and 94 deletions
|
|
@ -1 +1 @@
|
||||||
See [public/licenses.toml](public/licenses.toml)
|
See [src/data/licenses.toml](src/data/licenses.toml)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { defineConfig, envField } from "astro/config";
|
import { defineConfig, envField } from "astro/config";
|
||||||
import tailwindIntegration from "@astrojs/tailwind";
|
import tailwindIntegration from "@astrojs/tailwind";
|
||||||
|
import htaccessIntegration from "astro-htaccess";
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
|
@ -8,6 +9,49 @@ export default defineConfig({
|
||||||
tailwindIntegration({
|
tailwindIntegration({
|
||||||
applyBaseStyles: false,
|
applyBaseStyles: false,
|
||||||
}),
|
}),
|
||||||
|
htaccessIntegration({
|
||||||
|
generateHtaccessFile: import.meta.env.APACHE_CONFIG === "true",
|
||||||
|
redirects: [
|
||||||
|
{ match: /^\/@\/(aryion|ekas?(portal)?)\b/, url: "https://aryion.com/g4/user/BadManners" },
|
||||||
|
{ match: /^\/@\/(blue[_-]?sky|bsky)\b/, url: "https://bsky.app/profile/badmanners.xyz" },
|
||||||
|
{ match: /^\/@\/(buymeacoffee|buy_me_a_coffee|buy-me-a-coffee|bmac)\b/, url: "https://www.buymeacoffee.com/BadMannersXYZ" },
|
||||||
|
{ match: /^\/@\/carrd\b/, url: "https://badmanners.carrd.co" },
|
||||||
|
{ match: /^\/@\/code[_-]?berg\b/, url: "https://codeberg.org/BadManners" },
|
||||||
|
{ match: /^\/@\/co[_-]?host\b/, url: "https://cohost.org/BadManners" },
|
||||||
|
{ match: /^\/@\/discord\b/, url: "/#discord" },
|
||||||
|
{ match: /^\/@\/e[_-]?mail\b/, url: "/#e-mail" },
|
||||||
|
{ match: /^\/@\/(fur[_-]?affinity|fa)\b/, url: "https://www.furaffinity.net/user/badmanners" },
|
||||||
|
{ match: /^\/@\/(gallery|stor(y|ies)|games?)\b/, url: "https://gallery.badmanners.xyz" },
|
||||||
|
{ match: /^\/@\/(git[_-]?hub|gh)\b/, url: "https://github.com/BadMannersXYZ" },
|
||||||
|
{ match: /^\/@\/git[_-]?lab\b/, url: "https://gitlab.com/Bad_Manners" },
|
||||||
|
{ match: /^\/@\/(git[_-]?gud|sapp?hire)\b/, url: "https://gitgud.io/BadMannersXYZ" },
|
||||||
|
{ match: /^\/@\/(google|g[_-]?mail)\b/, url: "/#gmail" },
|
||||||
|
{ match: /^\/@\/gum[_-]?road\b/, url: "https://badmanners.gumroad.com" },
|
||||||
|
{ match: /^\/@\/(ink[_-]?bunny|ib)\b/, url: "https://inkbunny.net/BadManners" },
|
||||||
|
{ match: /^\/@\/itaku\b/, url: "https://itaku.ee/profile/badmanners" },
|
||||||
|
{ match: /^\/@\/itch\b/, url: "https://bad-manners.itch.io" },
|
||||||
|
{ match: /^\/@\/keybase\b/, url: "https://keybase.io/badmanners" },
|
||||||
|
{ match: /^\/@\/keyoxide\b/, url: "https://keyoxide.org/aspe:keyoxide.org:UWYBVFCBFXTVUF2U6FS6AYJHLU" },
|
||||||
|
{ match: /^\/@\/ko[._-]?fi\b/, url: "https://ko-fi.com/badmanners" },
|
||||||
|
{ match: /^\/@\/(mastodon|meow[._-]?social|gulp[._-]?cafe)\b/, url: "https://meow.social/@BadManners" },
|
||||||
|
{ match: /^\/@\/neo[_-]?cities\b/, url: "https://badmanners.neocities.org" },
|
||||||
|
{ match: /^\/@\/picarto\b/, url: "https://www.picarto.tv/BadManners" },
|
||||||
|
{ match: /^\/@\/pillow[_-]?fort\b/, url: "https://www.pillowfort.social/BadManners" },
|
||||||
|
{ match: /^\/@\/pronouns?\b/, url: "https://pronouns.cc/@BadManners" },
|
||||||
|
{ match: /^\/@\/redd\.?it\b/, url: "https://www.reddit.com/user/BadManners_" },
|
||||||
|
{ match: /^\/@\/signal\b/, url: "https://signal.me/#eu/ytt_rk0fFmAB2JAW-x2PbUiJyc_H3kYmfL_Pq4QNh5QIDsiFtjdFHaqFRs1D36tB" },
|
||||||
|
{ match: /^\/@\/(so[_-]?furry|sf)\b/, url: "https://bad-manners.sofurry.com" },
|
||||||
|
{ match: /^\/@\/ssh\b/, url: "/ssh.pub" },
|
||||||
|
{ match: /^\/@\/steam(community|powered)?\b/, url: "https://steamcommunity.com/id/badmanners_" },
|
||||||
|
{ match: /^\/@\/subscribe[_-]?star\b/, url: "https://subscribestar.adult/bad-manners" },
|
||||||
|
{ match: /^\/@\/(telegram|t\.me)\b/, url: "https://t.me/bad_manners" },
|
||||||
|
{ match: /^\/@\/tumblr\b/, url: "https://www.tumblr.com/badmannersxyz" },
|
||||||
|
{ match: /^\/@\/twitch\b/, url: "https://www.twitch.tv/bad__manners" },
|
||||||
|
{ match: /^\/@\/weasyl\b/, url: "https://www.weasyl.com/~badmanners" },
|
||||||
|
{ match: /^\/@\/(x|twitter)\b/, url: "https://x.com/BadManners__" },
|
||||||
|
{ match: /^\/@\/(you[_-]?tube|youtu\.be|yt)\b/, url: "https://www.youtube.com/@BadMannersXYZ" },
|
||||||
|
],
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
build: {
|
build: {
|
||||||
assets: "assets",
|
assets: "assets",
|
||||||
|
|
|
||||||
17
package-lock.json
generated
17
package-lock.json
generated
|
|
@ -13,9 +13,11 @@
|
||||||
"@astrojs/rss": "^4.0.7",
|
"@astrojs/rss": "^4.0.7",
|
||||||
"@astrojs/tailwind": "^5.1.0",
|
"@astrojs/tailwind": "^5.1.0",
|
||||||
"astro": "^4.13.3",
|
"astro": "^4.13.3",
|
||||||
|
"astro-htaccess": "^0.1.1",
|
||||||
"date-fns": "^3.6.0",
|
"date-fns": "^3.6.0",
|
||||||
"tailwindcss": "^3.4.9",
|
"tailwindcss": "^3.4.9",
|
||||||
"tippy.js": "^6.3.7",
|
"tippy.js": "^6.3.7",
|
||||||
|
"toml": "^3.0.0",
|
||||||
"typescript": "^5.5.4"
|
"typescript": "^5.5.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
@ -2236,6 +2238,15 @@
|
||||||
"sharp": "^0.33.3"
|
"sharp": "^0.33.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/astro-htaccess": {
|
||||||
|
"version": "0.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/astro-htaccess/-/astro-htaccess-0.1.1.tgz",
|
||||||
|
"integrity": "sha512-GbsQZkAk62DW1CzZ5KgEuRYuZXqZXFeKt9w8MMAacmJoV5F+BfKws4x4gszpKqUi1wXSKG6psaPRPQrYIGsu0Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"astro": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/autoprefixer": {
|
"node_modules/autoprefixer": {
|
||||||
"version": "10.4.18",
|
"version": "10.4.18",
|
||||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.18.tgz",
|
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.18.tgz",
|
||||||
|
|
@ -6430,6 +6441,12 @@
|
||||||
"node": ">=8.0"
|
"node": ">=8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/toml": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/trim-lines": {
|
"node_modules/trim-lines": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,11 @@
|
||||||
"@astrojs/rss": "^4.0.7",
|
"@astrojs/rss": "^4.0.7",
|
||||||
"@astrojs/tailwind": "^5.1.0",
|
"@astrojs/tailwind": "^5.1.0",
|
||||||
"astro": "^4.13.3",
|
"astro": "^4.13.3",
|
||||||
|
"astro-htaccess": "^0.1.1",
|
||||||
"date-fns": "^3.6.0",
|
"date-fns": "^3.6.0",
|
||||||
"tailwindcss": "^3.4.9",
|
"tailwindcss": "^3.4.9",
|
||||||
"tippy.js": "^6.3.7",
|
"tippy.js": "^6.3.7",
|
||||||
|
"toml": "^3.0.0",
|
||||||
"typescript": "^5.5.4"
|
"typescript": "^5.5.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
||||||
15
src/components/icons/brands/IconGitGud.astro
Normal file
15
src/components/icons/brands/IconGitGud.astro
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
import SVGIcon from "../SVGIcon.astro";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
width: string;
|
||||||
|
height: string;
|
||||||
|
class?: string;
|
||||||
|
};
|
||||||
|
---
|
||||||
|
|
||||||
|
<SVGIcon {...Astro.props} viewBox="0 0 64 64">
|
||||||
|
<path
|
||||||
|
d="m 36.993869,17.726834 v 12.225173 h 2.394368 V 20.09654 Z m -13.514274,0.08071 -2.12758,2.102917 v 7.913966 l 2.102918,2.12758 h 7.201038 l 2.105159,-2.12758 v -5.107086 h -3.631905 l -2.190352,2.266578 h 3.403229 v 1.833888 l -0.831751,0.789156 h -4.954636 l -0.813816,-0.735349 v -5.918661 l 0.813816,-0.939363 h 6.100256 l 2.18811,-2.206045 z m 20.141381,0 v 2.206045 h 3.495148 v 9.938418 h 2.208288 v -9.938418 h 2.311417 l 2.185868,-2.206045 z M 2.0804992,21.381159 c -1.015668,0 -2.0804994,1.073278 -2.0804994,2.098434 0,1.450184 0.9358272,2.417282 2.2979654,2.378673 0.560224,-0.01588 0.855434,0.172661 1.822677,1.150103 0.986935,0.99734 1.139079,1.248956 1.046976,1.730761 -0.13363,0.699044 0.377082,2.024795 0.883315,2.295722 0.347105,0.185766 0.376642,0.479482 0.376642,3.67226 0,3.444753 -0.0039,3.475336 -0.502189,3.943532 -1.167101,1.096434 -0.989099,3.009422 0.349739,3.752969 0.249472,0.138548 0.825602,0.253886 1.280135,0.25782 2.085557,0.01795 3.0021788,-2.459127 1.475181,-3.986128 l -0.594108,-0.594108 v -3.374085 -3.371843 l 1.188215,1.174764 c 1.1009768,1.089498 1.1849758,1.239391 1.1545878,2.024451 -0.06035,1.559523 0.857477,2.510947 2.42127,2.510947 0.899188,0 1.547075,-0.397971 1.966161,-1.208391 0.385952,-0.74635 0.37578,-1.276275 -0.03139,-2.134305 -0.394989,-0.832379 -1.264716,-1.324592 -2.197079,-1.244265 -0.604892,0.05211 -0.833817,-0.08825 -1.954952,-1.199424 -1.0771668,-1.067593 -1.2594548,-1.346266 -1.1882148,-1.831647 0.196023,-1.335595 -1.111686,-2.710788 -2.468351,-2.593898 -0.606738,0.05227 -0.834178,-0.07706 -1.78905,-1.020072 -1.02439,-1.01167 -1.093688,-1.138948 -1.073875,-2.008758 0.035079,-1.540265 -0.831856,-2.423512 -2.383156,-2.423512 z m 21.3990958,12.718394 -2.12758,2.107402 v 7.911724 l 2.102918,2.12758 h 7.201038 l 2.105159,-2.12758 v -5.104844 h -3.631905 l -2.190352,2.264336 h 3.403229 v 1.833888 l -0.831751,0.789155 h -4.954636 l -0.813816,-0.733106 v -5.920904 l 0.813816,-0.939362 h 6.100256 l 2.18811,-2.208289 z m 13.469436,0.03139 v 10.014643 l 2.102918,2.12758 h 7.201036 l 2.105161,-2.12758 V 34.13094 H 45.96602 v 9.176165 l -0.955056,0.686027 -4.802185,-0.009 -0.869865,-0.681543 v -9.171681 z m 15.641854,0 V 46.273165 H 61.89484 L 64,44.145585 v -7.891547 l -2.10516,-2.123095 z m 2.392125,2.203804 5.734823,0.04708 0.890042,0.71517 v 6.16303 l -0.919187,0.76001 -5.705678,0.04484 z"
|
||||||
|
></path>
|
||||||
|
</SVGIcon>
|
||||||
|
|
@ -4,6 +4,7 @@ export { default as IconCohost } from "./IconCohost.astro";
|
||||||
export { default as IconDiscord } from "./IconDiscord.astro";
|
export { default as IconDiscord } from "./IconDiscord.astro";
|
||||||
export { default as IconEkasPortal } from "./IconEkasPortal.astro";
|
export { default as IconEkasPortal } from "./IconEkasPortal.astro";
|
||||||
export { default as IconFurAffinity } from "./IconFurAffinity.astro";
|
export { default as IconFurAffinity } from "./IconFurAffinity.astro";
|
||||||
|
export { default as IconGitGud } from "./IconGitGud.astro";
|
||||||
export { default as IconGithub } from "./IconGithub.astro";
|
export { default as IconGithub } from "./IconGithub.astro";
|
||||||
export { default as IconGitlab } from "./IconGitlab.astro";
|
export { default as IconGitlab } from "./IconGitlab.astro";
|
||||||
export { default as IconGoogle } from "./IconGoogle.astro";
|
export { default as IconGoogle } from "./IconGoogle.astro";
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ title = "badmanners.xyz"
|
||||||
description = "Bad Manners's personal website."
|
description = "Bad Manners's personal website."
|
||||||
type = "website"
|
type = "website"
|
||||||
date = "2023-2024"
|
date = "2023-2024"
|
||||||
author = "Bad Manners <me@badmanners.xyz>"
|
author = { name = "Bad Manners", url = "https://badmanners.xyz", email = "me@badmanners.xyz>" }
|
||||||
source = "https://git.badmanners.xyz/badmanners/badmanners.xyz"
|
source = "https://git.badmanners.xyz/badmanners/badmanners.xyz"
|
||||||
license = { name = "MIT", url = "https://opensource.org/license/mit" }
|
license = { name = "MIT", url = "https://opensource.org/license/mit" }
|
||||||
notes = "All rights reserved."
|
notes = "All rights reserved."
|
||||||
|
|
@ -45,7 +45,7 @@ source = "https://indestructibletype.com/Jost.html"
|
||||||
license = { name = "SIL Open Font License v1.1", url = "https://opensource.org/license/ofl-1-1" }
|
license = { name = "SIL Open Font License v1.1", url = "https://opensource.org/license/ofl-1-1" }
|
||||||
|
|
||||||
[[attributions]]
|
[[attributions]]
|
||||||
title = "Simple Icons"
|
author = "Simple Icons"
|
||||||
description = "Icons for third-party brands."
|
description = "Icons for third-party brands."
|
||||||
type = "icons"
|
type = "icons"
|
||||||
source = "https://simpleicons.org"
|
source = "https://simpleicons.org"
|
||||||
|
|
@ -78,13 +78,14 @@ and I'm not affiliated with any of them."""
|
||||||
[[attributions]]
|
[[attributions]]
|
||||||
description = "Edited icons for other websites."
|
description = "Edited icons for other websites."
|
||||||
type = "icons"
|
type = "icons"
|
||||||
author = "Bad Manners <me@badmanners.xyz>"
|
author = { name = "Bad Manners", url = "https://badmanners.xyz", email = "me@badmanners.xyz>" }
|
||||||
source = "https://git.badmanners.xyz/badmanners/badmanners.xyz/src/branch/main/src/components/icons/brands"
|
source = "https://git.badmanners.xyz/badmanners/badmanners.xyz/src/branch/main/src/components/icons/brands"
|
||||||
license = { name = "CC0 1.0 Universal", url = "https://creativecommons.org/publicdomain/zero/1.0/" }
|
license = { name = "CC0 1.0 Universal", url = "https://creativecommons.org/publicdomain/zero/1.0/" }
|
||||||
items = [
|
items = [
|
||||||
"Cohost",
|
"Cohost",
|
||||||
"Eka's Portal",
|
"Eka's Portal",
|
||||||
"Fur Affinity",
|
"Fur Affinity",
|
||||||
|
"GitGud",
|
||||||
"Inkbunny",
|
"Inkbunny",
|
||||||
"Itaku",
|
"Itaku",
|
||||||
"Keyoxide",
|
"Keyoxide",
|
||||||
|
|
@ -97,7 +98,7 @@ All third-party copyrights and trademarks belong to their respective owners, \
|
||||||
and I'm not affiliated with any of them."""
|
and I'm not affiliated with any of them."""
|
||||||
|
|
||||||
[[attributions]]
|
[[attributions]]
|
||||||
title = "Font Awesome"
|
author = "Font Awesome"
|
||||||
description = "Generic icons."
|
description = "Generic icons."
|
||||||
type = "icons"
|
type = "icons"
|
||||||
source = "https://fontawesome.com"
|
source = "https://fontawesome.com"
|
||||||
|
|
@ -73,7 +73,7 @@ const title = pageTitle ? `${pageTitle} | Bad Manners` : "Bad Manners";
|
||||||
>
|
>
|
||||||
<IconSun width="1.5rem" height="1.5rem" class="hidden dark:block" />
|
<IconSun width="1.5rem" height="1.5rem" class="hidden dark:block" />
|
||||||
<IconMoon width="1.5rem" height="1.5rem" class="block dark:hidden" />
|
<IconMoon width="1.5rem" height="1.5rem" class="block dark:hidden" />
|
||||||
<span id="label-toggle-dark-mode" class="sr-only">Toggle dark mode</span>
|
<span id="label-toggle-dark-mode" class="sr-only select-none">Toggle dark mode</span>
|
||||||
</button>
|
</button>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
import type { APIRoute, GetStaticPaths } from "astro";
|
|
||||||
import { APACHE_CONFIG } from "astro:env/server";
|
|
||||||
|
|
||||||
const htaccess = String.raw`
|
|
||||||
ErrorDocument 404 /404.html
|
|
||||||
RedirectMatch 301 ^/tos(/(index.html)?)?$ /terms_of_service/
|
|
||||||
RedirectMatch 301 ^/contact(/(index.html)?)?$ /
|
|
||||||
RedirectMatch 301 ^/@/(aryion|ekas?(portal)?)\b https://aryion.com/g4/user/BadManners
|
|
||||||
RedirectMatch 301 ^/@/(blue[_-]?sky|bsky)\b https://bsky.app/profile/badmanners.xyz
|
|
||||||
RedirectMatch 301 ^/@/(buymeacoffee|buy_me_a_coffee|buy-me-a-coffee|bmac)\b https://www.buymeacoffee.com/BadMannersXYZ
|
|
||||||
RedirectMatch 301 ^/@/carrd\b https://badmanners.carrd.co
|
|
||||||
RedirectMatch 301 ^/@/code[_-]?berg\b https://codeberg.org/BadManners
|
|
||||||
RedirectMatch 301 ^/@/co[_-]?host\b https://cohost.org/BadManners
|
|
||||||
RedirectMatch 301 ^/@/discord\b /#discord
|
|
||||||
RedirectMatch 301 ^/@/e[_-]?mail\b /#e-mail
|
|
||||||
RedirectMatch 301 ^/@/(fur[_-]?affinity|fa)\b https://www.furaffinity.net/user/badmanners
|
|
||||||
RedirectMatch 301 ^/@/(gallery|stor(y|ies)|games?)\b https://gallery.badmanners.xyz
|
|
||||||
RedirectMatch 301 ^/@/(git[_-]?hub|gh)\b https://github.com/BadMannersXYZ
|
|
||||||
RedirectMatch 301 ^/@/git[_-]?lab\b https://gitlab.com/Bad_Manners
|
|
||||||
RedirectMatch 301 ^/@/(google|g[_-]?mail)\b /#gmail
|
|
||||||
RedirectMatch 301 ^/@/gum[_-]?road\b https://badmanners.gumroad.com
|
|
||||||
RedirectMatch 301 ^/@/(ink[_-]?bunny|ib)\b https://inkbunny.net/BadManners
|
|
||||||
RedirectMatch 301 ^/@/itaku\b https://itaku.ee/profile/badmanners
|
|
||||||
RedirectMatch 301 ^/@/itch\b https://bad-manners.itch.io
|
|
||||||
RedirectMatch 301 ^/@/keybase\b https://keybase.io/badmanners
|
|
||||||
RedirectMatch 301 ^/@/keyoxide\b https://keyoxide.org/aspe:keyoxide.org:UWYBVFCBFXTVUF2U6FS6AYJHLU
|
|
||||||
RedirectMatch 301 ^/@/ko[._-]?fi\b https://ko-fi.com/badmanners
|
|
||||||
RedirectMatch 301 ^/@/(mastodon|meow[._-]?social|gulp[._-]?cafe)\b https://meow.social/@BadManners
|
|
||||||
RedirectMatch 301 ^/@/neo[_-]?cities\b https://badmanners.neocities.org
|
|
||||||
RedirectMatch 301 ^/@/picarto\b https://www.picarto.tv/BadManners
|
|
||||||
RedirectMatch 301 ^/@/pillow[_-]?fort\b https://www.pillowfort.social/BadManners
|
|
||||||
RedirectMatch 301 ^/@/pronouns?\b https://pronouns.cc/@BadManners
|
|
||||||
RedirectMatch 301 ^/@/redd\.?it\b https://www.reddit.com/user/BadManners_
|
|
||||||
RedirectMatch 301 ^/@/signal\b https://signal.me/#eu/ytt_rk0fFmAB2JAW-x2PbUiJyc_H3kYmfL_Pq4QNh5QIDsiFtjdFHaqFRs1D36tB
|
|
||||||
RedirectMatch 301 ^/@/(so[_-]?furry|sf)\b https://bad-manners.sofurry.com
|
|
||||||
RedirectMatch 301 ^/@/ssh\b /ssh.pub
|
|
||||||
RedirectMatch 301 ^/@/steam(community|powered)?\b https://steamcommunity.com/id/badmanners_
|
|
||||||
RedirectMatch 301 ^/@/subscribe[_-]?star\b https://subscribestar.adult/bad-manners
|
|
||||||
RedirectMatch 301 ^/@/(telegram|t\.me)\b https://t.me/bad_manners
|
|
||||||
RedirectMatch 301 ^/@/tumblr\b https://www.tumblr.com/badmannersxyz
|
|
||||||
RedirectMatch 301 ^/@/twitch\b https://www.twitch.tv/bad__manners
|
|
||||||
RedirectMatch 301 ^/@/weasyl\b https://www.weasyl.com/~badmanners
|
|
||||||
RedirectMatch 301 ^/@/(x|twitter)\b https://x.com/BadManners__
|
|
||||||
RedirectMatch 301 ^/@/(you[_-]?tube|youtu\.be|yt)\b https://www.youtube.com/@BadMannersXYZ
|
|
||||||
`.trim();
|
|
||||||
|
|
||||||
export const getStaticPaths: GetStaticPaths = async () => {
|
|
||||||
if (APACHE_CONFIG) {
|
|
||||||
return [{ params: { config: ".htaccess" }, props: { body: htaccess } }];
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const GET: APIRoute = ({ props: { body } }) => new Response(body);
|
|
||||||
|
|
@ -8,6 +8,7 @@ import {
|
||||||
IconDiscord,
|
IconDiscord,
|
||||||
IconEkasPortal,
|
IconEkasPortal,
|
||||||
IconFurAffinity,
|
IconFurAffinity,
|
||||||
|
IconGitGud,
|
||||||
IconGithub,
|
IconGithub,
|
||||||
IconGitlab,
|
IconGitlab,
|
||||||
IconGoogle,
|
IconGoogle,
|
||||||
|
|
@ -79,7 +80,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="sr-only">https://badmanners.xyz</p>
|
<p class="sr-only select-none">https://badmanners.xyz</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
) : null
|
) : null
|
||||||
|
|
@ -98,7 +99,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="sr-only">Gallery on https://gallery.badmanners.xyz</p>
|
<p class="sr-only select-none">Gallery on https://gallery.badmanners.xyz</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -114,7 +115,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">@BadManners on pronouns.cc</p>
|
<p class="p-nickname sr-only select-none">@BadManners on pronouns.cc</p>
|
||||||
<p class="p-pronoun hidden">he/him/his/his/himself</p>
|
<p class="p-pronoun hidden">he/him/his/his/himself</p>
|
||||||
<p class="p-pronoun hidden">they/them/their/theirs/themself</p>
|
<p class="p-pronoun hidden">they/them/their/theirs/themself</p>
|
||||||
</a>
|
</a>
|
||||||
|
|
@ -134,7 +135,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="sr-only">me@badmanners.xyz</p>
|
<p class="sr-only select-none">me@badmanners.xyz</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -150,7 +151,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">@badmanners.xyz on Bluesky</p>
|
<p class="p-nickname sr-only select-none">@badmanners.xyz on Bluesky</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -166,7 +167,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">BadManners on Codeberg</p>
|
<p class="p-nickname sr-only select-none">BadManners on Codeberg</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -182,7 +183,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">BadManners on Cohost</p>
|
<p class="p-nickname sr-only select-none">BadManners on Cohost</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -199,7 +200,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">badmanners on Discord</p>
|
<p class="p-nickname sr-only select-none">badmanners on Discord</p>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -215,7 +216,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">BadManners on Eka's Portal</p>
|
<p class="p-nickname sr-only select-none">BadManners on Eka's Portal</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -231,7 +232,23 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">BadManners on Fur Affinity</p>
|
<p class="p-nickname sr-only select-none">BadManners on Fur Affinity</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
id="gitgud"
|
||||||
|
class="u-url text-link group block w-full py-2 transition-colors motion-reduce:transition-none"
|
||||||
|
href="https://gitgud.io/BadMannersXYZ"
|
||||||
|
rel="me"
|
||||||
|
aria-label="GitGud"
|
||||||
|
>
|
||||||
|
<IconGitGud
|
||||||
|
height="1.75rem"
|
||||||
|
width="1.75rem"
|
||||||
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
|
/>
|
||||||
|
<p class="p-nickname sr-only select-none">BadMannersXYZ on GitGud</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -247,7 +264,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">BadMannersXYZ on GitHub</p>
|
<p class="p-nickname sr-only select-none">BadMannersXYZ on GitHub</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -263,7 +280,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">Bad_Manners on GitLab</p>
|
<p class="p-nickname sr-only select-none">Bad_Manners on GitLab</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -281,7 +298,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="sr-only">badmanners.vore@gmail.com</p>
|
<p class="sr-only select-none">badmanners.vore@gmail.com</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -297,7 +314,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">BadManners on Inkbunny</p>
|
<p class="p-nickname sr-only select-none">BadManners on Inkbunny</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -313,7 +330,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">badmanners on Itaku</p>
|
<p class="p-nickname sr-only select-none">badmanners on Itaku</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -329,7 +346,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">Bad Manners on Itch.io</p>
|
<p class="p-nickname sr-only select-none">Bad Manners on Itch.io</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -345,7 +362,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">badmanners on Keybase</p>
|
<p class="p-nickname sr-only select-none">badmanners on Keybase</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -361,7 +378,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="sr-only"><span class="p-uid">aspe:keyoxide.org:UWYBVFCBFXTVUF2U6FS6AYJHLU</span> on Keyoxide</p>
|
<p class="sr-only select-none"><span class="p-uid">aspe:keyoxide.org:UWYBVFCBFXTVUF2U6FS6AYJHLU</span> on Keyoxide</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -377,7 +394,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">badmanners on Ko-fi</p>
|
<p class="p-nickname sr-only select-none">badmanners on Ko-fi</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -393,7 +410,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">@BadManners@meow.social on Mastodon</p>
|
<p class="p-nickname sr-only select-none">@BadManners@meow.social on Mastodon</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -409,7 +426,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">badmanners.neocities.org on Neocities</p>
|
<p class="p-nickname sr-only select-none">badmanners.neocities.org on Neocities</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -425,7 +442,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">BadManners on Picarto</p>
|
<p class="p-nickname sr-only select-none">BadManners on Picarto</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -441,7 +458,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">/u/BadManners_ on Reddit</p>
|
<p class="p-nickname sr-only select-none">/u/BadManners_ on Reddit</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -457,7 +474,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">badmanners.10 on Signal</p>
|
<p class="p-nickname sr-only select-none">badmanners.10 on Signal</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -473,7 +490,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">Bad Manners on SoFurry</p>
|
<p class="p-nickname sr-only select-none">Bad Manners on SoFurry</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -490,7 +507,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="sr-only">SSH public key</p>
|
<p class="sr-only select-none">SSH public key</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -506,7 +523,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">badmanners_ on Steam</p>
|
<p class="p-nickname sr-only select-none">badmanners_ on Steam</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -522,7 +539,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">Bad Manners on SubscribeStar</p>
|
<p class="p-nickname sr-only select-none">Bad Manners on SubscribeStar</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -538,7 +555,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">@bad_manners on Telegram</p>
|
<p class="p-nickname sr-only select-none">@bad_manners on Telegram</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -554,7 +571,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">badmannersxyz on Tumblr</p>
|
<p class="p-nickname sr-only select-none">badmannersxyz on Tumblr</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -570,7 +587,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">bad__manners on Twitch</p>
|
<p class="p-nickname sr-only select-none">bad__manners on Twitch</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -586,7 +603,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">BadManners on Weasyl</p>
|
<p class="p-nickname sr-only select-none">BadManners on Weasyl</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -602,7 +619,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">@BadManners__ on X</p>
|
<p class="p-nickname sr-only select-none">@BadManners__ on X</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -618,7 +635,7 @@ import {
|
||||||
width="1.75rem"
|
width="1.75rem"
|
||||||
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
class="inline transition-transform group-hover:scale-150 group-focus:scale-150 motion-reduce:transition-none motion-reduce:group-hover:scale-100 motion-reduce:group-focus:scale-100"
|
||||||
/>
|
/>
|
||||||
<p class="p-nickname sr-only">@BadMannersXYZ on YouTube</p>
|
<p class="p-nickname sr-only select-none">@BadMannersXYZ on YouTube</p>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
123
src/pages/licenses.toml.ts
Normal file
123
src/pages/licenses.toml.ts
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
import type { APIRoute } from "astro";
|
||||||
|
import { readFile } from "node:fs/promises";
|
||||||
|
import { parse } from "toml";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify attributions and copyright according to the [Creative Commons recommended practices](https://wiki.creativecommons.org/wiki/Recommended_practices_for_attribution)
|
||||||
|
* @param copyright Unparsed TOML copyright information.
|
||||||
|
*/
|
||||||
|
function verifyAttributions(licenses: string) {
|
||||||
|
const { copyright, attributions } = parse(licenses);
|
||||||
|
// Make sure each copyright and attribution follows the TASL format.
|
||||||
|
// - T: title (or description)
|
||||||
|
// - A: author
|
||||||
|
// - S: source
|
||||||
|
// - L: license
|
||||||
|
// - other fields that have custom validation: type, notes, items
|
||||||
|
[copyright, attributions].flat().forEach((value) => {
|
||||||
|
// Title or description must be a valid string
|
||||||
|
const title = value.title ?? value.description;
|
||||||
|
if (typeof title !== "string" || !title) {
|
||||||
|
throw new Error(`Missing "title" and/or "description" for attribution (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
// Author must be a valid string or object or list
|
||||||
|
const authors = [value.author].flat();
|
||||||
|
if (authors.length === 0) {
|
||||||
|
throw new Error(`Missing "author" for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
authors.forEach((author) => {
|
||||||
|
if (!author) {
|
||||||
|
throw new Error(`Missing "author" for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
if (typeof author !== "object" && typeof author !== "string") {
|
||||||
|
throw new Error(`Invalid "${typeof author}" type for "author"${JSON.stringify(author)} for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
if (typeof author === "object" && !(author.name || author.url)) {
|
||||||
|
throw new Error(`Missing both name and URL for "author" ${JSON.stringify(author)} for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Source must be a valid string or list of strings
|
||||||
|
const sources = [value.source].flat();
|
||||||
|
if (sources.length === 0) {
|
||||||
|
throw new Error(`Missing "source" for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
sources.forEach((source) => {
|
||||||
|
if (!source) {
|
||||||
|
throw new Error(`Missing "source" for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
if (typeof source !== "object" && typeof source !== "string") {
|
||||||
|
throw new Error(`Invalid "${typeof source}" type for "source"${JSON.stringify(source)} for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
if (typeof source === "object" && !(source.url)) {
|
||||||
|
throw new Error(`Missing URL for "source" ${JSON.stringify(source)} for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// License must be a valid string or object or list
|
||||||
|
const licenses = [value.license].flat();
|
||||||
|
if (licenses.length === 0) {
|
||||||
|
throw new Error(`Missing "license" for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
licenses.forEach((license) => {
|
||||||
|
if (!license) {
|
||||||
|
throw new Error(`Missing "license" for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
if (typeof license !== "object" && typeof license !== "string") {
|
||||||
|
throw new Error(`Invalid "${typeof license}" type for "license"${JSON.stringify(license)} for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
if (typeof license === "object" && !(license.name || license.url)) {
|
||||||
|
throw new Error(`Missing both name and URL for "license" ${JSON.stringify(license)} for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Validate extra optional fields
|
||||||
|
// 1. Type must be a valid string
|
||||||
|
if (typeof value.type !== "string") {
|
||||||
|
throw new Error(`Invalid "type" for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
if (!value.type) {
|
||||||
|
throw new Error(`Missing "type" for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
// 2. Items must be a valid list of strings/objects
|
||||||
|
if ("items" in value) {
|
||||||
|
const items = value.items;
|
||||||
|
if (!Array.isArray(items)) {
|
||||||
|
throw new Error(`Invalid non-array "items" ${JSON.stringify(items)} for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
items.forEach((item) => {
|
||||||
|
if (!item) {
|
||||||
|
throw new Error(`Invalid item ${JSON.stringify} in "items" for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 3. Type must be a valid string
|
||||||
|
if ("notes" in value) {
|
||||||
|
if (typeof value.notes !== "string" || !value.notes) {
|
||||||
|
throw new Error(`Invalid "notes" for attribution "${title}" (${JSON.stringify(value)})`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Check date for copyrights
|
||||||
|
if (typeof copyright.date !== "string") {
|
||||||
|
throw new Error(`Invalid "date" for copyright (${JSON.stringify(copyright)})`);
|
||||||
|
}
|
||||||
|
if (!copyright.date) {
|
||||||
|
throw new Error(`Missing "date" for copyright (${JSON.stringify(copyright)})`);
|
||||||
|
}
|
||||||
|
// Check notes for additional copyrights
|
||||||
|
if ("additional" in copyright) {
|
||||||
|
const additionals = copyright.additional;
|
||||||
|
if (!Array.isArray(additionals)) {
|
||||||
|
throw new Error(`Invalid non-array "additional" ${JSON.stringify(additionals)} for copyright (${JSON.stringify(copyright)})`);
|
||||||
|
}
|
||||||
|
additionals.forEach((additional) => {
|
||||||
|
if (typeof additional.notes !== "string" || !additional.notes) {
|
||||||
|
throw new Error(`Invalid "notes" for additional copyright (${JSON.stringify(additional)})`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GET: APIRoute = async () => {
|
||||||
|
const licenses = await readFile("./src/data/licenses.toml", { encoding: "utf-8" });
|
||||||
|
verifyAttributions(licenses);
|
||||||
|
return new Response(licenses, { headers: { "Content-Type": "application/toml; charset=utf-8" } })
|
||||||
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue