# -*- coding: utf-8 -*-
# This file is subject to the terms and conditions defined in
# file 'LICENSE', which is part of this source code package.
#       Copyright (c) 2011 R Pratap Chakravarthy
"""Module provides a plugin to handle standard html5 tags."""
import pluggdapps.utils     as h
from  tayra.tags    import Tags
[docs]class HTML5( Tags ):
    """Basic plugin to handle most of the HTML5 tags. Other than the common
    set of tokens and specifiers supported by the base 
    :class:`tayra.tags.Tags` this plugin defines other tokens that are
    specific to each tag. Individual tags are handle by their corresponding
    method prefixed with 'tag_'. Refer to them for more details about the tags.
    """
    def handle( self, mach, tagname, tokens, styles, attributes, content ):
        fn = getattr(self, 'tag_'+tagname, None)
        if fn :
            attrs, remtoks = self.parse_specs( tokens, styles, attributes )
            html = fn( mach, tagname, remtoks, attrs, content )
        else :
            html = None
        return html
[docs]    def tag_a( self, mach, tagname, tokens, attributes, content ):
        """<a> tag handler. Supported tokens,
        * a quoted string token is interpreted as ``href`` attribute and 
          translated to ``href="<string>"``
        """
        for tok in tokens :
            if (tok[0], tok[-1]) == ('"', '"') :
                attributes += ' href=%s' % tok
        return '<a %s>%s</a>' % (attributes, content)
 
[docs]    def tag_abbr( self, mach, tagname, tokens, attributes, content ):
        """<abbr> tag handler. Supported tokens,
        * a quoted string token is interpreted as ``title`` attribute and 
          translates to ``title="<string>"``
        """
        attributes += (' title=%s' % tokens[0]) if tokens else ''
        return '<abbr %s>%s</abbr>' % (attributes, content)
 
[docs]    def tag_area( self, mach, tagname, tokens, attributes, content ):
        """<area> tag handler. Supported tokens,
        * If token is of the form //<shape>:<coords>// it translates to
          ``shape="<shape>" coords="<coords>"`` attributes.
        * a quoted string token is interpreted as ``href`` attribute and 
          translated to ``href="<string>"``.
        """
        for tok in tokens :
            try    :
                shape, coords = tok.split(':', 1)
                attributes += ' shape="%s" coords="%s"' % (shape, coords)
            except :
                attributes += ' href=%s' % tok
        return '<area %s/>' % attributes     # Void element
 
    audio2attr = {
        'autoplay'  : ' autoplay="autoplay"',
        'controls'  : ' controls="controls"',
        'loop'      : ' loop="loop"',
        'auto'      : ' preload="auto"',
        'metadata'  : ' preload="metadata"',
        'none'      : ' preload="none"',
    }
[docs]    def tag_audio( self, mach, tagname, tokens, attributes, content ):
        """<audio> tag handler. Support tokens,
        * ``autoplay`` token translates to ``autoplay="autoplay"``
        * ``controls`` token translates to ``controls="controls"``
        * ``loop`` token translates to ``loop="loop"``
        * ``auto`` token translates to ``preload="auto"``
        * ``metadata`` token translates to ``preload="metadata"``
        * ``none`` token translates to ``preload="none"``
        * a quoted string is interpreted as ``src`` attribute and translates
          to ``src="<string>"``
        """
        for t in tokens :
            attr = self.audio2attr.get( t, None )
            attributes += attr if attr else (' src=%s' % t)
        return '<audio %s>%s</audio>' % (attributes, content)
 
[docs]    def tag_base( self, mach, tagname, tokens, attributes, content ):
        """<base> tag handler. Supported tokens,
        * If a token is present it is interpreted as ``target`` attribute 
          and translates to ``target="<token>"``
        """
        attributes += (' target="%s"' % tokens[0]) if tokens else ''
        return '<base %s/>' % attributes     # Void elements
 
