degal/html.py
author Tero Marttila <terom@fixme.fi>
Fri, 05 Jun 2009 21:47:45 +0300
changeset 61 fad360dd01da
parent 53 14d73f544764
child 69 5b53fe294034
permissions -rw-r--r--
rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     1
"""
61
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
     2
    Generating XHTML output
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
     3
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
     4
    XXX: use a 'real' XML builder?
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     5
"""
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     6
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     7
from cgi import escape
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
     8
import itertools as _itertools
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     9
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    10
class IRenderable (object) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    11
    """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    12
        Something that's renderable as the contents of a HTML tag
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    13
    """
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    14
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    15
    def render_raw_lines (self, indent=u'\t') :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    16
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    17
            Render the indented lines for tag and contents, without newlines
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    18
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    19
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    20
        abstract
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    21
61
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    22
    def render_lines (self, indent=u'\t', newline=u'\n') :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    23
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    24
            Render full output lines with given newlines
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    25
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    26
            >>> list(Tag('xx', 'yy').render_lines())
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    27
            [u'<xx>\\n', u'\\tyy\\n', u'</xx>\\n']
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    28
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    29
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    30
        for line in self.render_raw_lines(indent) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    31
            yield line + newline
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    32
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    33
    def render_unicode (self, **render_opts) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    34
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    35
            Render full tag as a single unicode string
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    36
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    37
            >>> Tag('xx', 'yy').render_unicode()
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    38
            u'<xx>\\n\\tyy\\n</xx>\\n'
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    39
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    40
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    41
        return "".join(self.render_lines(**render_opts))
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    42
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    43
    def render_str (self, encoding='ascii', **render_opts) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    44
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    45
            Render full tag as an encoded string
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    46
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    47
            >>> Tag('xx', 'yy').render_str()
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    48
            '<xx>\\n\\tyy\\n</xx>\\n'
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    49
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    50
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    51
        return self.render_unicode(**render_opts).encode(encoding)
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    52
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    53
    def render_out (self, stream, encoding, **render_opts) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    54
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    55
            Render output into the given stream, encoding using the given encoding
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    56
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    57
            >>> from StringIO import StringIO; buf = StringIO(); Tag('xx', 'yy').render_out(buf, 'ascii'); buf.getvalue()
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    58
            '<xx>\\n\\tyy\\n</xx>\\n'
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    59
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    60
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    61
        for line in self.render_lines(**render_opts) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    62
            stream.write(line.encode(encoding))
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    63
    
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    64
    # default output
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    65
    __str__ = render_str
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    66
    __unicode__ = render_unicode
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    67
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    68
    # default .render method
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    69
    render = render_unicode
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    70
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    71
class Tag (IRenderable) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    72
    """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    73
        A HTML tag, with attributes and contents, which can a mixture of data and other renderables(tags).
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    74
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    75
        Provides various kinds of rendering output
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    76
    """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    77
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    78
    @staticmethod
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    79
    def process_contents (contents) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    80
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    81
            Postprocess contents iterable to return new list.
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    82
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    83
            Items that are None will be omitted from the return value.
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    84
61
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    85
            XXX: flatten
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    86
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    87
            >>> Tag.process_contents([])
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    88
            []
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    89
            >>> Tag.process_contents([None])
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    90
            []
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    91
            >>> Tag.process_contents([u'foo'])
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    92
            [u'foo']
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    93
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    94
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    95
        return [c for c in contents if c is not None]
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    96
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    97
    @staticmethod
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    98
    def process_attrs (attrs) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    99
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   100
            Postprocess attributes.
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   101
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   102
            Key-value pairs where the value is None will be ommitted, and any trailing underscores in the key omitted.
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   103
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   104
            TODO: only remove one underscore
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   105
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   106
            >>> Tag.process_attrs(dict())
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   107
            {}
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   108
            >>> Tag.process_attrs(dict(foo='bar'))
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   109
            {'foo': 'bar'}
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   110
            >>> Tag.process_attrs(dict(class_='bar', frob=None))
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   111
            {'class': 'bar'}
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   112
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   113
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   114
        return dict((k.rstrip('_'), v) for k, v in attrs.iteritems() if v is not None)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   115
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   116
    def __init__ (self, name, *contents, **attrs) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   117
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   118
            Construct tag with given name/attributes or contents.
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   119
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   120
            The filtering rules desribed in process_contents/process_attrs apply.
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   121
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   122
            >>> Tag('foo')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   123
            Tag('foo')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   124
            >>> Tag('foo', 'quux')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   125
            Tag('foo', 'quux')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   126
            >>> Tag('foo', 'quux', bar=5)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   127
            Tag('foo', 'quux', bar=5)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   128
            >>> Tag('foo', class_='ten')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   129
            Tag('foo', class='ten')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   130
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   131
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   132
        self.name = name
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   133
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   134
        # store filtered/processed versions
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   135
        self.contents = self.process_contents(contents)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   136
        self.attrs = self.process_attrs(attrs)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   137
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   138
    def __call__ (self, *contents, **attrs) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   139
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   140
            Return a new Tag with this tag's attributes and contents, as well as the given attributes/contents.
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   141
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   142
            The filtering rules desribed in process_contents/process_attrs apply.
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   143
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   144
            >>> Tag('foo')('bar')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   145
            Tag('foo', 'bar')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   146
            >>> Tag('a', href='index.html')("Home")
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   147
            Tag('a', 'Home', href='index.html')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   148
            >>> Tag('bar', None)(5, foo=None, class_='bar')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   149
            Tag('bar', 5, class='bar')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   150
            >>> Tag('a')('b')('c')(asdf=5)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   151
            Tag('a', 'b', 'c', asdf=5)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   152
            >>> t1 = Tag('a'); t2 = t1('b'); t1
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   153
            Tag('a')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   154
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   155
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   156
        # merge attrs/contents
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   157
        # XXX: new_attrs is not an iterator...
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   158
        new_attrs = dict(_itertools.chain(self.attrs.iteritems(), attrs.iteritems()))
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   159
        new_contents = _itertools.chain(self.contents, contents)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   160
        
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   161
        # build new tag
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   162
        return Tag(self.name, *new_contents, **new_attrs)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   163
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   164
    @staticmethod
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   165
    def format_attr (name, value) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   166
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   167
            Format a single HTML tag attribute
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   168
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   169
            >>> Tag.format_attr('name', 'value')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   170
            u'name="value"'
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   171
            >>> Tag.format_attr('this', '<a"b>')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   172
            u'this="&lt;a&quot;b&gt;"'
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   173
            >>> Tag.format_attr('xx', 1337)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   174
            u'xx="1337"'
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   175
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   176
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   177
        return u'%s="%s"' % (name, escape(unicode(value), True))
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   178
 
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   179
    def render_attrs (self) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   180
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   181
            Return the HTML attributes string
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   182
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   183
            >>> Tag('x', foo=5, bar='<').render_attrs()
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   184
            u'foo="5" bar="&lt;"'
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   185
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   186
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   187
        return " ".join(self.format_attr(n, v) for n, v in self.attrs.iteritems())
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   188
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   189
    def render_contents (self, **render_opts) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   190
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   191
            Render the contents of the tag as a series of indented lines, with given render_lines options for subtags
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   192
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   193
            >>> list(Tag('x', 5).render_contents())
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   194
            [u'5']
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   195
            >>> list(Tag('x', 'line1', 'line2').render_contents())
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   196
            [u'line1', u'line2']
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   197
            >>> list(Tag('x', 'a', Tag('b', 'bb'), 'c').render_contents())
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   198
            [u'a', u'<b>', u'\\tbb', u'</b>', u'c']
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   199
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   200
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   201
        for content in self.contents :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   202
            if isinstance(content, IRenderable) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   203
                # sub-tags
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   204
                for line in content.render_raw_lines(**render_opts) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   205
                    yield line
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   206
            
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   207
            else :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   208
                # escape raw values
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   209
                yield escape(unicode(content))
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   210
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   211
    def render_raw_lines (self, indent=u'\t') :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   212
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   213
            Render the tag and indented content
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   214
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   215
            >>> list(Tag('xx', 'yy', zz='foo').render_raw_lines(indent=' '))
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   216
            [u'<xx zz="foo">', u' yy', u'</xx>']
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   217
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   218
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   219
        # render attr string, including preceding space
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   220
        attrs_stuff = (" " + self.render_attrs()) if self.attrs else ""
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   221
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   222
        if self.contents :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   223
            # tag with content
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   224
            yield u"<%s%s>" % (self.name, attrs_stuff)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   225
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   226
            for line in self.render_contents(indent=indent) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   227
                yield indent + line
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   228
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   229
            yield u"</%s>" % (self.name, )
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   230
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   231
        else :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   232
            # singleton tag
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   233
            yield u"<%s%s />" % (self.name, attrs_stuff)
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   234
    
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   235
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   236
    def __repr__ (self) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   237
        return 'Tag(%s)' % ', '.join(
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   238
            [
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   239
                repr(self.name)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   240
            ] + [
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   241
                repr(c) for c in self.contents
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   242
            ] + [
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   243
                '%s=%r' % (name, value) for name, value in self.attrs.iteritems()
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   244
            ]
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   245
        )
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   246
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   247
class Text (IRenderable) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   248
    """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   249
        Raw HTML text
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   250
    """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   251
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   252
    def __init__ (self, line) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   253
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   254
            Initialize to render as the given lines
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   255
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   256
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   257
        self.lines = [line]
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   258
    
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   259
    def render_raw_lines (self, indent=u'\t') :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   260
        return self.lines
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   261
61
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   262
class XHTMLDocument (IRenderable) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   263
    """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   264
        <?xml version="..." encoding="..." ?>
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   265
        <!DOCTYPE ...>
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   266
        
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   267
        <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   268
            <head>
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   269
                ...
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   270
            </head>
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   271
            <body>
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   272
                ...
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   273
            </body>
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   274
        </html>
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   275
    """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   276
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   277
    def __init__ (self, 
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   278
        head, body,
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   279
        xml_version='1.0', xml_encoding='utf-8', 
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   280
        doctype='html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"',
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   281
        html_xmlns='http://www.w3.org/1999/xhtml', html_lang='en'
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   282
    ) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   283
        # store
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   284
        self.xml_version = xml_version
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   285
        self.xml_encoding = xml_encoding
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   286
        self.doctype = doctype
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   287
        
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   288
        # build the document
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   289
        self.document = Tag('html', **{'xmlns': html_xmlns, 'xml:lang': html_lang})(
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   290
            Tag('head', head),
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   291
            Tag('body', body),
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   292
        )
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   293
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   294
    def render_raw_lines (self, **render_opts) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   295
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   296
            Render the two header lines, and then the document
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   297
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   298
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   299
        yield '<?xml version="%s" encoding="%s" ?>' % (self.xml_version, self.xml_encoding)
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   300
        yield '<!DOCTYPE %s>' % (self.doctype)
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   301
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   302
        for line in self.document.render_raw_lines(**render_opts) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   303
            yield line
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   304
    
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   305
    def _check_encoding (self, encoding) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   306
        if encoding and encoding != self.xml_encoding :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   307
            raise ValueError("encoding mismatch: %r should be %r" % (encoding, self.xml_encoding)
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   308
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   309
    def render_str (self, encoding=None, **render_opts) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   310
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   311
            Wrap render_str to verify that the right encoding is used
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   312
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   313
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   314
        self._check_encoding(encoding)
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   315
        
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   316
        return super(XHTMLDocument, self).render_str(self.xml_encoding, **render_opts)
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   317
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   318
    def render_out (self, stream, encoding=None, **render_opts) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   319
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   320
            Wrap render_out to verify that the right encoding is used
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   321
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   322
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   323
        self._check_encoding(encoding)
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   324
        
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   325
        return super(XHTMLDocument, self).render_out(stream, self.xml_encoding, **render_opts)
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   326
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   327
class TagFactory (object) :
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   328
    """
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   329
        Build Tags with names give as attribute names
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   330
    """
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   331
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   332
    def __getattr__ (self, name) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   333
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   334
            Get a Tag object with the given name, but no contents
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   335
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   336
            >>> TagFactory().a(href='bar')('quux')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   337
            Tag('a', 'quux', href='bar')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   338
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   339
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   340
        return Tag(name)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   341
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   342
# pretty names
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   343
tag = Tag
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   344
tags = TagFactory()
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   345
raw = Text
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   346
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   347
# testing
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   348
if __name__ == '__main__' :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   349
    import doctest
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   350
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   351
    doctest.testmod()
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   352