mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
174 lines
5.0 KiB
Plaintext
174 lines
5.0 KiB
Plaintext
---
|
|
import { Font } from 'astro:assets';
|
|
import type { ImageMetadata } from 'astro';
|
|
|
|
import { PRODUCTION_URL, SEO_SUFFIX, SITE_TITLE } from '@/consts';
|
|
|
|
import '@/styles/globals.css';
|
|
|
|
import BannerInit from '@/components/BannerInit.astro';
|
|
import { PreferenceSync } from '@/components/docs/PreferenceSync';
|
|
import LegacyBanner from '@/components/LegacyBanner.astro';
|
|
import ThemeInit from '@/components/ThemeInit.astro';
|
|
|
|
interface Props {
|
|
title: string | string[];
|
|
description: string;
|
|
image?: ImageMetadata | string;
|
|
twitterImage?: ImageMetadata | string;
|
|
canonical?: string;
|
|
suffix?: string;
|
|
}
|
|
const { canonical, suffix } = Astro.props;
|
|
const canonicalURL = canonical || new URL(Astro.url.pathname, PRODUCTION_URL);
|
|
|
|
const { title, description, image, twitterImage } = Astro.props;
|
|
|
|
function resolveImageUrl(img: ImageMetadata | string): string {
|
|
if (typeof img === 'string') return img;
|
|
return new URL(img.src, Astro.url).toString();
|
|
}
|
|
|
|
const resolvedTwitterImage = twitterImage ?? image;
|
|
|
|
const seoSuffix = suffix ?? SEO_SUFFIX;
|
|
const pageTitle = Array.isArray(title) ? title.join(' | ') : title;
|
|
const fullTitle =
|
|
pageTitle === SITE_TITLE ? `${SITE_TITLE} | ${seoSuffix}` : `${pageTitle} | ${SITE_TITLE} | ${seoSuffix}`;
|
|
---
|
|
|
|
<html lang="en">
|
|
<head>
|
|
{/* Global Metadata */}
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
<meta name="theme-color" content="#ebe4c1" />
|
|
<link rel="icon" href="/favicon.ico" sizes="32x32" />
|
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
|
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
|
<link rel="sitemap" href="/sitemap-index.xml" />
|
|
<link
|
|
rel="alternate"
|
|
type="application/rss+xml"
|
|
title={SITE_TITLE}
|
|
href={new URL("rss.xml", Astro.site)}
|
|
/>
|
|
<meta name="generator" content={Astro.generator} />
|
|
|
|
{/* Google Analytics (cookieless) */}
|
|
<script
|
|
is:inline
|
|
async
|
|
src="https://www.googletagmanager.com/gtag/js?id=G-WTF4CZJSGP"></script>
|
|
<script is:inline>
|
|
window.dataLayer = window.dataLayer || [];
|
|
function gtag() {
|
|
dataLayer.push(arguments);
|
|
}
|
|
gtag("consent", "default", {
|
|
analytics_storage: "denied",
|
|
ad_storage: "denied",
|
|
ad_user_data: "denied",
|
|
ad_personalization: "denied",
|
|
});
|
|
gtag("js", new Date());
|
|
gtag("config", "G-WTF4CZJSGP");
|
|
</script>
|
|
|
|
{/* Important stuff */}
|
|
<slot name="priority-head" />
|
|
|
|
{/* Preconnect to Mux for faster video/image loading */}
|
|
<link rel="preconnect" href="https://image.mux.com" crossorigin />
|
|
<link rel="preconnect" href="https://stream.mux.com" crossorigin />
|
|
|
|
{/* Font preloads */}
|
|
<Font cssVariable="--font-instrument-sans" preload />
|
|
<Font cssVariable="--font-ibm-plex-mono" preload />
|
|
<link
|
|
rel="preload"
|
|
href="https://static.mux.com/fonts/EurostileLTProBold/font.woff2"
|
|
as="font"
|
|
type="font/woff2"
|
|
crossorigin
|
|
/>
|
|
<link
|
|
rel="preload"
|
|
href="https://static.mux.com/fonts/EurostileLTProExtended2/font.woff2"
|
|
as="font"
|
|
type="font/woff2"
|
|
crossorigin
|
|
/>
|
|
<link
|
|
rel="preload"
|
|
href="https://static.mux.com/fonts/EurostileLTProBoldExtended2/font.woff2"
|
|
as="font"
|
|
type="font/woff2"
|
|
crossorigin
|
|
/>
|
|
|
|
{/* Canonical URL */}
|
|
<link rel="canonical" href={canonicalURL} />
|
|
|
|
{/* Primary Meta Tags */}
|
|
<title>{fullTitle}</title>
|
|
<meta name="title" content={fullTitle} />
|
|
<meta name="description" content={description} />
|
|
|
|
{/* Open Graph / Facebook */}
|
|
<meta property="og:type" content="website" />
|
|
<meta
|
|
property="og:url"
|
|
content={new URL(Astro.url.pathname, PRODUCTION_URL)}
|
|
/>
|
|
<meta property="og:title" content={fullTitle} />
|
|
<meta property="og:description" content={description} />
|
|
{image && <meta property="og:image" content={resolveImageUrl(image)} />}
|
|
|
|
{/* Twitter */}
|
|
<meta property="twitter:card" content="summary_large_image" />
|
|
<meta
|
|
property="twitter:url"
|
|
content={new URL(Astro.url.pathname, PRODUCTION_URL)}
|
|
/>
|
|
<meta property="twitter:title" content={fullTitle} />
|
|
<meta property="twitter:description" content={description} />
|
|
{
|
|
resolvedTwitterImage && (
|
|
<meta
|
|
property="twitter:image"
|
|
content={resolveImageUrl(resolvedTwitterImage)}
|
|
/>
|
|
)
|
|
}
|
|
|
|
{/* Whatever else */}
|
|
<slot name="head" />
|
|
|
|
<ThemeInit />
|
|
<BannerInit />
|
|
</head>
|
|
<body
|
|
class:list={[
|
|
"relative",
|
|
"font-sans text-p2 text-pretty antialiased",
|
|
"bg-manila-light text-faded-black dark:bg-faded-black dark:text-manila-light",
|
|
"min-w-80",
|
|
"selection:bg-gold selection:text-faded-black",
|
|
]}
|
|
>
|
|
<div
|
|
class:list={[
|
|
// BaseUI requires body.relative and div.isolate
|
|
"isolate",
|
|
// background colors are applied here for a more consistent FilmGrain blending
|
|
]}
|
|
>
|
|
<PreferenceSync client:idle />
|
|
|
|
<LegacyBanner />
|
|
<slot />
|
|
</div>
|
|
</body>
|
|
</html>
|