#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

250 lines
7.8 KiB

// SharpDevelop samples
// Copyright (c) 2007, AlphaSierraPapa
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this list
// of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// - Neither the name of the SharpDevelop team nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific prior written
// permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &AS IS& AND ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using ICSharpCode.TextEditor;
using ICSharpCode.TextEditor.Document;
namespace ICSharpCode.HtmlSyntaxColorizer
{
public class HtmlWriter
{
public bool AlternateLineBackground;
public bool ShowLineNumbers;
public string MainStyle = "font-size: small; font-family: Consolas, \"Courier New\", Courier, Monospace;";
public string LineStyle = "margin: 0em;";
public string AlternateLineStyle = "margin: 0em; width: 100%; background-color: #f0f0f0;";
#region Stylesheet cache
/// <summary>
/// Specifies whether a CSS stylesheet should be created to reduce the size of the created code.
/// The default value is true.
/// </summary>
public bool CreateStylesheet = true;
/// <summary>
/// Specifies the prefix to use in front of generate style class names.
/// </summary>
public string StyleClassPrefix = "code";
Dictionary<string, string> stylesheetCache = new Dictionary<string, string>();
/// <summary>
/// Resets the CSS stylesheet cache. Stylesheet classes will be cached on GenerateHtml calls.
/// If you want to reuse the HtmlWriter for multiple
/// </summary>
public void ResetStylesheetCache()
{
stylesheetCache.Clear();
}
string GetClass(string style)
{
return stylesheetCache[style];
}
void CacheClass(string style, StringBuilder b)
{
if (style == null) return;
if (!stylesheetCache.ContainsKey(style)) {
string styleName = StyleClassPrefix + stylesheetCache.Count;
stylesheetCache[style] = styleName;
b.Append('.');
b.Append(styleName);
b.Append(" { ");
b.Append(style);
b.AppendLine(" }");
}
}
#endregion
public string GenerateHtml(string code, string highlighterName)
{
IDocument doc = new DocumentFactory().CreateDocument();
doc.HighlightingStrategy = HighlightingManager.Manager.FindHighlighter(highlighterName);
doc.TextContent = code;
return GenerateHtml(doc);
}
HighlightColor currentDefaultTextColor;
public string GenerateHtml(IDocument document)
{
string myMainStyle = MainStyle;
currentDefaultTextColor = document.HighlightingStrategy.GetColorFor("Default");
myMainStyle += " color: " + ColorToString(currentDefaultTextColor.Color) + ";"
+ " background-color: " + ColorToString(currentDefaultTextColor.BackgroundColor) + ";";
string LineNumberStyle;
HighlightColor lineNumbersColor = document.HighlightingStrategy.GetColorFor("LineNumbers");
if (lineNumbersColor != null) {
LineNumberStyle = "color: " + ColorToString(lineNumbersColor.Color) + ";"
+ " background-color: " + ColorToString(lineNumbersColor.BackgroundColor) + ";";
} else {
LineNumberStyle = "color: #606060;";
}
StringBuilder b = new StringBuilder();
if (CreateStylesheet) {
b.AppendLine("<style type=\"text/css\">");
if (ShowLineNumbers || AlternateLineBackground) {
CacheClass(myMainStyle, b);
CacheClass(LineStyle, b);
} else {
CacheClass(myMainStyle + LineStyle, b);
}
if (AlternateLineBackground) CacheClass(AlternateLineStyle, b);
if (ShowLineNumbers) CacheClass(LineNumberStyle, b);
foreach (LineSegment ls in document.LineSegmentCollection) {
foreach (TextWord word in ls.Words) {
CacheClass(GetStyle(word), b);
}
}
b.AppendLine("</style>");
}
if (ShowLineNumbers || AlternateLineBackground) {
b.Append("<div");
WriteStyle(myMainStyle, b);
b.AppendLine(">");
int longestNumberLength = 1 + (int)Math.Log10(document.TotalNumberOfLines);
int lineNumber = 1;
foreach (LineSegment lineSegment in document.LineSegmentCollection) {
b.Append("<pre");
if (AlternateLineBackground && (lineNumber % 2) == 0) {
WriteStyle(AlternateLineStyle, b);
} else {
WriteStyle(LineStyle, b);
}
b.Append(">");
if (ShowLineNumbers) {
b.Append("<span");
WriteStyle(LineNumberStyle, b);
b.Append('>');
b.Append(lineNumber.ToString().PadLeft(longestNumberLength));
b.Append(": ");
b.Append("</span>");
}
if (lineSegment.Words.Count == 0) {
b.Append("&nbsp;");
} else {
PrintWords(lineSegment, b);
}
b.AppendLine("</pre>");
lineNumber++;
}
b.AppendLine("</div>");
} else {
b.Append("<pre");
WriteStyle(myMainStyle + LineStyle, b);
b.AppendLine(">");
foreach (LineSegment lineSegment in document.LineSegmentCollection) {
PrintWords(lineSegment, b);
b.AppendLine();
}
b.AppendLine("</pre>");
}
return b.ToString();
}
void PrintWords(LineSegment lineSegment, StringBuilder b)
{
string currentSpan = null;
foreach (TextWord word in lineSegment.Words) {
if (word.Type == TextWordType.Space) {
b.Append(' ');
} else if (word.Type == TextWordType.Tab) {
b.Append('\t');
} else {
string newSpan = GetStyle(word);
if (currentSpan != newSpan) {
if (currentSpan != null) b.Append("</span>");
if (newSpan != null) {
b.Append("<span");
WriteStyle(newSpan, b);
b.Append('>');
}
currentSpan = newSpan;
}
b.Append(HtmlEncode(word.Word));
}
}
if (currentSpan != null) b.Append("</span>");
}
static string HtmlEncode(string word)
{
return word.Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;");
}
void WriteStyle(string style, StringBuilder b)
{
if (CreateStylesheet) {
b.Append(" class=\"");
b.Append(GetClass(style));
b.Append('"');
} else {
b.Append(" style='");
b.Append(style);
b.Append("'");
}
}
string GetStyle(TextWord word)
{
if (word.SyntaxColor == null || word.SyntaxColor.ToString() == currentDefaultTextColor.ToString())
return null;
string style = "color: " + ColorToString(word.Color) + ";";
if (word.Bold) {
style += " font-weight: bold;";
}
if (word.Italic) {
style += " font-style: italic;";
}
if (word.SyntaxColor.HasBackground) {
style += " background-color: " + ColorToString(word.SyntaxColor.BackgroundColor) + ";";
}
return style;
}
static string ColorToString(System.Drawing.Color color)
{
return "#" + color.R.ToString("x2") + color.G.ToString("x2") + color.B.ToString("x2");
}
}
}