view data/plugin/macro/ @ 534:7bcfe0b3823a

span macro: reformat docstring
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Tue, 22 Jun 2010 16:56:31 +0200
parents 1f9926e7f5b5
children 4599602f00e5
line wrap: on
line source
# -*- coding: iso-8859-1 -*-
    MoinMoin - span generating macro

    Supported span attrs:
        class (use css_class param)
    Partially supported attrs:
        if SUPPORT_STYLE_ATTR is True:
        style - only support safe properties that are on whitelist,  others
                could contain javascript and thus, be dangerous (XSS etc.)!
        if SUPPORT_STYLE_ATTR is False:
        style - macro argument is accepted, but will be silently ignored, it
                won't create style attribute output.

    Unsupported attrs:
        event attrs - unsafe, can contain javascript, XSS danger
        align - deprecated by the W3C (use css classes)

    <<span(red)>>some text contained in a span with css class red<<span>>
    <<span(css_class=red)>>same as above<<span>>
    <<span(id=foobar)>>some text in a span with id foobar<<span>>
    <<span(title="read this!")>>some text with a mouseover title<<span>>
    <<span(style="color: red; font: 20pt sans-serif;")>>20pt sans-serif red<<span>>

    @copyright: 2010 MoinMoin:ThomasWaldmann
    @license: GNU GPL, see COPYING for details.

SUPPORT_STYLE_ATTR = True # True should be safe, False is safer :)

Dependencies = []

from MoinMoin.wikiutil import required_arg

def make_style_safe(style):
    """ make html 'style' attribute value safe """
    # whitelist of safe style attributes, taken from:
    whitelist = ("azimuth,background,background-color,border,border-bottom,"

    def style_split(style):
        split style into a list of declarations,
        split the declarations into property, value tuples,
        remove all surrounding whitespace
        decls = [decl.split(u':', 1) for decl in style.split(u';')]
        # remove spaces from property and value
        result = []
        for decl in decls:
            if len(decl) == 2:
                result.append((decl[0].strip(), decl[1].strip()))
        return result

    def style_join(decls):
        join a list of prop, value tuples into a style declaration
        decls = [u'%s: %s' % (prop, val) for prop, val in decls]
        style = u'; '.join(decls)
        return style

    def decl_filter(decls):
        filter a list of prop, value tuples, only let whitelisted props through
        return [(prop, val) for prop, val in decls if prop in whitelist]

    decls = style_split(style)
    decls = decl_filter(decls)
    style = style_join(decls)
    return style

def macro_span(macro,
               # first the stuff we can directly give to span formatter:
               # deprecated by W3C:
    attrs = {}
    for key, value in [
        ('css_class', css_class), ('id', id),
        ('lang', lang), ('dir', dir),
        ('title', title),
        #('align', align),
        if value:
            attrs[key] = value

        if style:
            attrs['style'] = make_style_safe(style)

    span = macro.formatter.span
    if attrs:
        return span(True, **attrs)
        return span(False)