Syntax Highlighting Template Tag for Django

August 30, 2008

Author: jart — Originally Posted 698 Days Ago Article Tags « django python web »

Have you ever wanted to have pain-free syntax highlighting in your Django templates? Using the power of Pygments and Django Custom Template Tags, you can! For example you can type:

{% load formatting %}
{% highlight 'python' %}
if 2 + 2 == 5:
    print "my compy is sad"
{% endhighlight %}

... and it will become:

if 2 + 2 == 5:
    print "my compy is sad"

The highlight tag supports any language that Pygments supports. Also the tag takes an option second argument where you can specify a title for the code block. This will be generated as a <div> with the class "predesc" before the <pre> block so you can create that cool text in the upper right hand corner.

The Code

File: myapp/templatetags/formatting.py
from pygments import highlight as pyghighlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import HtmlFormatter
from django import template
from django.template import Template, Context, Node, Variable
from django.template.defaultfilters import stringfilter

register = template.Library()

class CodeNode(Node):
    def __init__(self, language, nodelist, name=''):
        self.language = Variable(language)
        self.nodelist = nodelist
        if name:
            self.name = Variable(name)
        else:
            self.name = None

    def render(self, context):
        code = self.nodelist.render(context).strip()
        lexer = get_lexer_by_name(self.language.resolve(context))
        formatter = HtmlFormatter(linenos=False)
        html = ""
        if self.name:
            name = self.name.resolve(context)
            html = '<div class="predesc"><span>%s</span></div>' % (name)
        return html + pyghighlight(code, lexer, formatter)

@register.tag
def highlight(parser, token):
    nodelist = parser.parse(('endhighlight',))
    parser.delete_first_token()
    bits = token.split_contents()[1:]
    if len(bits) < 1:
        raise TemplateSyntaxError("'highlight' statement requires an argument")
    return CodeNode(bits[0], nodelist, *bits[1:])

Be sure to save the above code to an active applications "templatetags" subfolder. Also don't forget to create the little __init__.py file in that subdirectory. When you use the code {% load formatting %}, Django automatically scans the templatetags/ directories of all INSTALLED_APPS.

CSS
@import url("http://lobstertech.com/media/css/highlight.css");

.highlight { background: #f8f8f8; }
.highlight { font-size: 11px; margin: 1em; border: 1px solid #ccc; border-left: 3px solid #F90; padding: 0; }
.highlight pre { padding: 1em; overflow: auto; line-height: 120%; margin: 0; }

.predesc { margin: 1.5em 1.5em -2.5em 1em; text-align: right;
           font: bold 12px Tahoma, Arial, sans-serif;
           letter-spacing: 1px; color: #333; }

Comments

No comments found.

Post Comment