| | 360 | class DivSpanMacro(Component): |
| | 361 | """ |
| | 362 | Begin (`div` or `span`) or end (`/div` or `/span`) a division or a span, |
| | 363 | using the first argument as the class name. |
| | 364 | |
| | 365 | The remaining arguments are optional and allow configuring directly |
| | 366 | the style of the rendered element. Each argument is a `key:value` pair. |
| | 367 | """ |
| | 368 | implements(IWikiMacroProvider) |
| | 369 | |
| | 370 | def get_macros(self): |
| | 371 | for name in ('div', '/div', 'span', '/span'): |
| | 372 | yield name |
| | 373 | |
| | 374 | def get_macro_description(self, name): |
| | 375 | common = inspect.getdoc(DivSpanMacro).split('\n') |
| | 376 | end = name[0] == '/' |
| | 377 | return '%s a %s%s' % (end and 'End' or 'Begin', |
| | 378 | end and name[1:] or name, |
| | 379 | end and '.' or ',\n' + '\n'.join(common[1:])) |
| | 380 | |
| | 381 | def render_macro(self, req, name, content): |
| | 382 | # /div or /span: end the block |
| | 383 | if name[0] == '/': |
| | 384 | return '<%s>' % name |
| | 385 | args = content.split(',') |
| | 386 | # div or span: we expect the 1st argument to be a class name |
| | 387 | if len(args) == 0: |
| | 388 | raise Exception("Missing class name.") |
| | 389 | html_class = args[0] |
| | 390 | keyval_re = re.compile('^([-a-z0-9]+):(.*)') |
| | 391 | quoted_re = re.compile("^(?:\"|')(.*)(?:\"|')$") |
| | 392 | style = {} |
| | 393 | for arg in args[1:]: |
| | 394 | arg = arg.strip() |
| | 395 | match = keyval_re.search(arg) |
| | 396 | if match: |
| | 397 | key = match.group(1) |
| | 398 | val = match.group(2) |
| | 399 | m = quoted_re.search(val) # unquote "..." and '...' |
| | 400 | if m: |
| | 401 | val = m.group(1) |
| | 402 | style[key] = val |
| | 403 | styles = '; '.join(['%s:%s' % x for x in style.iteritems()]) |
| | 404 | style_attr = styles and ' style="%s"' % styles or '' |
| | 405 | return '<%s class="%s"%s>' % (name, html_class, style_attr) |
| | 406 | |
| | 407 | |