PLearn 0.1
HTMLUtils.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // HTMLUtils.cc
00004 //
00005 // Copyright (C) 2004-2006 Nicolas Chapados 
00006 // Copyright (C) 2007 Xavier Saint-Mleux, ApSTAT Technologies, inc.
00007 //
00008 // Redistribution and use in source and binary forms, with or without
00009 // modification, are permitted provided that the following conditions are met:
00010 //
00011 //  1. Redistributions of source code must retain the above copyright
00012 //     notice, this list of conditions and the following disclaimer.
00013 //
00014 //  2. Redistributions in binary form must reproduce the above copyright
00015 //     notice, this list of conditions and the following disclaimer in the
00016 //     documentation and/or other materials provided with the distribution.
00017 //
00018 //  3. The name of the authors may not be used to endorse or promote
00019 //     products derived from this software without specific prior written
00020 //     permission.
00021 //
00022 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00023 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00024 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00025 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00027 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00028 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00029 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00030 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00031 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032 //
00033 // This file is part of the PLearn library. For more information on the PLearn
00034 // library, go to the PLearn Web site at www.plearn.org
00035 
00036 // Authors: Xavier Saint-Mleux
00037 
00041 #include <plearn/base/Object.h>
00042 
00043 #include "HTMLUtils.h"
00044 
00045 #include <plearn/base/stringutils.h>
00046 #include <plearn/base/tostring.h>
00047 #include <boost/regex.hpp>
00048 #include <commands/PLearnCommands/plearn_main.h>
00049 #include <plearn/base/TypeFactory.h>
00050 #include <plearn/base/OptionBase.h>
00051 
00052 namespace PLearn {
00053 using namespace std;
00054 
00055 string HTMLUtils::quote(string s)
00056 {
00057 #ifndef __INTEL_COMPILER
00058     search_replace(s, "&", "&amp;");
00059     search_replace(s, "<", "&lt;");
00060     search_replace(s, ">", "&gt;");
00061     search_replace(s, "\"", "&quot;");
00062 #endif
00063     return s;
00064 }
00065 
00066 string HTMLUtils::highlight_known_classes(string typestr)
00067 {
00068 #ifndef __INTEL_COMPILER
00069     vector<string> tokens = split(typestr, " \t\n\r<>,.';:\"");
00070     set<string> replaced; // Carry out replacements for a given token only once
00071     const TypeMap& type_map = TypeFactory::instance().getTypeMap();
00072     vector<string>::size_type n=tokens.size();
00073     for (unsigned int i=0; i<n ; ++i) {
00074         TypeMap::const_iterator it = type_map.find(tokens[i]);
00075         if (it != type_map.end() && replaced.find(tokens[i]) == replaced.end()) {
00076             replaced.insert(tokens[i]);
00077       
00078             // ensure we only match whole words with the regular expression
00079             const boost::regex e("\\<" + tokens[i] + "\\>");
00080             const string repl_str("<a href=\"class_$&.html\\?level="
00081                                   + tostring(OptionBase::getCurrentOptionLevel()) 
00082                                   +"\">$&</a>");
00083             typestr = regex_replace(typestr, e, repl_str, boost::match_default | boost::format_default);
00084         }
00085     }
00086 #endif
00087     return typestr;
00088 }
00089 
00090 string HTMLUtils::format_free_text(string text)
00091 {
00092     // sort of DWIM HTML formatting for free-text; cannot use split since it
00093     // eats up consecutive delimiters
00094     text = removeblanks(text);
00095     size_t curpos = 0, curnl = text.find('\n');
00096     bool ul_active = false;
00097     bool start_paragraph = false;
00098     string finallines;
00099 #ifndef __INTEL_COMPILER
00100     for ( ; curpos != string::npos ;
00101           curpos = curnl+(curnl!=string::npos), curnl = text.find('\n', curpos) ) {
00102         string curline = text.substr(curpos, curnl-curpos);
00103 
00104         // step 1: check if the line starts with a '-': if so, start a new <UL>
00105         // if not in one, or extend one if so
00106         if (removeblanks(curline).substr(0,1) == "-" ||
00107             removeblanks(curline).substr(0,1) == "*" )
00108         {
00109             curline = removeblanks(curline).substr(1);
00110             if (! ul_active)
00111                 curline = "<ul><li>" + curline;
00112             else
00113                 curline = "<li>" + curline;
00114             start_paragraph = false;
00115             ul_active = true;
00116         }
00117 
00118         // otherwise, a line that starts with some whitespace within a list
00119         // just extends the previous <li> :: don't touch it
00120         else if (ul_active && (curline == "" ||
00121                                curline.substr(0,1) == " " ||
00122                                curline.substr(0,1) == "\t")) {
00123             /* do nothing */
00124         }
00125 
00126         // otherwise, normal processing
00127         else {
00128             // any line that is empty or starts with some whitespace gets its own <br>
00129             if (removeblanks(curline) == "") {
00130                 // Don't start new paragraph right away; wait until we
00131                 // encounter some text that's neither a <ul> or a <pre>
00132                 start_paragraph = true;
00133                 curline = "";
00134             }
00135             else if (curline[0] == ' ' || curline[0] == '\t') {
00136                 start_paragraph = false;
00137                 curline = "<pre>" + curline + "</pre>";
00138             }
00139 
00140             // if we were processing a list, close it first
00141             if (ul_active) {
00142                 curline = "</ul>" + curline;
00143                 ul_active = 0;
00144             }
00145         }
00146 
00147         if (!curline.empty() && start_paragraph) {
00148             finallines += "<p>";
00149             start_paragraph = false;
00150         }
00151         
00152         finallines += curline + "\n";
00153     }
00154 
00155     // Close any pending open blocks
00156     if (ul_active)
00157         finallines += "</ul>\n";
00158   
00159     // Finally join the lines
00160 #endif
00161     return make_http_hyperlinks(finallines);
00162 }
00163 
00164 string HTMLUtils::make_http_hyperlinks(string text)
00165 {
00166 #ifndef __INTEL_COMPILER
00167     // Find elements of the form XYZ://x.y.z/a/b/c and make them into
00168     // hyperlink. An issue is to determine when
00169     static const char* recognized_protocols[] = 
00170         { "http://", "https://", "ftp://", "mailto:" };        // for now...
00171     static const vector<string> protocols_vector(
00172         recognized_protocols,
00173         recognized_protocols + sizeof(recognized_protocols) / sizeof(recognized_protocols[0]));
00174 
00175     // Match everything that starts with the recognized protocol up to the
00176     // following whitespace, excluding trailing punctuation if any.
00177     // Make sure the URL is NOT enclosed in quotes
00178     static const boost::regex e( string("(?!\")") + "(" +
00179                                  "(?:" + join(protocols_vector, "|") + ")" +
00180                                  "\\S+(?:\\w|/)" +
00181                                  ")" + "(?!\")" + "([[:punct:]]*\\s|$)");
00182 
00183     const string repl_str("<a href=\"$1\?level=" 
00184                           + tostring(OptionBase::getCurrentOptionLevel())
00185                           +"\">$1</a>$2");
00186     text = regex_replace(text, e, repl_str, boost::match_default | boost::format_default);
00187 #endif
00188     return text;
00189 }
00190 
00191 string HTMLUtils::generated_by()
00192 {
00193     time_t curtime = time(NULL);
00194     struct tm *broken_down_time = localtime(&curtime);
00195     const int SIZE = 100;
00196     char time_buffer[SIZE];
00197     strftime(time_buffer,SIZE,"%Y/%m/%d %H:%M:%S",broken_down_time);
00198 
00199     return string("<p>&nbsp;</p><address>Generated on " ) +
00200         time_buffer + " by " + version_string() + "</address>";
00201 }
00202 
00203 } // end of namespace PLearn
00204 
00205 
00206 /*
00207   Local Variables:
00208   mode:c++
00209   c-basic-offset:4
00210   c-file-style:"stroustrup"
00211   c-file-offsets:((innamespace . 0)(inline-open . 0))
00212   indent-tabs-mode:nil
00213   fill-column:79
00214   End:
00215 */
00216 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines