Source code for the CoDocker CSharp to HTML converter from OfItselfSo.com
// CoDocker Implementor Notes // This file contains the open source code supplied by Jean-Claude Manoli // on his website page: http://www.manoli.net/csharpformat/ // // The copyright remains with Jean-Claude - all future implementors // please respect the license agreement below. As is permitted by the license, // this file is a modified version of the original source code. Here are the // updates made to the original source file // // 02-Jan-2011 Cynic Changed the namespace from Manoli.Utils.CSharpFormat // to CoDocker // 03-Jan-2011 Cynic The name of the CSharp.css file has been changed to // CoDocker.css #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 CoDocker { /// <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 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( "CoDocker.CoDocker.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(); } } }