diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-08-19 11:20:45 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-08-23 13:54:51 +0200 |
commit | 0ebdc6a8f9bd26d73687adc654120751f928188c (patch) | |
tree | c1da4f0f4c9f360d712b99ea19f40532be380252 | |
parent | bcd246076540a8353fa55fc0a5e19343c1a2dbc9 (diff) |
XHTML generation revision
-rw-r--r-- | brep/package-search.cxx | 69 | ||||
-rw-r--r-- | web/xhtml | 129 |
2 files changed, 123 insertions, 75 deletions
diff --git a/brep/package-search.cxx b/brep/package-search.cxx index 3317d43..455778b 100644 --- a/brep/package-search.cxx +++ b/brep/package-search.cxx @@ -58,7 +58,7 @@ namespace brep throw invalid_request (400, e.what ()); } - // @@ Would be nice to have a manipulator identing string properly + // @@ Would be nice to have a manipulator indenting string properly // according to the most nested element identation. // const char* ident ("\n "); @@ -68,11 +68,11 @@ namespace brep s << HTML << HEAD << TITLE << title << ~TITLE - << STYLE(TYPE="text/css") << ident + << CSS_STYLE << ident << ".package {margin: 0 0 0.5em;}" << ident << ".name a {text-decoration: none;}" << ident << ".summary {font-size: small;}" - << ~STYLE + << ~CSS_STYLE << ~HEAD << BODY; @@ -93,59 +93,52 @@ namespace brep for (const auto& p: r) { - s << DIV(CLASS="package") - << DIV(CLASS="name") - << A - << HREF - << "/go/" << mime_url_encode (p.name); + s << DIV(CLASS="package") + << DIV(CLASS="name") + << A + << HREF << "/go/" << mime_url_encode (p.name); // Propagate search criteria to the package version search url. // if (!q.empty ()) - s << "?" << q; - - s << ~HREF - << p.name - << ~A - << ~DIV - << DIV(CLASS="summary") - << p.summary - << ~DIV - << ~DIV; + s << "?" << q; + + s << ~HREF + << p.name + << ~A + << ~DIV + << DIV(CLASS="summary") + << p.summary + << ~DIV + << ~DIV; } t.commit (); if (pr.page () || r.size () == options_->results_on_page ()) { - s << DIV; + s << DIV; if (pr.page ()) - { - s << A - << HREF << "/?p=" << pr.page () - 1 - << (q.empty () ? "" : "&" + q) - << ~HREF - << "Previous" - << ~A - << " "; - } + s << A + << HREF << "/?p=" << pr.page () - 1 << (q.empty () ? "" : "&" + q) + << ~HREF + << "Previous" + << ~A + << " "; // @@ Not ideal as can produce link to an empty page, but easy to fix // and most likelly will be replaced with something more meaningful // based on knowing the total number of matched packages. // if (r.size () == options_->results_on_page ()) - { - s << A - << HREF << "/?p=" << pr.page () + 1 - << (q.empty () ? "" : "&" + q) - << ~HREF - << "Next" - << ~A; - } - - s << ~DIV; + s << A + << HREF << "/?p=" << pr.page () + 1 << (q.empty () ? "" : "&" + q) + << ~HREF + << "Next" + << ~A; + + s << ~DIV; } s << ~BODY @@ -5,15 +5,13 @@ #ifndef WEB_XHTML #define WEB_XHTML -#include <functional> // function - #include <xml/serializer> namespace web { // "Canonical" XHTML5 vocabulary. // - // One-letter tag names and local variable clash problem: + // * One-letter tag names and local variable clash problem // // a at|an|an anc anch // b bt|bo|bl bld bold @@ -27,6 +25,7 @@ namespace web // - _a, a_, xa // - A, I // - x::i + // - user-defined literals: "a"_e, "/a"_e, "id"_a // // Things can actually get much worse, consider: // @@ -36,12 +35,35 @@ namespace web // So perhaps this is the situation where the explicit namespace // qualification (e.g., x::p) is the only robust option? // + // + // * Element/attribute name clash problem (e.g., STYLE) + // + // - some attribute/element name decorator (STYLEA, STYLE_A, STYLE_) + // - rename attribute/element (e.g., STYLEDEF or CSSSTYLE[adds TYPE]); + // in case of STYLE we should probably rename the element since + // attribute will be much more frequently used. + // - "scope" attributes inside elements (P::STYLE); somewhat + // burdensome: P(P::STYLE); could then use low-case names + // for attributes + // - "scope" elements inside other elements (HEAD::STYLE); also + // burdensome. + // + // + // * Text wrapping/indentation + // + // For some (inline) elements we want additional indentation: + // + // 1. Indent content on newline (e.g., for <style>). + // 2. Automatically wrap and indent lines at (or before) certain + // length, say, 80 characters (e.g., for <p>). + // + // Would be nice to be able to implement this at the XHTML level, + // not XML. + // namespace xhtml { const char* const xmlns = "http://www.w3.org/1999/xhtml"; - using serializer_func = std::function<void(xml::serializer&)>; - struct attr_value_base { const char* name; @@ -83,12 +105,27 @@ namespace web operator() (xml::serializer& s) const; }; + class end_element + { + public: + const char* name; + + explicit + end_element (const char* n): name (n) {} + + virtual void + operator() (xml::serializer& s) const + { + return s.end_element (xmlns, name); + } + }; + struct element_base { virtual void operator() (xml::serializer& s) const = 0; - virtual serializer_func + virtual end_element operator~ () const = 0; empty_element @@ -111,7 +148,7 @@ namespace web virtual void operator() (xml::serializer& s) const {s << *e << *a;} - virtual serializer_func + virtual end_element operator~ () const {return ~*e;} }; @@ -125,11 +162,8 @@ namespace web virtual void operator() (xml::serializer& s) const {s.start_element (xmlns, name);} - virtual serializer_func - operator~ () const - { - return [this](xml::serializer& s) {s.end_element (xmlns, name);}; - } + virtual end_element + operator~ () const {return end_element (name);} // s << elem(attr1 = 123, attr2 = "abc"); // @@ -147,12 +181,20 @@ namespace web a1.next = operator() (an...).a; return attr_element (*this, a1); } + }; + + class end_inline_element: public end_element + { + public: + explicit + end_inline_element (const char* n): end_element (n) {} -// @@ Now always need to provide element name, so operator~ () could create -// the lambda capable to pass a valid name to end_element call. -// -// protected: -// element () = default; + virtual void + operator() (xml::serializer& s) const + { + s.end_element (xmlns, name); + s.resume_indentation (); + } }; struct inline_element: element @@ -167,14 +209,23 @@ namespace web element::operator() (s); } - virtual serializer_func - operator~ () const - { - return [this](xml::serializer& s) - { - s.end_element (xmlns, name); s.resume_indentation (); - }; - } + //@@ Can't do that: you are slicing end_inline_element to + // end_element. + // + virtual end_element + operator~ () const {return end_inline_element (name);} + }; + + class end_attribute + { + public: + const char* name; + + explicit + end_attribute (const char* n): name (n) {} + + virtual void + operator() (xml::serializer& s) const {return s.end_attribute (name);} }; struct attribute @@ -201,11 +252,8 @@ namespace web void operator() (xml::serializer& s) const {s.start_attribute (name);} - virtual serializer_func - operator~ () const - { - return [this](xml::serializer& s) {s.end_attribute (name);}; - } + virtual end_attribute + operator~ () const {return end_attribute (name);} }; // Elements. @@ -244,10 +292,22 @@ namespace web }; static const head_element HEAD; + struct css_style_element: element + { + css_style_element (): element ("style") {} + + virtual void + operator() (xml::serializer& s) const + { + s.start_element (xmlns, name); + s.attribute ("type", "text/css"); + } + }; + static const css_style_element CSS_STYLE; + static const element BODY ("body"); static const element DIV ("div"); static const element P ("p"); - static const element STYLE ("style"); static const element TITLE ("title"); static const inline_element A ("a"); @@ -263,13 +323,8 @@ namespace web static const attribute CLASS ("class"); static const attribute HREF ("href"); static const attribute ID ("id"); + static const attribute STYLE ("style"); static const attribute TYPE ("type"); - -// @@ Attribute variable names clash with element variable names. -// Should we prefix/suffix attribute names like _STYLE, STYLE_ or there -// are some better ideas ? -// -// static const attribute STYLE ("style"); } } |