@ -1,11 +1,10 @@
using System.Text.RegularExpressions ;
using System.Threading.Tasks ;
using System.Threading.Tasks ;
using MarkdownDeep ;
using Microsoft.AspNet.Mvc.Rendering ;
using Microsoft.AspNet.Mvc.Rendering ;
using Microsoft.AspNet.Razor.TagHelpers ;
using Microsoft.AspNet.Razor.TagHelpers ;
using CommonMark ;
using CommonMark.Syntax ;
using System.IO ;
namespace Yavsc.TagHelpers
namespace Yavsc.TagHelpers
{
{
@ -33,6 +32,45 @@ namespace Yavsc.TagHelpers
[HtmlAttributeName(MarkdownContentAttributeName)]
[HtmlAttributeName(MarkdownContentAttributeName)]
public string MarkdownContent { get ; set ; }
public string MarkdownContent { get ; set ; }
static Regex rxExtractLanguage = new Regex ( "^({{(.+)}}[\r\n])" , RegexOptions . Compiled ) ;
private static string FormatCodePrettyPrint ( MarkdownDeep . Markdown m , string code )
{
// Try to extract the language from the first line
var match = rxExtractLanguage . Match ( code ) ;
string language = null ;
if ( match . Success )
{
// Save the language
var g = ( Group ) match . Groups [ 2 ] ;
language = g . ToString ( ) ;
// Remove the first line
code = code . Substring ( match . Groups [ 1 ] . Length ) ;
}
// If not specified, look for a link definition called "default_syntax" and
// grab the language from its title
if ( language = = null )
{
var d = m . GetLinkDefinition ( "default_syntax" ) ;
if ( d ! = null )
language = d . title ;
}
// Common replacements
if ( language = = "C#" )
language = "csharp" ;
if ( language = = "C++" )
language = "cpp" ;
// Wrap code in pre/code tags and add PrettyPrint attributes if necessary
if ( string . IsNullOrEmpty ( language ) )
return string . Format ( "<pre><code>{0}</code></pre>\n" , code ) ;
else
return string . Format ( "<pre class=\"prettyprint lang-{0}\"><code>{1}</code></pre>\n" ,
language . ToLowerInvariant ( ) , code ) ;
}
/// <summary>
/// <summary>
@ -41,28 +79,28 @@ namespace Yavsc.TagHelpers
/// <param name="text">The Markdown that should be transformed.</param>
/// <param name="text">The Markdown that should be transformed.</param>
/// <param name="urlBaseLocation">The url Base Location.</param>
/// <param name="urlBaseLocation">The url Base Location.</param>
/// <returns>The HTML representation of the supplied Markdown.</returns>
/// <returns>The HTML representation of the supplied Markdown.</returns>
public string Markdown ( string commonMark , string urlBaseLocation = "" )
public string Markdown ( string text , string urlBaseLocation = "" )
{
{
// Transform the supplied text (Markdown) into HTML.
// Transform the supplied text (Markdown) into HTML.
string actual ;
var markdownTransformer = GetMarkdownTransformer ( ) ;
var settings = CommonMarkSettings . Default . Clone ( ) ;
markdownTransformer . UrlBaseLocation = urlBaseLocation ;
settings . OutputFormat = OutputFormat . Html ;
string html = markdownTransformer . Transform ( text ) ;
settings . AdditionalFeatures | = CommonMarkAdditionalFeatures . StrikethroughTilde ;
// Wrap the html in an MvcHtmlString otherwise it'll be HtmlEncoded and displayed to the user as HTML :(
return html ;
Block document ;
}
// Act
internal Markdown GetMarkdownTransformer ( )
using ( var reader = new StringReader ( commonMark ) )
using ( var writer = new StringWriter ( ) )
{
{
var prologue = CommonMarkConverter . ProcessPrologue ( reader , settings ) ;
var markdownTransformer = new Markdown ( ) ;
document = CommonMarkConverter . ProcessStage1 ( reader , settings , prologue ) ;
markdownTransformer . ExtraMode = true ;
CommonMarkConverter . ProcessStage2 ( document , settings ) ;
markdownTransformer . NoFollowLinks = true ;
CommonMarkConverter . ProcessStage3 ( document , writer , settings ) ;
markdownTransformer . SafeMode = false ;
actual = writer . ToString ( ) ;
markdownTransformer . FormatCodeBlock = FormatCodePrettyPrint ;
}
markdownTransformer . ExtractHeadBlocks = true ;
return actual ;
markdownTransformer . UserBreaks = true ;
return markdownTransformer ;
}
}
public ModelExpression Content { get ; set ; }
public ModelExpression Content { get ; set ; }
public async override Task ProcessAsync ( TagHelperContext context , TagHelperOutput output )
public async override Task ProcessAsync ( TagHelperContext context , TagHelperOutput output )