[docs]    def tag_blockquote( self, mach, tagname, tokens, attributes, content ):
        """<blockquote> tag handler. Supported tokens,
        * a quoted string is interpreted as ``cite`` attribute and 
          translates to ``cite="<string>"``
        """
        attributes += (' cite=%s' % tokens[0]) if tokens else ''
        return '<blockquote %s>%s</blockquote>' % (attributes, content)
 
[docs]    def tag_br( self, mach, tagname, tokens, attributes, content ):
        """<br> tag handler."""
        return '<br/>'  # Void element
 
    button2attr = {
        'button'            : ' type="button"',
        'reset'             : ' type="reset"',
        'submit'            : ' type="submit"',
        'autofocus'         : ' autofocus="autofocus"',
        'application/x-www-form-urlencoded': \
                            
' formenctype="application/x-www-form-urlencoded"',
        'multipart/form-data' : ' formenctype="multipart/form-data"',
        'text/plain'        : ' formenctype="text/plain"',
        'get'               : ' formmethod="get"',
        'post'              : ' formmethod="post"',
        'formnovalidate'    : ' formnovalidate="formnovalidate"',
        '_blank'            : ' target="_blank"',
        '_self'             : ' target="_self"',
        '_parent'           : ' target="_parent"',
        '_top'              : ' target="_top"',
    }
[docs]    def tag_canvas( self, mach, tagname, tokens, attributes, content ):
        """<canvas> tag handler. Supported tokens,
        * If a specifier token is of the form ``<width>,<height>`` it 
          translates to ``width="<width>" height="<height>"``.
        """
        try :
            attributes += (
                (' width="%s" height="%s"' % tokens[0].split(',', 1) )
                        if tokens else '' )
        except : pass
        return '<canvas %s>%s</canvas>' % (attributes, content)
 
[docs]    def tag_col( self, mach, tagname, tokens, attributes, content ):
        """<col> tag handler. Supported tokens,
        * If a token is present, it will be interpreted as ``span``
          attribute and translates to ``span="<span>"``
        """
        attributes += (' span="%s"' % tokens[0]) if tokens else ''
        return '<col %s/>' % attributes  # Void element
 
[docs]    def tag_colgroup( self, mach, tagname, tokens, attributes, content ):
        """<colgroup> tag handler. Supported tokens,
        * If a specifier token is present, it will be interpreted as ``span``
          attribute and translates to ``span="<span>"``
        """
        attributes += (' span="%s"' % tokens[0]) if tokens else ''
        return '<colgroup %s>%s</colgroup>' % (attributes, content)
 
    command2attr = {
        'checkbox' : ' type="checkbox"',
        'command' : ' type="command"',
        'radio' : ' type="radio"',
    }
[docs]    def tag_command( self, mach, tagname, tokens, attributes, content ):
        """<command> tag handler. Supported tokens,
        * ``checkbox`` token translates to ``type="checkbox"``
        * ``command`` token translates to ``type="command"``
        * ``radio`` token translates to ``type="radio"``
        * a quoted string is interpreted as ``icon`` attribute and translated
          to ``icon="<string>"``.
        """
        for t in tokens :
            attr = self.command2attr.get( t, None )
            attributes += attr or (' icon=%s' % t)
        return '<command %s/>' % attributes  # Void element
 
[docs]    def tag_del( self, mach, tagname, tokens, attributes, content ):
        """<del> tag handler. Supported tokens,
        * If a non quoted token is present, it will interpreted as ``datetime``
          attribute and translates to ``datetime="<token>"``
        * a quoted string is interpreted as ``cite`` attribute and translated
          to ``cite="<string>"``
        """
        for tok in tokens :
            if (tok[0], tok[-1]) == ('"', '"') :
                attributes += ' cite=%s' % tok
            else :
                attributes += ' datetime="%s"' % tok
        return '<del %s>%s</del>' % (attributes, content)
 
[docs]    def tag_detail( self, mach, tagname, tokens, attributes, content ):
        """<details> tag handler. Supported tokens,
        * ``open`` token translates to ``open="open"``
        """
        attributes += (' open="%s"' % tokens[0]) if tokens else ''
        return '<detail %s>%s</detail>' % (attributes, content)
 
