@@ -2,6 +2,7 @@ import type { GitBookSiteContext } from '@v2/lib/context';
22import { redirect } from 'next/navigation' ;
33
44import { resolvePageId , resolvePagePath } from '@/lib/pages' ;
5+ import { withLeadingSlash } from '@/lib/paths' ;
56import { getDataOrNull } from '@v2/lib/data' ;
67
78export interface PagePathParams {
@@ -35,14 +36,14 @@ export async function fetchPageData(context: GitBookSiteContext, params: PagePar
3536 * If the path can't be found, we try to resolve it from the API to handle redirects.
3637 */
3738async function resolvePage ( context : GitBookSiteContext , params : PagePathParams | PageIdParams ) {
38- const { organizationId, site, space, revisionId, pages, shareKey } = context ;
39+ const { organizationId, site, space, revisionId, pages, shareKey, linker } = context ;
3940
4041 if ( 'pageId' in params ) {
4142 return resolvePageId ( pages , params . pageId ) ;
4243 }
4344
4445 const rawPathname = getPathnameParam ( params ) ;
45- const pathname = normalizePathname ( rawPathname ) ;
46+ const pathname = rawPathname . toLowerCase ( ) ;
4647
4748 // When resolving a page, we use the lowercased pathname
4849 const page = resolvePagePath ( pages , pathname ) ;
@@ -67,16 +68,31 @@ async function resolvePage(context: GitBookSiteContext, params: PagePathParams |
6768 }
6869
6970 // If a page still can't be found, we try with the API, in case we have a redirect at site level.
70- const resolvedSiteRedirect = await getDataOrNull (
71- context . dataFetcher . getSiteRedirectBySource ( {
72- organizationId,
73- siteId : site . id ,
74- source : rawPathname . startsWith ( '/' ) ? rawPathname : `/${ rawPathname } ` ,
75- siteShareKey : shareKey ,
76- } )
77- ) ;
78- if ( resolvedSiteRedirect ) {
79- return redirect ( resolvedSiteRedirect . target ) ;
71+ const redirectPathname = withLeadingSlash ( rawPathname ) ;
72+ if ( / ^ \/ [ a - z A - Z 0 - 9 - _ .\/ ] + [ a - z A - Z 0 - 9 - _ .] $ / . test ( redirectPathname ) ) {
73+ const redirectSources = new Set < string > ( [
74+ // Test the pathname relative to the root
75+ // For example hello/world -> section/variant/hello/world
76+ withLeadingSlash (
77+ linker . toRelativePathInSite ( linker . toPathInSpace ( redirectPathname ) )
78+ ) ,
79+ // Test the pathname relative to the content/space
80+ // For example hello/world -> /hello/world
81+ redirectPathname ,
82+ ] ) ;
83+ for ( const source of redirectSources ) {
84+ const resolvedSiteRedirect = await getDataOrNull (
85+ context . dataFetcher . getSiteRedirectBySource ( {
86+ organizationId,
87+ siteId : site . id ,
88+ source,
89+ siteShareKey : shareKey ,
90+ } )
91+ ) ;
92+ if ( resolvedSiteRedirect ) {
93+ return redirect ( linker . toLinkForContent ( resolvedSiteRedirect . target ) ) ;
94+ }
95+ }
8096 }
8197 }
8298
@@ -99,10 +115,3 @@ export function getPathnameParam(params: PagePathParams): string {
99115
100116 return pathname . map ( ( part ) => decodeURIComponent ( part ) ) . join ( '/' ) ;
101117}
102-
103- /**
104- * Normalize the URL pathname into the format used in the revision page path.
105- */
106- export function normalizePathname ( pathname : string ) {
107- return pathname . toLowerCase ( ) ;
108- }
0 commit comments