@@ -26,8 +26,46 @@ public interface INavigationLookups
2626
2727public interface IPositionalNavigation
2828{
29+ FrozenDictionary < string , INavigationItem > MarkdownNavigationLookup { get ; }
30+
2931 MarkdownFile ? GetPrevious ( MarkdownFile current ) ;
3032 MarkdownFile ? GetNext ( MarkdownFile current ) ;
33+
34+ INavigationItem [ ] GetParents ( INavigationItem current )
35+ {
36+ var parents = new List < INavigationItem > ( ) ;
37+ var parent = current . Parent ;
38+ do
39+ {
40+ if ( parent is null )
41+ continue ;
42+ parents . Add ( parent ) ;
43+ parent = parent . Parent ;
44+ } while ( parent != null ) ;
45+
46+ return [ .. parents ] ;
47+ }
48+ MarkdownFile [ ] GetParentMarkdownFiles ( INavigationItem current )
49+ {
50+ var parents = new List < MarkdownFile > ( ) ;
51+ var navigationParents = GetParents ( current ) ;
52+ foreach ( var parent in navigationParents )
53+ {
54+ if ( parent is FileNavigationItem f )
55+ parents . Add ( f . File ) ;
56+ if ( parent is GroupNavigationItem { Group . Index : not null } g )
57+ parents . Add ( g . Group . Index ) ;
58+ if ( parent is DocumentationGroup { Index : not null } dg )
59+ parents . Add ( dg . Index ) ;
60+ }
61+ return [ .. parents ] ;
62+ }
63+ MarkdownFile [ ] GetParentMarkdownFiles ( MarkdownFile file )
64+ {
65+ if ( MarkdownNavigationLookup . TryGetValue ( file . CrossLink , out var navigationItem ) )
66+ return GetParentMarkdownFiles ( navigationItem ) ;
67+ return [ ] ;
68+ }
3169}
3270
3371public record NavigationLookups : INavigationLookups
@@ -71,6 +109,8 @@ public class DocumentationSet : INavigationLookups, IPositionalNavigation
71109
72110 IReadOnlyCollection < IDocsBuilderExtension > INavigationLookups . EnabledExtensions => Configuration . EnabledExtensions ;
73111
112+ public FrozenDictionary < string , INavigationItem > MarkdownNavigationLookup { get ; }
113+
74114 // FrozenDictionary<Uri, TableOfContentsReference>? indexedTableOfContents = null
75115 public DocumentationSet (
76116 BuildContext build ,
@@ -137,9 +177,32 @@ public DocumentationSet(
137177
138178 MarkdownFiles = markdownFiles . Where ( f => f . NavigationIndex > - 1 ) . ToDictionary ( i => i . NavigationIndex , i => i ) . ToFrozenDictionary ( ) ;
139179
180+ MarkdownNavigationLookup = Tree . NavigationItems
181+ . SelectMany ( Pairs )
182+ . ToDictionary ( kv => kv . Item1 , kv => kv . Item2 )
183+ . ToFrozenDictionary ( ) ;
184+
140185 ValidateRedirectsExists ( ) ;
141186 }
142187
188+ public static ( string , INavigationItem ) [ ] Pairs ( INavigationItem item )
189+ {
190+ if ( item is FileNavigationItem f )
191+ return [ ( f . File . CrossLink , item ) ] ;
192+ if ( item is GroupNavigationItem g )
193+ {
194+ var index = new List < ( string , INavigationItem ) > ( ) ;
195+ if ( g . Group . Index is not null )
196+ index . Add ( ( g . Group . Index . CrossLink , g ) ) ;
197+
198+ return index . Concat ( g . Group . NavigationItems . SelectMany ( Pairs ) . ToArray ( ) )
199+ . DistinctBy ( kv => kv . Item1 )
200+ . ToArray ( ) ;
201+ }
202+
203+ return [ ] ;
204+ }
205+
143206 private DocumentationFile [ ] ScanDocumentationFiles ( BuildContext build , IDirectoryInfo sourceDirectory ) =>
144207 [ .. build . ReadFileSystem . Directory
145208 . EnumerateFiles ( sourceDirectory . FullName , "*.*" , SearchOption . AllDirectories )
@@ -150,11 +213,11 @@ [.. build.ReadFileSystem.Directory
150213 . Where ( f => ! Path . GetRelativePath ( sourceDirectory . FullName , f . FullName ) . StartsWith ( '.' ) )
151214 . Select < IFileInfo , DocumentationFile > ( file => file . Extension switch
152215 {
153- ".jpg" => new ImageFile ( file , SourceDirectory , "image/jpeg" ) ,
154- ".jpeg" => new ImageFile ( file , SourceDirectory , "image/jpeg" ) ,
155- ".gif" => new ImageFile ( file , SourceDirectory , "image/gif" ) ,
156- ".svg" => new ImageFile ( file , SourceDirectory , "image/svg+xml" ) ,
157- ".png" => new ImageFile ( file , SourceDirectory ) ,
216+ ".jpg" => new ImageFile ( file , SourceDirectory , build . Git . RepositoryName , "image/jpeg" ) ,
217+ ".jpeg" => new ImageFile ( file , SourceDirectory , build . Git . RepositoryName , "image/jpeg" ) ,
218+ ".gif" => new ImageFile ( file , SourceDirectory , build . Git . RepositoryName , "image/gif" ) ,
219+ ".svg" => new ImageFile ( file , SourceDirectory , build . Git . RepositoryName , "image/svg+xml" ) ,
220+ ".png" => new ImageFile ( file , SourceDirectory , build . Git . RepositoryName ) ,
158221 ".md" => CreateMarkDownFile ( file , build ) ,
159222 _ => DefaultFileHandling ( file , sourceDirectory )
160223 } ) ] ;
@@ -167,7 +230,7 @@ private DocumentationFile DefaultFileHandling(IFileInfo file, IDirectoryInfo sou
167230 if ( documentationFile is not null )
168231 return documentationFile ;
169232 }
170- return new ExcludedFile ( file , sourceDirectory ) ;
233+ return new ExcludedFile ( file , sourceDirectory , Build . Git . RepositoryName ) ;
171234 }
172235
173236 private void ValidateRedirectsExists ( )
@@ -265,15 +328,15 @@ private DocumentationFile CreateMarkDownFile(IFileInfo file, BuildContext contex
265328 {
266329 var relativePath = Path . GetRelativePath ( SourceDirectory . FullName , file . FullName ) ;
267330 if ( Configuration . Exclude . Any ( g => g . IsMatch ( relativePath ) ) )
268- return new ExcludedFile ( file , SourceDirectory ) ;
331+ return new ExcludedFile ( file , SourceDirectory , context . Git . RepositoryName ) ;
269332
270333 if ( relativePath . Contains ( "_snippets" ) )
271- return new SnippetFile ( file , SourceDirectory ) ;
334+ return new SnippetFile ( file , SourceDirectory , context . Git . RepositoryName ) ;
272335
273336 // we ignore files in folders that start with an underscore
274337 var folder = Path . GetDirectoryName ( relativePath ) ;
275338 if ( folder is not null && ( folder . Contains ( $ "{ Path . DirectorySeparatorChar } _", StringComparison . Ordinal ) || folder . StartsWith ( '_' ) ) )
276- return new ExcludedFile ( file , SourceDirectory ) ;
339+ return new ExcludedFile ( file , SourceDirectory , context . Git . RepositoryName ) ;
277340
278341 if ( Configuration . Files . Contains ( relativePath ) )
279342 return ExtensionOrDefaultMarkdown ( ) ;
@@ -282,7 +345,7 @@ private DocumentationFile CreateMarkDownFile(IFileInfo file, BuildContext contex
282345 return ExtensionOrDefaultMarkdown ( ) ;
283346
284347 context . EmitError ( Configuration . SourceFile , $ "Not linked in toc: { relativePath } ") ;
285- return new ExcludedFile ( file , SourceDirectory ) ;
348+ return new ExcludedFile ( file , SourceDirectory , context . Git . RepositoryName ) ;
286349
287350 MarkdownFile ExtensionOrDefaultMarkdown ( )
288351 {
0 commit comments