logo4 Evolution is progress—                          
progress is creativity.        

Creole Macro to Include Pages

As already outlined there exist some macros quite helpful to start off.

The Initial Code Fragment

def include(macro,environ,pagename=None):
    """Return the parsed content of the page identified by arg_string"""
    if pagename is None:
        return None
    page_record = Page.get_by_key_name('-'+pagename)
    if page_record is not None:
        # infinit recursion protection
        if ('include',macro.arg_string,environ['wiki.page'].id,environ['wiki.metadata_page'].id) in environ['wiki.recurse']:
            return bldr.tag.div("<<include %s>> stopped, possible infite \
recursion encountered" % macro.arg_string.strip())
        environ = environ.copy()
        environ['wiki.metadata_page'] = page_record
        environ['wiki.page'] = page_record
        return environ['wiki.parser'].generate(page_record.body.value,environ=environ)

First Problem Solved

Even if adapting the page to my system this piece of code yields an error, which is caused because the variables environ['wiki.metadata_page'] and environ['wiki.page'] are initially not defined. I found a work around which allows to set the variable to the current page value if empty.

    if environ['my.metadata_page'] == None:
        environ['my.metadata_page'] = page
    if environ['my.page'] == None:
        environ['my.page'] = page

A much better solution is excluding the recursive test from the first page.

    if not environ['creole.metadata_page'] == None and not environ['creole.page'] == None:
        if ('include',macro.arg_string,environ['creole.page'].id,environ['creole.metadata_page'].id) in environ['creole.recurse']:
            return bldr.tag.div("<<include %s>> stopped, possible infinite recursion encountered" % macro.arg_string.strip())
        environ = environ.copy()

Downscaling The Included Text

Next I wanted my included text to fit the structure of the parent page. That is all subheadings have to be downgraded, so I created another parameter that signals the level at which the included page resides.

<<include slug=WaddingtonExperiment headerlevel=2>>

My include routine receives the parameter accordingly.

def include(macro,environ,slug=None,headerlevel=2):

#some stuff

    stream = XML(bldr.tag.div(environ['my.parser'].generate(page.content,environ=environ), id = slug, class_='include'))
    stream = stream.filter(SubstHeaderTag(int(headerlevel)-1))   

    headertag = "h%s" % headerlevel
    return bldr.tag.__getattr__(headertag)(rev.title) + stream

Finally for this Genshi filter to work I had to create a new class.

    class SubstHeaderTag(object):
        def __init__(self,downlevel):
            self.downlevel = downlevel
            self.newtag = 'h1'
        def __call__(self,stream):
            p = re.compile('^h(\d+)$', re.IGNORECASE)
            for kind, data, pos in stream:
                if kind is START:
                    tag, attrs = data
                    m = p.match(tag)
                    if m:
                        self.newtag = "h%s" % str(int(m.group(1))+self.downlevel)
                        data = QName(self.newtag), data[1]
                elif kind is END:
                    m = p.match(tag)
                    if m:
                        data = QName(self.newtag)
                yield kind, data, pos            

Probably this piece of code looks a bit awkward to those more experienced in python programming but it works. Unfortunately I didn't find any documentation how to create a filter and how the data structure in that filter look like.

Tags: Software


(c) Mato Nagel, Weißwasser 2004-2013, Disclaimer