Refactor routing in App component to enhance navigation and improve error handling by integrating dynamic routes and updating the NotFound route.

This commit is contained in:
becarta
2025-05-23 12:43:00 +02:00
parent f40db0f5c9
commit a544759a3b
11127 changed files with 1647032 additions and 0 deletions

102
node_modules/astro/dist/i18n/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,102 @@
import type { APIContext, AstroConfig, Locales, SSRManifest, ValidRedirectStatus } from '../@types/astro.js';
import type { RoutingStrategies } from './utils.js';
export declare function requestHasLocale(locales: Locales): (context: APIContext) => boolean;
export declare function requestIs404Or500(request: Request, base?: string): boolean;
export declare function pathHasLocale(path: string, locales: Locales): boolean;
type GetLocaleRelativeUrl = GetLocaleOptions & {
locale: string;
base: string;
locales: Locales;
trailingSlash: AstroConfig['trailingSlash'];
format: AstroConfig['build']['format'];
strategy?: RoutingStrategies;
defaultLocale: string;
domains: Record<string, string> | undefined;
path?: string;
};
export type GetLocaleOptions = {
/**
* Makes the locale URL-friendly by replacing underscores with dashes, and converting the locale to lower case.
* @default true
*/
normalizeLocale?: boolean;
/**
* An optional path to prepend to `locale`.
*/
prependWith?: string;
};
type GetLocaleAbsoluteUrl = GetLocaleRelativeUrl & {
site: AstroConfig['site'];
isBuild: boolean;
};
/**
* The base URL
*/
export declare function getLocaleRelativeUrl({ locale, base, locales: _locales, trailingSlash, format, path, prependWith, normalizeLocale, strategy, defaultLocale, }: GetLocaleRelativeUrl): string;
/**
* The absolute URL
*/
export declare function getLocaleAbsoluteUrl({ site, isBuild, ...rest }: GetLocaleAbsoluteUrl): string;
interface GetLocalesRelativeUrlList extends GetLocaleOptions {
base: string;
path?: string;
locales: Locales;
trailingSlash: AstroConfig['trailingSlash'];
format: AstroConfig['build']['format'];
strategy?: RoutingStrategies;
defaultLocale: string;
domains: Record<string, string> | undefined;
}
export declare function getLocaleRelativeUrlList({ locales: _locales, ...rest }: GetLocalesRelativeUrlList): string[];
interface GetLocalesAbsoluteUrlList extends GetLocalesRelativeUrlList {
site: AstroConfig['site'];
isBuild: boolean;
}
export declare function getLocaleAbsoluteUrlList(params: GetLocalesAbsoluteUrlList): string[];
/**
* Given a locale (code), it returns its corresponding path
* @param locale
* @param locales
*/
export declare function getPathByLocale(locale: string, locales: Locales): string;
/**
* A utility function that retrieves the preferred locale that correspond to a path.
*
* @param path
* @param locales
*/
export declare function getLocaleByPath(path: string, locales: Locales): string;
/**
*
* Given a locale, this function:
* - replaces the `_` with a `-`;
* - transforms all letters to be lower case;
*/
export declare function normalizeTheLocale(locale: string): string;
/**
* Returns an array of only locales, by picking the `code`
* @param locales
*/
export declare function toCodes(locales: Locales): string[];
/**
* It returns the array of paths
* @param locales
*/
export declare function toPaths(locales: Locales): string[];
export type MiddlewarePayload = {
base: string;
locales: Locales;
trailingSlash: AstroConfig['trailingSlash'];
format: AstroConfig['build']['format'];
strategy: RoutingStrategies;
defaultLocale: string;
domains: Record<string, string> | undefined;
fallback: Record<string, string> | undefined;
fallbackType: 'redirect' | 'rewrite';
};
export declare function redirectToDefaultLocale({ trailingSlash, format, base, defaultLocale, }: MiddlewarePayload): (context: APIContext, statusCode?: ValidRedirectStatus) => Response;
export declare function notFound({ base, locales }: MiddlewarePayload): (context: APIContext, response?: Response) => Response | undefined;
export type RedirectToFallback = (context: APIContext, response: Response) => Promise<Response>;
export declare function redirectToFallback({ fallback, locales, defaultLocale, strategy, base, fallbackType, }: MiddlewarePayload): (context: APIContext, response: Response) => Promise<Response>;
export declare function createMiddleware(i18nManifest: SSRManifest['i18n'], base: SSRManifest['base'], trailingSlash: SSRManifest['trailingSlash'], format: SSRManifest['buildFormat']): import("../@types/astro.js").MiddlewareHandler;
export {};

