BlogEngine.NET Alternate Line Highlighting breaks formatting
In testing out BlogEngine.NET, I found an issue with the source code formatter when alternate line highlighting is enabled. When the alternate line highligting option was on, the code would show the first line in the code block with code formatting, but all subsequent lines appeared outside of the code block without code formatting. In the following original code, you see that line 41 opens a div tag for an even line, and line 37 opens a p tag for an odd line. Unfortunately, as you can see on line 54, the code closes both tags as a div. This invalid syntax is what breaks the formatting.
1: //does the formatting job
2: private string FormatCode(string source, bool lineNumbers,
3: bool alternate, bool embedStyleSheet, bool subCode)
4: {
5: //replace special characters
6: StringBuilder sb = new StringBuilder(source);
7: if(!subCode)
8: {
9: sb.Replace("&", "&");
10: sb.Replace("<", "<");
11: sb.Replace(">", ">");
12: sb.Replace("\t", string.Empty.PadRight(_tabSpaces));
13: }
14: //color the code
15: source = codeRegex.Replace(sb.ToString(), new MatchEvaluator(this.MatchEval));
16: sb = new StringBuilder();
17: //if (embedStyleSheet)
18: //{
19: // sb.Append("<style type=\"text/css\">\n");
20: // sb.Append(GetCssString());
21: // sb.Append("</style>\n");
22: //}
23: if (lineNumbers || alternate) //we have to process the code line by line
24: {
25: if(!subCode)
26: sb.Append("<div class=\"code\">\n");
27: StringReader reader = new StringReader(source);
28: int i = 0;
29: string spaces = " ";
30: int order;
31: string line;
32: while ((line = reader.ReadLine()) != null)
33: {
34: i++;
35: if (alternate && ((i % 2) == 1))
36: {
37: sb.Append("<p class=\"alt\">");
38: }
39: else
40: {
41: sb.Append("<div>");
42: }
43: if(lineNumbers)
44: {
45: order = (int)Math.Log10(i);
46: sb.Append("<span class=\"lnum\">"
47: + spaces.Substring(0, 3 - order) + i.ToString()
48: + ": </span>");
49: }
50: if(line.Length == 0)
51: sb.Append(" ");
52: else
53: sb.Append(line);
54: sb.Append("</div>\n");
55: }
56: reader.Close();
57: if(!subCode)
58: sb.Append("</div>");
59: }
60: else
61: {
62: //have to use a <pre> because IE below ver 6 does not understand
63: //the "white-space: pre" CSS value
64: if(!subCode)
65: sb.Append("<div class=\"code\">\n");
66: sb.Append(source);
67: if(!subCode)
68: sb.Append("</div>");
69: }
70: return sb.ToString();
71: }
The following code snippet shows one possible fix, which is to change the p tag to a div tag, on line 37.
1: //does the formatting job
2: private string FormatCode(string source, bool lineNumbers,
3: bool alternate, bool embedStyleSheet, bool subCode)
4: {
5: //replace special characters
6: StringBuilder sb = new StringBuilder(source);
7: if(!subCode)
8: {
9: sb.Replace("&", "&");
10: sb.Replace("<", "<");
11: sb.Replace(">", ">");
12: sb.Replace("\t", string.Empty.PadRight(_tabSpaces));
13: }
14: //color the code
15: source = codeRegex.Replace(sb.ToString(), new MatchEvaluator(this.MatchEval));
16: sb = new StringBuilder();
17: //if (embedStyleSheet)
18: //{
19: // sb.Append("<style type=\"text/css\">\n");
20: // sb.Append(GetCssString());
21: // sb.Append("</style>\n");
22: //}
23: if (lineNumbers || alternate) //we have to process the code line by line
24: {
25: if(!subCode)
26: sb.Append("<div class=\"code\">\n");
27: StringReader reader = new StringReader(source);
28: int i = 0;
29: string spaces = " ";
30: int order;
31: string line;
32: while ((line = reader.ReadLine()) != null)
33: {
34: i++;
35: if (alternate && ((i % 2) == 1))
36: {
37: sb.Append("<div class=\"alt\">");
38: }
39: else
40: {
41: sb.Append("<div>");
42: }
43: if(lineNumbers)
44: {
45: order = (int)Math.Log10(i);
46: sb.Append("<span class=\"lnum\">"
47: + spaces.Substring(0, 3 - order) + i.ToString()
48: + ": </span>");
49: }
50: if(line.Length == 0)
51: sb.Append(" ");
52: else
53: sb.Append(line);
54: sb.Append("</div>\n");
55: }
56: reader.Close();
57: if(!subCode)
58: sb.Append("</div>");
59: }
60: else
61: {
62: //have to use a <pre> because IE below ver 6 does not understand
63: //the "white-space: pre" CSS value
64: if(!subCode)
65: sb.Append("<div class=\"code\">\n");
66: sb.Append(source);
67: if(!subCode)
68: sb.Append("</div>");
69: }
70: return sb.ToString();
71: }
An alternate fix would be to add an if statement and close the p tag for alternate line. I chose to use div tags, as the CSS class sufficiently differentiates the alternate lines thus no need for a different tag. The updated code file will be available for download in my next post, where I will discuss another issue with the source code formatter when posting from Windows Live Writer.
The code in this post is released under the Microsoft Reciprocal License, which is the license BlogEngine.NET uses.