diff --git a/packages/astro/src/core/routing/index.ts b/packages/astro/src/core/routing/index.ts index 13b23d78b..0c9a6040c 100644 --- a/packages/astro/src/core/routing/index.ts +++ b/packages/astro/src/core/routing/index.ts @@ -1,5 +1,5 @@ export { createRouteManifest } from './manifest/create.js'; export { deserializeRouteData, serializeRouteData } from './manifest/serialization.js'; -export { matchRoute, matchAllRoutes } from './match.js'; +export { matchAllRoutes, matchRoute } from './match.js'; export { getParams } from './params.js'; export { validateGetStaticPathsModule, validateGetStaticPathsResult } from './validation.js'; diff --git a/packages/astro/src/core/routing/manifest/create.ts b/packages/astro/src/core/routing/manifest/create.ts index bb718dd45..0efd29796 100644 --- a/packages/astro/src/core/routing/manifest/create.ts +++ b/packages/astro/src/core/routing/manifest/create.ts @@ -1,4 +1,10 @@ -import type { AstroConfig, InjectedRoute, ManifestData, RouteData, RoutePart } from '../../../@types/astro'; +import type { + AstroConfig, + InjectedRoute, + ManifestData, + RouteData, + RoutePart, +} from '../../../@types/astro'; import type { LogOptions } from '../../logger/core'; import fs from 'fs'; @@ -179,7 +185,7 @@ function injectedRouteToItem( isIndex: true, isPage, routeSuffix: pattern.slice(pattern.indexOf('.'), -ext.length), - } + }; } /** Create manifest of all static routes */ @@ -311,75 +317,74 @@ export function createRouteManifest( warn(logging, 'astro', `Missing pages directory: ${pagesDirRootRelative}`); } - config?._ctx?.injectedRoutes?.sort((a, b) => - // sort injected routes in the same way as user-defined routes - comparator( - injectedRouteToItem({ config, cwd }, a), - injectedRouteToItem({ config, cwd}, b) - )) + config?._ctx?.injectedRoutes + ?.sort((a, b) => + // sort injected routes in the same way as user-defined routes + comparator(injectedRouteToItem({ config, cwd }, a), injectedRouteToItem({ config, cwd }, b)) + ) .reverse() // prepend to the routes array from lowest to highest priority .forEach(({ pattern: name, entryPoint }) => { - const resolved = require.resolve(entryPoint, { paths: [cwd || fileURLToPath(config.root)] }); - const component = slash(path.relative(cwd || fileURLToPath(config.root), resolved)); + const resolved = require.resolve(entryPoint, { paths: [cwd || fileURLToPath(config.root)] }); + const component = slash(path.relative(cwd || fileURLToPath(config.root), resolved)); - const isDynamic = (str: string) => str?.[0] === '['; - const normalize = (str: string) => str?.substring(1, str?.length - 1); + const isDynamic = (str: string) => str?.[0] === '['; + const normalize = (str: string) => str?.substring(1, str?.length - 1); - const segments = removeLeadingForwardSlash(name) - .split(path.sep) - .filter(Boolean) - .map((s: string) => { - validateSegment(s); + const segments = removeLeadingForwardSlash(name) + .split(path.sep) + .filter(Boolean) + .map((s: string) => { + validateSegment(s); - const dynamic = isDynamic(s); - const content = dynamic ? normalize(s) : s; - return [ - { - content, - dynamic, - spread: isSpread(s), - }, - ]; + const dynamic = isDynamic(s); + const content = dynamic ? normalize(s) : s; + return [ + { + content, + dynamic, + spread: isSpread(s), + }, + ]; + }); + + const type = resolved.endsWith('.astro') ? 'page' : 'endpoint'; + const isPage = type === 'page'; + const trailingSlash = isPage ? config.trailingSlash : 'never'; + + const pattern = getPattern(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; + const params = segments + .flat() + .filter((p) => p.dynamic) + .map((p) => p.content); + const route = `/${segments + .map(([{ dynamic, content }]) => (dynamic ? `[${content}]` : content)) + .join('/')}`.toLowerCase(); + + const collision = routes.find(({ route: r }) => r === route); + if (collision) { + throw new Error( + `An integration attempted to inject a route that is already used in your project: "${route}" at "${component}". \nThis route collides with: "${collision.component}".` + ); + } + + // the routes array was already sorted by priority, + // pushing to the front of the list ensure that injected routes + // are given priority over all user-provided routes + routes.unshift({ + type, + route, + pattern, + segments, + params, + component, + generate, + pathname: pathname || void 0, }); - - const type = resolved.endsWith('.astro') ? 'page' : 'endpoint'; - const isPage = type === 'page'; - const trailingSlash = isPage ? config.trailingSlash : 'never'; - - const pattern = getPattern(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; - const params = segments - .flat() - .filter((p) => p.dynamic) - .map((p) => p.content); - const route = `/${segments - .map(([{ dynamic, content }]) => (dynamic ? `[${content}]` : content)) - .join('/')}`.toLowerCase(); - - const collision = routes.find(({ route: r }) => r === route); - if (collision) { - throw new Error( - `An integration attempted to inject a route that is already used in your project: "${route}" at "${component}". \nThis route collides with: "${collision.component}".` - ); - } - - // the routes array was already sorted by priority, - // pushing to the front of the list ensure that injected routes - // are given priority over all user-provided routes - routes.unshift({ - type, - route, - pattern, - segments, - params, - component, - generate, - pathname: pathname || void 0, }); - }); return { routes, diff --git a/packages/astro/src/vite-plugin-astro-server/index.ts b/packages/astro/src/vite-plugin-astro-server/index.ts index a77ca486d..282d1e49b 100644 --- a/packages/astro/src/vite-plugin-astro-server/index.ts +++ b/packages/astro/src/vite-plugin-astro-server/index.ts @@ -19,7 +19,7 @@ import { getParamsAndProps, GetParamsAndPropsError } from '../core/render/core.j import { preload, ssr } from '../core/render/dev/index.js'; import { RouteCache } from '../core/render/route-cache.js'; import { createRequest } from '../core/request.js'; -import { createRouteManifest, matchAllRoutes, matchRoute } from '../core/routing/index.js'; +import { createRouteManifest, matchAllRoutes } from '../core/routing/index.js'; import { createSafeError, resolvePages } from '../core/util.js'; import notFoundTemplate, { subpathNotUsedTemplate } from '../template/4xx.js'; @@ -254,9 +254,7 @@ async function handleRequest( if (config.output === 'server' && matches.length > 1) { throw new Error(`Found multiple matching routes for "${pathname}"! When using \`output: 'server'\`, only one route in \`src/pages\` can match a given URL. Found: -${ - matches.map(({ component }) => `- ${component}`).join('\n') -} +${matches.map(({ component }) => `- ${component}`).join('\n')} `); } @@ -281,7 +279,7 @@ ${ filePath, preloadedComponent, mod, - } + }; } } @@ -300,12 +298,12 @@ ${ const filePath = new URL(`./${custom404.component}`, config.root); const preloadedComponent = await preload({ astroConfig: config, filePath, viteServer }); const [, mod] = preloadedComponent; - + return { route: custom404, filePath, preloadedComponent, - mod + mod, }; } diff --git a/packages/astro/test/astro-get-static-paths.test.js b/packages/astro/test/astro-get-static-paths.test.js index 6d98446a1..bfc01d2f5 100644 --- a/packages/astro/test/astro-get-static-paths.test.js +++ b/packages/astro/test/astro-get-static-paths.test.js @@ -28,7 +28,7 @@ describe('getStaticPaths - dev calls', () => { before(async () => { // reset the flag used by [...calledTwiceTest].astro between each test globalThis.isCalledOnce = false; - + fixture = await loadFixture({ root: './fixtures/astro-get-static-paths/' }); devServer = await fixture.startDevServer(); }); @@ -43,7 +43,7 @@ describe('getStaticPaths - dev calls', () => { res = await fixture.fetch('/b'); expect(res.status).to.equal(200); - + res = await fixture.fetch('/c'); expect(res.status).to.equal(200); }); @@ -56,7 +56,7 @@ describe('getStaticPaths - 404 behavior', () => { before(async () => { // reset the flag used by [...calledTwiceTest].astro between each test globalThis.isCalledOnce = false; - + fixture = await loadFixture({ root: './fixtures/astro-get-static-paths/' }); devServer = await fixture.startDevServer(); }); @@ -121,7 +121,7 @@ describe('getStaticPaths - numeric route params', () => { before(async () => { // reset the flag used by [...calledTwiceTest].astro between each test globalThis.isCalledOnce = false; - + fixture = await loadFixture({ root: './fixtures/astro-get-static-paths/', site: 'https://mysite.dev/', diff --git a/packages/astro/test/routing-priority.test.js b/packages/astro/test/routing-priority.test.js index ca093fd5c..359b6981e 100644 --- a/packages/astro/test/routing-priority.test.js +++ b/packages/astro/test/routing-priority.test.js @@ -76,25 +76,25 @@ const routes = [ { description: 'matches /injected to to-inject.astro', url: '/injected', - h1: 'to-inject.astro' + h1: 'to-inject.astro', }, { description: 'matches /_injected to to-inject.astro', url: '/_injected', - h1: 'to-inject.astro' + h1: 'to-inject.astro', }, { description: 'matches /injected-1 to [id].astro', url: '/injected-1', h1: '[id].astro', - p: 'injected-1' + p: 'injected-1', }, { description: 'matches /injected-2 to [id].astro', url: '/injected-2', h1: '[id].astro', - p: 'injected-2' - } + p: 'injected-2', + }, ]; function appendForwardSlash(path) { @@ -147,7 +147,7 @@ describe('Routing priority', () => { it(description, async () => { const html = await fixture.fetch(url).then((res) => res.text()); const $ = cheerioLoad(html); - + expect($('h1').text()).to.equal(h1); if (p) { @@ -159,7 +159,7 @@ describe('Routing priority', () => { it(`${description} (trailing slash)`, async () => { const html = await fixture.fetch(appendForwardSlash(url)).then((res) => res.text()); const $ = cheerioLoad(html); - + expect($('h1').text()).to.equal(h1); if (p) { @@ -169,9 +169,11 @@ describe('Routing priority', () => { // checks with index.html, ex: '/de/index.html' instead of '/de' it(`${description} (index.html)`, async () => { - const html = await fixture.fetch(`${appendForwardSlash(url)}index.html`).then((res) => res.text()); + const html = await fixture + .fetch(`${appendForwardSlash(url)}index.html`) + .then((res) => res.text()); const $ = cheerioLoad(html); - + expect($('h1').text()).to.equal(h1); if (p) {