5 # see license for license details
7 from sys import stdout, modules
9 doc_type = '<!DOCTYPE HTML>\n'
10 default_title = "Html Page"
11 charset = '<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />\n'
13 html4_tags = {'a', 'abbr', 'acronym', 'address', 'area', 'b', 'base', 'bdo', 'big',
14 'blockquote', 'body', 'br', 'button', 'caption', 'cite', 'code', 'col',
15 'colgroup', 'dd', 'del', 'div', 'dfn', 'dl', 'dt', 'em', 'fieldset',
16 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head',
17 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd',
18 'label', 'legend', 'li', 'link', 'map', 'menu', 'menuitem', 'meta',
19 'noframes', 'noscript', 'object', 'ol', 'optgroup', 'option', 'p',
20 'param', 'pre', 'q', 'samp', 'script', 'select', 'small', 'span', 'strong',
21 'style', 'sub', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th',
22 'thead', 'title', 'tr', 'tt', 'ul', 'var'}
23 disused_tags = {'isindex', 'font', 'dir', 's', 'strike',
24 'u', 'center', 'basefont', 'applet', 'xmp'}
25 html5_tags = {'article', 'aside', 'audio', 'bdi', 'canvas', 'command', 'datalist', 'details',
26 'dialog', 'embed', 'figcaption', 'figure', 'footer', 'header',
27 'keygen', 'mark', 'meter', 'nav', 'output', 'progress', 'rp', 'rt', 'ruby',
28 'section', 'source', 'summary', 'details', 'time', 'track', 'video', 'wbr'}
31 tags = html4_tags | disused_tags | html5_tags
33 __all__ = [x.title() for x in tags] + ['PyHtml']
35 self_close = {'input', 'img', 'link', 'br'}
41 def __init__(self, *args, **kwargs):
42 self.attributes = kwargs
49 self._id = kwargs.get('id', name)
53 def __iadd__(self, obj):
54 if isinstance(obj, Tag) and obj.is_seq:
61 def add_obj(self, obj):
62 if not isinstance(obj, Tag):
64 _id = self.set_id(obj)
65 setattr(self, _id, obj)
68 def set_id(self, obj):
69 if isinstance(obj, Tag):
71 obj_lst = filter(lambda t: isinstance(
72 t, Tag) and t._id.startswith(_id), self)
75 obj_lst = filter(lambda t: not isinstance(t, Tag), self)
78 _id = '%s_%03i' % (_id, length)
79 if isinstance(obj, Tag):
83 def __add__(self, obj):
89 def __lshift__(self, obj):
90 if isinstance(obj, Tag):
93 print "unknown obj: %s " % obj
99 result += '<%s%s%s>' % (self.tag_name,
100 self._render_attr(), self._self_close() * ' /')
101 if not self._self_close():
104 if isinstance(c, Tag):
111 result += '</%s>' % self.tag_name
115 def _render_attr(self):
117 for key, value in self.attributes.iteritems():
118 if key != 'txt' and key != 'open':
121 result += ' %s="%s"' % (key, value)
124 def _self_close(self):
125 return self.tag_name in self_close
128 def tag_factory(tag):
132 F.__name__ = tag.title()
136 THIS = modules[__name__]
139 setattr(THIS, t.title(), tag_factory(t))
141 THIS = modules[__name__]
143 obj = type(t.title(), (Tag, ), {'tag_name': t})
144 setattr(THIS, t.title(), obj)
147 def _render_style(style):
153 for key, value in values.iteritems():
154 result += " %s: %s;\n" % (key, value)
157 result = '\n' + result
164 def __init__(self, title=default_title):
168 self.attributes = dict(xmlns='http://www.w3.org/1999/xhtml', lang='en')
169 self.head += Title(title)
171 def __iadd__(self, obj):
172 if isinstance(obj, Head) or isinstance(obj, Body):
174 elif isinstance(obj, Meta) or isinstance(obj, Link):
178 _id = self.set_id(obj)
179 setattr(self, _id, obj)
182 def add_js(self, *arg):
184 self.head += Script(type='text/javascript', src=f)
186 def add_css(self, *arg):
188 self.head += Link(rel='stylesheet', type='text/css', href=f)
190 def output(self, name=''):
192 fil = open(name, 'w')
195 fil.write(self.as_string())
201 return doc_type + self.render()
203 def add_style(self, style):
204 self.head += Style(_render_style(style))
206 def add_table(self, data):
207 table = self << Table()
209 cols = len(zip(*data))
211 for i in range(rows):
214 for j in range(1, cols):