Skip to content

Commit 69dcc22

Browse files
authored
1 parent b8773eb commit 69dcc22

File tree

1 file changed

+136
-83
lines changed

1 file changed

+136
-83
lines changed

src/middleware.ts

Lines changed: 136 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,141 @@
1-
import { NextResponse } from 'next/server'
2-
import type { NextRequest } from 'next/server'
3-
import docsConfig from '../docs.config.js'
4-
5-
const { updatedRedirectsData } = require('./data/redirects.ts');
6-
7-
function createRedirectUrl(request: NextRequest, destination: string, path: string): string {
8-
// Handle absolute URLs
9-
if (destination.startsWith('http')) {
10-
// Handle dynamic slug replacements
11-
if (destination.includes(':slug')) {
12-
const slugMatch = path.match(/[^/]+$/)
13-
const slug = slugMatch ? slugMatch[0] : ''
14-
destination = destination.replace(':slug*', slug)
15-
}
16-
// Handle version replacements
17-
if (destination.includes(':version')) {
18-
const versionMatch = path.match(/\d+\.\d+/)
19-
const version = versionMatch ? versionMatch[0] : ''
20-
destination = destination.replace(':version', version)
21-
}
22-
23-
return destination
24-
}
25-
26-
// Handle relative paths
27-
const basePath = '/docs'
28-
return destination.startsWith('/') ?
29-
`${request.nextUrl.origin}${basePath}${destination}` :
30-
`${request.nextUrl.origin}${basePath}/${destination}`
31-
}
1+
import type { NextRequest } from 'next/server';
2+
import { NextResponse } from 'next/server';
3+
import docsConfig from '../docs.config.js';
4+
5+
const {updatedRedirectsData} = require('./data/redirects.ts');
6+
7+
function createRedirectUrl(
8+
request: NextRequest,
9+
destination: string,
10+
path: string
11+
): string {
12+
// Handle absolute URLs
13+
if (destination.startsWith('http')) {
14+
// Extract version and full path after version
15+
const versionMatch = path.match(/(?:\/v\/|@)(\d+\.\d+)\/(.*)/);
16+
17+
if (versionMatch) {
18+
const version = versionMatch[1];
19+
const remainingPath = versionMatch[2];
20+
21+
// Find matching redirect for the remaining path
22+
const redirect = updatedRedirectsData.find(
23+
(r: any) =>
24+
r.source === `/${remainingPath}` ||
25+
r.source === remainingPath
26+
);
27+
28+
// If redirect exists, use its destination, otherwise use the remaining path
29+
const finalPath = redirect
30+
? redirect.destination.replace(/^\//, '')
31+
: remainingPath;
32+
33+
// Replace placeholders and construct final URL
34+
return destination
35+
.replace(':version', version)
36+
.replace(':slug*', finalPath);
37+
}
38+
39+
// Handle other cases as before
40+
if (destination.includes(':slug')) {
41+
const slugMatch = path.match(/[^/]+$/);
42+
const slug = slugMatch ? slugMatch[0] : '';
43+
destination = destination.replace(':slug*', slug);
44+
}
45+
46+
return destination;
47+
}
3248

49+
// Handle relative paths
50+
const basePath = '/docs';
51+
return destination.startsWith('/')
52+
? `${request.nextUrl.origin}${basePath}${destination}`
53+
: `${request.nextUrl.origin}${basePath}/${destination}`;
54+
}
3355
export function middleware(request: NextRequest) {
34-
const path = request.nextUrl.pathname
35-
const pathWithoutBase = path.replace('/docs', '')
36-
37-
// Handle base redirects from redirects.ts
38-
const redirect = updatedRedirectsData.find((r: any) => r.source === pathWithoutBase)
39-
if (redirect) {
40-
return NextResponse.redirect(createRedirectUrl(request, redirect.destination, path))
41-
}
42-
// Handle version without slug
43-
const versionOnlyMatch = pathWithoutBase.match(/^\/v\/(\d+\.\d+)$/)
44-
if (versionOnlyMatch) {
45-
return NextResponse.redirect(`https://${versionOnlyMatch[1]}.sourcegraph.com/`)
46-
}
47-
// Handle version-specific redirects
48-
if (pathWithoutBase.startsWith(`/v/${docsConfig.DOCS_LATEST_VERSION}/`)) {
49-
return NextResponse.redirect(createRedirectUrl(
50-
request,
51-
`https://sourcegraph.com/docs/:slug*`,
52-
pathWithoutBase
53-
))
54-
}
55-
if (pathWithoutBase.startsWith(`/@${docsConfig.DOCS_LATEST_VERSION}/`)) {
56-
return NextResponse.redirect(createRedirectUrl(
57-
request,
58-
`https://sourcegraph.com/docs/:slug*`,
59-
pathWithoutBase
60-
))
61-
}
62-
const versionMatch = pathWithoutBase.match(/^\/v\/(\d+\.\d+)\/(.*)/)
63-
if (versionMatch) {
64-
return NextResponse.redirect(createRedirectUrl(
65-
request,
66-
'https://:version.sourcegraph.com/:slug*',
67-
pathWithoutBase
68-
))
69-
}
70-
const atVersionMatch = pathWithoutBase.match(/^\/@(\d+\.\d+)\/(.*)/)
71-
if (atVersionMatch) {
72-
return NextResponse.redirect(createRedirectUrl(
73-
request,
74-
'https://:version.sourcegraph.com/:slug*',
75-
pathWithoutBase
76-
))
77-
}
78-
if (pathWithoutBase === '/changelog.rss')
79-
return NextResponse.redirect(createRedirectUrl(request, '/technical-changelog.rss', path))
80-
81-
return NextResponse.next()
56+
const path = request.nextUrl.pathname;
57+
const pathWithoutBase = path.replace('/docs', '');
58+
59+
// Handle base redirects from redirects.ts
60+
const redirect = updatedRedirectsData.find(
61+
(r: any) => r.source === pathWithoutBase
62+
);
63+
if (redirect) {
64+
return NextResponse.redirect(
65+
createRedirectUrl(request, redirect.destination, path)
66+
);
67+
}
68+
69+
// Handle latest version without path - redirect to main docs
70+
const latestVersionOnlyMatch = pathWithoutBase.match(
71+
`^\/(?:v\/|@)${docsConfig.DOCS_LATEST_VERSION}\/?$`
72+
);
73+
if (latestVersionOnlyMatch) {
74+
return NextResponse.redirect(`https://sourcegraph.com/docs`);
75+
}
76+
77+
// Handle version without slug - both /v/X.Y and @X.Y formats (for non-latest versions)
78+
const versionOnlyMatch = pathWithoutBase.match(
79+
/^\/(?:v\/|@)(\d+\.\d+)\/?$/
80+
);
81+
if (
82+
versionOnlyMatch &&
83+
versionOnlyMatch[1] !== docsConfig.DOCS_LATEST_VERSION
84+
) {
85+
return NextResponse.redirect(
86+
`https://${versionOnlyMatch[1]}.sourcegraph.com/`
87+
);
88+
}
89+
90+
// Handle version-specific redirects
91+
if (pathWithoutBase.startsWith(`/v/${docsConfig.DOCS_LATEST_VERSION}/`)) {
92+
return NextResponse.redirect(
93+
createRedirectUrl(
94+
request,
95+
`https://sourcegraph.com/docs/:slug*`,
96+
pathWithoutBase
97+
)
98+
);
99+
}
100+
if (pathWithoutBase.startsWith(`/@${docsConfig.DOCS_LATEST_VERSION}/`)) {
101+
return NextResponse.redirect(
102+
createRedirectUrl(
103+
request,
104+
`https://sourcegraph.com/docs/:slug*`,
105+
pathWithoutBase
106+
)
107+
);
108+
}
109+
const versionMatch = pathWithoutBase.match(/^\/v\/(\d+\.\d+)\/(.*)/);
110+
if (versionMatch) {
111+
return NextResponse.redirect(
112+
createRedirectUrl(
113+
request,
114+
'https://:version.sourcegraph.com/:slug*',
115+
pathWithoutBase
116+
)
117+
);
118+
}
119+
const atVersionMatch = pathWithoutBase.match(/^\/@(\d+\.\d+)\/(.*)/);
120+
121+
if (atVersionMatch) {
122+
return NextResponse.redirect(
123+
createRedirectUrl(
124+
request,
125+
'https://:version.sourcegraph.com/:slug*',
126+
pathWithoutBase
127+
)
128+
);
129+
}
130+
131+
if (pathWithoutBase === '/changelog.rss')
132+
return NextResponse.redirect(
133+
createRedirectUrl(request, '/technical-changelog.rss', path)
134+
);
135+
136+
return NextResponse.next();
82137
}
83138

84139
export const config = {
85-
matcher: [
86-
'/((?!api|_next/static|_next/image|assets|favicon.ico|sw.js).*)',
87-
],
88-
}
140+
matcher: ['/((?!api|_next/static|_next/image|assets|favicon.ico|sw.js).*)']
141+
};

0 commit comments

Comments
 (0)