@@ -14,11 +14,15 @@ public sealed class HtmlLocalLinkParser
1414 // <a type="media" href="/{localLink:7e21a725-b905-4c5f-86dc-8c41ec116e39}" title="media">media</a>
1515 // <a type="document" href="/{localLink:eed5fc6b-96fd-45a5-a0f1-b1adfb483c2f}" title="other page">other page</a>
1616 internal static readonly Regex LocalLinkTagPattern = new (
17- @"<a\s+(?:(?:(?:type=['""](?<type>document|media)['""].*?(?<locallink>href=[""']/{localLink:(?<guid>[a-fA-F0-9-]+)})[""'])|((?<locallink>href=[""']/{localLink:(?<guid>[a-fA-F0-9-]+)})[""'].*?type=(['""])(?<type>document|media)(?:['""])))|(?:(?:type=['""](?<type>document|media)['""])|(?:(?<locallink>href=[""']/{localLink:[a-fA-F0-9-]+})[""'])))[^>]*>" ,
17+ @"<a.+?href=['""](?<locallink>\/?{localLink:(?<guid>[a-fA-F0-9-]+)})[^>]*?>" ,
18+ RegexOptions . IgnoreCase | RegexOptions . IgnorePatternWhitespace | RegexOptions . Singleline ) ;
19+
20+ internal static readonly Regex TypePattern = new (
21+ """type=['"](?<type>(?:media|document))['"]""" ,
1822 RegexOptions . IgnoreCase | RegexOptions . IgnorePatternWhitespace ) ;
1923
2024 internal static readonly Regex LocalLinkPattern = new (
21- @"href=""[/]? (?:\{|\%7B)localLink:([a-zA-Z0-9-://]+)(?:\}|\%7D)" ,
25+ @"href=['""](?<locallink>\/? (?:\{|\%7B)localLink:(?<guid> [a-zA-Z0-9-://]+)(?:\}|\%7D) )" ,
2226 RegexOptions . IgnoreCase | RegexOptions . IgnorePatternWhitespace ) ;
2327
2428 private readonly IPublishedUrlProvider _publishedUrlProvider ;
@@ -58,32 +62,28 @@ public string EnsureInternalLinks(string text)
5862 {
5963 if ( tagData . Udi is not null )
6064 {
61- var newLink = "#" ;
62- if ( tagData . Udi ? . EntityType == Constants . UdiEntityType . Document )
63- {
64- newLink = _publishedUrlProvider . GetUrl ( tagData . Udi . Guid ) ;
65- }
66- else if ( tagData . Udi ? . EntityType == Constants . UdiEntityType . Media )
65+ var newLink = tagData . Udi ? . EntityType switch
6766 {
68- newLink = _publishedUrlProvider . GetMediaUrl ( tagData . Udi . Guid ) ;
69- }
70-
67+ Constants . UdiEntityType . Document => _publishedUrlProvider . GetUrl ( tagData . Udi . Guid ) ,
68+ Constants . UdiEntityType . Media => _publishedUrlProvider . GetMediaUrl ( tagData . Udi . Guid ) ,
69+ _ => ""
70+ } ;
7171
7272 text = StripTypeAttributeFromTag ( text , tagData . Udi ! . EntityType ) ;
73- text = text . Replace ( tagData . TagHref , "href= \" " + newLink ) ;
73+ text = text . Replace ( tagData . TagHref , newLink ) ;
7474 }
7575 else if ( tagData . IntId . HasValue )
7676 {
7777 var newLink = _publishedUrlProvider . GetUrl ( tagData . IntId . Value ) ;
78- text = text . Replace ( tagData . TagHref , "href= \" " + newLink ) ;
78+ text = text . Replace ( tagData . TagHref , newLink ) ;
7979 }
8080 }
8181
8282 return text ;
8383 }
8484
8585 // under normal circumstances, the type attribute is preceded by a space
86- // to cover the rare occasion where it isn't, we first replace with a a space and then without.
86+ // to cover the rare occasion where it isn't, we first replace with a space and then without.
8787 private string StripTypeAttributeFromTag ( string tag , string type ) =>
8888 tag . Replace ( $ " type=\" { type } \" ", string . Empty )
8989 . Replace ( $ "type=\" { type } \" ", string . Empty ) ;
@@ -93,21 +93,22 @@ private IEnumerable<LocalLinkTag> FindLocalLinkIds(string text)
9393 MatchCollection localLinkTagMatches = LocalLinkTagPattern . Matches ( text ) ;
9494 foreach ( Match linkTag in localLinkTagMatches )
9595 {
96- if ( linkTag . Groups . Count < 1 )
96+ if ( Guid . TryParse ( linkTag . Groups [ "guid" ] . Value , out Guid guid ) is false )
9797 {
9898 continue ;
9999 }
100100
101- if ( Guid . TryParse ( linkTag . Groups [ "guid" ] . Value , out Guid guid ) is false )
101+ // Find the type attribute
102+ Match typeMatch = TypePattern . Match ( linkTag . Value ) ;
103+ if ( typeMatch . Success is false )
102104 {
103105 continue ;
104106 }
105107
106108 yield return new LocalLinkTag (
107109 null ,
108- new GuidUdi ( linkTag . Groups [ "type" ] . Value , guid ) ,
109- linkTag . Groups [ "locallink" ] . Value ,
110- linkTag . Value ) ;
110+ new GuidUdi ( typeMatch . Groups [ "type" ] . Value , guid ) ,
111+ linkTag . Groups [ "locallink" ] . Value ) ;
111112 }
112113
113114 // also return legacy results for values that have not been migrated
@@ -124,25 +125,26 @@ private IEnumerable<LocalLinkTag> FindLegacyLocalLinkIds(string text)
124125 MatchCollection tags = LocalLinkPattern . Matches ( text ) ;
125126 foreach ( Match tag in tags )
126127 {
127- if ( tag . Groups . Count > 0 )
128+ if ( tag . Groups . Count <= 0 )
128129 {
129- var id = tag . Groups [ 1 ] . Value ; // .Remove(tag.Groups[1].Value.Length - 1, 1);
130+ continue ;
131+ }
130132
131- // The id could be an int or a UDI
132- if ( UdiParser . TryParse ( id , out Udi ? udi ) )
133- {
134- var guidUdi = udi as GuidUdi ;
135- if ( guidUdi is not null )
136- {
137- yield return new LocalLinkTag ( null , guidUdi , tag . Value , null ) ;
138- }
139- }
133+ var id = tag . Groups [ "guid" ] . Value ;
140134
141- if ( int . TryParse ( id , NumberStyles . Integer , CultureInfo . InvariantCulture , out var intId ) )
135+ // The id could be an int or a UDI
136+ if ( UdiParser . TryParse ( id , out Udi ? udi ) )
137+ {
138+ if ( udi is GuidUdi guidUdi )
142139 {
143- yield return new LocalLinkTag ( intId , null , tag . Value , null ) ;
140+ yield return new LocalLinkTag ( null , guidUdi , tag . Groups [ "locallink" ] . Value ) ;
144141 }
145142 }
143+
144+ if ( int . TryParse ( id , NumberStyles . Integer , CultureInfo . InvariantCulture , out var intId ) )
145+ {
146+ yield return new LocalLinkTag ( intId , null , tag . Groups [ "locallink" ] . Value ) ;
147+ }
146148 }
147149 }
148150
@@ -155,20 +157,10 @@ public LocalLinkTag(int? intId, GuidUdi? udi, string tagHref)
155157 TagHref = tagHref ;
156158 }
157159
158- public LocalLinkTag ( int ? intId , GuidUdi ? udi , string tagHref , string ? fullTag )
159- {
160- IntId = intId ;
161- Udi = udi ;
162- TagHref = tagHref ;
163- FullTag = fullTag ;
164- }
165-
166160 public int ? IntId { get ; }
167161
168162 public GuidUdi ? Udi { get ; }
169163
170164 public string TagHref { get ; }
171-
172- public string ? FullTag { get ; }
173165 }
174166}
0 commit comments