271
node_modules/astro/dist/i18n/index.js generated vendored Normal file
View File

@@ -0,0 +1,271 @@
import { appendForwardSlash, joinPaths } from "@astrojs/internal-helpers/path";
import { shouldAppendForwardSlash } from "../core/build/util.js";
import { REROUTE_DIRECTIVE_HEADER } from "../core/constants.js";
import { MissingLocale, i18nNoLocaleFoundInPath } from "../core/errors/errors-data.js";
import { AstroError } from "../core/errors/index.js";
import { createI18nMiddleware } from "./middleware.js";
function requestHasLocale(locales) {
return function(context) {
return pathHasLocale(context.url.pathname, locales);
};
}
function requestIs404Or500(request, base = "") {
const url = new URL(request.url);
return url.pathname.startsWith(`${base}/404`) || url.pathname.startsWith(`${base}/500`);
}
function pathHasLocale(path, locales) {
const segments = path.split("/");
for (const segment of segments) {
for (const locale of locales) {
if (typeof locale === "string") {
if (normalizeTheLocale(segment) === normalizeTheLocale(locale)) {
return true;
}
} else if (segment === locale.path) {
return true;
}
}
}
return false;
}
function getLocaleRelativeUrl({
locale,
base,
locales: _locales,
trailingSlash,
format,
path,
prependWith,
normalizeLocale = true,
strategy = "pathname-prefix-other-locales",
defaultLocale
}) {
const codeToUse = peekCodePathToUse(_locales, locale);
if (!codeToUse) {
throw new AstroError({
...MissingLocale,
message: MissingLocale.message(locale)
});
}
const pathsToJoin = [base, prependWith];
const normalizedLocale = normalizeLocale ? normalizeTheLocale(codeToUse) : codeToUse;
if (strategy === "pathname-prefix-always" || strategy === "pathname-prefix-always-no-redirect" || strategy === "domains-prefix-always" || strategy === "domains-prefix-always-no-redirect") {
pathsToJoin.push(normalizedLocale);
} else if (locale !== defaultLocale) {
pathsToJoin.push(normalizedLocale);
}
pathsToJoin.push(path);
if (shouldAppendForwardSlash(trailingSlash, format)) {
return appendForwardSlash(joinPaths(...pathsToJoin));
} else {
return joinPaths(...pathsToJoin);
}
}
function getLocaleAbsoluteUrl({ site, isBuild, ...rest }) {
const localeUrl = getLocaleRelativeUrl(rest);
const { domains, locale } = rest;
let url;
if (isBuild && domains && domains[locale]) {
const base = domains[locale];
url = joinPaths(base, localeUrl.replace(`/${rest.locale}`, ""));
} else {
if (site) {
url = joinPaths(site, localeUrl);
} else {
url = localeUrl;
}
}
if (shouldAppendForwardSlash(rest.trailingSlash, rest.format)) {
return appendForwardSlash(url);
} else {
return url;
}
}
function getLocaleRelativeUrlList({
locales: _locales,
...rest
}) {
const locales = toPaths(_locales);
return locales.map((locale) => {
return getLocaleRelativeUrl({ ...rest, locales, locale });
});
}
function getLocaleAbsoluteUrlList(params) {
const locales = toCodes(params.locales);
return locales.map((currentLocale) => {
return getLocaleAbsoluteUrl({ ...params, locale: currentLocale });
});
}
function getPathByLocale(locale, locales) {
for (const loopLocale of locales) {
if (typeof loopLocale === "string") {
if (loopLocale === locale) {
return loopLocale;
}
} else {
for (const code of loopLocale.codes) {
if (code === locale) {
return loopLocale.path;
}
}
}
}
throw new AstroError(i18nNoLocaleFoundInPath);
}
function getLocaleByPath(path, locales) {
for (const locale of locales) {
if (typeof locale !== "string") {
if (locale.path === path) {
const code = locale.codes.at(0);
if (code === void 0) throw new AstroError(i18nNoLocaleFoundInPath);
return code;
}
} else if (locale === path) {
return locale;
}
}
throw new AstroError(i18nNoLocaleFoundInPath);
}
function normalizeTheLocale(locale) {
return locale.replaceAll("_", "-").toLowerCase();
}
function toCodes(locales) {
return locales.map((loopLocale) => {
if (typeof loopLocale === "string") {
return loopLocale;
} else {
return loopLocale.codes[0];
}
});
}
function toPaths(locales) {
return locales.map((loopLocale) => {
if (typeof loopLocale === "string") {
return loopLocale;
} else {
return loopLocale.path;
}
});
}
function peekCodePathToUse(locales, locale) {
for (const loopLocale of locales) {
if (typeof loopLocale === "string") {
if (loopLocale === locale) {
return loopLocale;
}
} else {
for (const code of loopLocale.codes) {
if (code === locale) {
return loopLocale.path;
}
}
}
}
return void 0;
}
function redirectToDefaultLocale({
trailingSlash,
format,
base,
defaultLocale
}) {
return function(context, statusCode) {
if (shouldAppendForwardSlash(trailingSlash, format)) {
return context.redirect(`${appendForwardSlash(joinPaths(base, defaultLocale))}`, statusCode);
} else {
return context.redirect(`${joinPaths(base, defaultLocale)}`, statusCode);
}
};
}
function notFound({ base, locales }) {
return function(context, response) {
if (response?.headers.get(REROUTE_DIRECTIVE_HEADER) === "no") return response;
const url = context.url;
const isRoot = url.pathname === base + "/" || url.pathname === base;
if (!(isRoot || pathHasLocale(url.pathname, locales))) {
if (response) {
response.headers.set(REROUTE_DIRECTIVE_HEADER, "no");
return new Response(response.body, {
status: 404,
headers: response.headers
});
} else {
return new Response(null, {
status: 404,
headers: {
[REROUTE_DIRECTIVE_HEADER]: "no"
}
});
}
}
return void 0;
};
}
function redirectToFallback({
fallback,
locales,
defaultLocale,
strategy,
base,
fallbackType
}) {
return async function(context, response) {
if (response.status >= 300 && fallback) {
const fallbackKeys = fallback ? Object.keys(fallback) : [];
const segments = context.url.pathname.split("/");
const urlLocale = segments.find((segment) => {
for (const locale of locales) {
if (typeof locale === "string") {
if (locale === segment) {
return true;
}
} else if (locale.path === segment) {
return true;
}
}
return false;
});
if (urlLocale && fallbackKeys.includes(urlLocale)) {
const fallbackLocale = fallback[urlLocale];
const pathFallbackLocale = getPathByLocale(fallbackLocale, locales);
let newPathname;
if (pathFallbackLocale === defaultLocale && strategy === "pathname-prefix-other-locales") {
if (context.url.pathname.includes(`${base}`)) {
newPathname = context.url.pathname.replace(`/${urlLocale}`, ``);
} else {
newPathname = context.url.pathname.replace(`/${urlLocale}`, `/`);
}
} else {
newPathname = context.url.pathname.replace(`/${urlLocale}`, `/${pathFallbackLocale}`);
}
if (fallbackType === "rewrite") {
return await context.rewrite(newPathname);
} else {
return context.redirect(newPathname);
}
}
}
return response;
};
}
function createMiddleware(i18nManifest, base, trailingSlash, format) {
return createI18nMiddleware(i18nManifest, base, trailingSlash, format);
}
export {
createMiddleware,
getLocaleAbsoluteUrl,
getLocaleAbsoluteUrlList,
getLocaleByPath,
getLocaleRelativeUrl,
getLocaleRelativeUrlList,
getPathByLocale,
normalizeTheLocale,
notFound,
pathHasLocale,
redirectToDefaultLocale,
redirectToFallback,
requestHasLocale,
requestIs404Or500,
toCodes,
toPaths
};

