@@ -31,7 +31,7 @@ public record ApiTag(string Name, string Description, IReadOnlyCollection<ApiEnd
3131 public Task RenderAsync ( FileSystemStream stream , ApiRenderContext context , CancellationToken ctx = default ) => Task . CompletedTask ;
3232}
3333
34- public record ApiEndpoint ( string Route , IOpenApiPathItem OpenApiPath , List < ApiOperation > Operations , string ? Name ) : IApiGroupingModel
34+ public record ApiEndpoint ( List < ApiOperation > Operations , string ? Name ) : IApiGroupingModel
3535{
3636 /// <inheritdoc />
3737 public Task RenderAsync ( FileSystemStream stream , ApiRenderContext context , CancellationToken ctx = default ) => Task . CompletedTask ;
@@ -48,6 +48,54 @@ public static LandingNavigationItem CreateNavigation(OpenApiDocument openApiDocu
4848 var url = "/api" ;
4949 var rootNavigation = new LandingNavigationItem ( url ) ;
5050
51+ var ops = openApiDocument . Paths
52+ . SelectMany ( p => p . Value . Operations . Select ( op => ( Path : p , Operation : op ) ) )
53+ . Select ( pair =>
54+ {
55+ var op = pair . Operation ;
56+ var extensions = op . Value . Extensions ;
57+ var ns = ( extensions ? . TryGetValue ( "x-namespace" , out var n ) ?? false ) && n is OpenApiAny anyNs
58+ ? anyNs . Node . GetValue < string > ( )
59+ : null ;
60+ var api = ( extensions ? . TryGetValue ( "x-api-name" , out var a ) ?? false ) && a is OpenApiAny anyApi
61+ ? anyApi . Node . GetValue < string > ( )
62+ : null ;
63+ var tag = op . Value . Tags ? . FirstOrDefault ( ) ? . Reference . Id ;
64+ var classification = openApiDocument . Info . Title == "Elasticsearch Request & Response Specification"
65+ ? ClassifyElasticsearchTag ( tag ?? "unknown" )
66+ : "unknown" ;
67+
68+ var apiString = ns is null
69+ ? api ?? op . Value . Summary ?? Guid . NewGuid ( ) . ToString ( "N" ) : $ "{ ns } .{ api } ";
70+ return new
71+ {
72+ Classification = classification ,
73+ Api = apiString ,
74+ Tag = tag ,
75+ pair . Path ,
76+ pair . Operation
77+ } ;
78+ } )
79+ . ToArray ( ) ;
80+
81+ var nestedGrouping =
82+ (
83+ from op in ops
84+ group op by op . Classification
85+ into classificationGroup
86+ from tagGroup in
87+ from op in classificationGroup
88+ group op by op . Tag
89+ into apiGroups
90+ from apiGroup in
91+ from op in apiGroups
92+ group op by op . Api
93+ group apiGroup by apiGroups . Key
94+ group tagGroup by classificationGroup . Key
95+ ) . ToArray ( ) ;
96+
97+
98+ /*
5199 var grouped = openApiDocument.Paths
52100 .Select(p =>
53101 {
@@ -60,48 +108,48 @@ public static LandingNavigationItem CreateNavigation(OpenApiDocument openApiDocu
60108 ? anyApi.Node.GetValue<string>()
61109 : null;
62110 var tag = op.Value.Tags?.FirstOrDefault()?.Reference.Id;
63- if ( tag is not null )
64- {
65- }
66- var classification = openApiDocument . Info . Title == "Elasticsearch Request & Response Specification" ? ClassifyElasticsearchTag ( tag ?? "unknown" ) : "unknown" ;
111+ var classification = openApiDocument.Info.Title == "Elasticsearch Request & Response Specification"
112+ ? ClassifyElasticsearchTag(tag ?? "unknown")
113+ : "unknown";
67114
115+ var apiString = ns is null ? api ?? Guid.NewGuid().ToString("N") : $"{ns}.{api}";
68116 return new
69117 {
70118 Classification = classification,
71- Namespace = ns ,
72- Api = api ,
119+ Api = apiString,
73120 Tag = tag,
74121 Path = p
75122 };
76123 })
77124 .GroupBy(g => g.Classification)
78125 .ToArray();
126+ */
79127
80128 // intermediate grouping of models to create the navigation tree
81129 // this is two-phased because we need to know if an endpoint has one or more operations
82130 var classifications = new List < ApiClassification > ( ) ;
83- foreach ( var group in grouped )
131+ foreach ( var classificationGroup in nestedGrouping )
84132 {
85133 var tags = new List < ApiTag > ( ) ;
86- foreach ( var tagGroup in group . GroupBy ( g => g . Tag ) )
134+ foreach ( var tagGroup in classificationGroup )
87135 {
88- var endpoints = new List < ApiEndpoint > ( ) ;
89- foreach ( var endpoint in tagGroup )
136+ var apis = new List < ApiEndpoint > ( ) ;
137+ foreach ( var apiGroup in tagGroup )
90138 {
91- var api = endpoint . Namespace is null ? endpoint . Api ?? null : $ "{ endpoint . Namespace } .{ endpoint . Api } ";
92139 var operations = new List < ApiOperation > ( ) ;
93- foreach ( var operation in endpoint . Path . Value . Operations )
140+ foreach ( var api in apiGroup )
94141 {
95- var apiOperation = new ApiOperation ( operation . Key , operation . Value , endpoint . Path . Key , api ) ;
142+ var operation = api . Operation ;
143+ var apiOperation = new ApiOperation ( operation . Key , operation . Value , api . Path . Key , api . Path . Value , apiGroup . Key ) ;
96144 operations . Add ( apiOperation ) ;
97145 }
98- var apiEndpoint = new ApiEndpoint ( endpoint . Path . Key , endpoint . Path . Value , operations , api ) ;
99- endpoints . Add ( apiEndpoint ) ;
146+ var apiEndpoint = new ApiEndpoint ( operations , apiGroup . Key ) ;
147+ apis . Add ( apiEndpoint ) ;
100148 }
101- var tag = new ApiTag ( tagGroup . Key ?? "unknown" , "" , endpoints ) ;
149+ var tag = new ApiTag ( tagGroup . Key ?? "unknown" , "" , apis ) ;
102150 tags . Add ( tag ) ;
103151 }
104- var classification = new ApiClassification ( group . Key , "" , tags ) ;
152+ var classification = new ApiClassification ( classificationGroup . Key , "" , tags ) ;
105153 classifications . Add ( classification ) ;
106154 }
107155
@@ -171,7 +219,10 @@ List<IEndpointOrOperationNavigationItem> endpointNavigationItems
171219 var operationNavigationItems = new List < OperationNavigationItem > ( ) ;
172220 foreach ( var operation in endpoint . Operations )
173221 {
174- var operationNavigationItem = new OperationNavigationItem ( operation , rootNavigation , endpointNavigationItem ) ;
222+ var operationNavigationItem = new OperationNavigationItem ( operation , rootNavigation , endpointNavigationItem )
223+ {
224+ Hidden = true
225+ } ;
175226 operationNavigationItems . Add ( operationNavigationItem ) ;
176227 }
177228 endpointNavigationItem . NavigationItems = operationNavigationItems ;
@@ -219,12 +270,12 @@ async Task RenderNavigationItems(INavigationItem currentNavigation)
219270 await RenderNavigationItems ( child ) ;
220271 }
221272
273+ #pragma warning disable IDE0045
222274 else if ( currentNavigation is ILeafNavigationItem < IApiModel > leaf )
275+ #pragma warning restore IDE0045
223276 _ = await Render ( leaf , leaf . Model , renderContext , navigationRenderer , ctx ) ;
224277 else
225- {
226-
227- }
278+ throw new Exception ( $ "Unknown navigation item type { currentNavigation . GetType ( ) } ") ;
228279 }
229280 }
230281
0 commit comments