Implement priority (#7210)
This commit is contained in:
parent
ef9a456f25
commit
fa03a41a7a
2 changed files with 88 additions and 3 deletions
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -444,9 +491,7 @@ export function createRouteManifest(
|
|||
.map(([{ dynamic, content }]) => (dynamic ? `[${content}]` : content))
|
||||
.join('/')}`.toLowerCase();
|
||||
|
||||
|
||||
|
||||
routes.unshift({
|
||||
const routeData: RouteData = {
|
||||
type: 'redirect',
|
||||
route,
|
||||
pattern,
|
||||
|
@ -458,6 +503,17 @@ 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;
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -465,3 +521,4 @@ export function createRouteManifest(
|
|||
routes,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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]');
|
||||
})
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue