164 lines
5.2 KiB
C#
164 lines
5.2 KiB
C#
#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.Text;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace Nop.Services.Html.CodeFormatter;
|
|
|
|
/// <summary>
|
|
/// Provides a base class for formatting most programming languages.
|
|
/// </summary>
|
|
public abstract partial class CodeFormat : SourceFormat
|
|
{
|
|
/// <summary>
|
|
/// Must be overridden to provide a list of keywords defined in
|
|
/// each language.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Keywords must be separated with spaces.
|
|
/// </remarks>
|
|
protected abstract string Keywords
|
|
{
|
|
get;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Can be overridden to provide a list of preprocessors defined in
|
|
/// each language.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Preprocessors must be separated with spaces.
|
|
/// </remarks>
|
|
protected virtual string Preprocessors { get; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// Must be overridden to provide a regular expression string
|
|
/// to match strings literals.
|
|
/// </summary>
|
|
protected abstract string StringRegex
|
|
{
|
|
get;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Must be overridden to provide a regular expression string
|
|
/// to match comments.
|
|
/// </summary>
|
|
protected abstract string CommentRegex
|
|
{
|
|
get;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines if the language is case sensitive.
|
|
/// </summary>
|
|
/// <value><b>true</b> if the language is case sensitive, <b>false</b>
|
|
/// otherwise. The default is true.</value>
|
|
/// <remarks>
|
|
/// A case-insensitive language formatter must override this
|
|
/// property to return false.
|
|
/// </remarks>
|
|
public virtual bool CaseSensitive { get; } = true;
|
|
|
|
/// <summary/>
|
|
protected CodeFormat()
|
|
{
|
|
//generate the keyword and preprocessor regexes from the keyword lists
|
|
var r = new Regex(@"\w+|-\w+|#\w+|@@\w+|#(?:\\(?:s|w)(?:\*|\+)?\w+)+|@\\w\*+");
|
|
var regKeyword = r.Replace(Keywords, @"(?<=^|\W)$0(?=\W)");
|
|
var regPreproc = r.Replace(Preprocessors, @"(?<=^|\s)$0(?=\s|$)");
|
|
r = new Regex(@" +");
|
|
regKeyword = r.Replace(regKeyword, @"|");
|
|
regPreproc = r.Replace(regPreproc, @"|");
|
|
|
|
if (regPreproc.Length == 0)
|
|
{
|
|
regPreproc = "(?!.*)_{37}(?<!.*)"; //use something quite impossible...
|
|
}
|
|
|
|
//build a master regex with capturing groups
|
|
var regAll = new StringBuilder();
|
|
regAll.Append('(');
|
|
regAll.Append(CommentRegex);
|
|
regAll.Append(")|(");
|
|
regAll.Append(StringRegex);
|
|
//if (regPreproc.Length > 0)
|
|
//{
|
|
regAll.Append(")|(");
|
|
regAll.Append(regPreproc);
|
|
//}
|
|
regAll.Append(")|(");
|
|
regAll.Append(regKeyword);
|
|
regAll.Append(')');
|
|
|
|
var caseInsensitive = CaseSensitive ? 0 : RegexOptions.IgnoreCase;
|
|
CodeRegex = new Regex(regAll.ToString(), RegexOptions.Singleline | caseInsensitive);
|
|
}
|
|
|
|
/// <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) //comment
|
|
{
|
|
var reader = new StringReader(match.ToString());
|
|
string line;
|
|
var 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[2].Success) //string literal
|
|
{
|
|
return "<span class=\"str\">" + match + "</span>";
|
|
}
|
|
|
|
if (match.Groups[3].Success) //preprocessor keyword
|
|
{
|
|
return "<span class=\"preproc\">" + match + "</span>";
|
|
}
|
|
|
|
if (match.Groups[4].Success) //keyword
|
|
{
|
|
return "<span class=\"kwrd\">" + match + "</span>";
|
|
}
|
|
|
|
return string.Empty; //none of the above
|
|
}
|
|
} |