Skip to content

Commit

Permalink
Implement priority
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewp committed May 25, 2023
1 parent af2ceea commit 1eca7aa
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 3 deletions.
63 changes: 60 additions & 3 deletions packages/astro/src/core/routing/manifest/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ function getParts(part: string, file: string) {
return result;
}

function areSamePart(a: RoutePart, b: RoutePart) {
return a.content === b.content && a.dynamic === b.dynamic && a.spread === b.spread;
}

function getPattern(
segments: RoutePart[][],
base: string,
Expand Down Expand Up @@ -204,6 +208,49 @@ function injectedRouteToItem(
};
}

// Seeings if the two routes are siblings of each other, with `b` being the route
// in focus. If it is in the same parent folder as `a`, they are siblings.
function areSiblings(a: RouteData, b: RouteData) {
if(a.segments.length < b.segments.length) return false;
for(let i = 0; i < b.segments.length - 1; i++) {
let segment = b.segments[i];
if(segment.length === a.segments[i].length) {
for(let j = 0; j < segment.length; j++) {
if(!areSamePart(segment[j], a.segments[i][j])) {
return false;
}
}
} else {
return false;
}
}
return true;
}

// A fast insertion method based on binary search.
function binaryInsert<T>(sorted: T[], item: T, insertComparator: (a: T, item: T) => boolean) {
if(sorted.length === 0) {
sorted.push(item);
return 0;
}
let low = 0, high = sorted.length - 1, mid = 0;
while (low <= high) {
mid = low + (high - low >> 1);
if(insertComparator(sorted[mid], item)) {
low = mid + 1;
} else {
high = mid -1;
}
}

if(insertComparator(sorted[mid], item)) {
mid++;
}

sorted.splice(mid, 0, item);
return mid;
}

export interface CreateRouteManifestParams {
/** Astro Settings object */
settings: AstroSettings;
Expand Down Expand Up @@ -444,9 +491,7 @@ export function createRouteManifest(
.map(([{ dynamic, content }]) => (dynamic ? `[${content}]` : content))
.join('/')}`.toLowerCase();



routes.unshift({
const routeData: RouteData = {
type: 'redirect',
route,
pattern,
Expand All @@ -458,10 +503,22 @@ export function createRouteManifest(
prerender: false,
redirect: to,
redirectRoute: routes.find(r => r.route === to)
};
const isSpreadRoute = isSpread(route);

binaryInsert(routes, routeData, (a, item) => {
// If the routes are siblings and the redirect route is a spread
// Then it should come after the sibling unless it is also a spread.
// This essentially means that redirects are prioritized when *exactly* the same.
if(isSpreadRoute && areSiblings(a, item)) {
return !isSpread(a.route);
}
return true;
});
});

return {
routes,
};
}

28 changes: 28 additions & 0 deletions packages/astro/test/units/routing/manifest.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,32 @@ describe('routing - createRouteManifest', () => {
expect(pattern.test('')).to.equal(true);
expect(pattern.test('/')).to.equal(false);
});

it('redirects are sorted alongside the filesystem routes', async () => {
const fs = createFs(
{
'/src/pages/index.astro': `<h1>test</h1>`,
'/src/pages/blog/contributing.astro': `<h1>test</h1>`,
},
root
);
const settings = await createDefaultDevSettings(
{
base: '/search',
trailingSlash: 'never',
redirects: {
'/blog/[...slug]': '/'
}
},
root
);
const manifest = createRouteManifest({
cwd: fileURLToPath(root),
settings,
fsMod: fs,
});

expect(manifest.routes[1].route).to.equal('/blog/contributing');
expect(manifest.routes[2].route).to.equal('/blog/[...slug]');
})
});

0 comments on commit 1eca7aa

Please sign in to comment.