|
1 """ |
|
2 Generating HTML tags |
|
3 """ |
|
4 |
|
5 from cgi import escape |
|
6 |
|
7 def tag_attr (name, value) : |
|
8 return u'%s="%s"' % (name.rstrip('_'), escape(value, True)) |
|
9 |
|
10 def tag_subcontent (subcontent) : |
|
11 if not subcontent : |
|
12 # skip |
|
13 return |
|
14 |
|
15 elif not isinstance(subcontent, basestring) and hasattr(subcontent, '__iter__') : |
|
16 # render each sub-item recursively |
|
17 for sc in subcontent : |
|
18 for line in tag_subcontent(sc) : |
|
19 yield line |
|
20 |
|
21 else : |
|
22 yield subcontent |
|
23 |
|
24 def tag_content (content) : |
|
25 if not content: |
|
26 # no output |
|
27 return |
|
28 |
|
29 elif isinstance(content, basestring) : |
|
30 # escape raw vlues |
|
31 yield escape(unicode(content)) |
|
32 |
|
33 else : |
|
34 # treat it as subcontent |
|
35 for line in tag_subcontent(content) : |
|
36 yield line |
|
37 |
|
38 def tag (name, *content, **attrs) : |
|
39 attr_stuff = " " + " ".join(tag_attr(n, v) for n, v in attrs.iteritems()) if attrs else "" |
|
40 |
|
41 if content and all(content) : |
|
42 # tag with content |
|
43 yield u"<%s%s>" % (name, attr_stuff) |
|
44 |
|
45 for c in content : |
|
46 for line in tag_content(c) : |
|
47 yield u"\t" + line |
|
48 |
|
49 yield u"</%s>" % (name, ) |
|
50 |
|
51 else : |
|
52 # singleton tag |
|
53 yield u"<%s%s />" % (name, attr_stuff) |
|
54 |
|
55 def raw (data) : |
|
56 yield data |
|
57 |
|
58 class TagFactory (object) : |
|
59 def __getattr__ (self, name) : |
|
60 def build_tag (*content, **attrs) : |
|
61 return tag(name, *content, **attrs) |
|
62 |
|
63 return build_tag |
|
64 |
|
65 tags = TagFactory() |
|
66 |
|
67 def render_lines (tags, charset=None) : |
|
68 for line in tag_content(tags) : |
|
69 if charset : |
|
70 yield line.encode(charset) |
|
71 |
|
72 else : |
|
73 yield line |
|
74 |
|
75 def render (tags, charset=None) : |
|
76 data = u'\n'.join(render_lines(tags)) |
|
77 |
|
78 if charset : |
|
79 return data.encode(charset) |
|
80 |
|
81 else : |
|
82 return data |
|
83 |
|
84 def render_out (tags, out, charset='utf-8') : |
|
85 """ |
|
86 Write the rendered tags into the given output stream using the given encoding |
|
87 """ |
|
88 |
|
89 for line in render_lines(tags, charset) : |
|
90 out.write(line + '\n') |
|
91 |