[docs]    def tag_embed( self, mach, tagname, tokens, attributes, content ):
        """<embed> tag handler. Supported tokens,
        * If token of the form ``<width>,<height>`` it translates to 
          ``width="<width>" height="<height>"``.
        * a quoted string is interpreted as ``src`` attribute and translated
          to ``src="<string>"``.
        """
        for tok in tokens :
            if (tok[0], tok[-1]) == ('"', '"') :
                attributes += ' src=%s' % tok
            else :
                try :
                    attributes += ' width="%s" height="%s"' % tok.split(',', 1)
                except : pass
        return '<embed %s/>' % attributes   # Void element 
 
[docs]    def tag_fieldset( self, mach, tagname, tokens, attributes, content ):
        """<fieldset> tag handler. Supported tokens,
        * If a token is of the form ``f:<formname>``, it translates to
          ``form="<formname>"``.
        """
        try :
            attributes += (
                (' form="%s"' % tokens[0].split(':', 1)[1]) if tokens else '' )
        except : pass
        return '<fieldset %s>%s</fieldset>' % (attributes, content)
 
    form2attr = {
        'on'                : ' autocomplete="on"',
        'off'               : ' autocomplete="off"',
        'application/x-www-form-urlencoded' : \
                    
' enctype="application/x-www-form-urlencoded"',
        'multipart/form-data': ' enctype="multipart/form-data"',
        'text/plain'        : ' enctype="text/plain"',
        'get'               : ' method="get"',
        'post'              : ' method="post"',
        'novalidate'        : ' novalidate="novalidate"',
    }
[docs]    def tag_head( self, mach, tagname, tokens, attributes, content ):
        """<head> tag handler. Supported tokens,
        * a quoted string is interpreted as ``manifest`` attribute and
          translated to ``manifest="<string>"``.
        """
        attributes += (' manifest=%s' % tokens[0]) if tokens else ''
        return '<head %s>%s</head>' % (attributes, content)
 
[docs]    def tag_hr( self, mach, tagname, tokens, attributes, content ):
        """<hr> tag handler."""
        return '<hr/>'  # Void element
 
[docs]    def tag_html( self, mach, tagname, tokens, attributes, content ):
        """<html> tag handler. Supported tokens,
        * a quoted string is interpreted as ``manifest`` attribute and
          translated to ``manifest="<string>"``.
        """
        attributes += (' manifest=%s' % tokens[0]) if tokens else ''
        return '<html %s>%s</html>' % (attributes, content)
 
    iframe2attr = {
        'seamless' : ' seamless="seamless"',
    }
[docs]    def tag_iframe( self, mach, tagname, tokens, attributes, content ):
        """<frame> tag handler. Supported tokens,
        * ``seamless`` token translated to ``seamless="seamless"``.
        * If a token is of the form ``<width>,<height>`` where width and 
          height are integers, it translates to 
          ``width="<width>" height="<height>"``.
        * If a token starts with ``allow-`` it will be joined together as
          comma separated value to ``sandbox`` attribute.
        * a quoted string is interpreted as ``src`` attribute and
          translated to ``src="<string>"``
        """
        sandbox = []
        for t in tokens :
            if t.startswith( 'allow-' ) :
                sandbox.append(t)
            elif (t[0], t[1]) == ('"', '"') :
                attributes += ' src=%s' % t
            else :
                attr = self.iframe2attr.get( t, '' )
                try :
                    attributes += ( attr or 
                                    ' width="%s" height="%s"'%t.split(',', 1) )
                except : pass
        attributes += ' sandbox="%s"' % ' '.join(sandbox) if sandbox else ''
        return '<iframe %s>%s</iframe>' % (attributes, content)
 
    img2attr = {
        'ismap' : ' ismap="ismap"',
    }
