@@ -305,27 +305,70 @@ export class DefaultTheme extends Theme {
305305 return parent . groups . map ( toNavigation ) ;
306306 }
307307
308+ if (
309+ opts . includeFolders &&
310+ parent . children ?. every ( ( child ) => child . kindOf ( ReflectionKind . Module ) ) &&
311+ parent . children . some ( ( child ) => child . name . includes ( "/" ) )
312+ ) {
313+ return deriveModuleFolders ( parent . children ) ;
314+ }
315+
308316 return parent . children ?. map ( toNavigation ) ;
309317 }
310318
311- function shouldShowCategories (
312- reflection : Reflection ,
313- opts : { includeCategories : boolean ; includeGroups : boolean } ,
314- ) {
315- if ( opts . includeCategories ) {
316- return ! reflection . comment ?. hasModifier ( "@hideCategories" ) ;
319+ function deriveModuleFolders ( children : DeclarationReflection [ ] ) {
320+ const result : NavigationElement [ ] = [ ] ;
321+
322+ const resolveOrCreateParents = (
323+ path : string [ ] ,
324+ root : NavigationElement [ ] = result ,
325+ ) : NavigationElement [ ] => {
326+ if ( path . length > 1 ) {
327+ const inner = root . find ( ( el ) => el . text === path [ 0 ] ) ;
328+ if ( inner ) {
329+ inner . children ||= [ ] ;
330+ return resolveOrCreateParents ( path . slice ( 1 ) , inner . children ) ;
331+ } else {
332+ root . push ( {
333+ text : path [ 0 ] ,
334+ children : [ ] ,
335+ } ) ;
336+ return resolveOrCreateParents ( path . slice ( 1 ) , root [ root . length - 1 ] . children ) ;
337+ }
338+ }
339+
340+ return root ;
341+ } ;
342+
343+ // Note: This might end up putting a module within another module if we document
344+ // both foo/index.ts and foo/bar.ts.
345+ for ( const child of children ) {
346+ const parts = child . name . split ( "/" ) ;
347+ const collection = resolveOrCreateParents ( parts ) ;
348+ const nav = toNavigation ( child ) ;
349+ nav . text = parts [ parts . length - 1 ] ;
350+ collection . push ( nav ) ;
317351 }
318- return reflection . comment ?. hasModifier ( "@showCategories" ) === true ;
319- }
320352
321- function shouldShowGroups (
322- reflection : Reflection ,
323- opts : { includeCategories : boolean ; includeGroups : boolean } ,
324- ) {
325- if ( opts . includeGroups ) {
326- return ! reflection . comment ?. hasModifier ( "@hideGroups" ) ;
353+ // Now merge single-possible-paths together so we don't have folders in our navigation
354+ // which contain only another single folder.
355+ const queue = [ ...result ] ;
356+ while ( queue . length ) {
357+ const review = queue . shift ( ) ! ;
358+ queue . push ( ...( review . children || [ ] ) ) ;
359+ if ( review . kind || review . path ) continue ;
360+
361+ if ( review . children ?. length === 1 ) {
362+ const copyFrom = review . children [ 0 ] ;
363+ const fullName = `${ review . text } /${ copyFrom . text } ` ;
364+ delete review . children ;
365+ Object . assign ( review , copyFrom ) ;
366+ review . text = fullName ;
367+ queue . push ( review ) ;
368+ }
327369 }
328- return reflection . comment ?. hasModifier ( "@showGroups" ) === true ;
370+
371+ return result ;
329372 }
330373 }
331374
@@ -401,3 +444,17 @@ function getReflectionClasses(reflection: DeclarationReflection, filters: Record
401444
402445 return classes . join ( " " ) ;
403446}
447+
448+ function shouldShowCategories ( reflection : Reflection , opts : { includeCategories : boolean ; includeGroups : boolean } ) {
449+ if ( opts . includeCategories ) {
450+ return ! reflection . comment ?. hasModifier ( "@hideCategories" ) ;
451+ }
452+ return reflection . comment ?. hasModifier ( "@showCategories" ) === true ;
453+ }
454+
455+ function shouldShowGroups ( reflection : Reflection , opts : { includeCategories : boolean ; includeGroups : boolean } ) {
456+ if ( opts . includeGroups ) {
457+ return ! reflection . comment ?. hasModifier ( "@hideGroups" ) ;
458+ }
459+ return reflection . comment ?. hasModifier ( "@showGroups" ) === true ;
460+ }
0 commit comments