1- using System . Text ;
21using Markdig . Renderers ;
32using Markdig . Renderers . Html ;
43using Markdig . Syntax . Inlines ;
4+ using System . Text ;
5+ using System . Text . RegularExpressions ;
56
67namespace Blake . MarkdownParser ;
78
8-
9- public class ImageCaptionRenderer : HtmlObjectRenderer < LinkInline >
9+ public partial class ImageCaptionRenderer : HtmlObjectRenderer < LinkInline >
1010{
11+ private static readonly Regex _shorthandDimensionsRegex = ShorthandRegex ( ) ;
12+
1113 protected override void Write ( HtmlRenderer renderer , LinkInline link )
1214 {
1315 if ( link . IsImage )
1416 {
15-
1617 var caption = link . FirstChild ? . ToString ( ) ?? "" ;
17- var src = link . Url ? . Trim ( ) ?? "" ;
18+ var originalSrc = link . Url ? . Trim ( ) ?? "" ;
19+
20+ // Parse shorthand dimensions from URL (e.g., "/image.png =200x300")
21+ var ( src , shorthandWidth , shorthandHeight ) = ParseShorthandDimensions ( originalSrc ) ;
1822
1923 // Read GenericAttributes
2024 var attrs = link . TryGetAttributes ( ) ;
2125
26+ // Apply shorthand dimensions if no explicit width/height attributes are present
27+ if ( attrs == null )
28+ {
29+ attrs = new HtmlAttributes ( ) ;
30+ }
31+
32+ // Only apply shorthand if no explicit dimensions are set via generic attributes
33+ var hasExplicitWidth = attrs . Properties ? . Any ( p => p . Key == "width" ) ?? false ;
34+ var hasExplicitHeight = attrs . Properties ? . Any ( p => p . Key == "height" ) ?? false ;
35+
36+ if ( ! hasExplicitWidth && shorthandWidth . HasValue )
37+ {
38+ attrs . AddProperty ( "width" , shorthandWidth . Value . ToString ( ) ) ;
39+ }
40+
41+ if ( ! hasExplicitHeight && shorthandHeight . HasValue )
42+ {
43+ attrs . AddProperty ( "height" , shorthandHeight . Value . ToString ( ) ) ;
44+ }
45+
2246 // Build attribute string
2347 var attrString = BuildAttributeString ( attrs ) ;
2448
2549 // Fallback style if no explicit width or style
26- var hasWidth = attrs ? . Properties ? . Any ( p => p . Key == "width" ) ?? false ;
27- var hasStyle = attrs ? . Properties ? . Any ( p => p . Key == "style" ) ?? false ;
50+ var hasWidth = attrs . Properties ? . Any ( p => p . Key == "width" ) ?? false ;
51+ var hasStyle = attrs . Properties ? . Any ( p => p . Key == "style" ) ?? false ;
2852 if ( ! hasWidth && ! hasStyle )
2953 {
3054 attrString += " style=\" max-width:100%;height:auto;\" " ;
@@ -52,7 +76,7 @@ private string BuildAttributeString(HtmlAttributes? attrs)
5276
5377 var sb = new StringBuilder ( ) ;
5478
55- foreach ( var prop in attrs ? . Properties ?? [ ] )
79+ foreach ( var prop in attrs ? . Properties ?? [ ] )
5680 {
5781 var safeName = HtmlEscape ( prop . Key ) ;
5882 var safeValue = HtmlEscape ( prop . Value ?? "" ) ;
@@ -62,6 +86,44 @@ private string BuildAttributeString(HtmlAttributes? attrs)
6286 return sb . ToString ( ) ;
6387 }
6488
89+ private static ( string cleanUrl , int ? width , int ? height ) ParseShorthandDimensions ( string url )
90+ {
91+ var match = _shorthandDimensionsRegex . Match ( url ) ;
92+ if ( ! match . Success )
93+ {
94+ return ( url , null , null ) ;
95+ }
96+
97+ var cleanUrl = url . Substring ( 0 , match . Index ) . Trim ( ) ;
98+
99+ var widthGroup = match . Groups [ 1 ] ;
100+ var heightGroup = match . Groups [ 2 ] ;
101+
102+ int ? width = null ;
103+ int ? height = null ;
104+
105+ if ( widthGroup . Success && ! string . IsNullOrEmpty ( widthGroup . Value ) )
106+ {
107+ if ( int . TryParse ( widthGroup . Value , out var w ) )
108+ {
109+ width = w ;
110+ }
111+ }
112+
113+ if ( heightGroup . Success && ! string . IsNullOrEmpty ( heightGroup . Value ) )
114+ {
115+ if ( int . TryParse ( heightGroup . Value , out var h ) )
116+ {
117+ height = h ;
118+ }
119+ }
120+
121+ return ( cleanUrl , width , height ) ;
122+ }
123+
65124 private static string HtmlEscape ( string input ) =>
66125 System . Net . WebUtility . HtmlEncode ( input ) ;
67- }
126+
127+ [ GeneratedRegex ( @"\s*=(\d*)?x(\d*)?\s*$" , RegexOptions . Compiled ) ]
128+ private static partial Regex ShorthandRegex ( ) ;
129+ }
0 commit comments