55using Elastic . Markdown . Diagnostics ;
66using Elastic . Markdown . Myst . Directives ;
77using Elastic . Markdown . Slices . Directives ;
8+ using Markdig . Helpers ;
89using Markdig . Renderers ;
910using Markdig . Renderers . Html ;
1011using Markdig . Syntax ;
@@ -14,15 +15,71 @@ namespace Elastic.Markdown.Myst.CodeBlocks;
1415
1516public class EnhancedCodeBlockHtmlRenderer : HtmlObjectRenderer < EnhancedCodeBlock >
1617{
18+ private const int TabWidth = 4 ;
1719
1820 private static void RenderRazorSlice < T > ( RazorSlice < T > slice , HtmlRenderer renderer , EnhancedCodeBlock block )
1921 {
2022 var html = slice . RenderAsync ( ) . GetAwaiter ( ) . GetResult ( ) ;
2123 var blocks = html . Split ( "[CONTENT]" , 2 , StringSplitOptions . RemoveEmptyEntries ) ;
2224 renderer . Write ( blocks [ 0 ] ) ;
23- renderer . WriteLeafRawLines ( block , true , true , false ) ;
25+ RenderCodeBlockLines ( renderer , block ) ;
2426 renderer . Write ( blocks [ 1 ] ) ;
2527 }
28+
29+ /// <summary>
30+ /// Renders the code block lines while also removing the common indentation level.
31+ /// Required because EnableTrackTrivia preserves extra indentation.
32+ /// </summary>
33+ private static void RenderCodeBlockLines ( HtmlRenderer renderer , EnhancedCodeBlock block )
34+ {
35+ var commonIndent = GetCommonIndent ( block ) ;
36+ for ( var i = 0 ; i < block . Lines . Count ; i ++ )
37+ {
38+ var line = block . Lines . Lines [ i ] ;
39+ var slice = line . Slice ;
40+ var indent = CountIndentation ( slice ) ;
41+ if ( indent >= commonIndent )
42+ slice . Start += commonIndent ;
43+ RenderCodeBlockLine ( renderer , block , slice , i ) ;
44+ }
45+ }
46+
47+ private static void RenderCodeBlockLine ( HtmlRenderer renderer , EnhancedCodeBlock block , StringSlice slice , int i )
48+ {
49+ renderer . WriteEscape ( slice ) ;
50+ renderer . WriteLine ( ) ;
51+ }
52+
53+ private static int GetCommonIndent ( EnhancedCodeBlock block )
54+ {
55+ var commonIndent = int . MaxValue ;
56+ for ( var i = 0 ; i < block . Lines . Count ; i ++ )
57+ {
58+ var line = block . Lines . Lines [ i ] . Slice ;
59+ if ( line . IsEmptyOrWhitespace ( ) ) continue ;
60+ var indent = CountIndentation ( line ) ;
61+ commonIndent = Math . Min ( commonIndent , indent ) ;
62+ }
63+ return commonIndent ;
64+ }
65+
66+
67+ private static int CountIndentation ( StringSlice slice )
68+ {
69+ var indentCount = 0 ;
70+ for ( var i = slice . Start ; i <= slice . End ; i ++ )
71+ {
72+ var c = slice . Text [ i ] ;
73+ if ( c == ' ' )
74+ indentCount ++ ;
75+ else if ( c == '\t ' )
76+ indentCount += TabWidth ;
77+ else
78+ break ;
79+ }
80+ return indentCount ;
81+ }
82+
2683 protected override void Write ( HtmlRenderer renderer , EnhancedCodeBlock block )
2784 {
2885 var callOuts = block . UniqueCallOuts ;
0 commit comments