initial commit
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
/* ============================================================================
|
||||
ROOT LOADER DATA, READ FROM `meta`
|
||||
----------------------------------------------------------------------------
|
||||
`buildMeta` needs the locale, the pathname and the site origin, and all
|
||||
three are resolved once per request by the root loader. A `meta` function
|
||||
reaches them through its `matches`.
|
||||
|
||||
React Router 8 names that property `loaderData` on every match (see
|
||||
`CreateMetaArgs` in react-router/lib/types/route-module-annotations.d.ts and
|
||||
the `Meta` component that builds the array). Version 7 called it `data`, and
|
||||
plenty of examples still do, so both are read here.
|
||||
|
||||
Defensive rather than indexed: `matches[0]` has no data at all while the
|
||||
root loader is in flight or on an error render, and a `meta` that throws
|
||||
takes the whole document down with it.
|
||||
========================================================================= */
|
||||
|
||||
import { DEFAULT_LOCALE, isLocale, localizedPath, type Locale } from "~/i18n";
|
||||
|
||||
export interface RootSeo {
|
||||
readonly locale: Locale;
|
||||
/** Pathname INCLUDING the locale prefix. */
|
||||
readonly pathname: string;
|
||||
/** Site origin without a trailing slash. */
|
||||
readonly siteUrl: string;
|
||||
}
|
||||
|
||||
/** Matches the default in ~/lib/env.server, for the case root data is absent. */
|
||||
const FALLBACK_SITE_URL = "https://sharper.ly";
|
||||
|
||||
function readMatchData(match: unknown): Record<string, unknown> | undefined {
|
||||
if (!match || typeof match !== "object") return undefined;
|
||||
|
||||
const { id, loaderData, data } = match as {
|
||||
id?: unknown;
|
||||
loaderData?: unknown;
|
||||
data?: unknown;
|
||||
};
|
||||
if (id !== "root") return undefined;
|
||||
|
||||
const payload = loaderData ?? data;
|
||||
return payload && typeof payload === "object"
|
||||
? (payload as Record<string, unknown>)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
/** The root loader's `{ locale, pathname, siteUrl }`, with safe fallbacks. */
|
||||
export function readRootSeo(matches: readonly unknown[]): RootSeo {
|
||||
for (const match of matches) {
|
||||
const record = readMatchData(match);
|
||||
if (!record) continue;
|
||||
|
||||
const locale = isLocale(record.locale) ? record.locale : DEFAULT_LOCALE;
|
||||
|
||||
return {
|
||||
locale,
|
||||
pathname:
|
||||
typeof record.pathname === "string"
|
||||
? record.pathname
|
||||
: localizedPath("/", locale),
|
||||
siteUrl:
|
||||
typeof record.siteUrl === "string" ? record.siteUrl : FALLBACK_SITE_URL,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
locale: DEFAULT_LOCALE,
|
||||
pathname: localizedPath("/", DEFAULT_LOCALE),
|
||||
siteUrl: FALLBACK_SITE_URL,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user