On Wiki Plugins


Update: Whitespace is now properly handled for RSS (I forgot to handle that bit, 2-line fix now included in the code below)

I’ve been loathing to do this for a while, but Yaki now has an include plugin of sorts, tied into the syntax highlighting stuff. So to include and display a Python file, all I have to do is type:

<pre syntax="python" src="sample.py"></pre>

The result (and relevant bit of code) is this:

class SyntaxHighlightWikiPlugin(yaki.Engine.WikiPlugin):
  def __init__(self, registry, webapp):
    registry.register('markup',self, 'pre','syntax')
    self.ac = webapp.getContext()
    self.i18n = yaki.Locale.i18n[self.ac.locale]
  
  def run(self, serial, tag, tagname, pagename, soup, request, response):
    try:
      source = tag['src']
      (schema,host,path,parameters,query,fragment) = urlparse.urlparse(source)
      if schema == 'cid':
        filename = self.ac.store.getAttachmentFilename(pagename,path)
        if os.path.exists(filename):
          buffer = codecs.open(filename,'r','utf-8').read().strip()
        else:
          tag.replaceWith(self.i18n['error_include_file'])
          return False
      else:
        tag.replaceWith(self.i18n['error_reference_format'])
        return False
    except KeyError:
      try:
        # Remove character entities (since we'll be running things through pygments)
        buffer = unicode(BeautifulStoneSoup(tag.contents[0],convertEntities=BeautifulStoneSoup.XHTML_ENTITIES)).strip()
      except:
        buffer = ''
    try:
      lexer = tag['syntax']
    except KeyError:
      lexer = 'text'
    if request is False: # we're formatting for RSS
      lexer = 'text'
    lexer = get_lexer_by_name(lexer)
    formatter = HtmlFormatter(linenos=False, cssclass='syntax')
    result = highlight(buffer, lexer, formatter)
    tag.replaceWith(result.strip())
    return False

This makes it a lot easier to manage code snippets – since they’re in separate files, I can just drop them into the same folder and then refer to them inside the actual post markup.

And of course I avoid the usual mess of having TextMate or vim trying to highlight three or four different languages at once.

This will (eventually) make it to the Subversion repository – the code cleanup I’ve been doing (as well as removal of a couple of very nasty hacks) is nearer its end, so with some luck there’ll be a new snapshot of Yaki soon.

There’s only, oh… around three dozen things to fix first. Or so.

Oh, and incidentally, 过年好 to my Chinese readers – I’ve been remiss in celebrating the coming of the Year of the Rat, but there’s been far too much going on…