[docs]    def tag_img( self, mach, tagname, tokens, attributes, content ):
        """<img> tag handler. Supported tokens,
        * ``ismap`` token translates to ``ismap="ismap"``
        * If a token is of the form ``<width>,<height>`` it is translated
          to ``width="<width>" height="<height>"``.
        * a quoted string is interpreted as ``src`` attribute and translated
          to ``src="<string>"``
        """
        for tok in tokens :
            if (tok[0], tok[-1]) == ('"', '"') :
                attributes += ' src=%s' % tok
            else :
                attr = self.img2attr.get( tok, None )
                try :
                    attributes += ( 
                        attr or
                        (' width="%s" height="%s"' % tok.split(',', 1)) )
                except : pass
        return '<img %s/>' % attributes  # Void element
 
[docs]    def tag_ins( self, mach, tagname, tokens, attributes, content ):
        """<ins> tag handler. Supported tokens,
        * If a token is present it will interpreted as ``datetime`` 
          attribute and translated to ``datetime="<token>"``.
        * a quoted string is interpreted as ``cite`` attribute and translated
          to ``cite="<string>"``.
        """
        for tok in tokens :
            if (tok[0], tok[-1]) == ('"', '"') :
                attributes += ' cite=%s' % tok
            else :
                attributes += ' datetime="%s"' % tok
        return '<ins %s>%s</ins>' % (attributes, content)
 
[docs]    def tag_keygen(self, mach, tagname, tokens, attributes, content):
        """<keygen> handler"""
        return '<keygen %s/>' % attributes  # Void element
 
[docs]    def tag_label( self, mach, tagname, tokens, attributes, content ):
        """<label> tag handler. Supported tokens,
        * If a token looks like ``f:<formname>``, it will be translated to
          ``form="<formname>"``
        * Otherwise the token will be translated to ``for="<token>"``.
        """
        for tok in tokens :
            if tok.startswith( 'f:' ) :
                attributes += ' form="%s' % tok
            else :
                attributes += ' for="%s"' % tok
        return '<label %s>%s</label>' % (attributes, content)
 
[docs]    def tag_li( self, mach, tagname, tokens, attributes, content ):
        """<li> tag handler. Supported tokens,
        * If a token is present it will be translated to ``value="<token>"``.
        """
        attributes += (' value="%s"' % tokens[0]) if tokens else ''
        return '<li %s>%s</li>' % (attributes, content)
 
[docs]    def tag_link( self, mach, tagname, tokens, attributes, content ):
        """<link> tag handler. Supported tokens,
        * If a token is present it will be translated to ``type="<token>"``.
        * a quoted string is interpreted as ``cite`` attribute and translated
          to ``href="<string>"``.
        """
        for tok in tokens :
            if (tok[0], tok[-1]) == ('"', '"') :
                attributes += ' href=%s' % tok
            else :
                attributes += ' type="%s"' % tok
        return '<link %s/>' % attributes     # Void element
 
[docs]    def tag_meter( self, mach, tagname, tokens, attributes, content ):
        """<meter> tag hanlder. Supported tokens,
        * If a token starts with ``f:<formname>`` it will be translated to
          ``form="<formname>"``.
        * If a token is of the form ``low < high`` it will be translated to
          ``low="<low>" high="<high>"``
        * If a token is of the form ``low < optimum < high`` it will be 
          translated to ``low="<low>" optimum="<optimum>" high="<high>"``.
        * Otherwise the token will be interpreted as ``value`` attribute and
          translated as ``value="<value>"``.
        """
        for tok in tokens :
            if tok.startswith('f:') :
                attributes += ' form="%s' % tok
                continue
            parts = tok.split('<')
            if len(parts) == 2 :
                attributes += ' low="%s" high="%s"' % tuple( parts )
            elif len(parts) == 3 :
                attributes += ' low="%s" optimum="%s" high="%s"' % tuple(parts)
            else :
                attributes += ' value="%s"' % tok
        return '<meter %s>%s</meter>' % (attributes, content)
 