2
node_modules/astro/dist/i18n/middleware.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
import type { MiddlewareHandler, SSRManifest } from '../@types/astro.js';
export declare function createI18nMiddleware(i18n: SSRManifest['i18n'], base: SSRManifest['base'], trailingSlash: SSRManifest['trailingSlash'], format: SSRManifest['buildFormat']): MiddlewareHandler;

128
node_modules/astro/dist/i18n/middleware.js generated vendored Normal file
View File

@@ -0,0 +1,128 @@
import { REROUTE_DIRECTIVE_HEADER, ROUTE_TYPE_HEADER } from "../core/constants.js";
import {
normalizeTheLocale,
notFound,
redirectToDefaultLocale,
redirectToFallback,
requestHasLocale,
requestIs404Or500
} from "./index.js";
function createI18nMiddleware(i18n, base, trailingSlash, format) {
if (!i18n) return (_, next) => next();
const payload = {
...i18n,
trailingSlash,
base,
format,
domains: {}
};
const _redirectToDefaultLocale = redirectToDefaultLocale(payload);
const _noFoundForNonLocaleRoute = notFound(payload);
const _requestHasLocale = requestHasLocale(payload.locales);
const _redirectToFallback = redirectToFallback(payload);
const prefixAlways = (context) => {
const url = context.url;
if (url.pathname === base + "/" || url.pathname === base) {
return _redirectToDefaultLocale(context);
} else if (!_requestHasLocale(context)) {
return _noFoundForNonLocaleRoute(context);
}
return void 0;
};
const prefixOtherLocales = (context, response) => {
let pathnameContainsDefaultLocale = false;
const url = context.url;
for (const segment of url.pathname.split("/")) {
if (normalizeTheLocale(segment) === normalizeTheLocale(i18n.defaultLocale)) {
pathnameContainsDefaultLocale = true;
break;
}
}
if (pathnameContainsDefaultLocale) {
const newLocation = url.pathname.replace(`/${i18n.defaultLocale}`, "");
response.headers.set("Location", newLocation);
return _noFoundForNonLocaleRoute(context);
}
return void 0;
};
return async (context, next) => {
const response = await next();
const type = response.headers.get(ROUTE_TYPE_HEADER);
const isReroute = response.headers.get(REROUTE_DIRECTIVE_HEADER);
if (isReroute === "no" && typeof i18n.fallback === "undefined") {
return response;
}
if (type !== "page" && type !== "fallback") {
return response;
}
if (requestIs404Or500(context.request, base)) {
return response;
}
const { currentLocale } = context;
switch (i18n.strategy) {
case "manual": {
return response;
}
case "domains-prefix-other-locales": {
if (localeHasntDomain(i18n, currentLocale)) {
const result = prefixOtherLocales(context, response);
if (result) {
return result;
}
}
break;
}
case "pathname-prefix-other-locales": {
const result = prefixOtherLocales(context, response);
if (result) {
return result;
}
break;
}
case "domains-prefix-always-no-redirect": {
if (localeHasntDomain(i18n, currentLocale)) {
const result = _noFoundForNonLocaleRoute(context, response);
if (result) {
return result;
}
}
break;
}
case "pathname-prefix-always-no-redirect": {
const result = _noFoundForNonLocaleRoute(context, response);
if (result) {
return result;
}
break;
}
case "pathname-prefix-always": {
const result = prefixAlways(context);
if (result) {
return result;
}
break;
}
case "domains-prefix-always": {
if (localeHasntDomain(i18n, currentLocale)) {
const result = prefixAlways(context);
if (result) {
return result;
}
}
break;
}
}
return _redirectToFallback(context, response);
};
}
function localeHasntDomain(i18n, currentLocale) {
for (const domainLocale of Object.values(i18n.domainLookupTable)) {
if (domainLocale === currentLocale) {
return false;
}
}
return true;
}
export {
createI18nMiddleware
};

