22// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
33// See the LICENSE file in the project root for more information
44
5+ using System . Collections . Immutable ;
56using Elastic . Markdown . Diagnostics ;
67using Elastic . Markdown . IO ;
7- using Elastic . Markdown . Myst . Directives ;
88using Markdig ;
99using Markdig . Helpers ;
1010using Markdig . Parsers ;
1111using Markdig . Parsers . Inlines ;
1212using Markdig . Renderers ;
13- using Markdig . Syntax ;
1413using Markdig . Syntax . Inlines ;
1514
1615namespace Elastic . Markdown . Myst . InlineParsers ;
@@ -34,6 +33,9 @@ public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer) { }
3433
3534public class DiagnosticLinkInlineParser : LinkInlineParser
3635{
36+
37+ private static readonly ImmutableHashSet < string > ExcludedSchemes = new [ ] { "http" , "https" , "tel" , "jdbc" } . ToImmutableHashSet ( ) ;
38+
3739 public override bool Match ( InlineProcessor processor , ref StringSlice slice )
3840 {
3941 var match = base . Match ( processor , ref slice ) ;
@@ -44,10 +46,14 @@ public override bool Match(InlineProcessor processor, ref StringSlice slice)
4446 return match ;
4547
4648 var url = link . Url ;
49+ var uri = Uri . TryCreate ( url , UriKind . Absolute , out var u ) ? u : null ;
4750 var line = link . Line + 1 ;
4851 var column = link . Column ;
4952 var length = url ? . Length ?? 1 ;
5053
54+ if ( IsExternalLink ( uri ) )
55+ processor . GetContext ( ) . Build . Collector . EmitExternalLink ( url ! ) ;
56+
5157 var context = processor . GetContext ( ) ;
5258 if ( processor . GetContext ( ) . SkipValidation )
5359 return match ;
@@ -58,7 +64,7 @@ public override bool Match(InlineProcessor processor, ref StringSlice slice)
5864 return match ;
5965 }
6066
61- if ( Uri . TryCreate ( url , UriKind . Absolute , out var uri ) && uri . Scheme . StartsWith ( "http" ) )
67+ if ( uri != null && uri . Scheme . StartsWith ( "http" ) )
6268 {
6369 var baseDomain = uri . Host == "localhost" ? "localhost" : string . Join ( '.' , uri . Host . Split ( '.' ) [ ^ 2 ..] ) ;
6470 if ( ! context . Configuration . ExternalLinkHosts . Contains ( baseDomain ) )
@@ -82,15 +88,11 @@ public override bool Match(InlineProcessor processor, ref StringSlice slice)
8288 var anchor = anchors . Length > 1 ? anchors [ 1 ] . Trim ( ) : null ;
8389 url = anchors [ 0 ] ;
8490
85- if ( ! string . IsNullOrWhiteSpace ( url ) )
91+ if ( ! string . IsNullOrWhiteSpace ( url ) && uri != null )
8692 {
8793 var pathOnDisk = Path . Combine ( includeFrom , url . TrimStart ( '/' ) ) ;
88- if ( ! context . Build . ReadFileSystem . File . Exists ( pathOnDisk ) )
94+ if ( uri . IsFile && ! context . Build . ReadFileSystem . File . Exists ( pathOnDisk ) )
8995 processor . EmitError ( line , column , length , $ "`{ url } ` does not exist. resolved to `{ pathOnDisk } ") ;
90- else
91- {
92-
93- }
9496 }
9597 else
9698 link . Url = "" ;
@@ -128,8 +130,11 @@ public override bool Match(InlineProcessor processor, ref StringSlice slice)
128130 link . Url += $ "#{ anchor } ";
129131
130132 return match ;
131-
132-
133-
134133 }
134+
135+ private static bool IsExternalLink ( Uri ? uri ) =>
136+ uri != null
137+ && ! ExcludedSchemes . Contains ( uri . Scheme )
138+ && ! uri . IsFile
139+ && Path . GetExtension ( uri . OriginalString ) == ".md" ;
135140}
0 commit comments