[docs]    def tag_object( self, mach, tagname, tokens, attributes, content ):
        """<object> tag handler. Supported tokens,
        * If a token starts with ``form:`` it will be translated to 
          ``form="<formname>"``.
        * If a token is of the form ``<width>,<height>`` it will be
          translated to ``width="<width>" height="<height>"``.
        * a quoted string is interpreted as ``data`` attribute and
          translated as ``data="<string>"``.
        """
        for tok in tokens :
            if (tok[0], tok[-1]) == ('"', '"') :
                attributes += ' data=%s' % tok
            elif tok.startswith( 'form:' ) :
                attributes += ' form="%s"' % tok
            else :
                try : 
                    attributes += ' width="%s" height="%s"' % tok.split(',', 1)
                except : pass
        return '<object %s>%s</object>' % (attributes, content)
 
    ol2attr = {
        'reversed' : ' reversed="reversed"',
        '1' : ' type="1"',
        'A' : ' type="A"',
        'a' : ' type="a"',
        'l' : ' type="l"',
        'i' : ' type="i"',
    }
[docs]    def tag_ol( self, mach, tagname, tokens, attributes, content ):
        """<ol> tag handler. Supported tokens,
        * ``reversed`` token translates to ``reversed="reversed"``.
        * ``1`` token translates to ``type="1"``.
        * ``A`` token translates to ``type="A"``.
        * ''a'' token translates to ``type="a"``.
        * ''l'' token translates to ``type="l"``.
        * ''i'' token translates to ``type="i"``.
        * If a token is of the form ``<type>,<start>``, it will be 
          translated to ``type="<type>" start="<start>"``.
        """
        for tok in tokens :
            attr = self.ol2attr.get( tok, None )
            try :
                attributes += ( attr or 
                                ' type="%s" start="%s"' % tok.split(',', 1) )
            except : pass
        return '<ol %s>%s</ol>' % (attributes, content)
 
[docs]    def tag_optgroup( self, mach, tagname, tokens, attributes, content ):
        """<optgroup> tag handler. Supported tokens,
        * a quoted string is interpreted as ``label`` attribute and translated
          to ``label="<string>"``.
        """
        attributes += (' label=%s' % tokens[0]) if tokens else ''
        return '<optgroup %s>%s</optgroup>' % (attributes, content)
 
[docs]    def tag_option( self, mach, tagname, tokens, attributes, content ):
        """<option> tag handler. Supported tokens,
        * a quoted string is interpreted as ``value`` attribute and translated
          as ``value="<string>"``.
        """
        attributes += (' value=%s' % tokens[0]) if tokens else ''
        return '<option %s>%s</option>' % (attributes, content)
 
[docs]    def tag_output( self, mach, tagname, tokens, attributes, content ):
        """<output> tag handler. Supported tokens,
        * If a token is of the form ``<form>:<name>`` it will be translated
          to ``form="<form>" for="<name>"``.
        """
        try :
            attributes += (
                (' form="%s" for="%s"' % tokens[0].split(':', 1)) 
                if tokens else '' )
        except : pass
        return '<output %s>%s</output>' % (attributes, content)
 
[docs]    def tag_param( self, mach, tagname, tokens, attributes, content ):
        """<param> tag handler. Supported tokens,
        * a quoted string is interpreted as ``value`` attribute and translated
          as ``value="<string>"``.
        """
        attributes += (' value=%s' % tokens[0]) if tokens else ''
        return '<param %s/>' % attributes    # Void element
 
[docs]    def tag_progress( self, mach, tagname, tokens, attributes, content ):
        """<progress> tag handler. Supported tokens,
        * If token is of the form ``<max>,<value>`` it will be translated to
          ``max="<max>" value="<value>"``.
        """
        try :
            attributes += (
                (' max="%s" value="%s"' % tokens[0].split(',', 1)) \
                
if tokens else '' )
        except : pass
        return '<progress %s>%s</progress>' % (attributes, content)
 