27
node_modules/astro/dist/i18n/utils.d.ts generated vendored Normal file
View File

@@ -0,0 +1,27 @@
import type { AstroConfig, Locales } from '../@types/astro.js';
type BrowserLocale = {
locale: string;
qualityValue: number | undefined;
};
/**
* Parses the value of the `Accept-Language` header:
*
* More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language
*
* Complex example: `fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5`
*
*/
export declare function parseLocale(header: string): BrowserLocale[];
/**
* Set the current locale by parsing the value passed from the `Accept-Header`.
*
* If multiple locales are present in the header, they are sorted by their quality value and the highest is selected as current locale.
*
*/
export declare function computePreferredLocale(request: Request, locales: Locales): string | undefined;
export declare function computePreferredLocaleList(request: Request, locales: Locales): string[];
export declare function computeCurrentLocale(pathname: string, locales: Locales, defaultLocale: string): string | undefined;
export type RoutingStrategies = 'manual' | 'pathname-prefix-always' | 'pathname-prefix-other-locales' | 'pathname-prefix-always-no-redirect' | 'domains-prefix-always' | 'domains-prefix-other-locales' | 'domains-prefix-always-no-redirect';
export declare function toRoutingStrategy(routing: NonNullable<AstroConfig['i18n']>['routing'], domains: NonNullable<AstroConfig['i18n']>['domains']): RoutingStrategies;
export declare function toFallbackType(routing: NonNullable<AstroConfig['i18n']>['routing']): 'redirect' | 'rewrite';
export {};

