Skip to content

Commit

Permalink
add support for segments that ends with a more specific [dynamicRoute]
Browse files Browse the repository at this point in the history
support parallel routes that has [dynamicRoute] instead of `default`
  • Loading branch information
williamli committed Jan 17, 2024
1 parent 74a2fb4 commit 4a865c5
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 18 deletions.
14 changes: 14 additions & 0 deletions packages/next/src/build/normalize-catchall-routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,21 @@ describe('normalizeCatchallRoutes', () => {
}

const initialAppPaths = JSON.parse(JSON.stringify(appPaths))
normalizeCatchAllRoutes(appPaths)
expect(appPaths).toMatchObject(initialAppPaths)
})

it('should not add the catch-all route to segments that have a more specific [dynamicRoute]', () => {
const appPaths = {
'/': ['/page'],
'/[[...catchAll]]': ['/[[...catchAll]]/page'],
'/nested/[foo]/[bar]/default': ['/nested/[foo]/[bar]/default'],
'/nested/[foo]/[bar]': ['/nested/[foo]/[bar]/@slot/page'],
'/nested/[foo]/[bar]/[baz]': ['/nested/[foo]/[bar]/@slot/[baz]/page'],
}

const initialAppPaths = JSON.parse(JSON.stringify(appPaths))
normalizeCatchAllRoutes(appPaths)
expect(appPaths).toMatchObject(initialAppPaths)
})

Expand Down
33 changes: 15 additions & 18 deletions packages/next/src/build/normalize-catchall-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export function normalizeCatchAllRoutes(
appPaths: Record<string, string[]>,
normalizer = new AppPathnameNormalizer()
) {
console.log({ appPaths })
const catchAllRoutes = [
...new Set(
Object.values(appPaths)
Expand All @@ -33,7 +32,6 @@ export function normalizeCatchAllRoutes(

for (const appPath of filteredAppPaths) {
for (const catchAllRoute of catchAllRoutes) {
console.log(`${appPath} vs ${catchAllRoute}`)
const normalizedCatchAllRoute = normalizer.normalize(catchAllRoute)
const normalizedCatchAllRouteBasePath = normalizedCatchAllRoute.slice(
0,
Expand All @@ -43,33 +41,24 @@ export function normalizeCatchAllRoutes(
// check if the appPath could match the catch-all
appPath.startsWith(normalizedCatchAllRouteBasePath) &&
// check if there's not already a slot value that could match the catch-all
!appPaths[appPath].some((path) => {
const output = hasMatchedSlots(path, catchAllRoute)
console.log(`hasMatchedSlots: ${path} - ${catchAllRoute}: ${output}`)
return output
}) &&
!appPaths[appPath].some((path) =>
hasMatchedSlots(path, catchAllRoute)
) &&
// check if the catch-all is not already matched by a default route or page route
!appPaths[`${appPath}/default`] &&
// check if the appPath's end with a dynamic route
!endsInDynamic(appPath)
// check if appPath does not ends with a dynamic segment that is not a catch-all (with endsWithDynamic) AND is more specific than the catch-all
!(endsWithDynamic(appPath) && isMoreSpecific(appPath, catchAllRoute))
) {
console.log('✅')
appPaths[appPath].push(catchAllRoute)
} else {
console.log('❌')
}
}
}

console.log({ normalizedPaths: appPaths })
}

function hasMatchedSlots(path1: string, path2: string): boolean {
const slots1 = path1.split('/').filter(isMatchableSlot)
const slots2 = path2.split('/').filter(isMatchableSlot)

console.log({ slots1, slots2 })

// if the catch-all route does not have the same number of slots as the app path, it can't match
if (slots1.length !== slots2.length) return false

Expand All @@ -96,7 +85,15 @@ function isCatchAllRoute(pathname: string): boolean {
return pathname.includes('[...') || pathname.includes('[[...')
}

function endsInDynamic(pathname: string): boolean {
function endsWithDynamic(pathname: string): boolean {
const pathnameParts = pathname.split('/')
return isDynamicRoute(`/${pathnameParts[pathnameParts.length - 1]}`)
const endPath = `/${pathnameParts[pathnameParts.length - 1]}`

return isDynamicRoute(endPath) && !isCatchAllRoute(endPath)
}

function isMoreSpecific(pathname: string, catchAllRoute: string): boolean {
const pathnameDepth = pathname.split('/').length
const catchAllRouteDepth = catchAllRoute.split('/').length - 1
return pathnameDepth > catchAllRouteDepth
}

0 comments on commit 4a865c5

Please sign in to comment.