11using System ;
2- using System . Collections . Generic ;
32using System . Linq ;
3+ using System . Text . RegularExpressions ;
44using System . Threading . Tasks ;
55using Microsoft . AspNetCore . Html ;
66using Microsoft . AspNetCore . Mvc . Rendering ;
@@ -17,53 +17,52 @@ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutpu
1717 {
1818 output . TagName = "pre" ;
1919
20- var content = await output . GetChildContentAsync ( ) ;
21- var innerHtml = content . GetContent ( ) . Trim ( '\n ' ) ;
22- var body = TrimPreceding ( innerHtml , ' ' ) ;
20+ var rawContent = ( await output . GetChildContentAsync ( ) ) . GetContent ( ) ;
21+ var body = TrimBaseIndentation ( rawContent ) ;
2322
2423 var code = new TagBuilder ( "code" ) ;
2524 code . AddCssClass ( $ "language-{ Language } ") ;
26- code . InnerHtml . SetHtmlContent ( body ) ;
25+ code . InnerHtml . SetHtmlContent ( $ " { body } \n " ) ;
2726
2827 output . Content . SetHtmlContent ( code ) ;
2928 }
3029
31- private string TrimPreceding ( string value , char character )
30+ private string TrimBaseIndentation ( string content )
3231 {
33- var lines = value . Split ( Environment . NewLine ) ;
34- var preceding = CountPreceding ( lines , character ) ;
35- var trimmedLines = from line in lines
36- select TrimPrecedingLine ( line , character , preceding ) ;
32+ var endsTrimmedContent = TrimStartRegex . Replace ( content . TrimEnd ( ) , "$1" , 1 ) ;
33+ var lines = endsTrimmedContent . Split ( Environment . NewLine ) ;
34+ var baseIndentationLength = CountIndentation ( lines [ 0 ] ) ;
3735
38- return string . Join ( Environment . NewLine , trimmedLines ) ;
39- }
40-
41- private int CountPreceding ( IEnumerable < string > lines , char leadingCharacter )
42- {
43- foreach ( var line in lines )
36+ for ( int i = 0 ; i != lines . Length ; i ++ )
4437 {
45- // Make sure that the line actually starts with the leading character
46- if ( line . StartsWith ( leadingCharacter ) == false )
47- continue ;
38+ var line = lines [ i ] ;
4839
49- // Determine last index of leading character, return if something else is found
50- for ( var i = 0 ; i < line . Length ; i ++ )
40+ var indentationLength = CountIndentation ( line ) ;
41+ if ( indentationLength < baseIndentationLength )
5142 {
52- var character = line [ i ] ;
53- if ( character != leadingCharacter )
54- return i ;
43+ if ( indentationLength == line . Length )
44+ {
45+ lines [ i ] = "" ;
46+ continue ;
47+ }
48+
49+ return endsTrimmedContent ;
5550 }
5651
57- // Assume that this line is the template for trimming
58- return line . Length ;
52+ lines [ i ] = line . Substring ( Math . Min ( baseIndentationLength , line . Length ) ) . TrimEnd ( ) ;
5953 }
6054
61- throw new ArgumentException ( "No lines match the target leading character." , nameof ( lines ) ) ;
55+ return String . Join ( Environment . NewLine , lines ) ;
6256 }
6357
64- private string TrimPrecedingLine ( string line , char character , int amount )
58+ private static Regex TrimStartRegex = new Regex ( "^\\ s*\n (\\ s*)(?=\\ S*)" , RegexOptions . Compiled ) ;
59+
60+ private int CountIndentation ( string line )
6561 {
66- return line . StartsWith ( character ) ? new string ( line . Skip ( amount ) . ToArray ( ) ) : line ;
62+ for ( var i = 0 ; i < line . Length ; i ++ )
63+ if ( ! char . IsWhiteSpace ( line [ i ] ) )
64+ return i ;
65+ return int . MaxValue ;
6766 }
6867 }
6968}
0 commit comments