11import type { SidebarTab } from "fumadocs-ui/utils/get-sidebar-tabs" ;
22
33function normalize ( url : string ) {
4- if ( url . length > 1 && url . endsWith ( "/" ) ) return url . slice ( 0 , - 1 ) ;
5- return url ;
4+ if ( url . length > 1 && url . endsWith ( "/" ) ) return url . slice ( 0 , - 1 ) ;
5+ return url ;
66}
77
88// Products that have versioned paths like /product/X.Y.x/...
@@ -12,9 +12,9 @@ const VERSIONED_PRODUCTS = ["/relayer", "/monitor"];
1212const VERSION_PATTERN = / ^ ( \d + \. \d + \. x ) $ / ;
1313
1414interface ParsedPath {
15- base : string ;
16- version : string | null ; // null means development/unversioned
17- subpath : string ;
15+ base : string ;
16+ version : string | null ; // null means development/unversioned
17+ subpath : string ;
1818}
1919
2020/**
@@ -25,89 +25,89 @@ interface ParsedPath {
2525 * For non-product paths, returns null.
2626 */
2727function parseProductPath ( path : string ) : ParsedPath | null {
28- const normalizedPath = normalize ( path ) ;
29-
30- for ( const product of VERSIONED_PRODUCTS ) {
31- if ( normalizedPath === product ) {
32- // Exact match to product root (development version)
33- return { base : product , version : null , subpath : "" } ;
34- }
35-
36- if ( normalizedPath . startsWith ( `${ product } /` ) ) {
37- const remainder = normalizedPath . slice ( product . length + 1 ) ; // +1 for the slash
38- const segments = remainder . split ( "/" ) ;
39- const firstSegment = segments [ 0 ] ;
40-
41- if ( firstSegment && VERSION_PATTERN . test ( firstSegment ) ) {
42- // Versioned path: /relayer/1.3.x or /relayer/1.3.x/quickstart
43- return {
44- base : product ,
45- version : firstSegment ,
46- subpath : segments . length > 1 ? `/${ segments . slice ( 1 ) . join ( "/" ) } ` : "" ,
47- } ;
48- }
49- // Development path with subpath: /relayer/quickstart
50- return {
51- base : product ,
52- version : null ,
53- subpath : `/${ remainder } ` ,
54- } ;
55- }
56- }
57-
58- return null ;
28+ const normalizedPath = normalize ( path ) ;
29+
30+ for ( const product of VERSIONED_PRODUCTS ) {
31+ if ( normalizedPath === product ) {
32+ // Exact match to product root (development version)
33+ return { base : product , version : null , subpath : "" } ;
34+ }
35+
36+ if ( normalizedPath . startsWith ( `${ product } /` ) ) {
37+ const remainder = normalizedPath . slice ( product . length + 1 ) ; // +1 for the slash
38+ const segments = remainder . split ( "/" ) ;
39+ const firstSegment = segments [ 0 ] ;
40+
41+ if ( firstSegment && VERSION_PATTERN . test ( firstSegment ) ) {
42+ // Versioned path: /relayer/1.3.x or /relayer/1.3.x/quickstart
43+ return {
44+ base : product ,
45+ version : firstSegment ,
46+ subpath : segments . length > 1 ? `/${ segments . slice ( 1 ) . join ( "/" ) } ` : "" ,
47+ } ;
48+ }
49+ // Development path with subpath: /relayer/quickstart
50+ return {
51+ base : product ,
52+ version : null ,
53+ subpath : `/${ remainder } ` ,
54+ } ;
55+ }
56+ }
57+
58+ return null ;
5959}
6060
6161export function isActive (
62- url : string ,
63- pathname : string ,
64- nested = true
62+ url : string ,
63+ pathname : string ,
64+ nested = true ,
6565) : boolean {
66- url = normalize ( url ) ;
67- pathname = normalize ( pathname ) ;
68-
69- // Standard exact match or nested match
70- if ( url === pathname || ( nested && pathname . startsWith ( `${ url } /` ) ) ) {
71- return true ;
72- }
73-
74- // Check for versioned/development path matching
75- const urlParsed = parseProductPath ( url ) ;
76- const pathnameParsed = parseProductPath ( pathname ) ;
77-
78- if ( urlParsed && pathnameParsed ) {
79- // Both are paths for the same product
80- if ( urlParsed . base === pathnameParsed . base ) {
81- // Same subpath means it's the same "page" just different version
82- if ( urlParsed . subpath === pathnameParsed . subpath ) {
83- return true ;
84- }
85-
86- // Check if pathname is nested under url's subpath
87- if (
88- nested &&
89- pathnameParsed . subpath . startsWith ( `${ urlParsed . subpath } /` )
90- ) {
91- return true ;
92- }
93-
94- // Handle root match: /relayer/1.3.x should match any /relayer/* when nested
95- if ( nested && urlParsed . subpath === "" ) {
96- return true ;
97- }
98- }
99- }
100-
101- return false ;
66+ url = normalize ( url ) ;
67+ pathname = normalize ( pathname ) ;
68+
69+ // Standard exact match or nested match
70+ if ( url === pathname || ( nested && pathname . startsWith ( `${ url } /` ) ) ) {
71+ return true ;
72+ }
73+
74+ // Check for versioned/development path matching
75+ const urlParsed = parseProductPath ( url ) ;
76+ const pathnameParsed = parseProductPath ( pathname ) ;
77+
78+ if ( urlParsed && pathnameParsed ) {
79+ // Both are paths for the same product
80+ if ( urlParsed . base === pathnameParsed . base ) {
81+ // Same subpath means it's the same "page" just different version
82+ if ( urlParsed . subpath === pathnameParsed . subpath ) {
83+ return true ;
84+ }
85+
86+ // Check if pathname is nested under url's subpath
87+ if (
88+ nested &&
89+ pathnameParsed . subpath . startsWith ( `${ urlParsed . subpath } /` )
90+ ) {
91+ return true ;
92+ }
93+
94+ // Handle root match: /relayer/1.3.x should match any /relayer/* when nested
95+ if ( nested && urlParsed . subpath === "" ) {
96+ return true ;
97+ }
98+ }
99+ }
100+
101+ return false ;
102102}
103103
104104export function isTabActive ( tab : SidebarTab , pathname : string ) {
105- if ( tab . urls ) {
106- const normalizedPathname = normalize ( pathname ) ;
107- return Array . from ( tab . urls ) . some ( ( url ) =>
108- isActive ( url , normalizedPathname , true )
109- ) ;
110- }
111-
112- return isActive ( tab . url , pathname , true ) ;
105+ if ( tab . urls ) {
106+ const normalizedPathname = normalize ( pathname ) ;
107+ return Array . from ( tab . urls ) . some ( ( url ) =>
108+ isActive ( url , normalizedPathname , true ) ,
109+ ) ;
110+ }
111+
112+ return isActive ( tab . url , pathname , true ) ;
113113}
0 commit comments