aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-08-19 11:20:45 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-08-23 13:54:51 +0200
commit0ebdc6a8f9bd26d73687adc654120751f928188c (patch)
treec1da4f0f4c9f360d712b99ea19f40532be380252
parentbcd246076540a8353fa55fc0a5e19343c1a2dbc9 (diff)
XHTML generation revision
-rw-r--r--brep/package-search.cxx69
-rw-r--r--web/xhtml129
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
diff --git a/web/xhtml b/web/xhtml
index 4fc6119..2d4007c 100644
--- a/web/xhtml
+++ b/web/xhtml
@@ -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");
}
}