Skip to content
File

Blob: src/client/server/document.tsx

typescript56 lines
1import type { ReactNode } from "react";
2 
3import { highlightThemeHref } from "@/client/highlight-theme";
4import type { DocumentAssets } from "./assets";
5 
6type DocumentProps = {
7 title?: string;
8 assets: DocumentAssets;
9 needsHighlight?: boolean;
10 children: ReactNode;
11};
12 
13const initialHighlightThemeHref = highlightThemeHref.dark || highlightThemeHref.light;
14const themeBootstrap = `(function(){try{var saved=localStorage.getItem("theme");var theme=saved==="light"?"light":"dark";var root=document.documentElement;root.dataset.theme=theme;root.classList.toggle("dark",theme==="dark");var hljs=document.getElementById("hljs-theme");var darkHref="${highlightThemeHref.dark}";var lightHref="${highlightThemeHref.light}";if(hljs&&(darkHref||lightHref)){var nextHref=theme==="dark"?darkHref:lightHref;if(nextHref){hljs.setAttribute("href",nextHref);}else{hljs.removeAttribute("href");}}}catch(_err){document.documentElement.dataset.theme="dark";document.documentElement.classList.add("dark");}})();`;
15const reactRefreshPreamble = `import RefreshRuntime from "/@react-refresh";RefreshRuntime.injectIntoGlobalHook(window);window.$RefreshReg$=()=>{};window.$RefreshSig$=()=>type=>type;window.__vite_plugin_react_preamble_installed__=true;`;
16 
17export function Document({ title, assets, needsHighlight = false, children }: DocumentProps) {
18 const pageTitle = title || "git-on-cloudflare";
19 
20 return (
21 <html className="h-full" lang="en">
22 <head>
23 <meta charSet="utf-8" />
24 <meta name="viewport" content="width=device-width, initial-scale=1" />
25 <meta name="color-scheme" content="light dark" />
26 <title>{pageTitle}</title>
27 <link rel="preconnect" href="https://fonts.googleapis.com" />
28 <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
29 <link
30 href="https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400..700&family=JetBrains+Mono:wght@400;500&family=IBM+Plex+Serif:wght@600;700&display=swap"
31 rel="stylesheet"
32 />
33 {needsHighlight && initialHighlightThemeHref ? (
34 <link id="hljs-theme" rel="stylesheet" href={initialHighlightThemeHref} />
35 ) : null}
36 {import.meta.env.DEV ? (
37 <script type="module" dangerouslySetInnerHTML={{ __html: reactRefreshPreamble }} />
38 ) : null}
39 <script dangerouslySetInnerHTML={{ __html: themeBootstrap }} />
40 {assets.preloads.map((href) => (
41 <link key={href} rel="modulepreload" href={href} />
42 ))}
43 {assets.styles.map((href) => (
44 <link key={href} rel="stylesheet" href={href} />
45 ))}
46 </head>
47 <body className="min-h-screen text-zinc-900 dark:text-zinc-100">
48 {children}
49 {assets.moduleScripts.map((src) => (
50 <script key={src} type="module" src={src}></script>
51 ))}
52 </body>
53 </html>
54 );
55}