source: trunk/lib/html_utility.cc @ 228

Last change on this file since 228 was 228, checked in by Peter Johansson, 15 years ago

fixes #109

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 12.5 KB
Line 
1// $Id: html_utility.cc 228 2007-03-24 15:41:47Z peter $
2
3/*
4  Copyright (C) 2006, 2007 Peter Johansson
5
6  This file is part of svndigest, http://lev.thep.lu.se/trac/svndigest
7
8  svndigest is free software; you can redistribute it and/or modify it
9  under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12
13  svndigest is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21  02111-1307, USA.
22*/
23
24#include "html_utility.h"
25#include "Stats.h"
26#include "utility.h"
27#include <config.h> // this header file is created by configure
28
29#include <fstream>
30#include <iostream>
31#include <sstream>
32#include <stdexcept>
33#include <string>
34#include <sys/param.h>
35#include <unistd.h>
36#include <vector>
37
38namespace theplu{
39namespace svndigest{
40
41  void anchor(std::ostream& os, const std::string& href, 
42              const std::string& name, u_int level, 
43              const std::string& title)
44  {
45    os << "<a title=\"" << title << "\" href=\"" ;
46    for (size_t i=0; i<level; ++i)
47      os << "../";
48    os << href << "\">" << name << "</a>";
49  }
50
51
52 
53  void html(std::istream& is, std::ostream& os, char delim) 
54  {
55    char c;
56    while (true){
57      is.get(c);
58      if (c==delim || !is.good()){
59        return;
60      }
61      if (c=='"')
62        os << '\"';
63      else if (c=='\'')
64        os << "\'";
65      else if (c=='\n')
66        os << "<br/>";
67      else if (c=='<')
68        os << "&lt;";
69      else if (c=='>')
70        os << "&gt;";
71      else if (c=='&')
72        os << "&amp;";
73      else if (c=='\t')
74        os << "&nbsp;&nbsp;";
75      else if (c=='å')
76        os << "&aring;";
77      else if (c=='ä')
78        os << "&auml;";
79      else if (c=='ö')
80        os << "&ouml;";
81      else if (c=='Å')
82        os << "&Aring;";
83      else if (c=='Ä')
84        os << "&Auml;";
85      else if (c=='Ö')
86        os << "&Ouml;";
87      else if (c=='é')
88        os << "&eacute;";
89      else
90        os << c;
91    }
92  }
93 
94
95  void print_css(const std::string& str)
96  {
97    std::ofstream s(str.c_str());
98    s << "<-- svndigest.css generated by " << PACKAGE_STRING << "\n"
99
100      << "Copyright (C) 2006, 2007 Peter Johansson\n\n"
101      << "This file is part of svndigest, " 
102      << "http://lev.thep.lu.se/trac/svndigest\n\n"
103
104      << "svndigest is free software; you can redistribute it and/or " 
105      << "modify it\n"
106      << "under the terms of the GNU General Public License as published by\n"
107      << "the Free Software Foundation; either version 2 of the License, or\n"
108      << "(at your option) any later version.\n\n"
109
110      << "svndigest is distributed in the hope that it will be useful, but\n"
111      << "WITHOUT ANY WARRANTY; without even the implied warranty of\n"
112      << "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
113      << "General Public License for more details.\n\n"
114
115      << "You should have received a copy of the GNU General Public License\n"
116      << "along with this program; if not, write to the Free Software\n"
117      << "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA\n"
118      << "02111-1307, USA.\n\n"
119
120      << "This file was initially ispired by the cascading style sheet\n"
121      << "within the Trac open source project (http://trac.edgewall.org/)\n"
122      << "Copyright (C) 2003-2006 Edgewall Software\n"
123      << "All rights reserved.\n\n"
124
125      << "Redistribution and use in source and binary forms, with or without\n"
126      << "modification, are permitted provided that the following conditions\n"
127      << "are met:\n\n"
128     
129      << "1. Redistributions of source code must retain the above copyright\n"
130      << "   notice, this list of conditions and the following disclaimer.\n"
131      << "2. Redistributions in binary form must reproduce the above " 
132      << "copyright\n"
133      << "   notice, this list of conditions and the following disclaimer in\n"
134      << "   the documentation and/or other materials provided with the\n"
135      << "   distribution.\n"
136      << "3. The name of the author may not be used to endorse or promote\n"
137      << "   products derived from this software without specific prior\n"
138      << "   written permission.\n\n"
139     
140      << "THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS\n"
141      << "OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n"
142      << "WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n"
143      << "ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY\n"
144      << "DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n"
145      << "DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\n"
146      << "GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n"
147      << "INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n"
148      << "WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n"
149      << "NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n"
150      << "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.-->\n";
151
152
153    s << "body {\n";
154    s << " background: #fff; \n";
155    s << " color: #000; \n";
156    s << " margin: 0px; \n";
157    s << " padding: 0; \n";
158    s << "} \n";
159    s << "\n";
160    s << "#menu {\n";
161    s << " background: #eee;\n";
162    s << " width: 100%;\n";
163    s << " margin: 0px;\n";
164    s << " padding: 0px;\n";
165    s << "}\n\n";
166    s << "#menu ul\n";
167    s << "{ \n";
168    s << "padding: 0px;\n";
169    s << "margin: 0px;list-style-type: none; text-align: center;"
170      << "border-bottom: 1px solid black;}\n";
171    s << "#menu ul li { display: inline; border-right: 1px solid black;}\n";
172    s << "#menu ul li a {text-decoration: none; padding-right: 1em;" 
173      << "padding-left: 1em; margin: 0px;}\n";
174    s << "#menu ul li a:hover{ color: #000; background: #ddd;}\n";
175    s << "#menu ul li.highlight a {color: #fff; background: #777; }";
176    s << "\n";
177    s << "#main {\n";
178    s << " margin: 10px; \n";
179    s << "}\n";
180    s << "\n";
181    s << "body, th, td {\n";
182    s << " font: normal 13px verdana,arial,'Bitstream Vera Sans',"
183      << "helvetica,sans-serif;\n";
184    s << "}\n";
185    s << ":link, :visited {\n";
186    s << " text-decoration: none;\n";
187    s << " color: #b00;\n";
188    s << "}\n";
189    s << "\n";
190    s << "div.main {\n";
191    s << "margin-top: 50px;\n";         
192    s << "margin-left: 50px;\n";
193    s << " \n";
194    s << "}\n";
195    s << "table.main {\n"; 
196    s << " text-align: left;\n";
197    s << " padding: 0 1em .1em 0;\n";
198    s << "}\n";
199    s << "table.main th {\n";
200    s << " text-align: left;\n";
201    s << " padding: 0 1em 0.5em 0;\n";
202    s << " font-size: 150%;\n";
203    s << " font-wheight: bold;\n";
204    s << "}\n";
205    s << "table.main td {\n";
206    s << " padding: 0 1em .1em 0;\n";
207    s << "}\n";
208
209
210
211
212    s << "table.listings {\n";
213    s << " clear: both;\n";
214    s << " border-bottom: 1px solid #d7d7d7;\n";
215    s << " border-collapse: collapse;\n";
216    s << " border-spacing: 0;\n";
217    s << " margin-top: 1em;\n";
218    s << " width: 100%;\n";
219    s << "}\n";
220    s << "\n";
221    s << "table.listings th {\n";
222    s << " text-align: left;\n";
223    s << " padding: 0 1em .1em 0;\n";
224    s << " font-size: 12px\n";
225    s << "}\n";
226    s << "table.listings thead { background: #f7f7f0 }\n";
227    s << "table.listings thead th {\n";
228    s << " border: 1px solid #d7d7d7;\n";
229    s << " border-bottom-color: #999;\n";
230    s << " font-size: 11px;\n";
231    s << " font-wheight: bold;\n";
232    s << " padding: 2px .5em;\n";
233    s << " vertical-align: bottom;\n";
234    s << "}\n";
235    s << "\n";
236    s << "table.listings tbody td a:hover, table.listing tbody th a:hover {\n";
237    s << " background-color: transparent;\n";
238    s << "}\n";
239    s << "\n";
240    s << "table.listings tbody td, table.listing tbody th {\n";
241    s << " border: 1px dotted #ddd;\n";
242    s << " padding: .33em .5em;\n";
243    s << " vertical-align: top;\n";
244    s << "}\n";
245    s << "\n";
246    s << "table.listings tbody td a:hover, table.listing tbody th a:hover {\n";
247    s << " background-color: transparent;\n";
248    s << "}\n";
249    s << "table.listings tbody tr { border-top: 1px solid #ddd }\n";
250    s << "table.listings tbody tr.light { background-color: #fcfcfc }\n";
251    s << "table.listings tbody tr.dark { background-color: #f7f7f7 }\n";
252    s << "table.listings tbody tr:hover { background: #eed }\n";
253    s << "table.listings tbody td { text-align: left }\n";
254    s << "table.listings tbody td.directory a { font-weight: bold }\n";
255    s << "\n";
256    s << ".sep { color: #666}\n";
257    s << "\n";
258    s << "\n";
259    s.close();
260  }
261
262
263  void print_main_page(const std::string& dir,
264                       const std::vector<std::string>& commit_dates,
265                       const Stats& stats)
266  {
267    std::string filename="index.html";
268    std::ofstream os(filename.c_str());
269    print_header(os, dir, 0, "main", "index.html");
270    time_t first = str2time(commit_dates[1]);
271    std::string first_date = asctime(gmtime(&first)); 
272    time_t last = str2time(commit_dates.back());
273    std::string last_date = asctime(gmtime(&last));
274   
275    u_int years = 0;
276    u_int months  = 0;
277    u_int days = 0;
278    // No support in std for diffing two tm structs
279    time_t now = time(NULL);
280    tm* timeinfo = gmtime(&now);
281    std::string now_date = asctime(timeinfo);
282    while (difftime(now,first)>0){
283      --timeinfo->tm_year; 
284      now = mktime(timeinfo);
285      ++years;
286    }
287    --years;
288    ++timeinfo->tm_year; 
289    now = mktime(timeinfo);
290   
291    while (difftime(now,first)>0){
292      if (timeinfo->tm_mon>0) 
293        --timeinfo->tm_mon; 
294      else{
295        timeinfo->tm_mon=11; 
296        --timeinfo->tm_year;
297      }
298      now = mktime(timeinfo);
299      ++months;
300    }
301    --months;
302    ++timeinfo->tm_mon; 
303    if (timeinfo->tm_mon>11){
304      timeinfo->tm_mon=0;
305      ++timeinfo->tm_year;
306    } 
307    now = mktime(timeinfo);
308   
309    days = (now - first)/60/60/24;
310
311    now = time(NULL);
312    os << "<div class=\"main\">\n"
313       << "<table class=\"main\"><thead><tr><th colspan=\"2\">" 
314       << "General Information"
315       << "</th></tr><thead>\n"
316       << "<tr><td>First Revision:</td><td>" 
317       << first_date << "</td></tr>\n"
318       << "<tr><td>Latest Revision:</td><td>" 
319       << last_date << "</td></tr>\n"
320       << "<tr><td>Report Generated:</td><td>" 
321       <<  now_date << "</td></tr>\n"
322       << "<tr><td>Repository Age:</td><td>"; 
323    if (years){
324      os << years << " year";
325      if (years>1)
326        os << "s";
327      os << " ";
328    }
329    if (months){
330      os << months << " month";
331      if (months>1)
332        os << "s";
333      os << " ";
334    }
335    if (months || years)
336      os << "and ";
337    os << days << " day";
338    if (days>1)
339      os << "s";
340     
341    os << "</td></tr>\n"
342       << "<tr><td>Number of Authors:</td><td>" << stats.authors().size() 
343       << "</td></tr>\n"
344       << "<tr><td>Revisions:</td><td>" << commit_dates.size()-1 
345       << "</td></tr>\n"
346       << "</table></div>\n";
347    os << "<hr width=100% />";
348   
349       
350    print_footer(os);
351    os.close();
352  }
353
354
355  void print_footer(std::ostream& os)
356  {
357   
358    time_t rawtime;
359    struct tm * timeinfo;
360    time ( &rawtime );
361    timeinfo =  gmtime ( &rawtime );
362    os << "<p align=center><font size=-2>\nGenerated on "
363       << asctime (timeinfo) << " (UTC) by ";
364    anchor(os, "http://lev.thep.lu.se/trac/svndigest/", PACKAGE_STRING, 0, "");
365    os << "</font>\n</p>\n</div>\n</body>\n</html>\n";
366  }
367
368
369  void print_header(std::ostream& os, const std::string& title, u_int level,
370                    const std::string& item, const std::string& path)
371  {
372    os << "<!DOCTYPE html\n"
373       << "PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
374       << "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
375       << "<html xmlns=\"http://www.w3.org/1999/xhtml\""
376       << " xml:lang=\"en\" lang=\"en\"><head>\n"
377       << "<head>\n"
378       << "<title> " << title << " - svndigest</title>\n"
379       << "</head>\n"
380       << "<link rel=\"stylesheet\" "
381       << "href=\"";
382    for (u_int i=0; i<level; ++i)
383      os << "../";
384    os << "svndigest.css\" type=\"text/css\" />\n"
385       << "<body>\n"
386       << "<div id=\"menu\">"
387       << "<ul><li></li>";
388    if (item=="main")
389      os << "<li class=\"highlight\">";
390    else
391      os << "<li>";
392    anchor(os, "index.html", "Main", level, "Main page");
393    os << "</li>";
394
395    if (item=="total")
396      os << "<li class=\"highlight\">";
397    else
398      os << "<li>";
399    anchor(os, "all/total/"+path, "Total", level, 
400           "View statistics of all lines");
401    os << "</li>";
402
403    if (item=="code")
404      os << "<li class=\"highlight\">";
405    else
406      os << "<li>";
407    anchor(os, "all/code/"+path, "Code", level, 
408           "View statistics of code lines");
409    os << "</li>";
410
411    if (item=="comments")
412      os << "<li class=\"highlight\">";
413    else
414      os << "<li>";
415    anchor(os, "all/comments/"+path, "Comment", level, 
416           "View statistics of comment lines");
417    os << "</li>";
418
419
420    if (item=="empty")
421      os << "<li class=\"highlight\">";
422    else
423      os << "<li>";
424    anchor(os, "all/empty/"+path, "Empty", level, 
425           "View statistics of empty lines");
426    os << "</li>"
427       << "</ul></div>"
428       << "<div id=\"main\">\n";
429  }
430
431
432}} // end of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.