src/html.cpp

changeset 5
60c2588b4455
child 6
1040ba37d4c9
equal deleted inserted replaced
4:82680ce258d6 5:60c2588b4455
1 /* Copyright 2025 Mike Becker. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 *
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25 #include "html.h"
26
27 #include <cstdio>
28
29 namespace html {
30 static unsigned indentation;
31 static const char *tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
32 static void indent(int change = 0) {
33 indentation += change;
34 fwrite(tabs, 1, indentation, stdout);
35 }
36
37 static std::string encode(const std::string &data) {
38 std::string buffer;
39 buffer.reserve(data.size()+16);
40 for (const char &pos: data) {
41 switch (pos) {
42 case '&':
43 buffer.append("&amp;");
44 break;
45 case '\"':
46 buffer.append("&quot;");
47 break;
48 case '\'':
49 buffer.append("&apos;");
50 break;
51 case '<':
52 buffer.append("&lt;");
53 break;
54 case '>':
55 buffer.append("&gt;");
56 break;
57 default:
58 buffer.append(&pos, 1);
59 break;
60 }
61 }
62 return buffer;
63 }
64 }
65
66 void html::open() {
67 puts(
68 R"(<html>
69 <head>
70 <style>
71 table.heatmap {
72 table-layout: fixed;
73 border-collapse: collapse;
74 font-family: sans-serif;
75 }
76 table.heatmap td, table.heatmap th {
77 text-align: center;
78 border: solid 1px lightgray;
79 height: 1.5em;
80 }
81 table.heatmap td {
82 border: solid 1px lightgray;
83 width: 1.5em;
84 height: 1.5em;
85 }
86 table.heatmap td.out-of-range {
87 background-color: gray;
88 }
89 </style>
90 </head>
91 <body>)");
92 indentation = 2;
93 }
94
95 void html::close() {
96 puts("\t</body>\n</html>");
97 }
98
99 void html::h1(const std::string& heading) {
100 indent();
101 printf("<h1>%s</h1>\n", encode(heading).c_str());
102 }
103
104 void html::h2(const std::string& heading) {
105 indent();
106 printf("<h2>%s</h2>\n", encode(heading).c_str());
107 }
108
109 void html::table_begin() {
110 indent();
111 puts("<table class=\"heatmap\">");
112 indent(1);
113 puts("<tr>");
114 indent(1);
115 puts("<th></th>");
116 static constexpr const char* months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
117 static constexpr int colspans[] = {5, 4, 4, 5, 4, 4, 5, 4, 4, 5, 4, 5};
118 for (unsigned i = 0 ; i < 12 ; i++) {
119 indent();
120 printf("<th scope=\"col\" colspan=\"%d\">%s</th>\n", colspans[i], months[i]);
121 }
122 indent(-1);
123 puts("</tr>");
124 }
125
126 void html::table_end() {
127 indentation--;
128 indent();
129 puts("</table>");
130 }
131
132 void html::row_begin(unsigned int row) {
133 static constexpr const char* weekdays[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
134 indent();
135 puts("<tr>");
136 indent(1);
137 printf("<th scope=\"row\">%s</th>\n", weekdays[row]);
138 }
139
140 void html::row_end() {
141 indent(-1);
142 puts("</tr>");
143 }
144
145 void html::cell_out_of_range() {
146 indent();
147 puts("<td class=\"out-of-range\"></td>");
148 }
149
150 void html::cell(unsigned commits) {
151 indent();
152 // TODO: use nice coloring and tooltips instead of printing the commits
153 printf("<td>%u</td>\n", commits);
154 }

mercurial