Martin Geber
Martin is student at EUFH, Cologne, DE
working casually at DataCollect & EWE
who loves economies, web-technology
and all things J.K. Rowling.
Learn More.
These days I wrote my first Django project (you are currently browsing it). Of course I wanted to post entries into this blog with code snippets. To make the reading experiance better for my readers I decided to use a syntax highlighter. You find thousands of them around the WWW.
I decided to use syntaxhighlighter, which is purly JavaScript-based, so I didn't need to anything. (I was glad, because I was, and still am a Django and Python newbee.) The only thing I had to do was to use either of this to enable my syntax highlighting:
<!-- use a textarea, where I place the code --> <textarea name="code" class="c#" cols="60" rows="10"> // Python-code goes here </textarea> <!-- or use this (HTML-invalid --> <pre name="code" class="python"> // Python-code goes here </pre>
As the second possibility syntaxhighlighter provides is invalid HTML, and I want my pages to be XHTML1.1-valid, I wanted to use the first possibility.
To write even more comfortable I installed tiny_mce according to this tutorial.
But after writing my first entry I was completely sure that I have to change the way I highlight my syntax. The problem is that tiny_mce has problems with textareas, what forced me to edit the HTML directly, here is a little snipped of code I had to deal with:
<textarea class="html" name="code"> <!-- result, when {{ object.title }} was "My test entry" --> <html> <head> <title>Breadcrumps Location Bar</title> </head> <body> <div id="breadcrumbs"> <a href="/">Home</a> &raquo; <a href="/application/">Application</a> &raquo; My Test Entry </div> </body> </html> </textarea>
I guess it is obvious that it is close to impossible to write more complex code using the tiny_mce in combination with syntaxhighlighter.
The tiny_mce ever was a tool I loved. I still use it on my Emma Watson-website to enable people to write nice-styled news without knowing HTML or learning some markup. And somehow, I never wanted to learn markups as well.
Python gives you the ability with some helpers to create great documentations, which use reStructuredText. This markup doesn't differ too much from Markdown.
I guess this is why I decided to not just ban syntaxhighlighter from my blog but also tiny_mce. I want to learn markdown.
There is another point, why this isn't a bad idea: Markdown in combination with its extension CodeHilite enables codeblock highlighting using GNU Enscript, dp.SyntaxHighlighter or Pygments.
The definition of what I wanted to achieve i clear now, I guess.
I wanted to replace tiny_mce and syntaxhighlighter. And add instead markdown
with CodeHilite into my weblog.
First of all install Pygments and Markdown:
:~# easy_install Pygments :~# easy_install markdown
Now CodeHilite must be installed.
Just put the file, which can be downloaded from the homepage into your
PYTHONPATH (most commonly /usr/lib/python2.4/site-packages/). If you are
not sure how to do it on your server, here is a small explanation:
First copy the source code,
than go onto your server (SSH):
:~# cd /usr/lib/python2.4/site-packages/ :~# tough touch mdx_codehilite.py :~# vi mdx_codehilite.py # Insert copyed code here by pressing [Ins] and click the right mouse button # Press [Ctrl]+[C] now and type ":w" then ":q"
That's it. Now everything is ready to use markdown in your Django Project.
From now on it is easy. First create a Python module into one of your
templatetags-dir (I usually use project/utils/templatetags, make sure
utils is in your INSTALLED_APPS-attribute of your settings.py).
I created a filterlib.py into that directory. Into this file write the
following Python code:
from django import template from django.template.defaultfilters import stringfilter from django.conf import settings register = template.Library() @register.filter(name='markdown') @stringfilter def markdown(value, arg=''): """ Filter to create HTML out of Markdown, using custom extensions. The diffrence between this filter and the django-internal markdown filter (located in ``django/contrib/markup/templatetags/markup.py``) is that this filter enables extensions to be load. Usage:: {{ object.text|markdown }} {{ object.text|markdown:"save" }} {{ object.text|markdown:"codehilite" }} {{ object.text|markdown:"save,codehilite" }} This code is taken from http://www.freewisdom.org/projects/python-markdown/Django """ try: import markdown except ImportError: if settings.DEBUG: raise (template.TemplateSyntaxError, "Error in {% markdown %} filter: " + "The markdown library isn't installed.") else : from django.utils.html import escape, linebreaks return linebreaks(escape(value)) else: extensions=arg.split(",") if len(extensions) > 0 and extensions[0] == "safe" : extensions = extensions[1:] safe_mode = True else : safe_mode = False return markdown.markdown(value, extensions, safe_mode=safe_mode)
(As it is noticed in the Docstring, this code was taken from
http://www.freewisdom.org/projects/python-markdown/Django. They suggest to
overwrite the original definition of markdown, I strongly recommand you
not to do that for various reason, which doesn't belog here.)
This filter enables us now to load the CodeHilite into Markdown. See the magic:
<!-- we suggest object.text is filled with the following text --> Hello World =========== I'm the first Django-Markup test. * **Lorem ipsum** dolor sit amet, consectetuer adipiscing elit. * Nulla lacinia, mi eget congue aliquet, augue lorem vulputate mi, et ultricies enim ipsum vitae eros. * Nunc feugiat gravida *urna*. > Sed tincidunt nunc non velit. > Maecenas non felis. <!-- your django template --> {% load filterlib %} <html> <head>Test</head> <body> {{ object.text|markdown:"codehilite" }} </body> </html> <!-- this will be produced --> <html> <head>Test</head> <body> <h1>Hello World</h1> <p>I'm the first Django-Markup test.</p> <ul> <li><strong>Lorem ipsum</strong> dolor sit amet, consectetuer adipiscing elit.</li> <li>Nulla lacinia, mi eget congue aliquet, augue lorem vulputate mi, et ultricies enim ipsum vitae eros.</li> <li>Nunc feugiat gravida <em>urna</em>.</li> </ul> <blockquote> Sed tincidunt nunc non velit. Maecenas non felis. </blockquote> </body> </html>
Congratulations! You can use Markdown now.
Now you wonder how you can syntax highlight your source codes. Here the syntax of Markdown is limited, which is why we installed the CodeHilite. Markdown's syntax for code is:
Introducing text:
class Entry(models.Model):
pass
To add syntax highlighting you just have to do this:
Introducing text:
:::python
class Entry(models.Model):
pass
This code will now be syntax-highlighted, in case you already have loaded a
Syntax CSS into your HTML-page. As I love the look Jeff Croft
gave his syntax-blocks, I used his as a starting point. Check my CSS to see
which classes are available:
http://www.martin-geber.com/res/css/syntax.css
Please Notice: The class syntax is called codehilite by default, I
changed this in the module mdx_codehilite.py.
As shown above ::: will introduce the language, which is used below. In
case you want line numbers use #! instead.
Which languages are supported?
You can find a full list at Pygments, here is a
small selection (web-and-django-related):
Yes, isn't that cool? You are are able to markup django-template code now perfectly.
Markdown is quite a good tool to allow users to markup their texts without
allowing HTML. So just put it into your show_comments.html template the
following line:
{% load filterlib %} {{ comment.comment|striptags|markdown }}
In this example users aren't able to post source codes, which are highlighted.
In case you'd add :"codehilite", the problem is that users can use Python
and PHP highlighing, HTML would just be deleted. I'm not sure if there is a way
to allow HTML within the code-block and delete all other tags. In case you have
an answer to that, let me know.
Python Code is Poetry
© Copyright 1987-2008
Martin Geber
Django | XHTML 1.1 | CSS | Imprint
Paul commented, on April 13, 2008 at 5:17 a.m.:
Cool site! Very insightful! Now off to make my own Django-based site!