CookBook - Template filter BBCode

django version : 0.96

Many boards allow BBCode to format posts without allowing HTML. This is a save way to allow things like urls, emails, lists, etc.

This filter should be used in conjunction with the escape filter so you first escape the variable to strip out html and then filter it through bbcode.

Please note that this is a quickly written piece of code, and it isn't even fully tested. It is up to you to test it and improve it :) Feel free to edit it right here to make it even better.

bbcode.py:

import re
from django import template
register = template.Library()

@register.filter
def bbcode(value):

    bbdata = [
        (r'\[url\](.+?)\[/url\]', r'<a href="\1">\1</a>'),
        (r'\[url=(.+?)\](.+?)\[/url\]', r'<a href="\1">\2</a>'),
        (r'\[email\](.+?)\[/email\]', r'<a href="mailto:\1">\1</a>'),
        (r'\[email=(.+?)\](.+?)\[/email\]', r'<a href="mailto:\1">\2</a>'),
        (r'\[img\](.+?)\[/img\]', r'<img src="\1">'),
        (r'\[img=(.+?)\](.+?)\[/img\]', r'<img src="\1" alt="\2">'),
        (r'\[b\](.+?)\[/b\]', r'<b>\1</b>'),
        (r'\[i\](.+?)\[/i\]', r'<i>\1</i>'),
        (r'\[u\](.+?)\[/u\]', r'<u>\1</u>'),
        (r'\[quote\](.+?)\[/quote\]', r'<div style="margin-left: 1cm">\1</div>'),
        (r'\[center\](.+?)\[/center\]', r'<div align="center">\1</div>'),
        (r'\[code\](.+?)\[/code\]', r'<tt>\1</tt>'),
        (r'\[big\](.+?)\[/big\]', r'<big>\1</big>'),
        (r'\[small\](.+?)\[/small\]', r'<small>\1</small>'),
        ]

    for bbset in bbdata:
        p = re.compile(bbset[0], re.DOTALL)
        value = p.sub(bbset[1], value)

    #The following two code parts handle the more complex list statements
    temp = ''
    p = re.compile(r'\[list\](.+?)\[/list\]', re.DOTALL)
    m = p.search(value)
    if m:
        items = re.split(re.escape('[*]'), m.group(1))
        for i in items[1:]:
            temp = temp + '<li>' + i + '</li>'
        value = p.sub(r'<ul>'+temp+'</ul>', value)

    temp = ''
    p = re.compile(r'\[list=(.)\](.+?)\[/list\]', re.DOTALL)
    m = p.search(value)
    if m:
        items = re.split(re.escape('[*]'), m.group(2))
        for i in items[1:]:
            temp = temp + '<li>' + i + '</li>'
        value = p.sub(r'<ol type=\1>'+temp+'</ol>', value)

    return value

An alternative is an XHTML compliant and very well tested bbcode parser I wrote, now included in Ian Holsman's forum repository:

http://svn.zilbo.com/svn/django/common/forum


If the code is a block, how to parse it? -- Limodou

{% filter bbcode %}data to translate{% endfilter %} -- nesh

What I siad is:

[code]
def p(a):
    print a
[/code]

The "[code]" is a paragraph, but not a single string line. How to parse it? And if the bbcode has newline, there seems no process for it. ---- Limodou


I noticed that there is no handling of quote where a user name is given. phpBB, for example, has [quote="A User's Name"]text[/quote]. ---- Powerlord


While multiple urls, images, b's, etc are no problem, this is not the case with lists. I edited the middle part to the following to achieve this:

    temp = ''
    p = re.compile(r'\[list\](.+?)\[/list\]', re.DOTALL)
    m = p.search(value)
    while m:
        items = re.split(re.escape('[*]'), m.group(1))
        for i in items[1:]:
            temp = temp + '<li>' + i + '</li>'
        value = p.sub(r'<ul>'+temp+'</ul>', value, 1)
        m = p.search(value)
        temp = ''
    p = re.compile(r'\[list=(.)\](.+?)\[/list\]', re.DOTALL)
    m = p.search(value)
    while m:
        items = re.split(re.escape('[*]'), m.group(2))
        for i in items[1:]:
            temp = temp + '<li>' + i + '</li>'
        value = p.sub(r'<ol type=\1>'+temp+'</ol>', value, 1)
        m = p.search(value)
        temp = ''
    return mark_safe(value)

I don't know if this has side effects though... -- Hede

Last modified 15 years ago Last modified on Mar 15, 2010, 3:30:49 PM
Note: See TracWiki for help on using the wiki.
Back to Top