#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
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Reflection;
namespace NopSolutions.NopCommerce.Common.Utils.Html.CodeFormatter{
/// <summary>
/// Provides a base implementation for all code formatters.
/// </summary>
/// <remarks>
/// <para>
/// To display the formatted code on your web site, the web page must
/// refer to a stylesheet that defines the formatting for the different
/// CSS classes generated by CSharpFormat:
/// .csharpcode, pre, .rem, .kwrd, .str, .op, .preproc, .alt, .lnum.
/// </para>
/// <para>
/// Note that if you have multi-line comments in your source code
/// (like /* ... */), the "line numbers" or "alternate line background"
/// options will generate code that is not strictly HTML 4.01 compliant.
/// The code will still look good with IE5+ or Mozilla 0.8+.
/// </para>
/// </remarks>
public abstract partial class SourceFormat
{
/// <summary/>
protected SourceFormat()
{
_tabSpaces = 4;
_lineNumbers = false;
_alternate = false;
_embedStyleSheet = false;
}
private byte _tabSpaces;
/// <summary>
/// Gets or sets the tabs width.
/// </summary>
/// <value>The number of space characters to substitute for tab
/// characters. The default is <b>4</b>, unless overridden is a
/// derived class.</value>
public byte TabSpaces
{
get { return _tabSpaces; }
set { _tabSpaces = value; }
}
private bool _lineNumbers;
/// <summary>
/// Enables or disables line numbers in output.
/// </summary>
/// <value>When <b>true</b>, line numbers are generated.
/// The default is <b>false</b>.</value>
public bool LineNumbers
{
get { return _lineNumbers; }
set { _lineNumbers = value; }
}
private bool _alternate;
/// <summary>
/// Enables or disables alternating line background.
/// </summary>
/// <value>When <b>true</b>, lines background is alternated.
/// The default is <b>false</b>.</value>
public bool Alternate
{
get { return _alternate; }
set { _alternate = value; }
}
private bool _embedStyleSheet;
/// <summary>
/// Enables or disables the embedded CSS style sheet.
/// </summary>
/// <value>When <b>true</b>, the CSS <style> element is included
/// in the HTML output. The default is <b>false</b>.</value>
public bool EmbedStyleSheet
{
get { return _embedStyleSheet; }
set { _embedStyleSheet = value; }
}
/// <overloads>Transform source code to HTML 4.01.</overloads>
///
/// <summary>
/// Transforms a source code stream to HTML 4.01.
/// </summary>
/// <param name="source">Source code stream.</param>
/// <returns>A string containing the HTML formatted code.</returns>
public string FormatCode(Stream source)
{
StreamReader reader = new StreamReader(source);
string s = reader.ReadToEnd();
reader.Close();
return FormatCode(s, _lineNumbers, _alternate, _embedStyleSheet, false);
}
/// <summary>
/// Transforms a source code string to HTML 4.01.
/// </summary>
/// <returns>A string containing the HTML formatted code.</returns>
public string FormatCode(string source)
{
return FormatCode(source, _lineNumbers, _alternate, _embedStyleSheet, false);
}
/// <summary>
/// Allows formatting a part of the code in a different language,
/// for example a JavaScript block inside an HTML file.
/// </summary>
public string FormatSubCode(string source)
{
return FormatCode(source, false, false, false, true);
}
/// <summary>
/// Gets the CSS stylesheet as a stream.
/// </summary>
/// <returns>A text <see cref="Stream"/> of the CSS definitions.</returns>
public static Stream GetCssStream()
{
return Assembly.GetExecutingAssembly().GetManifestResourceStream(
"Manoli.Utils.CSharpFormat.csharp.css");
}
/// <summary>
/// Gets the CSS stylesheet as a string.
/// </summary>
/// <returns>A string containing the CSS definitions.</returns>
public static string GetCssString()
{
StreamReader reader = new StreamReader(GetCssStream());
return reader.ReadToEnd();
}
private Regex codeRegex;
/// <summary>
/// The regular expression used to capture language tokens.
/// </summary>
protected Regex CodeRegex
{
get { return codeRegex; }
set { codeRegex = value; }
}
/// <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 abstract string MatchEval(Match match);
//does the formatting job
private string FormatCode(string source, bool lineNumbers,
bool alternate, bool embedStyleSheet, bool subCode)
{
//replace special characters
StringBuilder sb = new StringBuilder(source);
if(!subCode)
{
sb.Replace("&", "&");
sb.Replace("<", "<");
sb.Replace(">", ">");
sb.Replace("\t", string.Empty.PadRight(_tabSpaces));
}
//color the code
source = codeRegex.Replace(sb.ToString(), new MatchEvaluator(this.MatchEval));
sb = new StringBuilder();
if (embedStyleSheet)
{
sb.Append("<style type=\"text/css\">\n");
sb.Append(GetCssString());
sb.Append("</style>\n");
}
if (lineNumbers || alternate) //we have to process the code line by line
{
if(!subCode)
sb.Append("<div class=\"csharpcode\">\n");
StringReader reader = new StringReader(source);
int i = 0;
string spaces = " ";
int order;
string line;
while ((line = reader.ReadLine()) != null)
{
i++;
if (alternate && ((i % 2) == 1))
{
sb.Append("<pre class=\"alt\">");
}
else
{
sb.Append("<pre>");
}
if(lineNumbers)
{
order = (int)Math.Log10(i);
sb.Append("<span class=\"lnum\">"
+ spaces.Substring(0, 3 - order) + i.ToString()
+ ": </span>");
}
if(line.Length == 0)
sb.Append(" ");
else
sb.Append(line);
sb.Append("</pre>\n");
}
reader.Close();
if(!subCode)
sb.Append("</div>");
}
else
{
//have to use a <pre> because IE below ver 6 does not understand
//the "white-space: pre" CSS value
if(!subCode)
sb.Append("<pre class=\"csharpcode\">\n");
sb.Append(source);
if(!subCode)
sb.Append("</pre>");
}
return sb.ToString();
}
}
}
|