@@ -14,7 +14,7 @@ namespace Elastic.Markdown.CrossLinks;
1414public interface ICrossLinkResolver
1515{
1616 Task FetchLinks ( ) ;
17- bool TryResolve ( Uri crosslinkUri , [ NotNullWhen ( true ) ] out Uri ? resolvedUri ) ;
17+ bool TryResolve ( Action < string > errorEmitter , Uri crossLinkUri , [ NotNullWhen ( true ) ] out Uri ? resolvedUri ) ;
1818}
1919
2020public class CrossLinkResolver ( ConfigurationFile configuration , ILoggerFactory logger ) : ICrossLinkResolver
@@ -41,29 +41,53 @@ public async Task FetchLinks()
4141 _linkReferences = dictionary . ToFrozenDictionary ( ) ;
4242 }
4343
44- public bool TryResolve ( Uri crosslinkUri , [ NotNullWhen ( true ) ] out Uri ? resolvedUri ) =>
45- TryResolve ( _linkReferences , crosslinkUri , out resolvedUri ) ;
44+ public bool TryResolve ( Action < string > errorEmitter , Uri crossLinkUri , [ NotNullWhen ( true ) ] out Uri ? resolvedUri ) =>
45+ TryResolve ( errorEmitter , _linkReferences , crossLinkUri , out resolvedUri ) ;
4646
47- public static bool TryResolve ( IDictionary < string , LinkReference > lookup , Uri crosslinkUri , [ NotNullWhen ( true ) ] out Uri ? resolvedUri )
47+ private static Uri BaseUri { get ; } = new Uri ( "https://docs-v3-preview.elastic.dev" ) ;
48+
49+ public static bool TryResolve ( Action < string > errorEmitter , IDictionary < string , LinkReference > lookup , Uri crossLinkUri , [ NotNullWhen ( true ) ] out Uri ? resolvedUri )
4850 {
4951 resolvedUri = null ;
50- if ( ! lookup . TryGetValue ( crosslinkUri . Scheme , out var linkReference ) )
52+ if ( ! lookup . TryGetValue ( crossLinkUri . Scheme , out var linkReference ) )
5153 {
52- //TODO emit error
54+ errorEmitter ( $ "' { crossLinkUri . Scheme } ' is not declared as valid cross link repository in docset.yml under cross_links" ) ;
5355 return false ;
5456 }
55- var lookupPath = crosslinkUri . AbsolutePath . TrimStart ( '/' ) ;
57+ var lookupPath = crossLinkUri . AbsolutePath . TrimStart ( '/' ) ;
58+ if ( string . IsNullOrEmpty ( lookupPath ) && crossLinkUri . Host . EndsWith ( ".md" ) )
59+ lookupPath = crossLinkUri . Host ;
5660
5761 if ( ! linkReference . Links . TryGetValue ( lookupPath , out var link ) )
5862 {
59- //TODO emit error
63+ errorEmitter ( $ "' { lookupPath } ' is not a valid link in the ' { crossLinkUri . Scheme } ' cross link repository." ) ;
6064 return false ;
6165 }
6266
6367 //https://docs-v3-preview.elastic.dev/elastic/docs-content/tree/main/cloud-account/change-your-password
6468 var path = lookupPath . Replace ( ".md" , "" ) ;
65- var baseUri = new Uri ( "https://docs-v3-preview.elastic.dev" ) ;
66- resolvedUri = new Uri ( baseUri , $ "elastic/{ crosslinkUri . Scheme } /tree/main/{ path } ") ;
69+ if ( path . EndsWith ( "/index" ) )
70+ path = path . Substring ( 0 , path . Length - 6 ) ;
71+ if ( path == "index" )
72+ path = string . Empty ;
73+
74+ if ( ! string . IsNullOrEmpty ( crossLinkUri . Fragment ) )
75+ {
76+ if ( link . Anchors is null )
77+ {
78+ errorEmitter ( $ "'{ lookupPath } ' does not have any anchors so linking to '{ crossLinkUri . Fragment } ' is impossible.") ;
79+ return false ;
80+ }
81+
82+ if ( ! link . Anchors . Contains ( crossLinkUri . Fragment . TrimStart ( '#' ) ) )
83+ {
84+ errorEmitter ( $ "'{ lookupPath } ' has no anchor named: '{ crossLinkUri . Fragment } '.") ;
85+ return false ;
86+ }
87+ path += crossLinkUri . Fragment ;
88+ }
89+
90+ resolvedUri = new Uri ( BaseUri , $ "elastic/{ crossLinkUri . Scheme } /tree/main/{ path } ") ;
6791 return true ;
6892 }
6993}
0 commit comments