Source code for html5builder

"""Simple HTML5 document builder."""

__version__ = '0.1.0'
__author__ = 'skitschy'


[docs]class HTML5Builder: """Simple HTML5 generator class. The following code generates a blank japanese HTML5 document. >>> tag = HTML5Builder() >>> doc = tag.html([tag.head(''), tag.body('')], lang='ja') >>> str(tag.doctype + str(doc)) '<!DOCTYPE html><html lang="ja"><head></head><body></body></html>' """ doctype = '<!DOCTYPE html>' """HTML5 Doctype string.""" class __ElementBuilder(object): def __init__(self, name): self.name = name def __call__(self, children=[], **kwargs): if 'cls' in kwargs: kwargs['class'] = kwargs.pop('cls') return HTML5Element(self.name, children, kwargs)
[docs] def __getattr__(self, name): """Return a callable element builder. This special method is called through ``self.name(children, **kwargs)``. This pseudo-method creates a :class:`HTML5Element`. The pseudo-method name specifies the name of a generating element. The argument ``children`` and the keyword arguments are passed to the :class:`HTML5Element` initializer as ``children`` and ``attrs`` arguments, respectively. In the keyword arguments, ``cls`` can be used instead of ``class``. >>> tag = HTML5Builder() >>> tag.a('anchor text', href='target.html') HTML5Element('a', ['anchor text'], {'href': 'target.html'}) >>> tag.img(src='image.png') HTML5Element('img', [], {'src': 'image.png'}) >>> tag.div('', cls='divclass') HTML5Element('div', [''], {'class': 'divclass'}) """ return self.__ElementBuilder(name)
[docs]class HTML5Element: """Simple HTML5 element class. An instance is usually created through :class:`HTML5Builder`. Args: name (str): The element name. children (sequence): The sequence of element children. attrs (mapping): The mapping of element attributes. If ``children`` is a string or non-sequence, the argument is the child of the instance. If ``children`` is a sequence, the elements of the sequence are the children of the instance. Attributes: name (str): The element name. child (:obj:`list`): The list of element children. attrs (:obj:`dict`): The dictionary of element attributes. """ def __init__(self, name, children, attrs): self.name = str(name) if isinstance(children, str) or not hasattr(children, '__iter__'): self.child = [children] else: self.child = list(children) self.attrs = dict(attrs)
[docs] def __getitem__(self, key): """Syntax sugar for ``self.attr[key]``.""" if key in self.attrs: return self.attrs[key] else: raise KeyError(key)
[docs] def __setitem__(self, key, value): """Syntax sugar for ``self.attr[key]=``.""" self.attrs[key] = value
def __repr__(self): return 'HTML5Element({!r}, {!r}, {!r})'.format( self.name, self.child, self.attrs)
[docs] def __str__(self): """Output a string of the outer HTML. For each child, :func:`str` is recursively called. >>> str(HTML5Element('span', 'inner', {})) '<span>inner</span>' >>> str(HTML5Element('div', '', {'class': 'divclass'})) '<div class="divclass"></div>' >>> str(HTML5Element('a', ... [HTML5Element('img', [], {'src': 'image.png'}), 'anchor text'], ... {'href': 'target.html'})) '<a href="target.html"><img src="image.png">anchor text</a>' """ if self.attrs: attrstr = ' '.join( [''] + ['{}="{}"'.format(k, v) for k, v in self.attrs.items()]) else: attrstr = '' if self.child: inner = ''.join([str(child) for child in self.child]) return '<{0}{1}>{2}</{0}>'.format(self.name, attrstr, inner) else: return '<{0}{1}>'.format(self.name, attrstr)