#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.Reflection; using System.Text; using System.Text.RegularExpressions; using Nop.Core; namespace Nop.Services.Html.CodeFormatter; /// /// Provides a base implementation for all code formatters. /// /// /// /// 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. /// /// /// 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+. /// /// public abstract partial class SourceFormat { /// protected SourceFormat() { TabSpaces = 4; LineNumbers = false; Alternate = false; EmbedStyleSheet = false; } /// /// Gets the CSS stylesheet as a stream. /// /// A text of the CSS definitions. public static Stream GetCssStream() { return Assembly.GetExecutingAssembly().GetManifestResourceStream( "Manoli.Utils.CSharpFormat.csharp.css"); } /// /// Gets the CSS stylesheet as a string. /// /// A string containing the CSS definitions. public static string GetCssString() { using var reader = new StreamReader(GetCssStream()); return reader.ReadToEnd(); } /// /// Gets or sets the tabs width. /// /// The number of space characters to substitute for tab /// characters. The default is 4, unless overridden is a /// derived class. public byte TabSpaces { get; set; } /// /// Enables or disables line numbers in output. /// /// When true, line numbers are generated. /// The default is false. public bool LineNumbers { get; set; } /// /// Enables or disables alternating line background. /// /// When true, lines background is alternated. /// The default is false. public bool Alternate { get; set; } /// /// Enables or disables the embedded CSS style sheet. /// /// When true, the CSS <style> element is included /// in the HTML output. The default is false. public bool EmbedStyleSheet { get; set; } /// Transform source code to HTML 4.01. /// /// /// Transforms a source code stream to HTML 4.01. /// /// Source code stream. /// A string containing the HTML formatted code. public string FormatCode(Stream source) { using var reader = new StreamReader(source); var s = reader.ReadToEnd(); return FormatCode(s, LineNumbers, Alternate, EmbedStyleSheet, false); } /// /// Transforms a source code string to HTML 4.01. /// /// A string containing the HTML formatted code. public string FormatCode(string source) { return FormatCode(source, LineNumbers, Alternate, EmbedStyleSheet, false); } /// /// Allows formatting a part of the code in a different language, /// for example a JavaScript block inside an HTML file. /// public string FormatSubCode(string source) { return FormatCode(source, false, false, false, true); } /// /// The regular expression used to capture language tokens. /// protected Regex CodeRegex { get; set; } /// /// Called to evaluate the HTML fragment corresponding to each /// matching token in the code. /// /// The resulting from a /// single regular expression match. /// A string containing the HTML code fragment. protected abstract string MatchEval(Match match); //does the formatting job protected string FormatCode(string source, bool lineNumbers, bool alternate, bool embedStyleSheet, bool subCode) { //replace special characters var 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(), MatchEval); sb = new StringBuilder(); if (embedStyleSheet) { sb.AppendFormat("\n"); } if (lineNumbers || alternate) //we have to process the code line by line { if (!subCode) sb.Append("
\n"); var reader = new StringReader(source); var i = 0; const string spaces = " "; string line; while ((line = reader.ReadLine()) != null) { i++; if (alternate && i % 2 == 1) { sb.Append("
");
                }
                else
                {
                    sb.Append("
");
                }

                if (lineNumbers)
                {
                    var order = (int)Math.Log10(i);
                    sb.Append(""
                              + spaces[0..(3 - order)] + i
                              + ":  ");
                }

                sb.Append(line.Length == 0 ? " " : line);
                sb.Append("
\n"); } reader.Close(); if (!subCode) sb.Append("
"); } else { //have to use a
 because IE below ver 6 does not understand 
            //the "white-space: pre" CSS value
            if (!subCode)
                sb.Append("
\n");

            sb.Append(source);
            if (!subCode)
                sb.Append("
"); } return sb.ToString(); } }