@@ -22,6 +22,7 @@ public class CrossLinkResolver(ConfigurationFile configuration, ILoggerFactory l
2222 private readonly string [ ] _links = configuration . CrossLinkRepositories ;
2323 private FrozenDictionary < string , LinkReference > _linkReferences = new Dictionary < string , LinkReference > ( ) . ToFrozenDictionary ( ) ;
2424 private readonly ILogger _logger = logger . CreateLogger ( nameof ( CrossLinkResolver ) ) ;
25+ private readonly HashSet < string > _declaredRepositories = new ( ) ;
2526
2627 public static LinkReference Deserialize ( string json ) =>
2728 JsonSerializer . Deserialize ( json , SourceGenerationContext . Default . LinkReference ) ! ;
@@ -32,28 +33,65 @@ public async Task FetchLinks()
3233 var dictionary = new Dictionary < string , LinkReference > ( ) ;
3334 foreach ( var link in _links )
3435 {
35- var url = $ "https://elastic-docs-link-index.s3.us-east-2.amazonaws.com/elastic/{ link } /main/links.json";
36- _logger . LogInformation ( $ "Fetching { url } ") ;
37- var json = await client . GetStringAsync ( url ) ;
38- var linkReference = Deserialize ( json ) ;
39- dictionary . Add ( link , linkReference ) ;
36+ _declaredRepositories . Add ( link ) ;
37+ try
38+ {
39+ var url = $ "https://elastic-docs-link-index.s3.us-east-2.amazonaws.com/elastic/{ link } /main/links.json";
40+ _logger . LogInformation ( $ "Fetching { url } ") ;
41+ var json = await client . GetStringAsync ( url ) ;
42+ var linkReference = Deserialize ( json ) ;
43+ dictionary . Add ( link , linkReference ) ;
44+ }
45+ catch when ( link == "docs-content" )
46+ {
47+ throw ;
48+ }
49+ catch when ( link != "docs-content" )
50+ {
51+ // TODO: ignored for now while we wait for all links.json files to populate
52+ }
4053 }
4154 _linkReferences = dictionary . ToFrozenDictionary ( ) ;
4255 }
4356
4457 public bool TryResolve ( Action < string > errorEmitter , Uri crossLinkUri , [ NotNullWhen ( true ) ] out Uri ? resolvedUri ) =>
45- TryResolve ( errorEmitter , _linkReferences , crossLinkUri , out resolvedUri ) ;
58+ TryResolve ( errorEmitter , _declaredRepositories , _linkReferences , crossLinkUri , out resolvedUri ) ;
4659
4760 private static Uri BaseUri { get ; } = new Uri ( "https://docs-v3-preview.elastic.dev" ) ;
4861
49- public static bool TryResolve ( Action < string > errorEmitter , IDictionary < string , LinkReference > lookup , Uri crossLinkUri , [ NotNullWhen ( true ) ] out Uri ? resolvedUri )
62+ public static bool TryResolve ( Action < string > errorEmitter , HashSet < string > declaredRepositories , IDictionary < string , LinkReference > lookup , Uri crossLinkUri , [ NotNullWhen ( true ) ] out Uri ? resolvedUri )
5063 {
5164 resolvedUri = null ;
52- if ( ! lookup . TryGetValue ( crossLinkUri . Scheme , out var linkReference ) )
65+ if ( crossLinkUri . Scheme == "docs-content" )
66+ {
67+ if ( ! lookup . TryGetValue ( crossLinkUri . Scheme , out var linkReference ) )
68+ {
69+ errorEmitter ( $ "'{ crossLinkUri . Scheme } ' is not declared as valid cross link repository in docset.yml under cross_links") ;
70+ return false ;
71+ }
72+ return TryFullyValidate ( errorEmitter , linkReference , crossLinkUri , out resolvedUri ) ;
73+ }
74+
75+ // TODO this is temporary while we wait for all links.json files to be published
76+ if ( ! declaredRepositories . Contains ( crossLinkUri . Scheme ) )
5377 {
5478 errorEmitter ( $ "'{ crossLinkUri . Scheme } ' is not declared as valid cross link repository in docset.yml under cross_links") ;
5579 return false ;
5680 }
81+
82+ var lookupPath = crossLinkUri . AbsolutePath . TrimStart ( '/' ) ;
83+ var path = ToTargetUrlPath ( lookupPath ) ;
84+ if ( ! string . IsNullOrEmpty ( crossLinkUri . Fragment ) )
85+ path += crossLinkUri . Fragment ;
86+
87+ var branch = GetBranch ( crossLinkUri ) ;
88+ resolvedUri = new Uri ( BaseUri , $ "elastic/{ crossLinkUri . Scheme } /tree/{ branch } /{ path } ") ;
89+ return true ;
90+ }
91+
92+ private static bool TryFullyValidate ( Action < string > errorEmitter , LinkReference linkReference , Uri crossLinkUri , [ NotNullWhen ( true ) ] out Uri ? resolvedUri )
93+ {
94+ resolvedUri = null ;
5795 var lookupPath = crossLinkUri . AbsolutePath . TrimStart ( '/' ) ;
5896 if ( string . IsNullOrEmpty ( lookupPath ) && crossLinkUri . Host . EndsWith ( ".md" ) )
5997 lookupPath = crossLinkUri . Host ;
@@ -64,12 +102,7 @@ public static bool TryResolve(Action<string> errorEmitter, IDictionary<string, L
64102 return false ;
65103 }
66104
67- //https://docs-v3-preview.elastic.dev/elastic/docs-content/tree/main/cloud-account/change-your-password
68- var path = lookupPath . Replace ( ".md" , "" ) ;
69- if ( path . EndsWith ( "/index" ) )
70- path = path . Substring ( 0 , path . Length - 6 ) ;
71- if ( path == "index" )
72- path = string . Empty ;
105+ var path = ToTargetUrlPath ( lookupPath ) ;
73106
74107 if ( ! string . IsNullOrEmpty ( crossLinkUri . Fragment ) )
75108 {
@@ -87,7 +120,32 @@ public static bool TryResolve(Action<string> errorEmitter, IDictionary<string, L
87120 path += crossLinkUri . Fragment ;
88121 }
89122
90- resolvedUri = new Uri ( BaseUri , $ "elastic/{ crossLinkUri . Scheme } /tree/main/{ path } ") ;
123+ var branch = GetBranch ( crossLinkUri ) ;
124+ resolvedUri = new Uri ( BaseUri , $ "elastic/{ crossLinkUri . Scheme } /tree/{ branch } /{ path } ") ;
91125 return true ;
92126 }
127+
128+ /// Hardcoding these for now, we'll have an index.json pointing to all links.json files
129+ /// at some point from which we can query the branch soon.
130+ private static string GetBranch ( Uri crossLinkUri )
131+ {
132+ var branch = crossLinkUri . Scheme switch
133+ {
134+ "docs-content" => "main" ,
135+ _ => "main"
136+ } ;
137+ return branch ;
138+ }
139+
140+
141+ private static string ToTargetUrlPath ( string lookupPath )
142+ {
143+ //https://docs-v3-preview.elastic.dev/elastic/docs-content/tree/main/cloud-account/change-your-password
144+ var path = lookupPath . Replace ( ".md" , "" ) ;
145+ if ( path . EndsWith ( "/index" ) )
146+ path = path . Substring ( 0 , path . Length - 6 ) ;
147+ if ( path == "index" )
148+ path = string . Empty ;
149+ return path ;
150+ }
93151}
0 commit comments