59 lines
2.3 KiB
JavaScript
59 lines
2.3 KiB
JavaScript
// Head-element setup for catcrafts.net.
|
|
//
|
|
// The Crafter.Graphics Dom partition only exposes element creation under <body>,
|
|
// so anything that has to live in <head> — title, stylesheet, favicon, viewport
|
|
// — is injected from this loader. EnableWasiBrowserRuntime emits a
|
|
// <script type="module"> for every *.js in cfg.files ahead of runtime.js, so
|
|
// this runs before the wasm module starts and styles are in place by first
|
|
// paint.
|
|
//
|
|
// EVERYTHING HERE IS CONDITIONAL, and that matters. There are two ways a
|
|
// document reaches the browser:
|
|
//
|
|
// 1. Server-rendered by catcrafts-server, which already emitted a correct
|
|
// per-route <title> plus the stylesheet, favicon and viewport. It marks
|
|
// that with <meta name="cc-ssr">.
|
|
// 2. The static fallback shell — Caddy serves the wasm bundle's index.html
|
|
// when the backend is down. That document has a bare <head> and an empty
|
|
// <body>, so the app has to supply all of it.
|
|
//
|
|
// Running unconditionally broke case 1: it replaced the route's real title with
|
|
// the generic site name, and appended a second stylesheet, favicon and viewport
|
|
// tag. So each addition checks whether the server already did the job.
|
|
|
|
const ssr = document.querySelector('meta[name="cc-ssr"]') !== null;
|
|
|
|
function ensure(selector, build) {
|
|
if (document.querySelector(selector)) return;
|
|
document.head.appendChild(build());
|
|
}
|
|
|
|
// Only claim the title when the server did not set one. On an SSR'd page the
|
|
// existing title is route-specific and strictly better than anything this file
|
|
// knows. "catcrafts.wasm" is what Crafter.Build's index.html template hardcodes,
|
|
// so it counts as unset.
|
|
if (!ssr && (!document.title || document.title === "catcrafts.wasm")) {
|
|
document.title = "Catcrafts";
|
|
}
|
|
|
|
ensure('link[rel="stylesheet"]', () => {
|
|
const el = document.createElement("link");
|
|
el.rel = "stylesheet";
|
|
el.href = "/styles.css";
|
|
return el;
|
|
});
|
|
|
|
ensure('link[rel="icon"]', () => {
|
|
const el = document.createElement("link");
|
|
el.rel = "icon";
|
|
el.type = "image/svg+xml";
|
|
el.href = "/favicon.svg";
|
|
return el;
|
|
});
|
|
|
|
ensure('meta[name="viewport"]', () => {
|
|
const el = document.createElement("meta");
|
|
el.name = "viewport";
|
|
el.content = "width=device-width, initial-scale=1";
|
|
return el;
|
|
});
|