Latest Version: 0.9.6.2
/Users/bbangert/Programming/Python/WebHelpers/webhelpers/rails/tags.py
0001"""Tag Helpers
0002
0003Use these methods to generate XHTML comliant tags programmatically.
0004"""
0005# Last synced with Rails copy at Revision 5857 on Feb 7th, 2007.
0006
0007from webhelpers.util import html_escape
0008import re
0009
0010def camelize(name):
0011    """
0012    Camelize a ``name``
0013    """
0014    def upcase(matchobj):
0015        return getattr(matchobj.group(0)[1:], 'upper')()
0016    name = re.sub(r'(_[a-zA-Z])', upcase, name)
0017    name = name[0].upper() + name[1:]
0018    return name
0019
0020def strip_unders(options):
0021    for x, y in options.iteritems():
0022        if x.endswith('_'):
0023            options[x[:-1]] = y
0024            del options[x]
0025
0026def tag(name, open=False, **options):
0027    """
0028    Returns an XHTML compliant tag of type ``name``.
0029    
0030    ``open``
0031        Set to True if the tag should remain open
0032    
0033    All additional keyword args become attribute/value's for the tag. To pass in Python
0034    reserved words, append _ to the name of the key. For attributes with no value (such as
0035    disabled and readonly), a value of True is permitted.
0036    
0037    Examples::
0038    
0039        >>> tag("br")
0040        '<br />'
0041        >>> tag("br", True)
0042        '<br>'
0043        >>> tag("input", type="text")
0044        '<input type="text" />'
0045        >>> tag("input", type='text', disabled=True)
0046        '<input disabled="disabled" type="text" />'
0047    """
0048    tag = '<%s%s%s' % (name, (options and tag_options(**options)) or '', (open and '>') or ' />')
0049    return tag
0050
0051def content_tag(name, content, **options):
0052    """
0053    Create a tag with content
0054    
0055    Takes the same keyword args as ``tag``
0056    
0057    Examples::
0058    
0059        >>> content_tag("p", "Hello world!")
0060        '<p>Hello world!</p>'
0061        >>> content_tag("div", content_tag("p", "Hello world!"), class_="strong")
0062        '<div class="strong"><p>Hello world!</p></div>'
0063    """
0064    if content is None:
0065        content = ''
0066    tag = '<%s%s>%s</%s>' % (name, (options and tag_options(**options)) or '', content, name)
0067    return tag
0068
0069def cdata_section(content):
0070    """
0071    Returns a CDATA section with the given ``content``.
0072    
0073    CDATA sections are used to escape blocks of text containing characters which would
0074    otherwise be recognized as markup. CDATA sections begin with the string
0075    ``<![CDATA[`` and end with (and may not contain) the string 
0076    ``]]>``. 
0077    """
0078    if content is None:
0079        content = ''
0080    return "<![CDATA[%s]]>" % content
0081
0082def escape_once(html):
0083    """Escapes a given string without affecting existing escaped entities.
0084
0085    >>> escape_once("1 < 2 &amp; 3")
0086    '1 &lt; 2 &amp; 3'
0087    """
0088    return fix_double_escape(html_escape(html))
0089
0090def fix_double_escape(escaped):
0091    """Fix double-escaped entities, such as &amp;amp;, &amp;#123;, etc"""
0092    return re.sub(r'&amp;([a-z]+|(#\d+));', r'&\1;', escaped)
0093
0094def tag_options(**options):
0095    strip_unders(options)
0096    cleaned_options = convert_booleans(dict([(x, y) for x, y in options.iteritems() if y is not None]))
0097    optionlist = ['%s="%s"' % (x, escape_once(y)) for x, y in cleaned_options.iteritems()]
0098    optionlist.sort()
0099    if optionlist:
0100        return ' ' + ' '.join(optionlist)
0101    else:
0102        return ''
0103
0104def convert_booleans(options):
0105    for attr in ['disabled', 'readonly', 'multiple']:
0106        boolean_attribute(options, attr)
0107    return options
0108
0109def boolean_attribute(options, attribute):
0110    if options.get(attribute):
0111        options[attribute] = attribute
0112    elif options.has_key(attribute):
0113        del options[attribute]
0114
0115__all__ = ['tag', 'content_tag', 'cdata_section', 'camelize', 'escape_once']

Top