Browse Source

Ported HtmlSyntaxColorizer to AvalonEdit.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5527 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
Daniel Grunwald 16 years ago
parent
commit
d79c461876
  1. 18
      samples/HtmlSyntaxColorizer/HtmlSyntaxColorizer.csproj
  2. 6
      samples/HtmlSyntaxColorizer/HtmlSyntaxColorizer.sln
  3. 219
      samples/HtmlSyntaxColorizer/HtmlWriter.cs
  4. 10
      samples/HtmlSyntaxColorizer/Main.cs
  5. 19
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightedLine.cs
  6. 35
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HtmlClipboard.cs

18
samples/HtmlSyntaxColorizer/HtmlSyntaxColorizer.csproj

@ -1,4 +1,5 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup> <PropertyGroup>
<ProjectGuid>{6D17428C-A444-4C26-8FE3-976160F41D97}</ProjectGuid> <ProjectGuid>{6D17428C-A444-4C26-8FE3-976160F41D97}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -6,6 +7,7 @@
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RootNamespace>HtmlSyntaxColorizer</RootNamespace> <RootNamespace>HtmlSyntaxColorizer</RootNamespace>
<AssemblyName>HtmlSyntaxColorizer</AssemblyName> <AssemblyName>HtmlSyntaxColorizer</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<OutputPath>bin\Debug\</OutputPath> <OutputPath>bin\Debug\</OutputPath>
@ -23,14 +25,22 @@
</PropertyGroup> </PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
<ItemGroup> <ItemGroup>
<Reference Include="ICSharpCode.TextEditor"> <Reference Include="ICSharpCode.AvalonEdit">
<HintPath>..\..\bin\ICSharpCode.TextEditor.dll</HintPath> <HintPath>..\..\bin\ICSharpCode.AvalonEdit.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Drawing" /> <Reference Include="System.Drawing" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="AssemblyInfo.cs" /> <Compile Include="AssemblyInfo.cs" />

6
samples/HtmlSyntaxColorizer/HtmlSyntaxColorizer.sln

@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 9.00 Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2005 # Visual Studio 2008
# SharpDevelop 2.1.0.2513 # SharpDevelop 4.0.0.5490
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HtmlSyntaxColorizer", "HtmlSyntaxColorizer.csproj", "{6D17428C-A444-4C26-8FE3-976160F41D97}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HtmlSyntaxColorizer", "HtmlSyntaxColorizer.csproj", "{6D17428C-A444-4C26-8FE3-976160F41D97}"
EndProject EndProject
Global Global

219
samples/HtmlSyntaxColorizer/HtmlWriter.cs

