File: Synopsis/Formatters/HTML/Tags.py
  1#
  2# Copyright (C) 2000 Stephen Davies
  3# Copyright (C) 2000 Stefan Seefeld
  4# All rights reserved.
  5# Licensed to the public under the terms of the GNU LGPL (>= 2),
  6# see the file COPYING for details.
  7#
  8
  9"""HTML Tag generation utilities.
 10You will probably find it easiest to import * from this module."""
 11
 12using_frames = True #overwritten by Formatter...
 13
 14def rel(origin, target):
 15    "Find link to target relative to origin URL."
 16
 17    origin, target = origin.split('/'), target.split('/')
 18    if len(origin) < len(target): check = len(origin) - 1
 19    else: check = len(target) - 1
 20    for l in range(check):
 21        if target[0] == origin[0]:
 22            del target[0]
 23            del origin[0]
 24        else: break
 25    # If origin is a directory, and target is in that directory, origin[0] == target[0]
 26    if len(origin) == 1 and len(target) > 1 and origin[0] == target[0]:
 27        # Remove directory from target, but respect len(origin) - 1 below
 28        del target[0]
 29    if origin: target = ['..'] * (len(origin) - 1) + target
 30    return '/'.join(target)
 31
 32def attributes(keys):
 33    """Convert a name/value dict to a string of attributes.
 34    A common HTML attribute is 'class'. Since 'class' is a Python keyword,
 35    we accept 'class_' instead, and translate that to 'class'."""
 36
 37    if 'class_' in keys:
 38        keys['class'] = keys['class_']
 39        del keys['class_']
 40    # Remove target if not using frames
 41    if 'target' in keys and not using_frames:
 42        del keys['target']
 43    return ' '.join(['%s="%s"'%(k,v) for k,v in keys.items()])
 44
 45def element(_, body = None, **keys):
 46    "Wrap the body in a tag of given type and attributes"
 47
 48    attrs = attributes(keys)
 49    if body != None:
 50        if attrs:
 51            return '<%s %s>%s</%s>'%(_, attrs, body, _)
 52        else:
 53            return '<%s>%s</%s>'%(_, body, _)
 54    else:
 55        if attrs:
 56            return '<%s %s/>'%(_, attrs)
 57        else:
 58            return '<%s/>'%(_)
 59
 60def href(ref, label, **attrs): return element('a', label, href=ref, **attrs)
 61def img(**attrs): return element('img', **attrs)
 62def name(ref, label): return element('a', label, class_='name', id=ref)
 63def span(body, **attrs): return element('span', body, **attrs)
 64def div(body, **attrs): return element('div', body, **attrs)
 65def para(body, **attrs): return element('p', body, **attrs)
 66
 67def desc(text):
 68    "Create a description div for the given text"
 69
 70    return text and div("desc", text) or ''
 71
 72
 73def escape(text):
 74
 75    for p in [('&', '&amp;'), ('"', '&quot;'), ('<', '&lt;'), ('>', '&gt;'),
 76              ('(', '&#40;'), (')', '&#41;'), (',', '&#44;'), (',', '&#59;')]:
 77        text = text.replace(*p)
 78    return text
 79
 80def quote_as_id(text):
 81
 82    for p in [(' ', '.'),
 83              ('<', '_L'), ('>', '_R'), ('(', '_l'), (')', '_r'), ('::', '-'), ('~', '_t'),
 84              (':', '.'), ('&', '_A'), ('*', '_S'), (' ', '_s'), (',', '_c'), (';', '_C'),
 85              ('!', '_n'), ('[', '_b'), (']', '_B'), ('=', '_e'), ('+', '_p'), ('-', '_m')]:
 86        text = text.replace(*p)
 87    return text
 88
 89
 90def replace_spaces(text):
 91    """Replaces spaces in the given string with &#160; sequences. Does NOT
 92    replace spaces inside tags"""
 93
 94    # original "hello <there stuff> fool <thing me bob>yo<a>hi"
 95    tags = text.split('<')
 96    # now ['hello ', 'there stuff> fool ', 'thing me bob>yo', 'a>hi']
 97    tags = [x.split('>') for x in tags]
 98    # now [['hello '], ['there stuff', ' fool '], ['thing me bob', 'yo'], ['a', 'hi']]
 99    tags = reduce(lambda x,y: x+y, tags)
100    # now ['hello ', 'there stuff', ' fool ', 'thing me bob', 'yo', 'a', 'hi']
101    for i in range(0,len(tags),2):
102        tags[i] = tags[i].replace(' ', '&#160;')
103    for i in range(1,len(tags),2):
104        tags[i] = '<' + tags[i] + '>'
105    return ''.join(tags)
106