#region using
using System;
using System.IO;
using System.Text;
using System.Web;
using System.Text.RegularExpressions;
using System.Web.Caching;
using BlogEngine.Core;
using BlogEngine.Core.Web.Controls;
using CodeFormatter;
#endregion
///
/// Converts text to formatted syntax highlighted code.
///
///
/// It is a work in progress.....
///
[Extension("Converts text to formatted syntax highlighted code (beta).", "0.1", "www.manoli.net")]
public class CodeFormatterExtension
{
#region Constructors
///
/// Maps custom events to the ServingContent event
///
public CodeFormatterExtension()
{
Page.Serving += new EventHandler(ServingContent);
Post.Serving += new EventHandler(ServingContent);
}
#endregion
#region RegEx
private Regex codeRegex = new Regex(@"(?\[code:(?.*?)(?:;ln=(?(?:on|off)))?(?:;alt=(?(?:on|off)))?(?:;(?.*?))?\])(?.*?)(?\[/code\])",
RegexOptions.Compiled
| RegexOptions.CultureInvariant
| RegexOptions.IgnoreCase
| RegexOptions.Singleline);
#endregion
///
/// An event that handles ServingEventArgs
///
///
///
void ServingContent(object sender, ServingEventArgs e)
{
if (e.Body.Contains("[/code]"))
{
e.Body = codeRegex.Replace(e.Body, new MatchEvaluator(CodeEvaluator));
}
}
///
///
///
///
///
private string CodeEvaluator(Match match)
{
if (!match.Success)
return match.Value;
HighlightOptions options = new HighlightOptions();
options.Language = match.Groups["lang"].Value;
options.Code = match.Groups["code"].Value;
options.DisplayLineNumbers = match.Groups["linenumbers"].Value == "on" ? true : false;
options.Title = match.Groups["title"].Value;
options.AlternateLineNumbers = match.Groups["altlinenumbers"].Value == "on" ? true : false;
string result = match.Value.Replace(match.Groups["begin"].Value, "");
result = result.Replace(match.Groups["end"].Value, "");
result = Highlight(options, result);
return result;
}
///
/// Returns the formatted text.
///
/// Whatever options were set in the regex groups.
/// Send the e.body so it can get formatted.
/// The formatted string of the match.
private string Highlight(HighlightOptions options, string text)
{
switch (options.Language)
{
case "c#":
CSharpFormat csf = new CSharpFormat();
csf.LineNumbers = options.DisplayLineNumbers;
csf.Alternate = options.AlternateLineNumbers;
return HttpContext.Current.Server.HtmlDecode(csf.FormatCode(text));
case "vb":
VisualBasicFormat vbf = new VisualBasicFormat();
vbf.LineNumbers = options.DisplayLineNumbers;
vbf.Alternate = options.AlternateLineNumbers;
return HttpContext.Current.Server.HtmlDecode(vbf.FormatCode(text));
case "js":
JavaScriptFormat jsf = new JavaScriptFormat();
jsf.LineNumbers = options.DisplayLineNumbers;
jsf.Alternate = options.AlternateLineNumbers;
return HttpContext.Current.Server.HtmlDecode(jsf.FormatCode(text));
case "html":
HtmlFormat htmlf = new HtmlFormat();
htmlf.LineNumbers = options.DisplayLineNumbers;
htmlf.Alternate = options.AlternateLineNumbers;
text = StripHtml(text).Trim();
string code = htmlf.FormatCode(HttpContext.Current.Server.HtmlDecode(text)).Trim();
return code.Replace("\r\n", "
").Replace("\n", "
");
case "xml":
HtmlFormat xmlf = new HtmlFormat();
xmlf.LineNumbers = options.DisplayLineNumbers;
xmlf.Alternate = options.AlternateLineNumbers;
text = text.Replace("
", "\r\n");
text = StripHtml(text).Trim();
string xml = xmlf.FormatCode(HttpContext.Current.Server.HtmlDecode(text)).Trim();
return xml.Replace("\r\n", "
").Replace("\n", "
");
case "tsql":
TsqlFormat tsqlf = new TsqlFormat();
tsqlf.LineNumbers = options.DisplayLineNumbers;
tsqlf.Alternate = options.AlternateLineNumbers;
return HttpContext.Current.Server.HtmlDecode(tsqlf.FormatCode(text));
case "msh":
MshFormat mshf = new MshFormat();
mshf.LineNumbers = options.DisplayLineNumbers;
mshf.Alternate = options.AlternateLineNumbers;
return HttpContext.Current.Server.HtmlDecode(mshf.FormatCode(text));
}
return string.Empty;
}
private static Regex _Regex = new Regex("<[^>]*>", RegexOptions.Compiled);
private static string StripHtml(string html)
{
if (string.IsNullOrEmpty(html))
return string.Empty;
return _Regex.Replace(html, string.Empty);
}
///
/// Handles all of the options for changing the rendered code.
///
private class HighlightOptions
{
private string language, title, code;
private bool displayLineNumbers = false;
private bool alternateLineNumbers = false;
public HighlightOptions()
{
}
public HighlightOptions(string language, string title, bool linenumbers, string code, bool alternateLineNumbers)
{
this.language = language;
this.title = title;
this.alternateLineNumbers = alternateLineNumbers;
this.code = code;
this.displayLineNumbers = linenumbers;
}
public string Code
{
get { return code; }
set { code = value; }
}
public bool DisplayLineNumbers
{
get { return displayLineNumbers; }
set { displayLineNumbers = value; }
}
public string Language
{
get { return language; }
set { language = value; }
}
public string Title
{
get { return title; }
set { title = value; }
}
public bool AlternateLineNumbers
{
get { return alternateLineNumbers; }
set { alternateLineNumbers = value; }
}
}
}