diff -r 406da27a4be2 -r fad360dd01da degal/html.py
--- a/degal/html.py Fri Jun 05 21:46:43 2009 +0300
+++ b/degal/html.py Fri Jun 05 21:47:45 2009 +0300
@@ -1,5 +1,7 @@
"""
- Generating HTML tags
+ Generating XHTML output
+
+ XXX: use a 'real' XML builder?
"""
from cgi import escape
@@ -17,6 +19,55 @@
abstract
+ def render_lines (self, indent=u'\t', newline=u'\n') :
+ """
+ Render full output lines with given newlines
+
+ >>> list(Tag('xx', 'yy').render_lines())
+ [u'\\n', u'\\tyy\\n', u'\\n']
+ """
+
+ for line in self.render_raw_lines(indent) :
+ yield line + newline
+
+ def render_unicode (self, **render_opts) :
+ """
+ Render full tag as a single unicode string
+
+ >>> Tag('xx', 'yy').render_unicode()
+ u'\\n\\tyy\\n\\n'
+ """
+
+ return "".join(self.render_lines(**render_opts))
+
+ def render_str (self, encoding='ascii', **render_opts) :
+ """
+ Render full tag as an encoded string
+
+ >>> Tag('xx', 'yy').render_str()
+ '\\n\\tyy\\n\\n'
+ """
+
+ return self.render_unicode(**render_opts).encode(encoding)
+
+ def render_out (self, stream, encoding, **render_opts) :
+ """
+ Render output into the given stream, encoding using the given encoding
+
+ >>> from StringIO import StringIO; buf = StringIO(); Tag('xx', 'yy').render_out(buf, 'ascii'); buf.getvalue()
+ '\\n\\tyy\\n\\n'
+ """
+
+ for line in self.render_lines(**render_opts) :
+ stream.write(line.encode(encoding))
+
+ # default output
+ __str__ = render_str
+ __unicode__ = render_unicode
+
+ # default .render method
+ render = render_unicode
+
class Tag (IRenderable) :
"""
A HTML tag, with attributes and contents, which can a mixture of data and other renderables(tags).
@@ -31,6 +82,8 @@
Items that are None will be omitted from the return value.
+ XXX: flatten
+
>>> Tag.process_contents([])
[]
>>> Tag.process_contents([None])
@@ -179,54 +232,6 @@
# singleton tag
yield u"<%s%s />" % (self.name, attrs_stuff)
- def render_lines (self, indent=u'\t', newline=u'\n') :
- """
- Render full output lines with given newlines
-
- >>> list(Tag('xx', 'yy').render_lines())
- [u'\\n', u'\\tyy\\n', u'\\n']
- """
-
- for line in self.render_raw_lines(indent) :
- yield line + newline
-
- def render_unicode (self, **render_opts) :
- """
- Render full tag as a single unicode string
-
- >>> Tag('xx', 'yy').render_unicode()
- u'\\n\\tyy\\n\\n'
- """
-
- return "".join(self.render_lines(**render_opts))
-
- def render_str (self, charset='ascii', **render_opts) :
- """
- Render full tag as an encoded string
-
- >>> Tag('xx', 'yy').render_str()
- '\\n\\tyy\\n\\n'
- """
-
- return self.render_unicode(**render_opts).encode(charset)
-
- def render_out (self, stream, charset, **render_opts) :
- """
- Render output into the given stream, encoding using the given charset
-
- >>> from StringIO import StringIO; buf = StringIO(); Tag('xx', 'yy').render_out(buf, 'ascii'); buf.getvalue()
- '\\n\\tyy\\n\\n'
- """
-
- for line in self.render_lines(**render_opts) :
- stream.write(line.encode(charset))
-
- # default output
- __str__ = render_str
- __unicode__ = render_unicode
-
- # default .render method
- render = render_unicode
def __repr__ (self) :
return 'Tag(%s)' % ', '.join(
@@ -254,6 +259,71 @@
def render_raw_lines (self, indent=u'\t') :
return self.lines
+class XHTMLDocument (IRenderable) :
+ """
+
+
+
+
+
+ ...
+
+
+ ...
+
+
+ """
+
+ def __init__ (self,
+ head, body,
+ xml_version='1.0', xml_encoding='utf-8',
+ doctype='html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"',
+ html_xmlns='http://www.w3.org/1999/xhtml', html_lang='en'
+ ) :
+ # store
+ self.xml_version = xml_version
+ self.xml_encoding = xml_encoding
+ self.doctype = doctype
+
+ # build the document
+ self.document = Tag('html', **{'xmlns': html_xmlns, 'xml:lang': html_lang})(
+ Tag('head', head),
+ Tag('body', body),
+ )
+
+ def render_raw_lines (self, **render_opts) :
+ """
+ Render the two header lines, and then the document
+ """
+
+ yield '' % (self.xml_version, self.xml_encoding)
+ yield '' % (self.doctype)
+
+ for line in self.document.render_raw_lines(**render_opts) :
+ yield line
+
+ def _check_encoding (self, encoding) :
+ if encoding and encoding != self.xml_encoding :
+ raise ValueError("encoding mismatch: %r should be %r" % (encoding, self.xml_encoding)
+
+ def render_str (self, encoding=None, **render_opts) :
+ """
+ Wrap render_str to verify that the right encoding is used
+ """
+
+ self._check_encoding(encoding)
+
+ return super(XHTMLDocument, self).render_str(self.xml_encoding, **render_opts)
+
+ def render_out (self, stream, encoding=None, **render_opts) :
+ """
+ Wrap render_out to verify that the right encoding is used
+ """
+
+ self._check_encoding(encoding)
+
+ return super(XHTMLDocument, self).render_out(stream, self.xml_encoding, **render_opts)
+
class TagFactory (object) :
"""
Build Tags with names give as attribute names