diff options
Diffstat (limited to 'packages/integrations/vercel/src')
-rw-r--r-- | packages/integrations/vercel/src/lib/redirects.ts | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/packages/integrations/vercel/src/lib/redirects.ts b/packages/integrations/vercel/src/lib/redirects.ts index 8f8db4dcf..1e476cb1f 100644 --- a/packages/integrations/vercel/src/lib/redirects.ts +++ b/packages/integrations/vercel/src/lib/redirects.ts @@ -1,5 +1,5 @@ import nodePath from 'node:path'; -import { appendForwardSlash } from '@astrojs/internal-helpers/path'; +import { appendForwardSlash, removeLeadingForwardSlash } from '@astrojs/internal-helpers/path'; import type { AstroConfig, RouteData, RoutePart } from 'astro'; const pathJoin = nodePath.posix.join; @@ -14,6 +14,33 @@ interface VercelRoute { continue?: boolean; } +// Copied from astro/packages/astro/src/core/routing/manifest/create.ts +// Disable eslint as we're not sure how to improve this regex yet +// eslint-disable-next-line regexp/no-super-linear-backtracking +const ROUTE_DYNAMIC_SPLIT = /\[(.+?\(.+?\)|.+?)\]/; +const ROUTE_SPREAD = /^\.{3}.+$/; +function getParts(part: string, file: string) { + const result: RoutePart[] = []; + part.split(ROUTE_DYNAMIC_SPLIT).map((str, i) => { + if (!str) return; + const dynamic = i % 2 === 1; + + const [, content] = dynamic ? /([^(]+)$/.exec(str) || [null, null] : [null, str]; + + if (!content || (dynamic && !/^(?:\.\.\.)?[\w$]+$/.test(content))) { + throw new Error(`Invalid route ${file} — parameter name must match /^[a-zA-Z0-9_$]+$/`); + } + + result.push({ + content, + dynamic, + spread: dynamic && ROUTE_SPREAD.test(content), + }); + }); + + return result; +} + // Copied from /home/juanm04/dev/misc/astro/packages/astro/src/core/routing/manifest/create.ts // 2022-04-26 function getMatchPattern(segments: RoutePart[][]) { @@ -77,7 +104,13 @@ function getRedirectStatus(route: RouteData): number { } export function escapeRegex(content: string) { - return `^${getMatchPattern([[{ content, dynamic: false, spread: false }]])}$`; + const segments = removeLeadingForwardSlash(content) + .split(nodePath.posix.sep) + .filter(Boolean) + .map((s: string) => { + return getParts(s, content); + }); + return `^/${getMatchPattern(segments)}$`; } export function getRedirects(routes: RouteData[], config: AstroConfig): VercelRoute[] { |