Source code for dk.html.html


"""
    HTML helper file.

"""
import six
try:
    import htmlentitydefs as _h
except ImportError:
    import html.entities as _h
import string as _s
import types as _types
from .css import css
from ..text import u8, unicode_repr


_map = map

# pylint: disable=W0232,R0903,C0111

raw_string_encodings = ('utf-8', 'iso-8859-1')


[docs]class color: black = '"#000000"' silver = '"#COCOCO"' gray = '"#808080"' white = '"#FFFFFF"' maroon = '"#800000"' red = '"#FF0000"' purple = '"#800080"' fuchsia = '"#FF00FF"' green = '"#008000"' lime = '"#00FF00"' olive = '"#808000"' yellow = '"#FFFF00"' navy = '"#000080"' blue = '"#0000FF"' teal = '"#008080"' aqua = '"#00FFFF"'
INLINE_ELEMENTS = ''' a abbr acronym b basefont bdo big br cite code dfn em font i img input kbd label q s samp select small span strike strong sub sup textarea tt u var applet button del iframe ins map object script'''.split() BLOCKLEVEL_ELEMENTS = ''' address blockquote center dir div dl fieldset form h1 h2 h3 h4 h5 h6 hr isindex menu noframes noscript ol p pre table ul dd dt frameset li tbody td tfoot th thead tr applet button del iframe ins map object script main section article nav header footer '''.split()
[docs]def escape_char(unichar): if len(unichar) > 1 and (unichar[0] == '&' and unichar[-1] == ';'): return str(unichar) o = ord(unichar) t = _h.codepoint2name.get(o, o) if t == o: if 0 < t < 128: return str(unichar) else: return '' else: return '&' + t + ';'
[docs]def escaped_array(strval): """Convert unicode string to list of ascii characters or entitydefs like &oslash; etc. """ return [escape_char(ch) for ch in strval]
[docs]def escape(strval, enc=None): """Convert string s (potentially unicode) to a ascii string with entitydefs like &oslash; &aelig; etc. """ if strval is None: return '' if not isinstance(strval, unicode): if enc is not None: strval = strval.decode(enc) return ''.join(escape_char(c) for c in strval)
[docs]def unescape(txt): """Convert text containing entitydefs into Unicode. """ import HTMLParser h = HTMLParser.HTMLParser() # this one is undocumented... return h.unescape(txt)
[docs]def u8escape(strval): return escape(strval, 'u8')
[docs]def rawstr2unicode(strval): for enc in raw_string_encodings: try: return unicode(strval, enc) except UnicodeDecodeError: pass raise UnicodeError("Could not decode raw string.")
[docs]def normalize(v): """returns a stringified unicode version of v """ if not isinstance(v, basestring): # all 'other' objects: call their __str__ method v = unicode(str(v)) elif not isinstance(v, unicode): # str objects: try to find encoding v = rawstr2unicode(v) return v
[docs]def quote_xhtml(v): if '"' in v: v = v.replace('"', '&quot;') return '"%s"' % v
[docs]def quote_smart(strval): dq = '"' in strval sq = "'" in strval if dq and sq: return "'%s'" % s.replace('"', '&quot;') elif dq: return "'%s'" % strval else: return '"%s"' % strval
[docs]def plain_attribute(strval, legal=_s.ascii_letters + _s.digits + '-._:'): # html 4: 3.2.2 p4 some attributes may be unquoted for c in strval: if c not in legal: return False return True
[docs]def quote_if_needed(strval): if plain_attribute(strval): return strval else: return quote_smart(strval)
quote = quote_smart
[docs]def norm_attr_name(attr): if attr[0] == '_': return attr if attr[-1] == '_': attr = attr[:-1] return attr.replace('_', '-')
[docs]class xtag(object): """x(ml-style)tag: a tag without content or a closing tag. E.g. <br/> would be xtag('br') [2009-03-11] w3 validator complains that 4.01 loose should not use <foo /> but <foo>. """ def __init__(self, tag_name, **kw): self._attr = {} self._name = tag_name self._nlafter = '' for k, v in kw.items(): self._attr[norm_attr_name(k)] = v def __getattr__(self, name): try: return self._attr[norm_attr_name(name)] except KeyError: raise AttributeError def __setattr__(self, name, value): name = norm_attr_name(name) if name.startswith('_'): object.__setattr__(self, name, value) elif name in self._attr: self._attr[name] = value elif hasattr(self, name): object.__setattr__(self, name, value) else: self._attr[name] = value
[docs] def attributes(self): """return a string like key="val". """ res = [] for k, v in self._attr.items(): if isinstance(v, css): v = str(v) if isinstance(v, bool): if v: res.append(' %s' % k) else: v = normalize(v) if v: res.append(' %s=%s' % (k, quote(escape(v)))) return ''.join(res)
def _flatten(self): yield self
[docs] def flatten(self): yield self
def __str__(self): return '<' + self._name + self.attributes() + '>' def __unicode__(self): return unicode(str(self), 'u8') def __repr__(self): return str(self)
[docs]class stag(xtag): """s(ingle)tag """ def __str__(self): return '<' + self._name + self.attributes() + '>'
[docs]class tag(xtag): """Regular tag: outputs an open tag with attributes, followed by its contents, followed by a closing tag. Attributes can be set either as keyword arguments in the constructor or by assigning to attributes of the object. Content can be any combination of items, iterables, and generators:: >>> table(tr(td(i) for i in range(5)), tr(td(i**i) for i in range(5))) <table><tr><td>0</td><td>1</td><td>2</td><td>3</td><td>4</td></tr> <tr><td>1</td><td>1</td><td>4</td><td>27</td><td>256</td></tr> </table> <BLANKLINE> NB: Attributes that conflict with Python keywords have an underline appended, e.g.: mytag.class\_ = ... """ def __init__(self, tag_name, *content, **kw): xtag.__init__(self, tag_name, **kw) if len(content) == 1 and type(content[0]) == _types.GeneratorType: self._content = list(content[0]) else: self._content = content def xcontent(): # pylint: disable=E0211 # pylint: disable=W0612 def fget(self): return self._content def fset(self, v): self._content = v return locals() xcontent = property(**xcontent()) def _flatten(self, lst): for item in lst: if isinstance(item, (str, unicode, int, long, float)): yield item elif isinstance(item, xtag): for subitem in item.flatten(): yield subitem else: try: for subitem in self._flatten(iter(item)): yield subitem except TypeError: yield item
[docs] def flatten(self, lst=None): if lst is None: lst = self._content yield self.open_tag() for item in self._flatten(lst): yield item yield self.close_tag() return
[docs] def open_tag(self): return '<' + self._name + self.attributes() + '>'
[docs] def close_tag(self): return '</' + self._name + '>' + self._nlafter
def __str__(self): res = [] for item in self.flatten(): try: res.append(u8(item)) except TypeError: # generator found for some reason six.print_(type(item), dir(item)) raise return ''.join(res)
[docs]class opentag(tag):
[docs] def flatten(self, lst=None): yield self.open_tag()
[docs]class closetag(tag):
[docs] def flatten(self, lst=None): yield self.close_tag()
[docs]class text(tag): """text tag: outputs its contents without any tags around it. Useful for grouping at the top level. """ def __init__(self, *content): super(text, self).__init__('text', *content)
[docs] def flatten(self): return self._flatten(self._content)
[docs]class lines(text): """like text, except each item in content is separated with a <br> tag. """
[docs] def flatten(self): content = [] for c in self._content[:-1]: content.append(c) content.append('<br>') content.append(self._content[-1]) return self._flatten(content)
[docs]class dtag(tag): """d(issappearing)tag: if the content is empty, i.e. self.content == ('',) this tag doesn't output anything at all. Useful for legends, table captions, etc. """ def __str__(self): if self._content: if len(self._content) == 1 and self._content[0] == '': return '' return super(dtag, self).__str__() else: return ''
def _add(left, right): t = {} t.update(left) t.update(right) return t
[docs]def mktag(name, _parent=tag, _nlafter=False, **attrs): class _tmp(_parent): def __init__(self, *content, **kw): _parent.__init__(self, name, *content, **_add(attrs, kw)) self._nlafter = _nlafter and '\n' or '' _tmp.__name__ = name return _tmp
[docs]def mkxtag(name, **attrs): class _tmp(xtag): def __init__(self, **kw): xtag.__init__(self, name, **_add(attrs, kw)) _tmp.__name__ = name return _tmp
[docs]def mkdtag(name, **attrs): return mktag(name, _parent=dtag, **attrs)
[docs]def mkstag(name): return mktag(name, _parent=stag)
doctype401strict = mkstag( '!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"\n' ' "http://www.w3.org/TR/html4/strict.dtd"') doctype401transitional = mkstag( '!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"\n' ' "http://www.w3.org/TR/html4/loose.dtd"') doctype401frameset = mkstag( '!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"\n' ' "http://www.w3.org/TR/html4/frameset.dtd"') doctype = doctype401strict xtags = "br hr img input link col meta".split() #for t in xtags: # print '%s = mkxtag("%s")' % (t,t) # globals()[t] = mkxtag(t) # these are created by the forloop above. br = mkxtag("br") hr = mkxtag("hr") img = mkxtag("img") input = mkxtag("input") # ouch! link = mkxtag("link") col = mkxtag("col") meta = mkxtag("meta") tags = ''' a abbr acronym address applet area b base bsefont bdo big blockquote body button center cite code colgroup dd dfn div dl dt em fieldset font form frame frameset h1 h2 h3 h4 h5 h6 head html i iframe ins kbd label li map menu nobr noframes noscript ol optgroup option p param pre q s samp small span strike strong sub sup table tbody td textarea tfoot th thead title tr tt u ul var '''.split() _nlafter = ''' blockquote body center div dl dt fieldset form frame h1 h2 h3 h4 h5 h6 head html iframe legend li ol option p pre table tbody title tr ul col colgroup '''.split() #for t in tags: # print '%s = mktag("%s", tag, %r)' % (t,t, t in _nlafter) # globals()[t] = mktag(t, tag, t in _nlafter) # these are created by the forloop above. a = mktag("a", tag, False) abbr = mktag("abbr", tag, False) acronym = mktag("acronym", tag, False) address = mktag("address", tag, False) applet = mktag("applet", tag, False) area = mktag("area", tag, False) b = mktag("b", tag, False) base = mktag("base", tag, False) bsefont = mktag("bsefont", tag, False) bdo = mktag("bdo", tag, False) big = mktag("big", tag, False) blockquote = mktag("blockquote", tag, True) body = mktag("body", tag, True) button = mktag("button", tag, False) center = mktag("center", tag, True) cite = mktag("cite", tag, False) code = mktag("code", tag, False) colgroup = mktag("colgroup", tag, True) dd = mktag("dd", tag, False) dfn = mktag("dfn", tag, False) div = mktag("div", tag, True) dl = mktag("dl", tag, True) dt = mktag("dt", tag, True) em = mktag("em", tag, False) fieldset = mktag("fieldset", tag, True) font = mktag("font", tag, False) form = mktag("form", tag, True) frame = mktag("frame", tag, True) frameset = mktag("frameset", tag, False) h1 = mktag("h1", tag, True) h2 = mktag("h2", tag, True) h3 = mktag("h3", tag, True) h4 = mktag("h4", tag, True) h5 = mktag("h5", tag, True) h6 = mktag("h6", tag, True) head = mktag("head", tag, True) html = mktag("html", tag, True) # same name as module :-( i = mktag("i", tag, False) iframe = mktag("iframe", tag, True) ins = mktag("ins", tag, False) kbd = mktag("kbd", tag, False) label = mktag("label", tag, False) li = mktag("li", tag, True) map = mktag("map", tag, False) # ouch! menu = mktag("menu", tag, False) nobr = mktag("nobr", tag, False) noframes = mktag("noframes", tag, False) noscript = mktag("noscript", tag, False) ol = mktag("ol", tag, True) optgroup = mktag("optgroup", tag, False) option = mktag("option", tag, True) p = mktag("p", tag, True) param = mktag("param", tag, False) pre = mktag("pre", tag, True) q = mktag("q", tag, False) s = mktag("s", tag, False) samp = mktag("samp", tag, False) small = mktag("small", tag, False) span = mktag("span", tag, False) strike = mktag("strike", tag, False) strong = mktag("strong", tag, False) sub = mktag("sub", tag, False) sup = mktag("sup", tag, False) table = mktag("table", tag, True) tbody = mktag("tbody", tag, True) td = mktag("td", tag, False) textarea = mktag("textarea", tag, False) tfoot = mktag("tfoot", tag, False) th = mktag("th", tag, False) thead = mktag("thead", tag, False) title = mktag("title", tag, True) tr = mktag("tr", tag, True) tt = mktag("tt", tag, False) u = mktag("u", tag, False) ul = mktag("ul", tag, True) var = mktag("var", tag, False) dtags = "caption legend".split() #for t in dtags: # print '%s = mkdtag("%s")' % (t,t) # globals()[t] = mkdtag(t) # created from above for loop caption = mkdtag("caption") legend = mkdtag("legend") # special case (del is a keyword) del_ = mktag('del') dir_ = mktag('dir') object_ = mktag('object') start = mkxtag('link', rel='start') prev = mkxtag('link', rel='prev') next = mkxtag('link', rel='next') stylesheet = mkxtag('link', rel='stylesheet', type='text/css', media='screen') nynorsk = mkxtag('link', rel='alternate', hreflang='nn', lang='nn') bokmaal = mkxtag('link', rel='alternate', hreflang='nb', lang='nb') norsk = mkxtag('link', rel='alternate', hreflang='no', lang='no') english = mkxtag('link', rel='alternate', hreflang='en', lang='en') pdf = mkxtag('link', rel='alternate', type='application/pdf', media='print') script = mktag('script', type='text/javascript') style = mktag('style', type='text/css') text_input = mkxtag('input', type='text') hidden_input = mkxtag('input', type='hidden') password_input = mkxtag('input', type='password') checkbox_input = mkxtag('input', type='checkbox') radio_input = mkxtag('input', type='radio') submit_button = mkxtag('input', type='submit')
[docs]class select(tag): def __init__(self, options, selected=None, **kw): if 'id' not in kw: kw['id'] = 'id_' + kw['name'] super(select, self).__init__('select', **kw) self._options = None self.options = options if selected is not None: selected = u8(selected) content = [] for k, v in self.options: if u8(k) == selected: opt = option(v, value=k, selected='selected') else: opt = option(v, value=k) content.append(opt) self._content = tuple(content) def options(): # pylint: disable=E0211 # pylint: disable=W0612 def fset(self, options): if len(options) == 0: self._options = [] else: first = options[0] if len(first) == 2 and not isinstance(first, basestring): self._options = [(unicode_repr(k), unicode_repr(v)) for (k, v) in options] else: self._options = [(unicode_repr(o), unicode_repr(o)) for o in options] def fget(self): return self._options return locals() options = property(**options()) def selected(): # pylint: disable=E0211 # pylint: disable=W0612 def fset(self, v): if v not in self.values: raise ValueError("Only valid options can be selected.") self._selected = v def fget(self): return self._selected return locals() selected = property(**selected()) def values(): # pylint: disable=E0211 # pylint: disable=W0612 def fget(self): return [k for (k, v) in self.options] return locals() values = property(**values())
[docs]class tabledesc(object): def __init__(self, *cols): self.cols = cols
[docs]class sqlresult(tag): def __init__(self, res, desc=None, **kw): super(sqlresult, self).__init__('div', **kw) evenstyle = css(background='lightyellow') oddstyle = css(background='aqua') _tablestyle = css(font='9pt/16pt Verdana') result = [] if desc: heading = [d[0] for d in desc.cols] tdcell = [d[1] for d in desc.cols] result.append(map(th, heading)) else: pass for j, item in enumerate(res): if desc: cells = [tdcell[n](cell) for (n, cell) in enumerate(item)] else: cells = [td(cell) for cell in item] if j % 2 == 0: row = tr(cells, style=evenstyle) else: row = tr(cells, style=oddstyle) result.append(row) tbl = table(result, style=css(font='10pt Verdana', margin_left='10%')) self.content = (tbl,)
[docs]def page(xtitle, abody): """Shortcut to get a page up quickly.""" return html(head(title(xtitle)), body(h1(xtitle), abody))