@@ -123,7 +123,6 @@ func parse(glob string, extraFiles []string) (*result, error) {
123123 }
124124
125125 pages := map [string ]* page {}
126- toc := tableOfContents {}
127126
128127 module := pkgs [0 ].Module
129128 skippedModules := map [string ]struct {}{}
@@ -177,6 +176,8 @@ func parse(glob string, extraFiles []string) (*result, error) {
177176 }
178177 sort .Strings (pkgNames )
179178
179+ toc := buildTOC (module .Path , pkgNames , extraFiles )
180+
180181 // Once the files are grouped by package, process each package
181182 // independently.
182183 for _ , pkgPath := range pkgNames {
@@ -201,26 +202,6 @@ func parse(glob string, extraFiles []string) (*result, error) {
201202 continue
202203 }
203204
204- pkgTOCITem := & tocItem {
205- UID : docPkg .ImportPath ,
206- Name : docPkg .ImportPath ,
207- }
208- toc = append (toc , pkgTOCITem )
209-
210- // If the package path == module path, add the extra files to the TOC
211- // as a child of the module==pkg item.
212- if pkgPath == module .Path {
213- for _ , path := range extraFiles {
214- base := filepath .Base (path )
215- name := strings .TrimSuffix (base , filepath .Ext (base ))
216- name = strings .Title (name )
217- pkgTOCITem .addItem (& tocItem {
218- Href : path ,
219- Name : name ,
220- })
221- }
222- }
223-
224205 pkgItem := & item {
225206 UID : docPkg .ImportPath ,
226207 Name : docPkg .ImportPath ,
@@ -412,3 +393,114 @@ func processExamples(exs []*doc.Example, fset *token.FileSet) []example {
412393 }
413394 return result
414395}
396+
397+ func buildTOC (mod string , pkgs []string , extraFiles []string ) tableOfContents {
398+ toc := tableOfContents {}
399+
400+ modTOC := & tocItem {
401+ UID : mod , // Assume the module root has a package.
402+ Name : mod ,
403+ }
404+ for _ , path := range extraFiles {
405+ base := filepath .Base (path )
406+ name := strings .TrimSuffix (base , filepath .Ext (base ))
407+ name = strings .Title (name )
408+ modTOC .addItem (& tocItem {
409+ Href : path ,
410+ Name : name ,
411+ })
412+ }
413+
414+ toc = append (toc , modTOC )
415+
416+ if len (pkgs ) == 1 {
417+ // The module only has one package.
418+ return toc
419+ }
420+
421+ // partialTrie represents the parts of each package name that come after
422+ // the module name.
423+ //
424+ // A package name is three parts: mod/mid/suffix
425+ //
426+ // For example, cloud.google.com/go/bigquery/connection/apiv1 would be split
427+ // into cloud.google.com/go, bigquery, and connection/apiv1.
428+ //
429+ // Don't do a full trie to keep nesting to a minimum.
430+ partialTrie := map [string ][]string {}
431+ mids := []string {}
432+
433+ for _ , pkg := range pkgs {
434+ if pkg == mod {
435+ continue
436+ }
437+ if ! strings .HasPrefix (pkg , mod ) {
438+ panic (fmt .Sprintf ("Package %q does not start with %q, should never happen" , pkg , mod ))
439+ }
440+ midAndSuffix := strings .TrimPrefix (pkg , mod + "/" )
441+ parts := strings .SplitN (midAndSuffix , "/" , 2 )
442+
443+ mid := parts [0 ]
444+ suffix := ""
445+ if len (parts ) > 1 {
446+ suffix = parts [1 ]
447+ }
448+
449+ if _ , ok := partialTrie [mid ]; ! ok {
450+ mids = append (mids , mid )
451+ }
452+
453+ partialTrie [mid ] = append (partialTrie [mid ], suffix )
454+ }
455+
456+ sort .Strings (mids )
457+
458+ for _ , mid := range mids {
459+ suffixes := partialTrie [mid ]
460+
461+ // No need to nest if there is only one suffix.
462+ if len (suffixes ) == 1 {
463+ suffix := suffixes [0 ]
464+ name := mid
465+ if suffix != "" {
466+ name = name + "/" + suffix
467+ }
468+ uid := mod + "/" + name
469+ pkgTOCItem := & tocItem {
470+ UID : uid ,
471+ Name : name ,
472+ }
473+ modTOC .addItem (pkgTOCItem )
474+ continue
475+ }
476+
477+ sort .Strings (suffixes )
478+
479+ midTOC := & tocItem {
480+ // No Uref or UID because this may not be a package.
481+ Name : mid ,
482+ }
483+ modTOC .addItem (midTOC )
484+
485+ for _ , suffix := range suffixes {
486+ uid := mod + "/" + mid
487+ if suffix != "" {
488+ uid = uid + "/" + suffix
489+ }
490+
491+ // Empty suffix means this mid is a package itself.
492+ if suffix == "" {
493+ midTOC .UID = uid
494+ continue
495+ }
496+
497+ pkgTOC := & tocItem {
498+ UID : uid ,
499+ Name : suffix ,
500+ }
501+ midTOC .addItem (pkgTOC )
502+ }
503+ }
504+
505+ return toc
506+ }
0 commit comments