55using System . IO . Abstractions ;
66using System . Runtime . InteropServices ;
77using Elastic . Markdown . Extensions . DetectionRules ;
8- using Elastic . Markdown . IO . Navigation ;
98using YamlDotNet . RepresentationModel ;
109
1110namespace Elastic . Markdown . IO . Configuration ;
@@ -15,6 +14,18 @@ public interface ITableOfContentsScope
1514 IDirectoryInfo ScopeDirectory { get ; }
1615}
1716
17+ public static class ContentSourceMoniker
18+ {
19+ public static Uri Create ( string repo , string ? path ) => new ( CreateString ( repo , path ) ) ;
20+
21+ public static string CreateString ( string repo , string ? path )
22+ {
23+ if ( string . IsNullOrWhiteSpace ( path ) )
24+ return $ "{ repo } ://";
25+ return $ "{ repo } ://{ path . Replace ( "\\ " , "/" ) . Trim ( '/' ) } /";
26+ }
27+ }
28+
1829public record TableOfContentsConfiguration : ITableOfContentsScope
1930{
2031 private readonly BuildContext _context ;
@@ -24,24 +35,64 @@ public record TableOfContentsConfiguration : ITableOfContentsScope
2435 private readonly IDirectoryInfo _rootPath ;
2536 private readonly ConfigurationFile _configuration ;
2637
38+ public Uri Source { get ; }
39+
2740 public HashSet < string > Files { get ; } = new ( StringComparer . OrdinalIgnoreCase ) ;
2841
2942 public IReadOnlyCollection < ITocItem > TableOfContents { get ; private set ; } = [ ] ;
3043
44+ public IFileInfo DefinitionFile { get ; }
3145 public IDirectoryInfo ScopeDirectory { get ; }
3246
33- public TableOfContentsConfiguration ( ConfigurationFile configuration , IDirectoryInfo scope , BuildContext context , int depth , string parentPath )
47+ public TableOfContentsConfiguration (
48+ ConfigurationFile configuration ,
49+ IFileInfo definitionFile ,
50+ IDirectoryInfo scope ,
51+ BuildContext context ,
52+ int depth ,
53+ string parentPath )
3454 {
3555 _configuration = configuration ;
56+ DefinitionFile = definitionFile ;
3657 ScopeDirectory = scope ;
3758 _maxTocDepth = configuration . MaxTocDepth ;
3859 _rootPath = context . DocumentationSourceDirectory ;
3960 _context = context ;
4061 _depth = depth ;
4162 _parentPath = parentPath ;
63+
64+ var tocPath = scope . FullName ;
65+ var relativePath = Path . GetRelativePath ( context . DocumentationSourceDirectory . FullName , tocPath ) ;
66+ var moniker = ContentSourceMoniker . Create ( context . Git . RepositoryName , relativePath ) ;
67+ Source = moniker ;
68+
69+ TableOfContents = ReadChildren ( ) ;
70+
71+ }
72+
73+ private IReadOnlyCollection < ITocItem > ReadChildren ( )
74+ {
75+ if ( ! DefinitionFile . Exists )
76+ return [ ] ;
77+ var reader = new YamlStreamReader ( DefinitionFile , _context . Collector ) ;
78+ foreach ( var entry in reader . Read ( ) )
79+ {
80+ switch ( entry . Key )
81+ {
82+ case "toc" :
83+ var children = ReadChildren ( reader , entry . Entry ) ;
84+ var tocEntries = TableOfContents . OfType < TocReference > ( ) . ToArray ( ) ;
85+ if ( ! _configuration . DevelopmentDocs && ! _configuration . IsNarrativeDocs && tocEntries . Length > 0 && TableOfContents . Count != tocEntries . Length )
86+ reader . EmitError ( "toc links to other toc sections it may only contain other toc references" , entry . Key ) ;
87+ return children ;
88+ }
89+ }
90+
91+
92+ return [ ] ;
4293 }
4394
44- public IReadOnlyCollection < ITocItem > ReadChildren ( YamlStreamReader reader , KeyValuePair < YamlNode , YamlNode > entry , string ? parentPath = null )
95+ private IReadOnlyCollection < ITocItem > ReadChildren ( YamlStreamReader reader , KeyValuePair < YamlNode , YamlNode > entry , string ? parentPath = null )
4596 {
4697 parentPath ??= _parentPath ;
4798 if ( _depth > _maxTocDepth )
@@ -118,7 +169,7 @@ public IReadOnlyCollection<ITocItem> ReadChildren(YamlStreamReader reader, KeyVa
118169 foreach ( var f in toc . Files )
119170 _ = Files . Add ( f ) ;
120171
121- return [ new TocReference ( this , $ "{ parentPath } ". TrimStart ( Path . DirectorySeparatorChar ) , folderFound , toc . TableOfContents ) ] ;
172+ return [ new TocReference ( toc . Source , toc , $ "{ parentPath } ". TrimStart ( Path . DirectorySeparatorChar ) , folderFound , toc . TableOfContents ) ] ;
122173 }
123174
124175 if ( file is not null )
@@ -244,7 +295,7 @@ public IReadOnlyCollection<ITocItem> ReadChildren(YamlStreamReader reader, KeyVa
244295 switch ( kv . Key )
245296 {
246297 case "toc" :
247- var nestedConfiguration = new TableOfContentsConfiguration ( _configuration , source . Directory ! , _context , _depth + 1 , fullTocPath ) ;
298+ var nestedConfiguration = new TableOfContentsConfiguration ( _configuration , source , source . Directory ! , _context , _depth + 1 , fullTocPath ) ;
248299 _ = nestedConfiguration . ReadChildren ( reader , kv . Entry ) ;
249300 return nestedConfiguration ;
250301 }
0 commit comments