Skip to content
Merged
12 changes: 10 additions & 2 deletions packages/next/src/build/normalize-catchall-routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,21 @@ export function normalizeCatchAllRoutes(
normalizer = new AppPathnameNormalizer()
) {
const catchAllRoutes = [
...new Set(Object.values(appPaths).flat().filter(isCatchAllRoute)),
...new Set(
Object.values(appPaths)
.flat()
.filter(isCatchAllRoute)
// Sorting is important because we want to match the most specific path.
.sort((a, b) => b.split('/').length - a.split('/').length)
),
]

for (const appPath of Object.keys(appPaths)) {
for (const catchAllRoute of catchAllRoutes) {
const normalizedCatchAllRoute = normalizer.normalize(catchAllRoute)
const normalizedCatchAllRouteBasePath = normalizedCatchAllRoute.slice(
0,
normalizedCatchAllRoute.indexOf('[')
normalizedCatchAllRoute.search(catchAllRouteRegex)
)

if (
Expand Down Expand Up @@ -48,6 +54,8 @@ function hasMatchedSlots(path1: string, path2: string): boolean {
return true
}

const catchAllRouteRegex = /\[?\[\.\.\./

function isCatchAllRoute(pathname: string): boolean {
return pathname.includes('[...') || pathname.includes('[[...')
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Page() {
return 'slot catchall'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default function Default() {
return (
<div>
<div>Default</div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Foo() {
return 'foo id catchAll'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Foo() {
return 'foo slot'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Page() {
return 'main catchall'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Bar() {
return 'bar'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Page() {
return 'foo id'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Page() {
return 'foo'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Link from 'next/link'

export default function Layout({ children, slot }) {
return (
<div>
<div>Main content</div>
<div id="main">{children}</div>
<div>
Slot content:
<div id="slot-content">{slot}</div>
</div>

<div>
<Link href="/parallel-nested-catchall/foo">foo</Link>
</div>
<div>
<Link href="/parallel-nested-catchall/bar">catchall bar</Link>
</div>
<div>
<Link href="/parallel-nested-catchall/foo/123">catchall foo id</Link>
</div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default function Page() {
return (
<div>
<div>Page</div>
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,37 @@ createNextDescribe(
)
})

it('Should match the catch-all routes of the more specific path, If there is more than one catch-all route', async () => {
const browser = await next.browser('/parallel-nested-catchall')

await browser
.elementByCss('[href="/parallel-nested-catchall/foo"]')
.click()
await check(() => browser.waitForElementByCss('#main').text(), 'foo')
await check(
() => browser.waitForElementByCss('#slot-content').text(),
'foo slot'
)

await browser
.elementByCss('[href="/parallel-nested-catchall/bar"]')
.click()
await check(() => browser.waitForElementByCss('#main').text(), 'bar')
await check(
() => browser.waitForElementByCss('#slot-content').text(),
'slot catchall'
)

await browser
.elementByCss('[href="/parallel-nested-catchall/foo/123"]')
.click()
await check(() => browser.waitForElementByCss('#main').text(), 'foo id')
await check(
() => browser.waitForElementByCss('#slot-content').text(),
'foo id catchAll'
)
})

it('should navigate with a link with prefetch=false', async () => {
const browser = await next.browser('/parallel-prefetch-false')

Expand Down