[docs]    def tag_q( self, mach, tagname, tokens, attributes, content ):
        """<q> tag handler. Supported tokens,
        * a quoted string is interpreted as ``value`` attribute and 
          translated to ``cite="<string>"``.
        """
        attributes += (' cite=%s' % tokens[0]) if tokens else ''
        return '<q %s>%s</q>' % (attributes, content)
 
    script2attr = {
        'async' : ' async="async"',
        'defer' : ' defer="defer"',
    }
[docs]    def tag_script(self, mach, tagname, tokens, attributes, content):
        """<script> tag handler. Supported tokens,
        * ``async`` token translates to ``async="async"``.
        * ''defer'' token translates to ``defer="defer"``.
        * Otherwise it will be interpreted as ``type`` attribute and 
          translated to ``type="<token>"``.
        * a quoted string is interpreted as ``src`` attribute and 
          as ``src="<string>"``.
        """
        for tok in tokens :
            if (tok[0], tok[-1]) == ('"', '"') :
                attributes += ' src=%s' % tok
            else :
                attr = self.script2attr.get( tok, None )
                attributes += attr or ' type="%s"' % tok
        return '<script %s>%s</script>' % (attributes, content)
 
[docs]    def tag_source(self, mach, tagname, tokens, attributes, content):
        """<source> tag handler. Supported tokens,
        * If a token is present it will be interpreted as ``type`` 
          attribute and translated to ``type="<token>"``.
        * a quoted string is interpreted as ``src`` attribute and 
          as ``src="<string>"``.
        """
        for tok in tokens :
            if (tok[0], tok[1]) == ('"', '"') :
                attributes += ' src=%s' % tok
            else :
                attributes += ' type="%s"' % tok
        return '<source %s/>' % attributes # Void element
 
    style2attr = {
        'text/css' : ' type="text/css"',
        'scoped'   : ' scoped="scoped"',
    }
[docs]    def tag_style(self, mach, tagname, tokens, attributes, content):
        """<style> tag handler. Supported tokens,
        * ``text/css`` token translates to ``type="text/css"``.
        * ``scoped`` token translates to ``scoped="scoped"``.
        * a quoted string is interpreted as ``src`` attribute and 
          as ``src="<string>"``.
        """
        attributes += (' ' + 
                       ''.join([ self.style2attr.get(t, '') for t in tokens ]))
        return '<style %s>%s</style>' % (attributes, content)
 
[docs]    def tag_table(self, mach, tagname, tokens, attributes, content):
        """<table> tag handler. Supported tokens,
        * ``1`` token translates to ``border="1"``.
        """
        attributes += (' border="%s"' % tokens[0]) if tokens else ''
        return '<table %s>%s</table>' % (attributes, content)
 
[docs]    def tag_time( self, mach, tagname, tokens, attributes, content ):
        """<time> tag handler. Supported tokens,
        * If a token is present it will be interpreted as ``pubdate``
          attribute and translated as ``pubdate="<token>"``.
        * a quoted string is interpreted as ``datetime`` attribute and 
          translated as ``datetime="<string>"``.
        """
        for tok in tokens :
            if (tok[0], tok[-1]) == ('"', '"') :
                attributes += ' datetime=%s' % tok
            else :
                attributes += ' pubdate="%s"' % tok
        return '<abbr %s>%s</abbr>' % (attributes, content)
 
[docs]    def tag_track(self, mach, tagname, tokens, attributes, content):
        """<track> handler"""
        return '<track %s/>' % attributes  # Void element
 
[docs]    def tag_wbr(self, mach, tagname, tokens, attributes, content):
        """<wbr> handler"""
        return '<wbr %s/>' % attributes  # Void element
    #---- ISettings interface methods
 
    @classmethod
    def default_settings( cls ):
        return _default_settings
    @classmethod
    def normalize_settings( cls, sett ):
        return sett
 
_default_settings = h.ConfigDict()
_default_settings.__doc__ = (
    "Plugin to handle tayra template's standard html tags." )