diff options
Diffstat (limited to 'Source/cmDocumentationFormatterHTML.cxx')
-rw-r--r-- | Source/cmDocumentationFormatterHTML.cxx | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/Source/cmDocumentationFormatterHTML.cxx b/Source/cmDocumentationFormatterHTML.cxx new file mode 100644 index 0000000..7213b43 --- /dev/null +++ b/Source/cmDocumentationFormatterHTML.cxx @@ -0,0 +1,288 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmDocumentationFormatterHTML.h" +#include "cmDocumentationSection.h" +#include "cmVersion.h" +//---------------------------------------------------------------------------- +static bool cmDocumentationIsHyperlinkChar(char c) +{ + // This is not a complete list but works for CMake documentation. + return ((c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9') || + c == '-' || c == '.' || c == '/' || c == '~' || c == '@' || + c == ':' || c == '_' || c == '&' || c == '?' || c == '='); +} + +//---------------------------------------------------------------------------- +static void cmDocumentationPrintHTMLChar(std::ostream& os, char c) +{ + // Use an escape sequence if necessary. + switch (c) + { + case '<': + os << "<"; + break; + case '>': + os << ">"; + break; + case '&': + os << "&"; + break; + case '\n': + os << "<br />"; + break; + default: + os << c; + } +} + +//---------------------------------------------------------------------------- +bool cmDocumentationHTMLIsIdChar(char c) +{ + // From the HTML specification: + // ID and NAME tokens must begin with a letter ([A-Za-z]) and may + // be followed by any number of letters, digits ([0-9]), hyphens + // ("-"), underscores ("_"), colons (":"), and periods ("."). + return ((c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9') || + c == '-' || c == '_' || c == ':' || c == '.'); +} + +//---------------------------------------------------------------------------- +void cmDocumentationPrintHTMLId(std::ostream& os, const char* begin) +{ + for(const char* c = begin; *c; ++c) + { + if(cmDocumentationHTMLIsIdChar(*c)) + { + os << *c; + } + } +} + +//---------------------------------------------------------------------------- +const char* cmDocumentationPrintHTMLLink(std::ostream& os, const char* begin) +{ + // Look for the end of the link. + const char* end = begin; + while(cmDocumentationIsHyperlinkChar(*end)) + { + ++end; + } + + // Print the hyperlink itself. + os << "<a href=\""; + for(const char* c = begin; c != end; ++c) + { + cmDocumentationPrintHTMLChar(os, *c); + } + os << "\">"; + + // The name of the hyperlink is the text itself. + for(const char* c = begin; c != end; ++c) + { + cmDocumentationPrintHTMLChar(os, *c); + } + os << "</a>"; + + // Return the position at which to continue scanning the input + // string. + return end; +} + + +cmDocumentationFormatterHTML::cmDocumentationFormatterHTML() +:cmDocumentationFormatter() +{ +} + +void cmDocumentationFormatterHTML +::PrintSection(std::ostream& os, + const cmDocumentationSection §ion, + const char* name) +{ + std::string prefix = this->ComputeSectionLinkPrefix(name); + + const std::vector<cmDocumentationEntry> &entries = + section.GetEntries(); + + // skip the index if the help for only a single item (--help-command, + // --help-policy, --help-property, --help-module) is printed + bool isSingleItemHelp = ((name!=0) && (strcmp(name, "SingleItem")==0)); + + if (!isSingleItemHelp) + { + if (name) + { + os << "<h2><a name=\"section_"; + cmDocumentationPrintHTMLId(os, name); + os << "\"></a>" << name << "</h2>\n"; + } + + // Is a list needed? + for(std::vector<cmDocumentationEntry>::const_iterator op + = entries.begin(); op != entries.end(); ++ op ) + { + if (op->Name.size()) + { + os << "<ul>\n"; + for(;op != entries.end() && op->Name.size(); ++op) + { + if(op->Name.size()) + { + os << " <li><a href=\"#" << prefix << ":"; + cmDocumentationPrintHTMLId(os, op->Name.c_str()); + os << "\"><b><code>"; + this->PrintHTMLEscapes(os, op->Name.c_str()); + os << "</code></b></a></li>\n"; + } + } + os << "</ul>\n" ; + break; // Skip outer loop termination test + } + } + } + + for(std::vector<cmDocumentationEntry>::const_iterator op = entries.begin(); + op != entries.end();) + { + if(op->Name.size()) + { + os << "<ul>\n"; + for(;op != entries.end() && op->Name.size(); ++op) + { + os << " <li>\n"; + if(op->Name.size()) + { + os << " <a name=\"" << prefix << ":"; + cmDocumentationPrintHTMLId(os, op->Name.c_str()); + os << "\"></a><b><code>"; + this->PrintHTMLEscapes(os, op->Name.c_str()); + os << "</code></b>: "; + } + this->PrintHTMLEscapes(os, op->Brief.c_str()); + if(op->Full.size()) + { + os << "<br />\n "; + this->PrintFormatted(os, op->Full.c_str()); + } + os << "\n"; + os << " </li>\n"; + } + os << "</ul>\n"; + } + else + { + this->PrintFormatted(os, op->Brief.c_str()); + os << "\n"; + ++op; + } + } +} + +void cmDocumentationFormatterHTML::PrintPreformatted(std::ostream& os, + const char* text) +{ + os << "<pre>"; + this->PrintHTMLEscapes(os, text); + os << "</pre>\n "; +} + +void cmDocumentationFormatterHTML::PrintParagraph(std::ostream& os, + const char* text) +{ + os << "<p>"; + this->PrintHTMLEscapes(os, text); + os << "</p>\n"; +} + +//---------------------------------------------------------------------------- +void cmDocumentationFormatterHTML::PrintHeader(const char* docname, + const char* appname, + std::ostream& os) +{ + os << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"" + << " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"; + os << "<html xmlns=\"http://www.w3.org/1999/xhtml\"" + << " xml:lang=\"en\" lang=\"en\">\n"; + os << "<head><meta http-equiv=\"Content-Type\" " + << "content=\"text/html;charset=utf-8\" /><title>"; + os << docname << " - " << appname; + os << "</title></head><body>\n"; +} + +//---------------------------------------------------------------------------- +void cmDocumentationFormatterHTML::PrintFooter(std::ostream& os) +{ + os << "</body></html>\n"; +} + +//---------------------------------------------------------------------------- +void cmDocumentationFormatterHTML::PrintHTMLEscapes(std::ostream& os, + const char* text) +{ + // Hyperlink prefixes. + static const char* hyperlinks[] = {"http://", "ftp://", "mailto:", 0}; + + // Print each character. + for(const char* p = text; *p;) + { + // Handle hyperlinks specially to make them active. + bool found_hyperlink = false; + for(const char** h = hyperlinks; !found_hyperlink && *h; ++h) + { + if(strncmp(p, *h, strlen(*h)) == 0) + { + p = cmDocumentationPrintHTMLLink(os, p); + found_hyperlink = true; + } + } + + // Print other characters normally. + if(!found_hyperlink) + { + cmDocumentationPrintHTMLChar(os, *p++); + } + } +} + +void cmDocumentationFormatterHTML +::PrintIndex(std::ostream& os, + std::vector<const cmDocumentationSection *>& sections) +{ + // skip the index if only the help for a single item is printed + if ((sections.size() == 1) + && (sections[0]->GetName(this->GetForm()) != 0 ) + && (std::string(sections[0]->GetName(this->GetForm())) == "SingleItem")) + { + return; + } + + os << "<h2><a name=\"section_Index\"></a>Master Index " + << "CMake " << cmVersion::GetCMakeVersion() + << "</h2>\n"; + + if (!sections.empty()) + { + os << "<ul>\n"; + for(unsigned int i=0; i < sections.size(); ++i) + { + std::string name = sections[i]->GetName((this->GetForm())); + os << " <li><a href=\"#section_"; + cmDocumentationPrintHTMLId(os, name.c_str()); + os << "\"><b>" << name << "</b></a></li>\n"; + } + os << "</ul>\n"; + } +} |