Added prettier

This commit is contained in:
DrMint 2024-03-02 20:35:36 +01:00
parent f76ac860e5
commit 6c1956ce5c
71 changed files with 327 additions and 664 deletions

1
.prettierignore Normal file
View File

@ -0,0 +1 @@
src/shared/*

View File

@ -20,7 +20,7 @@
## CSS Component classes ## CSS Component classes
- `pressable-icon`: used to make a SVG/Text look pressable - `pressable-icon`: used to make a SVG/Text look pressable
- `pressable`: used to make a container look pressable - `pressable`: used to make a container look pressable
## CSS Global Variables ## CSS Global Variables

BIN
bun.lockb

Binary file not shown.

View File

@ -12,7 +12,8 @@
"script:download-payload-sdk": "bun run scripts/download-payload-sdk.ts", "script:download-payload-sdk": "bun run scripts/download-payload-sdk.ts",
"script:download-currencies": "bun run scripts/download-currencies.ts", "script:download-currencies": "bun run scripts/download-currencies.ts",
"script:download-wording-keys": "bun run scripts/download-wording-keys.ts", "script:download-wording-keys": "bun run scripts/download-wording-keys.ts",
"precommit": "bun run script:download-wording-keys && bun run script:download-payload-sdk && bun run astro check" "prettier": "prettier --write --list-different --plugin=prettier-plugin-astro .",
"precommit": "bun run script:download-wording-keys && bun run script:download-payload-sdk && bun run prettier && bun run astro check"
}, },
"engines": { "engines": {
"npm": ">=10.0.0", "npm": ">=10.0.0",
@ -38,6 +39,8 @@
"bun-types": "^1.0.29", "bun-types": "^1.0.29",
"npm-check-updates": "^16.14.15", "npm-check-updates": "^16.14.15",
"postcss-preset-env": "^9.4.0", "postcss-preset-env": "^9.4.0",
"prettier": "^3.2.5",
"prettier-plugin-astro": "^0.13.0",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"typescript": "^5.3.3" "typescript": "^5.3.3"
} }

21
prettier.config.js Normal file
View File

@ -0,0 +1,21 @@
module.exports = {
printWidth: 100,
tabWidth: 2,
useTabs: false,
semi: true,
singleQuote: false,
quoteProps: "as-needed",
jsxSingleQuote: false,
trailingComma: "es5",
bracketSpacing: true,
bracketSameLine: true,
arrowParens: "always",
rangeStart: 0,
rangeEnd: Infinity,
requirePragma: false,
insertPragma: false,
proseWrap: "preserve",
htmlWhitespaceSensitivity: "ignore",
endOfLine: "lf",
singleAttributePerLine: false,
};

View File

@ -1,90 +1,91 @@
.tippy-box[data-animation="fade"][data-state="hidden"] { .tippy-box[data-animation="fade"][data-state="hidden"] {
opacity: 0; opacity: 0;
} }
[data-tippy-root] { [data-tippy-root] {
max-width: calc(100vw - 10px); max-width: calc(100vw - 10px);
} }
.tippy-box { .tippy-box {
position: relative; position: relative;
background-color: var(--color-elevation-2); background-color: var(--color-elevation-2);
color: var(--color-base-1000); color: var(--color-base-1000);
border-radius: 0.5rem; border-radius: 0.5rem;
border: 1px solid var(--color-base-650); border: 1px solid var(--color-base-650);
box-shadow: 0 20px 25px -5px var(--color-shadow-2), box-shadow:
0 0 10px -6px var(--color-shadow-2); 0 20px 25px -5px var(--color-shadow-2),
transition-property: transform, visibility, opacity; 0 0 10px -6px var(--color-shadow-2);
box-sizing: border-box; transition-property: transform, visibility, opacity;
} box-sizing: border-box;
.tippy-box[data-placement^="top"] > .tippy-arrow { }
bottom: 0; .tippy-box[data-placement^="top"] > .tippy-arrow {
} bottom: 0;
.tippy-box[data-placement^="top"] > .tippy-arrow:before { }
bottom: -8px; .tippy-box[data-placement^="top"] > .tippy-arrow:before {
left: 0; bottom: -8px;
border-width: 8px 8px 0; left: 0;
border-top-color: initial; border-width: 8px 8px 0;
transform-origin: center top; border-top-color: initial;
} transform-origin: center top;
.tippy-box[data-placement^="bottom"] > .tippy-arrow { }
top: 0; .tippy-box[data-placement^="bottom"] > .tippy-arrow {
} top: 0;
.tippy-box[data-placement^="bottom"] > .tippy-arrow:before { }
top: -8px; .tippy-box[data-placement^="bottom"] > .tippy-arrow:before {
left: 0; top: -8px;
border-width: 0 8px 8px; left: 0;
border-bottom-color: initial; border-width: 0 8px 8px;
transform-origin: center bottom; border-bottom-color: initial;
} transform-origin: center bottom;
.tippy-box[data-placement^="left"] > .tippy-arrow { }
right: 0; .tippy-box[data-placement^="left"] > .tippy-arrow {
} right: 0;
.tippy-box[data-placement^="left"] > .tippy-arrow:before { }
border-width: 8px 0 8px 8px; .tippy-box[data-placement^="left"] > .tippy-arrow:before {
border-left-color: initial; border-width: 8px 0 8px 8px;
right: -8px; border-left-color: initial;
transform-origin: center left; right: -8px;
} transform-origin: center left;
.tippy-box[data-placement^="right"] > .tippy-arrow { }
left: 0; .tippy-box[data-placement^="right"] > .tippy-arrow {
} left: 0;
.tippy-box[data-placement^="right"] > .tippy-arrow:before { }
left: -8px; .tippy-box[data-placement^="right"] > .tippy-arrow:before {
border-width: 8px 8px 8px 0; left: -8px;
border-right-color: initial; border-width: 8px 8px 8px 0;
transform-origin: center right; border-right-color: initial;
} transform-origin: center right;
.tippy-box[data-inertia][data-state="visible"] { }
transition-timing-function: cubic-bezier(0.54, 1.5, 0.38, 1.11); .tippy-box[data-inertia][data-state="visible"] {
} transition-timing-function: cubic-bezier(0.54, 1.5, 0.38, 1.11);
.tippy-arrow { }
width: 1em; .tippy-arrow {
height: 1em; width: 1em;
color: var(--color-base-650); height: 1em;
} color: var(--color-base-650);
.tippy-arrow:before { }
content: ""; .tippy-arrow:before {
position: absolute; content: "";
border-color: transparent; position: absolute;
border-style: solid; border-color: transparent;
} border-style: solid;
.tippy-content { }
position: relative; .tippy-content {
padding: 1rem 1.5rem; position: relative;
z-index: 1; padding: 1rem 1.5rem;
} z-index: 1;
.tippy-box[data-placement^="top"] { }
transform-origin: bottom; .tippy-box[data-placement^="top"] {
} transform-origin: bottom;
.tippy-box[data-placement^="bottom"] { }
transform-origin: top; .tippy-box[data-placement^="bottom"] {
} transform-origin: top;
.tippy-box[data-placement^="left"] { }
transform-origin: right; .tippy-box[data-placement^="left"] {
} transform-origin: right;
.tippy-box[data-placement^="right"] { }
transform-origin: left; .tippy-box[data-placement^="right"] {
} transform-origin: left;
.tippy-box[data-state="hidden"] { }
transform: scale(0.8); .tippy-box[data-state="hidden"] {
opacity: 0; transform: scale(0.8);
} opacity: 0;
}

View File

@ -55,5 +55,4 @@
"description": "Thousands of offcial artworks" "description": "Thousands of offcial artworks"
} }
] ]
} }

View File

@ -22,17 +22,9 @@ if (rates.ok) {
const currencies = await fetch(currenciesUrl); const currencies = await fetch(currenciesUrl);
if (currencies.ok) { if (currencies.ok) {
writeFileSync( writeFileSync(`${OPEN_EXCHANGE_FOLDER}/currencies.json`, await currencies.text(), {
`${OPEN_EXCHANGE_FOLDER}/currencies.json`, encoding: "utf-8",
await currencies.text(), });
{
encoding: "utf-8",
}
);
} else { } else {
console.error( console.error("Failed to get the currencies", currencies.status, currencies.statusText);
"Failed to get the currencies",
currencies.status,
currencies.statusText
);
} }

View File

@ -12,34 +12,21 @@ interface Props {
backgroundIllustration?: string | undefined; backgroundIllustration?: string | undefined;
} }
const { const { metaTitle, hideFooterLinks = false, parentPages, backgroundIllustration } = Astro.props;
metaTitle,
hideFooterLinks = false,
parentPages,
backgroundIllustration,
} = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<Html title={metaTitle}> <Html title={metaTitle}>
<header> <header>
{ {backgroundIllustration && <AppLayoutBackgroundImg src={backgroundIllustration} />}
backgroundIllustration && (
<AppLayoutBackgroundImg src={backgroundIllustration} />
)
}
<Topbar parentPages={parentPages} /> <Topbar parentPages={parentPages} />
</header> </header>
<main><slot /></main> <main><slot /></main>
<Footer withLinks={!hideFooterLinks} /> <Footer withLinks={!hideFooterLinks} />
</Html> </Html>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
header { header {

View File

@ -35,17 +35,11 @@ const {
} = Astro.props; } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<Html title={title}> <Html title={title}>
<header> <header>
{ {backgroundIllustration && <AppLayoutBackgroundImg src={backgroundIllustration} />}
backgroundIllustration && (
<AppLayoutBackgroundImg src={backgroundIllustration} />
)
}
<Topbar parentPages={parentPages} hideHomeButton={hideHomeButton} /> <Topbar parentPages={parentPages} hideHomeButton={hideHomeButton} />
{ {
@ -53,11 +47,7 @@ const {
<div id="header-content"> <div id="header-content">
<div id="header-left"> <div id="header-left">
<slot name="header-title"> <slot name="header-title">
<AppLayoutTitle <AppLayoutTitle pretitle={pretitle} title={title} subtitle={subtitle} />
pretitle={pretitle}
title={title}
subtitle={subtitle}
/>
</slot> </slot>
<div class="prose"> <div class="prose">
@ -75,9 +65,7 @@ const {
<Footer withLinks={!hideFooterLinks} /> <Footer withLinks={!hideFooterLinks} />
</Html> </Html>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
{/* TODO: Not use CSS image if possible */} {/* TODO: Not use CSS image if possible */}
<style <style
@ -108,11 +96,7 @@ const {
background-size: var(--illustrationSize); background-size: var(--illustrationSize);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: right var(--illustrationPosition); background-position: right var(--illustrationPosition);
mask-image: linear-gradient( mask-image: linear-gradient(to left, rgba(0, 0, 0, 1) 50%, transparent 80%);
to left,
rgba(0, 0, 0, 1) 50%,
transparent 80%
);
@media (max-width: 60rem) { @media (max-width: 60rem) {
display: none; display: none;

View File

@ -20,16 +20,12 @@ const styleNoScript = `
</style>`; </style>`;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<img id={uniqueId} src={src} alt={alt} class="when-no-print" /> <img id={uniqueId} src={src} alt={alt} class="when-no-print" />
<noscript set:html={styleNoScript} /> <noscript set:html={styleNoScript} />
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
img { img {
@ -44,17 +40,11 @@ const styleNoScript = `
object-fit: cover; object-fit: cover;
object-position: 50% 0; object-position: 50% 0;
width: 100%; width: 100%;
mask-image: linear-gradient( mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0) 100%);
to bottom,
rgba(0, 0, 0, 0.3) 0%,
rgba(0, 0, 0, 0) 100%
);
} }
</style> </style>
{ {/* ------------------------------------------- JS --------------------------------------------- */}
/* ------------------------------------------- JS --------------------------------------------- */
}
<script define:vars={{ uniqueId }}> <script define:vars={{ uniqueId }}>
const element = document.getElementById(uniqueId); const element = document.getElementById(uniqueId);

View File

@ -8,9 +8,7 @@ interface Props {
const { title, subtitle, pretitle } = Astro.props; const { title, subtitle, pretitle } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<h1 class="high-contrast-text"> <h1 class="high-contrast-text">
{pretitle && <span id="pretitle">{pretitle}&nbsp;</span>} {pretitle && <span id="pretitle">{pretitle}&nbsp;</span>}
@ -18,9 +16,7 @@ const { title, subtitle, pretitle } = Astro.props;
{subtitle && <span id="subtitle">{subtitle}</span>} {subtitle && <span id="subtitle">{subtitle}</span>}
</h1> </h1>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
h1 { h1 {

View File

@ -17,18 +17,14 @@ const twitterLabel = `${t("footer.socials.twitter.title")} - ${t(
"footer.socials.twitter.subtitle" "footer.socials.twitter.subtitle"
)}`; )}`;
const githubLabel = `${t("footer.socials.github.title")} - ${t( const githubLabel = `${t("footer.socials.github.title")} - ${t("footer.socials.github.subtitle")}`;
"footer.socials.github.subtitle"
)}`;
const contactLabel = `${t("footer.socials.contact.title")} - ${t( const contactLabel = `${t("footer.socials.contact.title")} - ${t(
"footer.socials.contact.subtitle" "footer.socials.contact.subtitle"
)}`; )}`;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<footer> <footer>
{ {
@ -80,8 +76,7 @@ const contactLabel = `${t("footer.socials.contact.title")} - ${t(
id="common-creative" id="common-creative"
aria-label={t("footer.license.icons.tooltip")} aria-label={t("footer.license.icons.tooltip")}
title={t("footer.license.icons.tooltip")} title={t("footer.license.icons.tooltip")}
class="pressable-icon" class="pressable-icon">
>
<Icon name="creative-commons-brands" /> <Icon name="creative-commons-brands" />
<Icon name="creative-commons-by-brands" /> <Icon name="creative-commons-by-brands" />
<Icon name="creative-commons-sa-brands" /> <Icon name="creative-commons-sa-brands" />
@ -91,37 +86,25 @@ const contactLabel = `${t("footer.socials.contact.title")} - ${t(
{ {
withLinks && ( withLinks && (
<div id="socials" class="when-no-print"> <div id="socials" class="when-no-print">
<a <a href="/discord" class="pressable-icon" aria-label={discordLabel} title={discordLabel}>
href="/discord"
class="pressable-icon"
aria-label={discordLabel}
title={discordLabel}
>
<Icon name="discord-brands" /> <Icon name="discord-brands" />
</a> </a>
<a <a
href="https://twitter.com/AccordsLibrary" href="https://twitter.com/AccordsLibrary"
class="pressable-icon" class="pressable-icon"
aria-label={twitterLabel} aria-label={twitterLabel}
title={twitterLabel} title={twitterLabel}>
>
<Icon name="x-brands" /> <Icon name="x-brands" />
</a> </a>
<a <a
href="https://github.com/Accords-Library" href="https://github.com/Accords-Library"
class="pressable-icon" class="pressable-icon"
aria-label={githubLabel} aria-label={githubLabel}
title={githubLabel} title={githubLabel}>
>
<Icon name="github-brands" /> <Icon name="github-brands" />
</a> </a>
<a <a href="/contact" class="pressable-icon" aria-label={contactLabel} title={contactLabel}>
href="/contact"
class="pressable-icon"
aria-label={contactLabel}
title={contactLabel}
>
<Icon name="material-symbols:mail-outline" /> <Icon name="material-symbols:mail-outline" />
</a> </a>
</div> </div>
@ -131,9 +114,7 @@ const contactLabel = `${t("footer.socials.contact.title")} - ${t(
<div id="copyright" set:html={t("footer.disclaimer")} /> <div id="copyright" set:html={t("footer.disclaimer")} />
</footer> </footer>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
footer { footer {

View File

@ -27,24 +27,15 @@ const { currentTheme } = Astro.locals;
"light-theme": currentTheme === "light", "light-theme": currentTheme === "light",
"dark-theme": currentTheme === "dark", "dark-theme": currentTheme === "dark",
"texture-dots": !isIOS, "texture-dots": !isIOS,
}} }}>
>
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<title>{title}</title> <title>{title}</title>
<link rel="icon" type="image/svg+xml" href="/favicon.ico" /> <link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<link rel="stylesheet" href="/css/tippy.css" /> <link rel="stylesheet" href="/css/tippy.css" />
<meta <meta name="theme-color" media="(prefers-color-scheme: light)" content="#fdebd4" />
name="theme-color" <meta name="theme-color" media="(prefers-color-scheme: dark)" content="#27231e" />
media="(prefers-color-scheme: light)"
content="#fdebd4"
/>
<meta
name="theme-color"
media="(prefers-color-scheme: dark)"
content="#27231e"
/>
<link rel="manifest" href="/site.webmanifest" /> <link rel="manifest" href="/site.webmanifest" />
<style is:global> <style is:global>
@ -71,9 +62,7 @@ const { currentTheme } = Astro.locals;
</body> </body>
</html> </html>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style is:global> <style is:global>
html { html {
@ -368,8 +357,7 @@ const { currentTheme } = Astro.locals;
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
transition-duration: 250ms; transition-duration: 250ms;
transition-property: padding-top, box-shadow, background-color, color, transition-property: padding-top, box-shadow, background-color, color, border-color, translate;
border-color, translate;
&:hover { &:hover {
--foreground-color: var(--color-base-1000); --foreground-color: var(--color-base-1000);

View File

@ -18,9 +18,7 @@ const { parentPages = [], hideHomeButton = false } = Astro.props;
const { t, getLocalizedUrl } = await getI18n(Astro.locals.currentLocale); const { t, getLocalizedUrl } = await getI18n(Astro.locals.currentLocale);
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<nav id="topbar" class="when-no-print"> <nav id="topbar" class="when-no-print">
{ {
@ -31,19 +29,14 @@ const { t, getLocalizedUrl } = await getI18n(Astro.locals.currentLocale);
<p>{t("home.title")}</p> <p>{t("home.title")}</p>
</a> </a>
{parentPages.length > 0 && ( {parentPages.length > 0 && <ParentPagesButton parentPages={parentPages} />}
<ParentPagesButton parentPages={parentPages} />
)}
</div> </div>
) )
} }
<div id="toolbar" class="hide-scrollbar"> <div id="toolbar" class="hide-scrollbar">
<a href={getLocalizedUrl("/search")}> <a href={getLocalizedUrl("/search")}>
<Button <Button icon="material-symbols:search" ariaLabel={t("header.topbar.search.tooltip")} />
icon="material-symbols:search"
ariaLabel={t("header.topbar.search.tooltip")}
/>
</a> </a>
<div class="separator"></div> <div class="separator"></div>
@ -68,9 +61,7 @@ const { t, getLocalizedUrl } = await getI18n(Astro.locals.currentLocale);
</div> </div>
</nav> </nav>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
nav { nav {

View File

@ -16,9 +16,7 @@ const { t } = await getI18n(Astro.locals.currentLocale);
const { currentCurrency } = Astro.locals; const { currentCurrency } = Astro.locals;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<Tooltip trigger="click" class={className}> <Tooltip trigger="click" class={className}>
<div id="content" slot="tooltip-content"> <div id="content" slot="tooltip-content">
@ -27,8 +25,7 @@ const { currentCurrency } = Astro.locals;
<a <a
class:list={{ current: currentCurrency === id }} class:list={{ current: currentCurrency === id }}
href={`?action-currency=${id}`} href={`?action-currency=${id}`}
data-astro-prefetch="tap" data-astro-prefetch="tap">
>
{`${id} (${formatCurrency(id)})`} {`${id} (${formatCurrency(id)})`}
</a> </a>
)) ))
@ -41,9 +38,7 @@ const { currentCurrency } = Astro.locals;
/> />
</Tooltip> </Tooltip>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
#content { #content {

View File

@ -16,9 +16,7 @@ const { currentLocale } = Astro.locals;
const { t } = await getI18n(currentLocale); const { t } = await getI18n(currentLocale);
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<Tooltip trigger="click" class={className}> <Tooltip trigger="click" class={className}>
<div id="content" slot="tooltip-content"> <div id="content" slot="tooltip-content">
@ -27,8 +25,7 @@ const { t } = await getI18n(currentLocale);
<a <a
class:list={{ current: currentLocale === id }} class:list={{ current: currentLocale === id }}
href={`?action-lang=${id}`} href={`?action-lang=${id}`}
data-astro-prefetch="tap" data-astro-prefetch="tap">
>
{formatLocale(id)} {formatLocale(id)}
</a> </a>
)) ))
@ -41,9 +38,7 @@ const { t } = await getI18n(currentLocale);
/> />
</Tooltip> </Tooltip>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
#content { #content {

