1 //          Copyright Brian Schott (Hackerpilot) 2012.
2 // Distributed under the Boost Software License, Version 1.0.
3 //    (See accompanying file LICENSE_1_0.txt or copy at
4 //          http://www.boost.org/LICENSE_1_0.txt)
5 
6 module highlighter;
7 
8 import std.stdio;
9 import std.array;
10 import dparse.lexer;
11 
12 // http://ethanschoonover.com/solarized
13 void highlight(R)(ref R tokens, string fileName)
14 {
15 	stdout.writeln(q"[
16 <!DOCTYPE html>
17 <html>
18 <head>
19 <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>]");
20 	stdout.writeln("<title>", fileName, "</title>");
21 	stdout.writeln(q"[</head>
22 <body>
23 <style type="text/css">
24 html  { background-color: #fdf6e3; color: #002b36; }
25 .kwrd { color: #b58900; font-weight: bold;  }
26 .com  { color: #93a1a1; font-style: italic; }
27 .num  { color: #dc322f; font-weigth: bold;  }
28 .str  { color: #2aa198; font-style: italic; }
29 .op   { color: #586e75; font-weight: bold;  }
30 .type { color: #268bd2; font-weight: bold;  }
31 .cons { color: #859900; font-weight: bold;  }
32 </style>
33 <pre>]");
34 
35 	while (!tokens.empty)
36 	{
37 		auto t = tokens.front;
38 		tokens.popFront();
39 		if (isBasicType(t.type))
40 			writeSpan("type", str(t.type));
41 		else if (isKeyword(t.type))
42 			writeSpan("kwrd", str(t.type));
43 		else if (t.type == tok!"comment")
44 			writeSpan("com", t.text);
45 		else if (isStringLiteral(t.type) || t.type == tok!"characterLiteral")
46 			writeSpan("str", t.text);
47 		else if (isNumberLiteral(t.type))
48 			writeSpan("num", t.text);
49 		else if (isOperator(t.type))
50 			writeSpan("op", str(t.type));
51 		else if (t.type == tok!"specialTokenSequence" || t.type == tok!"scriptLine")
52 			writeSpan("cons", t.text.replace("<", "&lt;"));
53 		else
54 		{
55 			version (Windows)
56 			{
57 				// Stupid Windows automatically does a LF → CRLF, so
58 				// CRLF → CRCRLF, which is obviously wrong.
59 				// Strip out the CR characters here to avoid this.
60 				stdout.write(t.text.replace("<", "&lt;").replace("\r", ""));
61 			}
62 			else
63 				stdout.write(t.text.replace("<", "&lt;"));
64 		}
65 
66 	}
67 	stdout.writeln("</pre>\n</body></html>");
68 }
69 
70 void writeSpan(string cssClass, string value)
71 {
72 	version (Windows)
73 		stdout.write(`<span class="`, cssClass, `">`, value.replace("&",
74 				"&amp;").replace("<", "&lt;").replace("\r", ""), `</span>`);
75 	else
76 		stdout.write(`<span class="`, cssClass, `">`, value.replace("&",
77 				"&amp;").replace("<", "&lt;"), `</span>`);
78 }