UNPKG

shelving

Version:

Toolkit for using data in JavaScript.

49 lines (48 loc) 2.62 kB
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useEffect } from "react"; import { getProps } from "../../util/object.js"; import { requireMeta } from "../misc/MetaContext.js"; import { joinTitles } from "../util/meta.js"; /** Meta tags with a capital first letter and hyphens, e.g. `Content-Security-Policy` or `Accept`, are `http-equiv=""` tags. */ const R_HTTP_EQUIV = /^[A-Z][a-zA-Z0-9]*(-[A-Z][a-zA-Z0-9]*)*$/; /** * Per-page meta tags plus history navigation. * - Emits hoistable head elements (title, meta, links, stylesheets, scripts) inline; React 19 hoists each one into the document `<head>`. * - Does not render `<base>` (not hoistable — that lives in `<Head>` in the `<HTML>` shell component). * - Updates `window.history` to match the page URL. */ export function Head() { const meta = requireMeta(); const { url, title, app, description, links, tags, stylesheets, modules, scripts } = meta; useEffect(() => { if (typeof window === "undefined") return; if (url) window.history.replaceState(null, "", url); }, [url]); const fullTitle = joinTitles(title, app); return (_jsxs(_Fragment, { children: [fullTitle && _jsx("title", { children: fullTitle }), description && _jsx("meta", { name: "description", content: description }), tags && getProps(tags).map(_renderTag), links && getProps(links).map(_renderLink), stylesheets?.map(_renderStylesheet), modules?.map(_renderModule), scripts?.map(_renderScript)] })); } function _renderTag([k, x]) { if (x === null || x === undefined) return null; const y = x === true ? "yes" : x === false ? "no" : x; if (k.startsWith("og:")) return _jsx("meta", { property: k, content: y }, k); // Tags that start with `og:` use `property=""` if (k.match(R_HTTP_EQUIV)) return _jsx("meta", { httpEquiv: k, content: y }, k); // Tags that are in `Snake-Case` use `http-equiv=""` return _jsx("meta", { name: k, content: y }, k); // All other tags use `content=""` } function _renderLink([k, { href }]) { const type = k.endsWith("icon") ? "image/x-icon" : "text/css"; return _jsx("link", { rel: k, href: href, type: type }, k); } function _renderStylesheet({ href }) { return _jsx("link", { rel: "stylesheet", type: "text/css", href: href, precedence: "default" }, href); } function _renderModule({ href }) { return _jsx("script", { type: "module", src: href, async: true }, href); } function _renderScript({ href }) { return _jsx("script", { type: "text/javascript", src: href, async: true }, href); }