View File

@ -7,9 +7,7 @@ interface Props {
} }
const { parentPage } = Astro.props; const { parentPage } = Astro.props;
const { getLocalizedMatch, getLocalizedUrl } = await getI18n( const { getLocalizedMatch, getLocalizedUrl } = await getI18n(Astro.locals.currentLocale);
Astro.locals.currentLocale
);
const translation = getLocalizedMatch(parentPage.translations); const translation = getLocalizedMatch(parentPage.translations);
@ -24,15 +22,11 @@ switch (parentPage.collection) {
} }
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<a href={href}><span>{parentPage.tag}</span>{translation.name}</a> <a href={href}><span>{parentPage.tag}</span>{translation.name}</a>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
a { a {

View File

@ -14,18 +14,12 @@ const { parentPages } = Astro.props;
const { t } = await getI18n(Astro.locals.currentLocale); const { t } = await getI18n(Astro.locals.currentLocale);
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<Tooltip trigger="click"> <Tooltip trigger="click">
<div id="tooltip-content" slot="tooltip-content"> <div id="tooltip-content" slot="tooltip-content">
<p>This content is part of these pages:</p> <p>This content is part of these pages:</p>
{ {parentPages.map((parentPage) => <ParentPageLink parentPage={parentPage} />)}
parentPages.map((parentPage) => (
<ParentPageLink parentPage={parentPage} />
))
}
</div> </div>
<div class="pressable-label"> <div class="pressable-label">
<Icon name="material-symbols:keyboard-return" /> <Icon name="material-symbols:keyboard-return" />
@ -39,9 +33,7 @@ const { t } = await getI18n(Astro.locals.currentLocale);
</div> </div>
</Tooltip> </Tooltip>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
#tooltip-content { #tooltip-content {

View File

@ -7,24 +7,19 @@ const { currentLocale, currentTheme } = Astro.locals;
const { t } = await getI18n(currentLocale); const { t } = await getI18n(currentLocale);
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<Tooltip trigger="click"> <Tooltip trigger="click">
<div id="content" slot="tooltip-content"> <div id="content" slot="tooltip-content">
<a <a class:list={{ current: currentTheme === "dark" }} href="?action-theme=dark">
class:list={{ current: currentTheme === "dark" }} {t("global.theme.dark")}
href="?action-theme=dark">{t("global.theme.dark")}</a </a>
> <a class:list={{ current: currentTheme === "auto" }} href="?action-theme=auto">
<a {t("global.theme.auto")}
class:list={{ current: currentTheme === "auto" }} </a>
href="?action-theme=auto">{t("global.theme.auto")}</a <a class:list={{ current: currentTheme === "light" }} href="?action-theme=light">
> {t("global.theme.light")}
<a </a>
class:list={{ current: currentTheme === "light" }}
href="?action-theme=light">{t("global.theme.light")}</a
>
</div> </div>
<Button <Button
class="when-light-theme" class="when-light-theme"
@ -38,9 +33,7 @@ const { t } = await getI18n(currentLocale);
/> />
</Tooltip> </Tooltip>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
#content { #content {

View File

@ -18,9 +18,7 @@ interface Props {
const { block } = Astro.props; const { block } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
{ {
isBlockLineBlock(block) ? ( isBlockLineBlock(block) ? (

View File

@ -9,17 +9,13 @@ interface Props {
const { block } = Astro.props; const { block } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<div> <div>
<RichText content={block.content} /> <RichText content={block.content} />
</div> </div>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
div { div {

View File

@ -9,9 +9,7 @@ interface Props {
const { block } = Astro.props; const { block } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<div id="line"> <div id="line">
<p>{block.blockName}</p> <p>{block.blockName}</p>
@ -20,9 +18,7 @@ const { block } = Astro.props;
</div> </div>
</div> </div>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
#line { #line {

View File

@ -4,34 +4,26 @@ import { Icon } from "astro-icon/components";
interface Props { interface Props {
id?: string; id?: string;
title?: string | undefined; title?: string | undefined;
icon?: string | string[]; icon?: string;
class?: string; class?: string;
ariaLabel?: string; ariaLabel?: string;
} }
const { title, icon, class: className, ariaLabel, id } = Astro.props; const { title, icon, class: className, ariaLabel, id } = Astro.props;
const icons =
icon === undefined ? [] : typeof icon === "string" ? [icon] : icon;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<button <button
id={id} id={id}
class:list={["pressable", "high-contrast-text", { "with-title": !!title }, className]} class:list={["pressable", "high-contrast-text", { "with-title": !!title }, className]}
aria-label={ariaLabel} aria-label={ariaLabel}
title={ariaLabel} title={ariaLabel}>
> {icon && <Icon name={icon} />}
{icons.map((cIcon) => <Icon name={cIcon} />)}
{title} {title}
</button> </button>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
button { button {
@ -52,8 +44,7 @@ const icons =
cursor: pointer; cursor: pointer;
transition-duration: 250ms; transition-duration: 250ms;
transition-property: padding-top, box-shadow, background-color, color, transition-property: padding-top, box-shadow, background-color, color, border-color;
border-color;
&.with-title > svg { &.with-title > svg {
width: 1.2em; width: 1.2em;

View File

@ -7,9 +7,7 @@ interface Props {
const { wrapper: Wrapper, condition } = Astro.props; const { wrapper: Wrapper, condition } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
{ {
condition ? ( condition ? (

View File

@ -11,9 +11,7 @@ interface Props {
const { translators = [], transcribers = [], proofreaders = [] } = Astro.props; const { translators = [], transcribers = [], proofreaders = [] } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<Metadata <Metadata
icon="material-symbols:person-outline" icon="material-symbols:person-outline"

View File

@ -13,24 +13,16 @@ interface Props {
const { currentLang, getPartialUrl, availableLanguages } = Astro.props; const { currentLang, getPartialUrl, availableLanguages } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<div id="lang-selector" class="when-js when-no-print"> <div id="lang-selector" class="when-js when-no-print">
<Tooltip trigger="click"> <Tooltip trigger="click">
<Button <Button icon="material-symbols:translate" title={currentLang.toUpperCase()} />
icon="material-symbols:translate"
title={currentLang.toUpperCase()}
/>
<div id="tooltip-content" slot="tooltip-content"> <div id="tooltip-content" slot="tooltip-content">
{ {
availableLanguages.map((id) => ( availableLanguages.map((id) => (
<MasoActor <MasoActor class:list={{ current: id === currentLang }} href={getPartialUrl(id)}>
class:list={{ current: id === currentLang }}
href={getPartialUrl(id)}
>
{formatLocale(id)} {formatLocale(id)}
</MasoActor> </MasoActor>
)) ))
@ -42,9 +34,7 @@ const { currentLang, getPartialUrl, availableLanguages } = Astro.props;
</p> </p>
</div> </div>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
#lang-selector { #lang-selector {

View File

@ -9,17 +9,13 @@ interface Props {
const { href, method = "get", class: className, id } = Astro.props; const { href, method = "get", class: className, id } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<maso-actor href={href} method={method} class={className} id={id}> <maso-actor href={href} method={method} class={className} id={id}>
<slot /> <slot />
</maso-actor> </maso-actor>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
maso-actor { maso-actor {
@ -27,9 +23,7 @@ const { href, method = "get", class: className, id } = Astro.props;
} }
</style> </style>
{ {/* ------------------------------------------- JS --------------------------------------------- */}
/* ------------------------------------------- JS --------------------------------------------- */
}
<script> <script>
import { customElement } from "src/utils/customElements"; import { customElement } from "src/utils/customElements";

View File

@ -1,14 +1,10 @@
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<maso-target> <maso-target>
<slot /> <slot />
</maso-target> </maso-target>
{ {/* ------------------------------------------- JS --------------------------------------------- */}
/* ------------------------------------------- JS --------------------------------------------- */
}
<script> <script>
import { customElement } from "src/utils/customElements"; import { customElement } from "src/utils/customElements";

View File

@ -12,9 +12,7 @@ const { icon, title, values } = Astro.props;
if (values.length === 0) return; if (values.length === 0) return;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<div id="container"> <div id="container">
<div id="title"> <div id="title">
@ -26,9 +24,7 @@ if (values.length === 0) return;
</div> </div>
</div> </div>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
#container { #container {

View File

@ -13,14 +13,8 @@ interface Props {
const { content, context = defaultContext } = Astro.props; const { content, context = defaultContext } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<ConditionalWrapper condition={context.depth === 1} wrapper={RTProse}> <ConditionalWrapper condition={context.depth === 1} wrapper={RTProse}>
{ {content.root.children.map((node) => <RTNode node={node} context={context} />)}
content.root.children.map((node) => (
<RTNode node={node} context={context} />
))
}
</ConditionalWrapper> </ConditionalWrapper>

View File

@ -24,10 +24,10 @@ const { node, context } = Astro.props;
<RTSection node={node} context={context} /> <RTSection node={node} context={context} />
) : isBlockNodeTranscriptBlock(node) ? ( ) : isBlockNodeTranscriptBlock(node) ? (
<RTTranscript node={node} context={context} /> <RTTranscript node={node} context={context} />
) :isBlockNodeSpacerBlock(node) ? ( ) : isBlockNodeSpacerBlock(node) ? (
<RTSpacer node={node} context={context} /> <RTSpacer node={node} context={context} />
) : ( ) : (
<ErrorMessage <ErrorMessage
title={`Unknown block type: ${node.fields.blockType}`} title={`Unknown block type: ${node.fields.blockType}`}
description="Please contact website technical administrator." description="Please contact website technical administrator."
/> />

View File

@ -1,8 +1,6 @@
--- ---
import RichText from "components/RichText/RichText.astro"; import RichText from "components/RichText/RichText.astro";
import type { import type { RichTextSectionBlock } from "src/shared/payload/payload-sdk";
RichTextSectionBlock,
} from "src/shared/payload/payload-sdk";
import type { RichTextContext } from "src/utils/richText"; import type { RichTextContext } from "src/utils/richText";
interface Props { interface Props {
@ -42,10 +40,7 @@ const { node, context } = Astro.props;
) )
} }
<RichText <RichText content={node.fields.content} context={{ ...context, depth: context.depth + 1 }} />
content={node.fields.content}
context={{ ...context, depth: context.depth + 1 }}
/>
<style> <style>
span { span {

View File

@ -10,7 +10,6 @@ const { href, newTab } = Astro.props;
<a <a
href={href} href={href}
target={newTab ? "_blank" : undefined} target={newTab ? "_blank" : undefined}
rel={newTab ? "noopener noreferrer" : undefined} rel={newTab ? "noopener noreferrer" : undefined}>
>
<slot /> <slot />
</a> </a>

View File

@ -22,9 +22,7 @@ const { node, context } = Astro.props;
<li> <li>
<Icon <Icon
name={node.checked name={node.checked ? "material-symbols:check-box" : "material-symbols:check-box-outline-blank"}
? "material-symbols:check-box"
: "material-symbols:check-box-outline-blank"}
/> />
{node.children.map((node) => <RTNode node={node} context={context} />)} {node.children.map((node) => <RTNode node={node} context={context} />)}
</li> </li>

View File

@ -25,9 +25,7 @@ interface Props {
const { node, context } = Astro.props; const { node, context } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
{ {
isNodeParagraphNode(node) ? ( isNodeParagraphNode(node) ? (

View File

@ -11,9 +11,7 @@ interface Props {
const { node, context } = Astro.props; const { node, context } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
{ {
node.children.length > 0 && ( node.children.length > 0 && (

View File

@ -1,4 +1,5 @@
--- ---
---
{""} ---
&#8197;

View File

@ -20,26 +20,11 @@ const { node } = Astro.props;
<ConditionalWrapper wrapper={RTBold} condition={Boolean(node.format & 1)}> <ConditionalWrapper wrapper={RTBold} condition={Boolean(node.format & 1)}>
<ConditionalWrapper wrapper={RTItalic} condition={Boolean(node.format & 2)}> <ConditionalWrapper wrapper={RTItalic} condition={Boolean(node.format & 2)}>
<ConditionalWrapper <ConditionalWrapper wrapper={RTLineThrough} condition={Boolean(node.format & 4)}>
wrapper={RTLineThrough} <ConditionalWrapper wrapper={RTUnderline} condition={Boolean(node.format & 8)}>
condition={Boolean(node.format & 4)} <ConditionalWrapper wrapper={RTInlineCode} condition={Boolean(node.format & 16)}>
> <ConditionalWrapper wrapper={RTSubscript} condition={Boolean(node.format & 32)}>
<ConditionalWrapper <ConditionalWrapper wrapper={RTSuperscript} condition={Boolean(node.format & 64)}>
wrapper={RTUnderline}
condition={Boolean(node.format & 8)}
>
<ConditionalWrapper
wrapper={RTInlineCode}
condition={Boolean(node.format & 16)}
>
<ConditionalWrapper
wrapper={RTSubscript}
condition={Boolean(node.format & 32)}
>
<ConditionalWrapper
wrapper={RTSuperscript}
condition={Boolean(node.format & 64)}
>
{node.text} {node.text}
</ConditionalWrapper> </ConditionalWrapper>
</ConditionalWrapper> </ConditionalWrapper>

View File

@ -5,8 +5,7 @@
<span><slot /></span> <span><slot /></span>
<style> <style>
span { span {
font-family: monospace; font-family: monospace;
} }
</style> </style>

View File

@ -10,9 +10,7 @@ interface Props {
const { toc } = Astro.props; const { toc } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<div id="container"> <div id="container">
<div id="title"> <div id="title">
@ -24,9 +22,7 @@ const { toc } = Astro.props;
</ol> </ol>
</div> </div>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
#container { #container {

View File

@ -8,9 +8,7 @@ interface Props {
const { entry } = Astro.props; const { entry } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<li data-prefix={entry.prefix}> <li data-prefix={entry.prefix}>
<a href={`#${entry.prefix}`}>{entry.title}</a> <a href={`#${entry.prefix}`}>{entry.title}</a>
@ -25,9 +23,7 @@ const { entry } = Astro.props;
} }
</li> </li>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
a { a {

View File

@ -9,17 +9,9 @@ interface Props {
} }
const { icon, slug, values } = Astro.props; const { icon, slug, values } = Astro.props;
const { formatTag, formatTagsGroup } = await getI18n( const { formatTag, formatTagsGroup } = await getI18n(Astro.locals.currentLocale);
Astro.locals.currentLocale
);
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<Metadata <Metadata icon={icon} title={formatTagsGroup(slug)} values={values.map(formatTag)} />
icon={icon}
title={formatTagsGroup(slug)}
values={values.map(formatTag)}
/>

View File

@ -8,15 +8,11 @@ interface Props {
const { tagGroups } = Astro.props; const { tagGroups } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<div>{tagGroups.map((tag) => <TagGroup {...tag} />)}</div> <div>{tagGroups.map((tag) => <TagGroup {...tag} />)}</div>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
div { div {

View File

@ -7,18 +7,14 @@ interface Props {
const { class: className, trigger } = Astro.props; const { class: className, trigger } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<tippy-tooltip class={className} trigger={trigger}> <tippy-tooltip class={className} trigger={trigger}>
<template><slot name="tooltip-content" /></template> <template><slot name="tooltip-content" /></template>
<slot /> <slot />
</tippy-tooltip> </tippy-tooltip>
{ {/* ------------------------------------------- JS --------------------------------------------- */}
/* ------------------------------------------- JS --------------------------------------------- */
}
<script> <script>
import tippy from "tippy.js"; import tippy from "tippy.js";

9
src/env.d.ts vendored
View File

@ -1,11 +1,10 @@
/// <reference path="../.astro/types.d.ts" /> /// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" /> /// <reference types="astro/client" />
declare namespace App { declare namespace App {
interface Locals { interface Locals {
currentLocale: string currentLocale: string;
currentTheme: "dark" | "auto" | "light" currentTheme: "dark" | "auto" | "light";
currentCurrency: string currentCurrency: string;
} }
} }

View File

@ -9,9 +9,7 @@ export const getI18n = async (locale: string) => {
template: string, template: string,
values: Record<string, any> values: Record<string, any>
): string => { ): string => {
const limitMatchToBalanceCurlyBraces = ( const limitMatchToBalanceCurlyBraces = (matchArray: RegExpMatchArray): string => {
matchArray: RegExpMatchArray
): string => {
// Cut match as soon as curly braces are balanced. // Cut match as soon as curly braces are balanced.
const match = matchArray[0]; const match = matchArray[0];
let curlyCount = 2; let curlyCount = 2;
@ -29,9 +27,7 @@ export const getI18n = async (locale: string) => {
}; };
Object.entries(values).forEach(([key, value]) => { Object.entries(values).forEach(([key, value]) => {
if ( if (!template.match(new RegExp(`{{ ${key}\\+|{{ ${key}\\?|{{ ${key} }}`))) {
!template.match(new RegExp(`{{ ${key}\\+|{{ ${key}\\?|{{ ${key} }}`))
) {
console.warn( console.warn(
"Value", "Value",
key, key,
@ -44,9 +40,7 @@ export const getI18n = async (locale: string) => {
if (typeof value === "number") { if (typeof value === "number") {
// Find "plural" tokens // Find "plural" tokens
const matches = [ const matches = [
...template.matchAll( ...template.matchAll(new RegExp(`{{ ${key}\\+,[\\w\\s=>{},]+ }}`, "g")),
new RegExp(`{{ ${key}\\+,[\\w\\s=>{},]+ }}`, "g")
),
].map(limitMatchToBalanceCurlyBraces); ].map(limitMatchToBalanceCurlyBraces);
const handlePlural = (match: string): string => { const handlePlural = (match: string): string => {
@ -59,23 +53,17 @@ export const getI18n = async (locale: string) => {
if (!optionValue) continue; if (!optionValue) continue;
optionValue = optionValue.substring(0, optionValue.length - 1); optionValue = optionValue.substring(0, optionValue.length - 1);
if (option.startsWith("=")) { if (option.startsWith("=")) {
const optionConditionValue = Number.parseInt( const optionConditionValue = Number.parseInt(optionCondition.substring(1));
optionCondition.substring(1)
);
if (value === optionConditionValue) { if (value === optionConditionValue) {
return optionValue; return optionValue;
} }
} else if (option.startsWith(">")) { } else if (option.startsWith(">")) {
const optionConditionValue = Number.parseInt( const optionConditionValue = Number.parseInt(optionCondition.substring(1));
optionCondition.substring(1)
);
if (value > optionConditionValue) { if (value > optionConditionValue) {
return optionValue; return optionValue;
} }
} else if (option.startsWith("<")) { } else if (option.startsWith("<")) {
const optionConditionValue = Number.parseInt( const optionConditionValue = Number.parseInt(optionCondition.substring(1));
optionCondition.substring(1)
);
if (value < optionConditionValue) { if (value < optionConditionValue) {
return optionValue; return optionValue;
} }
@ -90,9 +78,9 @@ export const getI18n = async (locale: string) => {
} }
// Find "conditional" tokens // Find "conditional" tokens
const matches = [ const matches = [...template.matchAll(new RegExp(`{{ ${key}\\?,[\\w\\s{},]+ }}`, "g"))].map(
...template.matchAll(new RegExp(`{{ ${key}\\?,[\\w\\s{},]+ }}`, "g")), limitMatchToBalanceCurlyBraces
].map(limitMatchToBalanceCurlyBraces); );
const handleConditional = (match: string): string => { const handleConditional = (match: string): string => {
match = match.substring(3, match.length - 3); match = match.substring(3, match.length - 3);

View File

@ -5,13 +5,9 @@ import type { AstroCookies } from "astro";
import { z } from "astro:content"; import { z } from "astro:content";
import { defaultLocale } from "src/i18n/i18n"; import { defaultLocale } from "src/i18n/i18n";
const getAbsoluteLocaleUrl = (locale: string, url: string) => const getAbsoluteLocaleUrl = (locale: string, url: string) => `/${locale}${url}`;
`/${locale}${url}`;
const redirect = ( const redirect = (redirectURL: string, headers: Record<string, string> = {}): Response => {
redirectURL: string,
headers: Record<string, string> = {}
): Response => {
return new Response(undefined, { return new Response(undefined, {
headers: { ...headers, Location: redirectURL }, headers: { ...headers, Location: redirectURL },
status: 302, status: 302,
@ -29,8 +25,7 @@ const localeNegotiator = defineMiddleware(({ cookies, url, request }, next) => {
const currentLocale = getCurrentLocale(url.pathname); const currentLocale = getCurrentLocale(url.pathname);
const acceptedLocale = getBestAcceptedLanguage(request); const acceptedLocale = getBestAcceptedLanguage(request);
const cookieLocale = getCookieLocale(cookies); const cookieLocale = getCookieLocale(cookies);
const bestMatchingLocale = const bestMatchingLocale = cookieLocale ?? acceptedLocale ?? currentLocale ?? defaultLocale;
cookieLocale ?? acceptedLocale ?? currentLocale ?? defaultLocale;
if (!currentLocale) { if (!currentLocale) {
const redirectURL = getAbsoluteLocaleUrl(bestMatchingLocale, url.pathname); const redirectURL = getAbsoluteLocaleUrl(bestMatchingLocale, url.pathname);
@ -38,13 +33,8 @@ const localeNegotiator = defineMiddleware(({ cookies, url, request }, next) => {
} }
if (currentLocale !== bestMatchingLocale) { if (currentLocale !== bestMatchingLocale) {
const pathnameWithoutLocale = url.pathname.substring( const pathnameWithoutLocale = url.pathname.substring(currentLocale.length + 1);
currentLocale.length + 1 const redirectURL = getAbsoluteLocaleUrl(bestMatchingLocale, pathnameWithoutLocale);
);
const redirectURL = getAbsoluteLocaleUrl(
bestMatchingLocale,
pathnameWithoutLocale
);
return redirect(redirectURL); return redirect(redirectURL);
} }
@ -60,18 +50,14 @@ const handleActionsSearchParams = defineMiddleware(async ({ url }, next) => {
: url.pathname; : url.pathname;
const redirectURL = getAbsoluteLocaleUrl(actionLang, pathnameWithoutLocale); const redirectURL = getAbsoluteLocaleUrl(actionLang, pathnameWithoutLocale);
return redirect(redirectURL, { return redirect(redirectURL, {
"Set-Cookie": `${CookieKeys.Languages}=${JSON.stringify([ "Set-Cookie": `${CookieKeys.Languages}=${JSON.stringify([actionLang])}; Path=/`,
actionLang,
])}; Path=/`,
}); });
} }
const actionCurrency = url.searchParams.get("action-currency"); const actionCurrency = url.searchParams.get("action-currency");
if (isValidCurrency(actionCurrency)) { if (isValidCurrency(actionCurrency)) {
return redirect(url.pathname, { return redirect(url.pathname, {
"Set-Cookie": `${CookieKeys.Currency}=${JSON.stringify( "Set-Cookie": `${CookieKeys.Currency}=${JSON.stringify(actionCurrency)}; Path=/`,
actionCurrency
)}; Path=/`,
}); });
} }
@ -81,9 +67,7 @@ const handleActionsSearchParams = defineMiddleware(async ({ url }, next) => {
url.searchParams.delete("action-theme"); url.searchParams.delete("action-theme");
if (verifiedActionTheme.data === "auto") { if (verifiedActionTheme.data === "auto") {
return redirect(url.pathname, { return redirect(url.pathname, {
"Set-Cookie": `${CookieKeys.Theme}=; Path=/; Expires=${new Date( "Set-Cookie": `${CookieKeys.Theme}=; Path=/; Expires=${new Date(0).toUTCString()}`,
0
).toUTCString()}`,
}); });
} }
return redirect(url.pathname, { return redirect(url.pathname, {
@ -94,26 +78,22 @@ const handleActionsSearchParams = defineMiddleware(async ({ url }, next) => {
return next(); return next();
}); });
const addContentLanguageResponseHeader = defineMiddleware( const addContentLanguageResponseHeader = defineMiddleware(async ({ url }, next) => {
async ({ url }, next) => { const currentLocale = getCurrentLocale(url.pathname);
const currentLocale = getCurrentLocale(url.pathname);
const response = await next(); const response = await next();
if (response.status === 200 && currentLocale) { if (response.status === 200 && currentLocale) {
response.headers.set("Content-Language", currentLocale); response.headers.set("Content-Language", currentLocale);
}
return response;
} }
); return response;
});
const provideLocalsToRequest = defineMiddleware( const provideLocalsToRequest = defineMiddleware(async ({ url, locals, cookies }, next) => {
async ({ url, locals, cookies }, next) => { locals.currentLocale = getCurrentLocale(url.pathname) ?? "en";
locals.currentLocale = getCurrentLocale(url.pathname) ?? "en"; locals.currentCurrency = getCookieCurrency(cookies) ?? "USD";
locals.currentCurrency = getCookieCurrency(cookies) ?? "USD"; locals.currentTheme = getCookieTheme(cookies) ?? "auto";
locals.currentTheme = getCookieTheme(cookies) ?? "auto"; return next();
return next(); });
}
);
export const onRequest = sequence( export const onRequest = sequence(
addContentLanguageResponseHeader, addContentLanguageResponseHeader,
@ -139,9 +119,7 @@ const getBestAcceptedLanguage = (request: Request): string | undefined => {
acceptLanguage.languages(cache.locales.map(({ id }) => id)); acceptLanguage.languages(cache.locales.map(({ id }) => id));
return ( return acceptLanguage.get(request.headers.get("Accept-Language")) ?? undefined;
acceptLanguage.get(request.headers.get("Accept-Language")) ?? undefined
);
}; };
/* COOKIES */ /* COOKIES */
@ -170,31 +148,19 @@ export const getCookieLocale = (cookies: AstroCookies): string | undefined => {
return undefined; return undefined;
}; };
export const getCookieCurrency = ( export const getCookieCurrency = (cookies: AstroCookies): string | undefined => {
cookies: AstroCookies
): string | undefined => {
const cookieValue = cookies.get(CookieKeys.Currency)?.value; const cookieValue = cookies.get(CookieKeys.Currency)?.value;
return isValidCurrency(cookieValue) ? cookieValue : undefined; return isValidCurrency(cookieValue) ? cookieValue : undefined;
}; };
export const getCookieTheme = ( export const getCookieTheme = (cookies: AstroCookies): z.infer<typeof themeSchema> | undefined => {
cookies: AstroCookies
): z.infer<typeof themeSchema> | undefined => {
const cookieValue = cookies.get(CookieKeys.Theme)?.value; const cookieValue = cookies.get(CookieKeys.Theme)?.value;
const result = themeSchema.safeParse(cookieValue); const result = themeSchema.safeParse(cookieValue);
return result.success ? result.data : undefined; return result.success ? result.data : undefined;
}; };
export const isValidCurrency = ( export const isValidCurrency = (currency: string | null | undefined): currency is string =>
currency: string | null | undefined currency !== null && currency != undefined && cache.currencies.includes(currency);
): currency is string =>
currency !== null &&
currency != undefined &&
cache.currencies.includes(currency);
export const isValidLocale = ( export const isValidLocale = (locale: string | null | undefined): locale is string =>
locale: string | null | undefined locale !== null && locale != undefined && cache.locales.map(({ id }) => id).includes(locale);
): locale is string =>
locale !== null &&
locale != undefined &&
cache.locales.map(({ id }) => id).includes(locale);

View File

@ -2,8 +2,6 @@
import AppLayout from "components/AppLayout/AppLayout.astro"; import AppLayout from "components/AppLayout/AppLayout.astro";
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<AppLayout title="Oh nyo..." /> <AppLayout title="Oh nyo..." />

View File

@ -8,9 +8,7 @@ interface Props {
const { img, name, href } = Astro.props; const { img, name, href } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<a href={href} aria-label={name} class="pressable"> <a href={href} aria-label={name} class="pressable">
{ {
@ -27,9 +25,7 @@ const { img, name, href } = Astro.props;
} }
</a> </a>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
a { a {

View File

@ -9,9 +9,7 @@ interface Props {
const { pretitle, subtitle, title, href } = Astro.props; const { pretitle, subtitle, title, href } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<a href={href} class="pressable"> <a href={href} class="pressable">
<p class="pretitle">{pretitle}</p> <p class="pretitle">{pretitle}</p>
@ -19,9 +17,7 @@ const { pretitle, subtitle, title, href } = Astro.props;
<p>{subtitle}</p> <p>{subtitle}</p>
</a> </a>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
a { a {

View File

@ -4,14 +4,10 @@ import CategoryCard from "./CategoryCard.astro";
import { getI18n } from "src/i18n/i18n"; import { getI18n } from "src/i18n/i18n";
const folders = await payload.getRootFolders(); const folders = await payload.getRootFolders();
const { getLocalizedUrl, getLocalizedMatch } = await getI18n( const { getLocalizedUrl, getLocalizedMatch } = await getI18n(Astro.locals.currentLocale);
Astro.locals.currentLocale
);
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
{ {
folders.map(({ slug, translations, darkThumbnail, lightThumbnail }) => ( folders.map(({ slug, translations, darkThumbnail, lightThumbnail }) => (

View File

@ -10,9 +10,7 @@ interface Props {
const { icon, subtitle, title, href } = Astro.props; const { icon, subtitle, title, href } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<a href={href} class="pressable"> <a href={href} class="pressable">
<Icon name={icon} /> <Icon name={icon} />
@ -22,9 +20,7 @@ const { icon, subtitle, title, href } = Astro.props;
</div> </div>
</a> </a>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
a { a {

View File

@ -2,8 +2,6 @@
import AppLayout from "components/AppLayout/AppLayout.astro"; import AppLayout from "components/AppLayout/AppLayout.astro";
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<AppLayout title="WIP" /> <AppLayout title="WIP" />

View File

@ -28,9 +28,7 @@ const { getLocalizedMatch } = await getI18n(lang);
const translation = getLocalizedMatch(page.translations); const translation = getLocalizedMatch(page.translations);
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<MasoTarget> <MasoTarget>
<div id="layout"> <div id="layout">
@ -68,19 +66,14 @@ const translation = getLocalizedMatch(page.translations);
page.translations.length > 1 && ( page.translations.length > 1 && (
<LanguageOverride <LanguageOverride
currentLang={lang} currentLang={lang}
availableLanguages={page.translations.map( availableLanguages={page.translations.map(({ language }) => language)}
({ language }) => language
)}
getPartialUrl={(lang) => getPartialUrl={(lang) =>
getLocalizedUrl(`/api/pages/partial?lang=${lang}&slug=${slug}`) getLocalizedUrl(`/api/pages/partial?lang=${lang}&slug=${slug}`)
} }
/> />
) )
} }
<Credits <Credits translators={translation.translators} proofreaders={translation.proofreaders} />
translators={translation.translators}
proofreaders={translation.proofreaders}
/>
</div> </div>
<div class="when-not-large meta-container"> <div class="when-not-large meta-container">
@ -110,19 +103,14 @@ const translation = getLocalizedMatch(page.translations);
page.translations.length > 1 && ( page.translations.length > 1 && (
<LanguageOverride <LanguageOverride
currentLang={lang} currentLang={lang}
availableLanguages={page.translations.map( availableLanguages={page.translations.map(({ language }) => language)}
({ language }) => language
)}
getPartialUrl={(lang) => getPartialUrl={(lang) =>
getLocalizedUrl(`/api/pages/partial?lang=${lang}&slug=${slug}`) getLocalizedUrl(`/api/pages/partial?lang=${lang}&slug=${slug}`)
} }
/> />
) )
} }
<Credits <Credits translators={translation.translators} proofreaders={translation.proofreaders} />
translators={translation.translators}
proofreaders={translation.proofreaders}
/>
</div> </div>
<TableOfContent toc={translation.toc} /> <TableOfContent toc={translation.toc} />
@ -130,9 +118,7 @@ const translation = getLocalizedMatch(page.translations);
</div> </div>
</MasoTarget> </MasoTarget>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
#layout { #layout {

View File

@ -2,8 +2,6 @@
import AppLayout from "components/AppLayout/AppLayout.astro"; import AppLayout from "components/AppLayout/AppLayout.astro";
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<AppLayout title="WIP" /> <AppLayout title="WIP" />

View File

@ -2,8 +2,6 @@
import AppLayout from "components/AppLayout/AppLayout.astro"; import AppLayout from "components/AppLayout/AppLayout.astro";
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<AppLayout title="WIP" /> <AppLayout title="WIP" />

View File

@ -2,17 +2,18 @@
import AppLayout from "components/AppLayout/AppLayout.astro"; import AppLayout from "components/AppLayout/AppLayout.astro";
--- ---
<AppLayout pretitle="Guide to" title="Rich Text Editor" description="Having troubles using the Rich Text Editor? Looking for tips and advanced techniques? You've come to the right place!"> <AppLayout
pretitle="Guide to"
title="Rich Text Editor"
description="Having troubles using the Rich Text Editor? Looking for tips and advanced techniques? You've come to the right place!">
<div class="prose"> <div class="prose">
<h2>Add indentation / spaces between words</h2> <h2>Add indentation / spaces between words</h2>
<p> <p>
By default, additional spaces are collapsed. This means that if multiple By default, additional spaces are collapsed. This means that if multiple spaces are adjacent,
spaces are adjacent, only one space is preserved. To create spaces that only one space is preserved. To create spaces that will not be collapsed, you can use tabs
will not be collapsed, you can use tabs instead. Simply press the <kbd instead. Simply press the <kbd>Tab</kbd> key a few times on your keyboard to create additional
>Tab</kbd spaces between words. Be mindful of the use of these spaces.
> key a few times on your keyboard to create additional spaces between words.
Be mindful of the use of these spaces.
</p> </p>
</div> </div>
</AppLayout> </AppLayout>

View File

@ -2,8 +2,6 @@
import AppLayout from "components/AppLayout/AppLayout.astro"; import AppLayout from "components/AppLayout/AppLayout.astro";
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<AppLayout title="WIP" /> <AppLayout title="WIP" />

View File

@ -8,9 +8,7 @@ import ErrorMessage from "components/ErrorMessage.astro";
import { getI18n } from "src/i18n/i18n"; import { getI18n } from "src/i18n/i18n";
const { slug } = Astro.params; const { slug } = Astro.params;
const { getLocalizedMatch, getLocalizedUrl } = await getI18n( const { getLocalizedMatch, getLocalizedUrl } = await getI18n(Astro.locals.currentLocale);
Astro.locals.currentLocale
);
const folder = await fetchOr404(() => payload.getFolder(slug!)); const folder = await fetchOr404(() => payload.getFolder(slug!));
if (folder instanceof Response) { if (folder instanceof Response) {
@ -21,9 +19,7 @@ const meta = getLocalizedMatch(folder.translations);
// TODO: handle light and dark illustration for applayout // TODO: handle light and dark illustration for applayout
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<AppLayout title={meta.name}> <AppLayout title={meta.name}>
{ {
@ -63,10 +59,7 @@ const meta = getLocalizedMatch(folder.translations);
case "pages": case "pages":
return ( return (
<a <a class="pressable" href={getLocalizedUrl(`/pages/${value.slug}`)}>
class="pressable"
href={getLocalizedUrl(`/pages/${value.slug}`)}
>
{value.slug} {value.slug}
</a> </a>
); );
@ -85,9 +78,7 @@ const meta = getLocalizedMatch(folder.translations);
</div> </div>
</AppLayout> </AppLayout>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
#main { #main {

View File

@ -9,9 +9,7 @@ interface Props {
const { icon = "material-symbols:folder-outline", title, href } = Astro.props; const { icon = "material-symbols:folder-outline", title, href } = Astro.props;
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<a href={href} class="pressable"> <a href={href} class="pressable">
<Icon name={icon} /> <Icon name={icon} />
@ -20,9 +18,7 @@ const { icon = "material-symbols:folder-outline", title, href } = Astro.props;
</div> </div>
</a> </a>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
a { a {

View File

@ -10,14 +10,10 @@ interface Props {
const { title, folders } = Astro.props; const { title, folders } = Astro.props;
const { getLocalizedUrl, getLocalizedMatch } = await getI18n( const { getLocalizedUrl, getLocalizedMatch } = await getI18n(Astro.locals.currentLocale);
Astro.locals.currentLocale
);
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<div> <div>
{title && <h3>{title}</h3>} {title && <h3>{title}</h3>}
@ -34,9 +30,7 @@ const { getLocalizedUrl, getLocalizedMatch } = await getI18n(
</section> </section>
</div> </div>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
h3 { h3 {

View File

@ -10,16 +10,13 @@ import { getI18n } from "src/i18n/i18n";
const { t, getLocalizedUrl } = await getI18n(Astro.locals.currentLocale); const { t, getLocalizedUrl } = await getI18n(Astro.locals.currentLocale);
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<AppLayout <AppLayout
title="Accords Library" title="Accords Library"
backgroundIllustration="/img/bg-home2.webp" backgroundIllustration="/img/bg-home2.webp"
hideFooterLinks hideFooterLinks
hideHomeButton hideHomeButton>
>
<div id="title" slot="header-title"> <div id="title" slot="header-title">
<Icon name="accords" /> <Icon name="accords" />
<div> <div>
@ -30,10 +27,7 @@ const { t, getLocalizedUrl } = await getI18n(Astro.locals.currentLocale);
<div id="description" slot="header-description"> <div id="description" slot="header-description">
<p set:html={t("home.description")} class="high-contrast-text" /> <p set:html={t("home.description")} class="high-contrast-text" />
<a href={getLocalizedUrl("/about")}> <a href={getLocalizedUrl("/about")}>
<Button <Button title={t("home.aboutUsButton")} icon="material-symbols:left-click" />
title={t("home.aboutUsButton")}
icon="material-symbols:left-click"
/>
</a> </a>
</div> </div>
@ -175,9 +169,7 @@ const { t, getLocalizedUrl } = await getI18n(Astro.locals.currentLocale);
</div> </div>
</AppLayout> </AppLayout>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
#description { #description {

View File

@ -12,13 +12,8 @@ if (page instanceof Response) {
} }
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<AppEmptyLayout <AppEmptyLayout parentPages={page.parentPages} backgroundIllustration={page.thumbnail?.url}>
parentPages={page.parentPages}
backgroundIllustration={page.thumbnail?.url}
>
<Page slug={page.slug} lang={Astro.locals.currentLocale} page={page} /> <Page slug={page.slug} lang={Astro.locals.currentLocale} page={page} />
</AppEmptyLayout> </AppEmptyLayout>

View File

@ -7,9 +7,7 @@ const { currentLocale, currentTheme, currentCurrency } = Astro.locals;
const { t } = await getI18n(currentLocale); const { t } = await getI18n(currentLocale);
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<AppLayout title={t("settings.title")}> <AppLayout title={t("settings.title")}>
<div id="main"> <div id="main">
@ -21,8 +19,7 @@ const { t } = await getI18n(currentLocale);
<a <a
class:list={{ current: currentLocale === id }} class:list={{ current: currentLocale === id }}
href={`?action-lang=${id}`} href={`?action-lang=${id}`}
data-astro-prefetch="tap" data-astro-prefetch="tap">
>
{id} {id}
</a> </a>
)) ))
@ -35,22 +32,19 @@ const { t } = await getI18n(currentLocale);
<a <a
class:list={{ current: currentTheme === "dark" }} class:list={{ current: currentTheme === "dark" }}
href="?action-theme=dark" href="?action-theme=dark"
data-astro-prefetch="tap" data-astro-prefetch="tap">
>
{t("global.theme.dark")} {t("global.theme.dark")}
</a> </a>
<a <a
class:list={{ current: currentTheme === "auto" }} class:list={{ current: currentTheme === "auto" }}
href="?action-theme=auto" href="?action-theme=auto"
data-astro-prefetch="tap" data-astro-prefetch="tap">
>
{t("global.theme.auto")} {t("global.theme.auto")}
</a> </a>
<a <a
class:list={{ current: currentTheme === "light" }} class:list={{ current: currentTheme === "light" }}
href="?action-theme=light" href="?action-theme=light"
data-astro-prefetch="tap" data-astro-prefetch="tap">
>
{t("global.theme.light")} {t("global.theme.light")}
</a> </a>
</div> </div>
@ -63,8 +57,7 @@ const { t } = await getI18n(currentLocale);
<a <a
class:list={{ current: currentCurrency === id }} class:list={{ current: currentCurrency === id }}
href={`?action-currency=${id}`} href={`?action-currency=${id}`}
data-astro-prefetch="tap" data-astro-prefetch="tap">
>
{id} {id}
</a> </a>
)) ))
@ -73,9 +66,7 @@ const { t } = await getI18n(currentLocale);
</div> </div>
</AppLayout> </AppLayout>
{ {/* ------------------------------------------- CSS -------------------------------------------- */}
/* ------------------------------------------- CSS -------------------------------------------- */
}
<style> <style>
.section { .section {

View File

@ -2,8 +2,6 @@
import AppLayout from "components/AppLayout/AppLayout.astro"; import AppLayout from "components/AppLayout/AppLayout.astro";
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<AppLayout title="WIP" /> <AppLayout title="WIP" />

View File

@ -2,8 +2,6 @@
import AppLayout from "components/AppLayout/AppLayout.astro"; import AppLayout from "components/AppLayout/AppLayout.astro";
--- ---
{ {/* ------------------------------------------- HTML ------------------------------------------- */}
/* ------------------------------------------- HTML ------------------------------------------- */
}
<AppLayout title="WIP" /> <AppLayout title="WIP" />

View File

@ -169,4 +169,4 @@
"ZAR": "South African Rand", "ZAR": "South African Rand",
"ZMW": "Zambian Kwacha", "ZMW": "Zambian Kwacha",
"ZWL": "Zimbabwean Dollar" "ZWL": "Zimbabwean Dollar"
} }

View File

@ -174,4 +174,4 @@
"ZMW": 22.954829, "ZMW": 22.954829,
"ZWL": 322 "ZWL": 322
} }
} }

View File

@ -1,7 +1,4 @@
export const customElement = ( export const customElement = (name: string, constructor?: (elem: HTMLElement) => void) => {
name: string,
constructor?: (elem: HTMLElement) => void
) => {
class CustomElementClass extends HTMLElement { class CustomElementClass extends HTMLElement {
constructor() { constructor() {
super(); super();

View File

@ -1,6 +1,4 @@
export const fetchOr404 = async <T>( export const fetchOr404 = async <T>(promise: () => Promise<T>): Promise<T | Response> => {
promise: () => Promise<T>
): Promise<T | Response> => {
try { try {
return await promise(); return await promise();
} catch { } catch {