Extending Creoleparser Using Macros 101

Say you have a function that takes some textual input and returns HTML. It's very easy to make a Creoleparser macro so your fuction can by used in a wiki (or whatever). In the example below, let's call our function itex. This function takes some itex math markup and returns HTML.

Were are going to make a macro of the same name, that could be used something like this:

<<itex>>$ e^{i\pi}+1=0 $<</itex>>

The key to getting your function's HTML into Genshi output is wrapping it in a Markup object:

import genshi.builder as bldr
from genshi.core import Markup

def html2stream(text):
    wrapped = Markup(text)         
    fragment = bldr.tag(wrapped)
    stream = fragment.generate() #this won't be needed post version 0.5.0
    return stream

def macro_func(macro_name, arg_string,body,isblock):
    if macro_name == 'itex':
        return html2stream(itex(body))

That's about it. You now just need to pass in this macro_func when instantiating your Parser. That part is described pretty well here.

Of course, there are a few extra features you may want to add:

def html2stream(text, isblock):
    wrapped = Markup(text)
    # we will place our output in a div or a span, depending on the context (see below)
    # and add a class attribute (note that and underscore is needed because class is a keyword)
    if isblock:      
        fragment = bldr.tag.div(wrapped,class_="itex")
    else:
        fragment = bldr.tag.span(wrapped,class_="itex")
    stream = fragment.generate() #this won't be needed post version 0.5.0
    return stream

def macro_func(macro_name, arg_string,body,isblock):
    if macro_name == 'itex' and arg_string == None: #let's require that no arg_string is present
        return html2stream(itex(body),isblock)

The isblock parameter will only be true here if the macro is called as follows (with some fresh sample input):

<<itex>>
\[ \sum_{n=1}^\infty \frac{1}{n} \text{ is divergent, but } \lim_{n \to \infty} \sum_{i=1}^n
\frac{1}{i} - \ln n \text{ exists.}\]
<</itex>>

Note that both the opening and closing macro tags must be on a line by themselves and have no leading spaces.

The macro_func here is pretty basic. If other macros were in use, it should probably at least parse the arg_string before passing it along. And it doesn't have to ignore unrecognized macro names (it could return an error message instead). Version 0.6.0 of Creoleparser will likely include it's own macro_func implementation that will be optional to use. (It may also be renamed to macro_handler_func or something similar).