feat: First attempt at an ANSI to HTML converter

This commit is contained in:
Chris Cameron
2020-02-17 21:38:58 -05:00
committed by Chris Cameron
parent fde3106389
commit c453717998
4 changed files with 98 additions and 0 deletions

View File

@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Added public access to GetValues enumeration extension
- Added extensions for getting JsonReader values as long or ulong
- Added DateTimeUtils methods for creating DateTimes from epoch seconds or milliseconds
- Added AnsiToHtml converter for visualizing ANSI logs
### Changed
- Fixed exception trying to get DHCP status of network interfaces on Linux

View File

@@ -0,0 +1,22 @@
using ICD.Common.Utils.Converters;
using NUnit.Framework;
namespace ICD.Common.Utils.Tests.Converters
{
[TestFixture]
public sealed class AnsiToHtmlTest
{
[TestCase("black\x1b[37mwhite",
@"black<span style=""color:#BBBBBB"">white</span>")]
[TestCase("black\x1b[0mblack",
@"blackblack")]
[TestCase("black\x1b[37mwhite\x1b[0m",
@"black<span style=""color:#BBBBBB"">white</span>")]
[TestCase("\x1b[30mblack\x1b[37mwhite",
@"<span style=""color:#000000"">black<span style=""color:#BBBBBB"">white</span></span>")]
public void ConvertTest(string ansi, string expected)
{
Assert.AreEqual(expected, AnsiToHtml.Convert(ansi));
}
}
}

View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
namespace ICD.Common.Utils.Converters
{
public static class AnsiToHtml
{
/// <summary>
/// Matches ANSI escape codes, e.g. \x1b[31m and \x1b[30;1m
/// </summary>
private const string ANSI_PATTERN = "(?'match'\x01b\\[(?'code'[\\d;]+)m)";
private const string CODE_RESET = "0";
/// <summary>
/// Matches ANSI escape codes to HTML styles.
/// Color values are taken from PuTTY.
/// </summary>
private static readonly Dictionary<string, string> s_Colors =
new Dictionary<string, string>
{
{"30", "color:#000000"}, // Black
{"31", "color:#BB0000"}, // Red
{"32", "color:#00BB00"}, // Green
{"33", "color:#BBBB00"}, // Yellow
{"34", "color:#0000BB"}, // Blue
{"35", "color:#BB00BB"}, // Magenta
{"36", "color:#00BBBB"}, // Cyan
{"37", "color:#BBBBBB"}, // White
{"30;1", "color:#555555"}, // Bright Black
{"31;1", "color:#FF5555"}, // Bright Red
{"32;1", "color:#55FF55"}, // Bright Green
{"33;1", "color:#FFFF55"}, // Bright Yellow
{"34;1", "color:#5555FF"}, // Bright Blue
{"35;1", "color:#FF55FF"}, // Bright Magenta
{"36;1", "color:#55FFFF"}, // Bright Cyan
{"37;1", "color:#FFFFFF"}, // Bright White
};
/// <summary>
/// Converts the input ansi string into html with color attributes.
/// </summary>
/// <param name="ansi"></param>
/// <returns></returns>
public static string Convert(string ansi)
{
int depth = 0;
// Hack - Append a reset to close any open spans
ansi += "\x1b[0m";
return RegexUtils.ReplaceGroup(ansi, ANSI_PATTERN, "match", match =>
{
string code = match.Groups["code"].Value;
// Reset code - close all of the open spans.
if (code == CODE_RESET)
{
string output = StringUtils.Repeat("</span>", depth);
depth = 0;
return output;
}
string style;
if (!s_Colors.TryGetValue(code, out style))
return match.Value;
depth++;
return string.Format("<span style=\"{0}\">", style);
});
}
}
}

View File

@@ -86,6 +86,7 @@
<Compile Include="Comparers\PredicateComparer.cs" />
<Compile Include="Comparers\SequenceComparer.cs" />
<Compile Include="ConsoleColor.cs" />
<Compile Include="Converters\AnsiToHtml.cs" />
<Compile Include="DateTimeUtils.cs" />
<Compile Include="Email\EmailClient.cs" />
<Compile Include="Email\eMailErrorCode.cs" />