184
node_modules/astro/dist/i18n/utils.js generated vendored Normal file
View File

@@ -0,0 +1,184 @@
import { normalizeTheLocale, toCodes } from "./index.js";
function parseLocale(header) {
if (header === "*") {
return [{ locale: header, qualityValue: void 0 }];
}
const result = [];
const localeValues = header.split(",").map((str) => str.trim());
for (const localeValue of localeValues) {
const split = localeValue.split(";").map((str) => str.trim());
const localeName = split[0];
const qualityValue = split[1];
if (!split) {
continue;
}
if (qualityValue && qualityValue.startsWith("q=")) {
const qualityValueAsFloat = Number.parseFloat(qualityValue.slice("q=".length));
if (Number.isNaN(qualityValueAsFloat) || qualityValueAsFloat > 1) {
result.push({
locale: localeName,
qualityValue: void 0
});
} else {
result.push({
locale: localeName,
qualityValue: qualityValueAsFloat
});
}
} else {
result.push({
locale: localeName,
qualityValue: void 0
});
}
}
return result;
}
function sortAndFilterLocales(browserLocaleList, locales) {
const normalizedLocales = toCodes(locales).map(normalizeTheLocale);
return browserLocaleList.filter((browserLocale) => {
if (browserLocale.locale !== "*") {
return normalizedLocales.includes(normalizeTheLocale(browserLocale.locale));
}
return true;
}).sort((a, b) => {
if (a.qualityValue && b.qualityValue) {
return Math.sign(b.qualityValue - a.qualityValue);
}
return 0;
});
}
function computePreferredLocale(request, locales) {
const acceptHeader = request.headers.get("Accept-Language");
let result = void 0;
if (acceptHeader) {
const browserLocaleList = sortAndFilterLocales(parseLocale(acceptHeader), locales);
const firstResult = browserLocaleList.at(0);
if (firstResult && firstResult.locale !== "*") {
for (const currentLocale of locales) {
if (typeof currentLocale === "string") {
if (normalizeTheLocale(currentLocale) === normalizeTheLocale(firstResult.locale)) {
result = currentLocale;
}
} else {
for (const currentCode of currentLocale.codes) {
if (normalizeTheLocale(currentCode) === normalizeTheLocale(firstResult.locale)) {
result = currentLocale.path;
}
}
}
}
}
}
return result;
}
function computePreferredLocaleList(request, locales) {
const acceptHeader = request.headers.get("Accept-Language");
let result = [];
if (acceptHeader) {
const browserLocaleList = sortAndFilterLocales(parseLocale(acceptHeader), locales);
if (browserLocaleList.length === 1 && browserLocaleList.at(0).locale === "*") {
return locales.map((locale) => {
if (typeof locale === "string") {
return locale;
} else {
return locale.codes.at(0);
}
});
} else if (browserLocaleList.length > 0) {
for (const browserLocale of browserLocaleList) {
for (const loopLocale of locales) {
if (typeof loopLocale === "string") {
if (normalizeTheLocale(loopLocale) === normalizeTheLocale(browserLocale.locale)) {
result.push(loopLocale);
}
} else {
for (const code of loopLocale.codes) {
if (code === browserLocale.locale) {
result.push(loopLocale.path);
}
}
}
}
}
}
}
return result;
}
function computeCurrentLocale(pathname, locales, defaultLocale) {
for (const segment of pathname.split("/")) {
for (const locale of locales) {
if (typeof locale === "string") {
if (!segment.includes(locale)) continue;
if (normalizeTheLocale(locale) === normalizeTheLocale(segment)) {
return locale;
}
} else {
if (locale.path === segment) {
return locale.codes.at(0);
} else {
for (const code of locale.codes) {
if (normalizeTheLocale(code) === normalizeTheLocale(segment)) {
return code;
}
}
}
}
}
}
for (const locale of locales) {
if (typeof locale === "string") {
if (locale === defaultLocale) {
return locale;
}
} else {
if (locale.path === defaultLocale) {
return locale.codes.at(0);
}
}
}
}
function toRoutingStrategy(routing, domains) {
let strategy;
const hasDomains = domains ? Object.keys(domains).length > 0 : false;
if (routing === "manual") {
strategy = "manual";
} else {
if (!hasDomains) {
if (routing?.prefixDefaultLocale === true) {
if (routing.redirectToDefaultLocale) {
strategy = "pathname-prefix-always";
} else {
strategy = "pathname-prefix-always-no-redirect";
}
} else {
strategy = "pathname-prefix-other-locales";
}
} else {
if (routing?.prefixDefaultLocale === true) {
if (routing.redirectToDefaultLocale) {
strategy = "domains-prefix-always";
} else {
strategy = "domains-prefix-always-no-redirect";
}
} else {
strategy = "domains-prefix-other-locales";
}
}
}
return strategy;
}
function toFallbackType(routing) {
if (routing === "manual") {
return "rewrite";
}
return routing.fallbackType;
}
export {
computeCurrentLocale,
computePreferredLocale,
computePreferredLocaleList,
parseLocale,
toFallbackType,
toRoutingStrategy
};

