public static StringBuilder PrintToHtmlCore(
StringBuilder input, StringBuilder output = null,
bool addPreCode = true, string newline = "\n",
string[] colorCodesToCssClasses = null)
{
CheckParam.Arg("output", output != input);
colorCodesToCssClasses = colorCodesToCssClasses ?? DefaultCssClassTable;
output = output ?? new StringBuilder(input.Length);
if (addPreCode)
output.Append("<pre class='highlight'><code>");
string cssClass = null;
int depth = 0;
char c, next = input.TryGet(0, '\0');
for (int i = 0; i < input.Length; i++) {
c = next;
next = input.TryGet(i + 1, '\0');
if (c < colorCodesToCssClasses.Length) {
if (c <= '\n') { // \n is 10
if (c == '\n') {
output.Append(newline);
} else if (c != '\0') {
// If the LNode contains control codes, printer should have \escaped them
Debug.Assert(c == '\t'); // \t is 9
output.Append(c);
}
} else if (c == (char)LesColorCode.Opener) {
if (next == '(' || next == '[')
c = (char)((++depth & 1) == 0 ? LesColorCode.Closer : LesColorCode.Opener);
else
c = (char)LesColorCode.Separator;
} else if (c == (char)LesColorCode.Closer) {
if (next == ')' || next == ']')
c = (char)((--depth & 1) == 1 ? LesColorCode.Closer : LesColorCode.Opener);
else
c = (char)LesColorCode.Separator;
}
var newClass = colorCodesToCssClasses[(int)c];
if (newClass != cssClass) {
if (cssClass != null)
output.Append("</span>");
if (newClass != null)
output.Append("<span class='").Append(newClass).Append("'>");
cssClass = newClass;
}
if (c == (char)LesColorCode.Attribute && next == '@' &&
input.TryGet(i + 2, '\0').IsOneOf((char)LesColorCode.Id, (char)LesColorCode.Number, (char)LesColorCode.KeywordLiteral, (char)LesColorCode.CustomLiteral, (char)LesColorCode.String))
{
output.Append('@');
// skip over @ and the next control code to extend attribute coloring over it
i += 2;
}
} else if (c == '<') {
output.Append("<");
} else if (c == '&') {
output.Append("&");
} else {
output.Append(c);
}
}
if (cssClass != null)
output.Append("</span>");
if (addPreCode)
output.Append("</code></pre>");
return output;
}