diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 9e4514698..9cd7dd85a 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -974,6 +974,9 @@ export interface RouteData { export type SerializedRouteData = Omit & { generate: undefined; pattern: string; + _meta: { + trailingSlash: AstroConfig['trailingSlash']; + }; }; export type RuntimeMode = 'development' | 'production'; diff --git a/packages/astro/src/core/build/vite-plugin-ssr.ts b/packages/astro/src/core/build/vite-plugin-ssr.ts index 1a4a0d291..8c821f608 100644 --- a/packages/astro/src/core/build/vite-plugin-ssr.ts +++ b/packages/astro/src/core/build/vite-plugin-ssr.ts @@ -115,7 +115,7 @@ function buildManifest( .filter((script) => script.stage === 'head-inline') .map(({ stage, content }) => ({ stage, children: content })), ], - routeData: serializeRouteData(pageData.route), + routeData: serializeRouteData(pageData.route, astroConfig.trailingSlash), }); } diff --git a/packages/astro/src/core/routing/manifest/create.ts b/packages/astro/src/core/routing/manifest/create.ts index 3f29fddd3..4958e9abd 100644 --- a/packages/astro/src/core/routing/manifest/create.ts +++ b/packages/astro/src/core/routing/manifest/create.ts @@ -3,11 +3,11 @@ import type { LogOptions } from '../../logger/core'; import fs from 'fs'; import path from 'path'; -import { compile } from 'path-to-regexp'; import slash from 'slash'; import { fileURLToPath } from 'url'; import { warn } from '../../logger/core.js'; import { resolvePages } from '../../util.js'; +import { getRouteGenerator } from './generator.js'; interface Item { basename: string; @@ -88,34 +88,6 @@ function getTrailingSlashPattern(addTrailingSlash: AstroConfig['trailingSlash']) return '\\/?$'; } -function getGenerator(segments: RoutePart[][], addTrailingSlash: AstroConfig['trailingSlash']) { - const template = segments - .map((segment) => { - return segment[0].spread - ? `/:${segment[0].content.slice(3)}(.*)?` - : '/' + - segment - .map((part) => { - if (part) - return part.dynamic - ? `:${part.content}` - : part.content - .normalize() - .replace(/\?/g, '%3F') - .replace(/#/g, '%23') - .replace(/%5B/g, '[') - .replace(/%5D/g, ']') - .replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - }) - .join(''); - }) - .join(''); - - const trailing = addTrailingSlash !== 'never' && segments.length ? '/' : ''; - const toPath = compile(template + trailing); - return toPath; -} - function isSpread(str: string) { const spreadPattern = /\[\.{3}/g; return spreadPattern.test(str); @@ -271,7 +243,7 @@ export function createRouteManifest( const component = item.file; const trailingSlash = item.isPage ? config.trailingSlash : 'never'; const pattern = getPattern(segments, trailingSlash); - const generate = getGenerator(segments, trailingSlash); + const generate = getRouteGenerator(segments, trailingSlash); const pathname = segments.every((segment) => segment.length === 1 && !segment[0].dynamic) ? `/${segments.map((segment) => segment[0].content).join('/')}` : null; diff --git a/packages/astro/src/core/routing/manifest/generator.ts b/packages/astro/src/core/routing/manifest/generator.ts new file mode 100644 index 000000000..27039950c --- /dev/null +++ b/packages/astro/src/core/routing/manifest/generator.ts @@ -0,0 +1,34 @@ +import type { AstroConfig, RoutePart } from '../../../@types/astro'; + +import { compile } from 'path-to-regexp'; + +export function getRouteGenerator( + segments: RoutePart[][], + addTrailingSlash: AstroConfig['trailingSlash'] +) { + const template = segments + .map((segment) => { + return segment[0].spread + ? `/:${segment[0].content.slice(3)}(.*)?` + : '/' + + segment + .map((part) => { + if (part) + return part.dynamic + ? `:${part.content}` + : part.content + .normalize() + .replace(/\?/g, '%3F') + .replace(/#/g, '%23') + .replace(/%5B/g, '[') + .replace(/%5D/g, ']') + .replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + }) + .join(''); + }) + .join(''); + + const trailing = addTrailingSlash !== 'never' && segments.length ? '/' : ''; + const toPath = compile(template + trailing); + return toPath; +} diff --git a/packages/astro/src/core/routing/manifest/serialization.ts b/packages/astro/src/core/routing/manifest/serialization.ts index dfae7e63e..f5cce5697 100644 --- a/packages/astro/src/core/routing/manifest/serialization.ts +++ b/packages/astro/src/core/routing/manifest/serialization.ts @@ -1,34 +1,27 @@ -import type { RouteData, SerializedRouteData, RoutePart } from '../../../@types/astro'; +import type { RouteData, SerializedRouteData, AstroConfig } from '../../../@types/astro'; -function createRouteData( - pattern: RegExp, - params: string[], - component: string, - pathname: string | undefined, - type: 'page' | 'endpoint', - segments: RoutePart[][] -): RouteData { +import { getRouteGenerator } from './generator.js'; + +export function serializeRouteData( + routeData: RouteData, + trailingSlash: AstroConfig['trailingSlash'] +): SerializedRouteData { return { - type, - pattern, - params, - component, - // TODO bring back - generate: () => '', - pathname: pathname || undefined, - segments, + ...routeData, + generate: undefined, + pattern: routeData.pattern.source, + _meta: { trailingSlash }, }; } -export function serializeRouteData(routeData: RouteData): SerializedRouteData { - // Is there a better way to do this in TypeScript? - const outRouteData = routeData as unknown as SerializedRouteData; - outRouteData.pattern = routeData.pattern.source; - return outRouteData; -} - -export function deserializeRouteData(rawRouteData: SerializedRouteData) { - const { component, params, pathname, type, segments } = rawRouteData; - const pattern = new RegExp(rawRouteData.pattern); - return createRouteData(pattern, params, component, pathname, type, segments); +export function deserializeRouteData(rawRouteData: SerializedRouteData): RouteData { + return { + type: rawRouteData.type, + pattern: new RegExp(rawRouteData.pattern), + params: rawRouteData.params, + component: rawRouteData.component, + generate: getRouteGenerator(rawRouteData.segments, rawRouteData._meta.trailingSlash), + pathname: rawRouteData.pathname || undefined, + segments: rawRouteData.segments, + }; }