11
node_modules/astro/dist/i18n/vite-plugin-i18n.d.ts generated vendored Normal file
View File

@@ -0,0 +1,11 @@
import type * as vite from 'vite';
import type { AstroConfig, AstroSettings } from '../@types/astro.js';
type AstroInternationalization = {
settings: AstroSettings;
};
export interface I18nInternalConfig extends Pick<AstroConfig, 'base' | 'site' | 'trailingSlash'>, Pick<AstroConfig['build'], 'format'> {
i18n: AstroConfig['i18n'];
isBuild: boolean;
}
export default function astroInternationalization({ settings, }: AstroInternationalization): vite.Plugin;
export {};

42
node_modules/astro/dist/i18n/vite-plugin-i18n.js generated vendored Normal file
View File

@@ -0,0 +1,42 @@
import { AstroError } from "../core/errors/errors.js";
import { AstroErrorData } from "../core/errors/index.js";
const virtualModuleId = "astro:i18n";
function astroInternationalization({
settings
}) {
const {
base,
build: { format },
i18n,
site,
trailingSlash
} = settings.config;
return {
name: "astro:i18n",
enforce: "pre",
config(_config, { command }) {
const i18nConfig = {
base,
format,
site,
trailingSlash,
i18n,
isBuild: command === "build"
};
return {
define: {
__ASTRO_INTERNAL_I18N_CONFIG__: JSON.stringify(i18nConfig)
}
};
},
resolveId(id) {
if (id === virtualModuleId) {
if (i18n === void 0) throw new AstroError(AstroErrorData.i18nNotEnabled);
return this.resolve("astro/virtual-modules/i18n.js");
}
}
};
}
export {
astroInternationalization as default
};