/BlogEngine/BlogEngine.NET/App_Code/Extensions/CodeFormatter/HtmlFormat.cs
C# | 209 lines | 103 code | 29 blank | 77 comment | 13 complexity | e6956dc99e76e613b8dbba21c634c186 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0, BSD-3-Clause
- #region Copyright © 2001-2003 Jean-Claude Manoli [jc@manoli.net]
-
- /*
- * This software is provided 'as-is', without any express or implied warranty.
- * In no event will the author(s) be held liable for any damages arising from
- * the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- *
- * 2. Altered source versions must be plainly marked as such, and must not
- * be misrepresented as being the original software.
- *
- * 3. This notice may not be removed or altered from any source distribution.
- */
- #endregion
-
- namespace CodeFormatter
- {
- using System.IO;
- using System.Text;
- using System.Text.RegularExpressions;
-
- /// <summary>
- /// Generates color-coded HTML 4.01 from HTML/XML/ASPX source code.
- /// </summary>
- /// <remarks>
- /// <para>
- /// This implementation assumes that code inside <script> blocks
- /// is JavaScript, and code inside <% %> blocks is C#.
- /// </para>
- /// <para>
- /// The default tab width is set to 2 characters in this class.
- /// </para>
- /// </remarks>
- public class HtmlFormat : SourceFormat
- {
- #region Constants and Fields
-
- /// <summary>
- /// The attrib regex.
- /// </summary>
- private readonly Regex attribRegex;
-
- /// <summary>
- /// To format embedded C# code.
- /// </summary>
- private readonly CSharpFormat csf;
-
- /// <summary>
- /// To format client-side JavaScript code.
- /// </summary>
- private readonly JavaScriptFormat jsf;
-
- #endregion
-
- #region Constructors and Destructors
-
- /// <summary>
- /// Initializes a new instance of the <see cref="HtmlFormat"/> class.
- /// The html format.
- /// </summary>
- public HtmlFormat()
- {
- const string RegJavaScript = @"(?<=<script(?:\s.*?)?>).+?(?=</script>)";
- const string RegComment = @"<!--.*?-->";
- const string RegAspTag = @"<%@.*?%>|<%|%>";
- const string RegAspCode = @"(?<=<%).*?(?=%>)";
- const string RegTagDelimiter = @"(?:</?!?\??(?!%)|(?<!%)/?>)+";
- const string RegTagName = @"(?<=</?!?\??(?!%))[\w\.:-]+(?=.*>)";
- const string RegAttributes = @"(?<=<(?!%)/?!?\??[\w:-]+).*?(?=(?<!%)/?>)";
- const string RegEntity = @"&\w+;";
- const string RegAttributeMatch = @"(=?"".*?""|=?'.*?')|([\w:-]+)";
-
- // the regex object will handle all the replacements in one pass
- const string RegAll = "(" + RegJavaScript + ")|(" + RegComment + ")|(" + RegAspTag + ")|(" + RegAspCode + ")|(" +
- RegTagDelimiter + ")|(" + RegTagName + ")|(" + RegAttributes + ")|(" + RegEntity + ")";
-
- this.CodeRegex = new Regex(RegAll, RegexOptions.IgnoreCase | RegexOptions.Singleline);
- this.attribRegex = new Regex(RegAttributeMatch, RegexOptions.Singleline);
-
- this.csf = new CSharpFormat();
- this.jsf = new JavaScriptFormat();
- }
-
- #endregion
-
- #region Methods
-
- /// <summary>
- /// Called to evaluate the HTML fragment corresponding to each
- /// matching token in the code.
- /// </summary>
- /// <param name="match">
- /// The <see cref="Match"/> resulting from a
- /// single regular expression match.
- /// </param>
- /// <returns>
- /// A string containing the HTML code fragment.
- /// </returns>
- protected override string MatchEval(Match match)
- {
- if (match.Groups[1].Success)
- {
- // JavaScript code
- var s = match.ToString();
- return this.jsf.FormatSubCode(match.ToString());
- }
-
- if (match.Groups[2].Success)
- {
- // comment
- StringBuilder sb;
- using (var reader = new StringReader(match.ToString()))
- {
- string line;
- sb = new StringBuilder();
- while ((line = reader.ReadLine()) != null)
- {
- if (sb.Length > 0)
- {
- sb.Append("\n");
- }
-
- sb.Append("<span class=\"rem\">");
- sb.Append(line);
- sb.Append("</span>");
- }
- }
-
- return sb.ToString();
- }
-
- if (match.Groups[3].Success)
- {
- // asp tag
- return string.Format("<span class=\"asp\">{0}</span>", match);
- }
-
- if (match.Groups[4].Success)
- {
- // asp C# code
- return this.csf.FormatSubCode(match.ToString());
- }
-
- if (match.Groups[5].Success)
- {
- // tag delimiter
- return string.Format("<span class=\"kwrd\">{0}</span>", match);
- }
-
- if (match.Groups[6].Success)
- {
- // html tagname
- return string.Format("<span class=\"html\">{0}</span>", match);
- }
-
- if (match.Groups[7].Success)
- {
- // attributes
- return this.attribRegex.Replace(match.ToString(), new MatchEvaluator(AttributeMatchEval));
- }
-
- if (match.Groups[8].Success)
- {
- // entity
- return string.Format("<span class=\"attr\">{0}</span>", match);
- }
-
- return match.ToString();
- }
-
- /// <summary>
- /// Called to evaluate the HTML fragment corresponding to each
- /// attribute's name/value in the code.
- /// </summary>
- /// <param name="match">
- /// The <see cref="Match"/> resulting from a
- /// single regular expression match.
- /// </param>
- /// <returns>
- /// A string containing the HTML code fragment.
- /// </returns>
- private static string AttributeMatchEval(Match match)
- {
- if (match.Groups[1].Success)
- {
- // attribute value
- return string.Format("<span class=\"kwrd\">{0}</span>", match);
- }
-
- if (match.Groups[2].Success)
- {
- // attribute name
- return string.Format("<span class=\"attr\">{0}</span>", match);
- }
-
- return match.ToString();
- }
-
- #endregion
- }
- }