@ -1,5 +1,5 @@
// SharpDevelop samples // SharpDevelop samples
// Copyright (c) 2007, AlphaSierraPapa // Copyright (c) 2010, AlphaSierraPapa
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
@ -30,8 +30,9 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Xml; using System.Xml;
using ICSharpCode.TextEditor;
using ICSharpCode.TextEditor.Document; using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Highlighting;
namespace ICSharpCode.HtmlSyntaxColorizer namespace ICSharpCode.HtmlSyntaxColorizer
{ {
@ -57,10 +58,11 @@ namespace ICSharpCode.HtmlSyntaxColorizer
public string StyleClassPrefix = "code"; public string StyleClassPrefix = "code";
Dictionary<string, string> stylesheetCache = new Dictionary<string, string>(); Dictionary<string, string> stylesheetCache = new Dictionary<string, string>();
StringBuilder stylesheet = new StringBuilder();
/// <summary> /// <summary>
/// Resets the CSS stylesheet cache. Stylesheet classes will be cached on GenerateHtml calls. /// Resets the CSS stylesheet cache. Stylesheet classes will be cached on GenerateHtml calls.
/// If you want to reuse the HtmlWriter for multiple /// If you want to reuse the HtmlWriter for multiple .html files.
/// </summary> /// </summary>
public void ResetStylesheetCache() public void ResetStylesheetCache()
{ {
@ -69,182 +71,117 @@ namespace ICSharpCode.HtmlSyntaxColorizer
string GetClass(string style) string GetClass(string style)
{ {
return stylesheetCache[style]; string className;
if (!stylesheetCache.TryGetValue(style, out className)) {
className = StyleClassPrefix + stylesheetCache.Count;
stylesheet.Append('.');
stylesheet.Append(className);
stylesheet.Append(" { ");
stylesheet.Append(style);
stylesheet.AppendLine(" }");
stylesheetCache[style] = className;
}
return className;
} }
#endregion
void CacheClass(string style, StringBuilder b) public string GenerateHtml(string code, IHighlightingDefinition highlightDefinition)
{ {
if (style == null) return; return GenerateHtml(new TextDocument(code), highlightDefinition);
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) public string GenerateHtml(TextDocument document, IHighlightingDefinition highlightDefinition)
{ {
IDocument doc = new DocumentFactory().CreateDocument(); return GenerateHtml(document, new DocumentHighlighter(document, highlightDefinition.MainRuleSet));
doc.HighlightingStrategy = HighlightingManager.Manager.FindHighlighter(highlighterName);
doc.TextContent = code;
return GenerateHtml(doc);
} }
HighlightColor currentDefaultTextColor; public string GenerateHtml(TextDocument document, IHighlighter highlighter)
public string GenerateHtml(IDocument document)
{ {
string myMainStyle = MainStyle; string myMainStyle = MainStyle;
currentDefaultTextColor = document.HighlightingStrategy.GetColorFor("Default"); string LineNumberStyle = "color: #606060;";
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(); StringWriter output = new StringWriter();
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) { if (ShowLineNumbers || AlternateLineBackground) {
b.Append("<div"); output.Write("<div");
WriteStyle(myMainStyle, b); WriteStyle(output, myMainStyle);
b.AppendLine(">"); output.WriteLine(">");
int longestNumberLength = 1 + (int)Math.Log10(document.TotalNumberOfLines); int longestNumberLength = 1 + (int)Math.Log10(document.LineCount);
int lineNumber = 1; for (int lineNumber = 1; lineNumber <= document.LineCount; lineNumber++) {
foreach (LineSegment lineSegment in document.LineSegmentCollection) { HighlightedLine line = highlighter.HighlightLine(lineNumber);
b.Append("<pre"); output.Write("<pre");
if (AlternateLineBackground && (lineNumber % 2) == 0) { if (AlternateLineBackground && (lineNumber % 2) == 0) {
WriteStyle(AlternateLineStyle, b); WriteStyle(output, AlternateLineStyle);
} else { } else {
WriteStyle(LineStyle, b); WriteStyle(output, LineStyle);
} }
b.Append(">"); output.Write(">");
if (ShowLineNumbers) { if (ShowLineNumbers) {
b.Append("<span"); output.Write("<span");
WriteStyle(LineNumberStyle, b); WriteStyle(output, LineNumberStyle);
b.Append('>'); output.Write('>');
b.Append(lineNumber.ToString().PadLeft(longestNumberLength)); output.Write(lineNumber.ToString().PadLeft(longestNumberLength));
b.Append(": "); output.Write(": ");
b.Append("</span>"); output.Write("</span>");
}
if (lineSegment.Words.Count == 0) {
b.Append("&nbsp;");
} else {
PrintWords(lineSegment, b);
} }
b.AppendLine("</pre>");
lineNumber++; PrintWords(output, line);
output.WriteLine("</pre>");
} }
b.AppendLine("</div>"); output.WriteLine("</div>");
} else { } else {
b.Append("<pre"); output.Write("<pre");
WriteStyle(myMainStyle + LineStyle, b); WriteStyle(output, myMainStyle + LineStyle);
b.AppendLine(">"); output.WriteLine(">");
foreach (LineSegment lineSegment in document.LineSegmentCollection) { for (int lineNumber = 1; lineNumber <= document.LineCount; lineNumber++) {
PrintWords(lineSegment, b); HighlightedLine line = highlighter.HighlightLine(lineNumber);
b.AppendLine(); PrintWords(output, line);
} output.WriteLine();
b.AppendLine("</pre>"); }
output.WriteLine("</pre>");
}
if (CreateStylesheet && stylesheet.Length > 0) {
string result = "<style type=\"text/css\">" + stylesheet.ToString() + "</style>" + output.ToString();
stylesheet = new StringBuilder();
return result;
} else {
return output.ToString();
} }
return b.ToString();
} }
void PrintWords(LineSegment lineSegment, StringBuilder b) void PrintWords(TextWriter writer, HighlightedLine line)
{ {
string currentSpan = null; writer.Write(line.ToHtml(new MyHtmlOptions(this)));
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) class MyHtmlOptions : HtmlOptions
{ {
return word.Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;"); readonly HtmlWriter htmlWriter;
}
void WriteStyle(string style, StringBuilder b) internal MyHtmlOptions(HtmlWriter htmlWriter)
{ {
if (CreateStylesheet) { this.htmlWriter = htmlWriter;
b.Append(" class=\"");
b.Append(GetClass(style));
b.Append('"');
} else {
b.Append(" style='");
b.Append(style);
b.Append("'");
}
} }
string GetStyle(TextWord word) public override void WriteStyleAttributeForColor(TextWriter writer, HighlightingColor color)
{ {
if (word.SyntaxColor == null || word.SyntaxColor.ToString() == currentDefaultTextColor.ToString()) htmlWriter.WriteStyle(writer, color.ToCss());
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) void WriteStyle(TextWriter writer, string style)
{ {
return "#" + color.R.ToString("x2") + color.G.ToString("x2") + color.B.ToString("x2"); if (CreateStylesheet) {
writer.Write(" class=\"");
writer.Write(GetClass(style));
writer.Write('"');
} else {
writer.Write(" style='");
writer.Write(style);
writer.Write("'");
}
} }
} }
} }

10
samples/HtmlSyntaxColorizer/Main.cs

@ -1,5 +1,5 @@
// SharpDevelop samples // SharpDevelop samples
// Copyright (c) 2007, AlphaSierraPapa // Copyright (c) 2010, AlphaSierraPapa
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
@ -26,9 +26,11 @@
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Collections.Generic;
using ICSharpCode.AvalonEdit.Highlighting;
namespace ICSharpCode.HtmlSyntaxColorizer namespace ICSharpCode.HtmlSyntaxColorizer
{ {
@ -36,11 +38,13 @@ namespace ICSharpCode.HtmlSyntaxColorizer
{ {
public static void Main(string[] args) public static void Main(string[] args)
{ {
IHighlightingDefinition highlightDefinition = HighlightingManager.Instance.GetDefinition("C#");
HtmlWriter w = new HtmlWriter(); HtmlWriter w = new HtmlWriter();
w.ShowLineNumbers = true; w.ShowLineNumbers = true;
w.AlternateLineBackground = true; w.AlternateLineBackground = true;
string code = File.ReadAllText("../../Main.cs"); string code = File.ReadAllText("../../Main.cs");
string html = w.GenerateHtml(code, "C#"); string html = w.GenerateHtml(code, highlightDefinition);
File.WriteAllText("output.html", "<html><body>" + html + "</body></html>"); File.WriteAllText("output.html", "<html><body>" + html + "</body></html>");
Process.Start("output.html"); // view in browser Process.Start("output.html"); // view in browser
} }

19
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightedLine.cs

@ -7,6 +7,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Text; using System.Text;
using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Document;
@ -79,7 +80,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting
return 1; return 1;
} else { } else {
if (IsEnd) if (IsEnd)
return -Nesting.CompareTo(other.Nesting); return other.Nesting.CompareTo(Nesting);
else else
return Nesting.CompareTo(other.Nesting); return Nesting.CompareTo(other.Nesting);
} }
@ -121,24 +122,24 @@ namespace ICSharpCode.AvalonEdit.Highlighting
elements.Sort(); elements.Sort();
TextDocument document = this.Document; TextDocument document = this.Document;
StringBuilder b = new StringBuilder(); StringWriter w = new StringWriter();
int textOffset = startOffset; int textOffset = startOffset;
foreach (HtmlElement e in elements) { foreach (HtmlElement e in elements) {
int newOffset = Math.Min(e.Offset, endOffset); int newOffset = Math.Min(e.Offset, endOffset);
if (newOffset > startOffset) { if (newOffset > startOffset) {
HtmlClipboard.EscapeHtml(b, document.GetText(textOffset, newOffset - textOffset), options); HtmlClipboard.EscapeHtml(w, document.GetText(textOffset, newOffset - textOffset), options);
} }
textOffset = Math.Max(textOffset, newOffset); textOffset = Math.Max(textOffset, newOffset);
if (e.IsEnd) { if (e.IsEnd) {
b.Append("</span>"); w.Write("</span>");
} else { } else {
b.Append("<span style=\""); w.Write("<span");
b.Append(e.Color.ToCss()); options.WriteStyleAttributeForColor(w, e.Color);
b.Append("\">"); w.Write('>');
} }
} }
HtmlClipboard.EscapeHtml(b, document.GetText(textOffset, endOffset - textOffset), options); HtmlClipboard.EscapeHtml(w, document.GetText(textOffset, endOffset - textOffset), options);
return b.ToString(); return w.ToString();
} }
/// <inheritdoc/> /// <inheritdoc/>

35
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HtmlClipboard.cs

@ -8,6 +8,7 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO;
using System.Text; using System.Text;
using System.Windows; using System.Windows;
@ -101,13 +102,13 @@ namespace ICSharpCode.AvalonEdit.Highlighting
/// <summary> /// <summary>
/// Escapes text and writes the result to the StringBuilder. /// Escapes text and writes the result to the StringBuilder.
/// </summary> /// </summary>
internal static void EscapeHtml(StringBuilder b, string text, HtmlOptions options) internal static void EscapeHtml(StringWriter w, string text, HtmlOptions options)
{ {
int spaceCount = -1; int spaceCount = -1;
foreach (char c in text) { foreach (char c in text) {
if (c == ' ') { if (c == ' ') {
if (spaceCount < 0) if (spaceCount < 0)
b.Append("&nbsp;"); w.Write("&nbsp;");
else else
spaceCount++; spaceCount++;
} else if (c == '\t') { } else if (c == '\t') {
@ -116,34 +117,34 @@ namespace ICSharpCode.AvalonEdit.Highlighting
spaceCount += options.TabSize; spaceCount += options.TabSize;
} else { } else {
if (spaceCount == 1) { if (spaceCount == 1) {
b.Append(' '); w.Write(' ');
} else if (spaceCount >= 1) { } else if (spaceCount >= 1) {
for (int i = 0; i < spaceCount; i++) { for (int i = 0; i < spaceCount; i++) {
b.Append("&nbsp;"); w.Write("&nbsp;");
} }
} }
spaceCount = 0; spaceCount = 0;
switch (c) { switch (c) {
case '<': case '<':
b.Append("&lt;"); w.Write("&lt;");
break; break;
case '>': case '>':
b.Append("&gt;"); w.Write("&gt;");
break; break;
case '&': case '&':
b.Append("&amp;"); w.Write("&amp;");
break; break;
case '"': case '"':
b.Append("&quot;"); w.Write("&quot;");
break; break;
default: default:
b.Append(c); w.Write(c);
break; break;
} }
} }
} }
for (int i = 0; i < spaceCount; i++) { for (int i = 0; i < spaceCount; i++) {
b.Append("&nbsp;"); w.Write("&nbsp;");
} }
} }
} }
@ -176,5 +177,19 @@ namespace ICSharpCode.AvalonEdit.Highlighting
/// The amount of spaces a tab gets converted to. /// The amount of spaces a tab gets converted to.
/// </summary> /// </summary>
public int TabSize { get; set; } public int TabSize { get; set; }
/// <summary>
/// Writes the HTML attribute for the style to the text writer.
/// </summary>
public virtual void WriteStyleAttributeForColor(TextWriter writer, HighlightingColor color)
{
if (writer == null)
throw new ArgumentNullException("writer");
if (color == null)
throw new ArgumentNullException("color");
writer.Write(" style=\"");
writer.Write(color.ToCss());
writer.Write("\"");
}
} }
} }

Loading…
Cancel
Save