Index: django/contrib/markup/templatetags/markup.py
===================================================================
--- django/contrib/markup/templatetags/markup.py	(revision 6442)
+++ django/contrib/markup/templatetags/markup.py	(working copy)
@@ -30,15 +30,41 @@
     else:
         return force_unicode(textile.textile(smart_str(value), encoding='utf-8', output='utf-8'))
 
-def markdown(value):
+def markdown(value, arg=''):
+    """
+    Runs Markdown over a given value, optionally using various
+    extensions python-markdown supports.
+    
+     Syntax::
+    
+        {{ value|markdown:"extension1_name,extension2_name..." }}
+    
+    To enable safe mode, which strips raw HTML and only returns HTML
+    generated by actual Markdown syntax, pass "safe" as the first
+    extension in the list.
+     
+    If the version of Markdown in use does not support extensions,
+    they will be silently ignored.
+    
+    """
     try:
         import markdown
     except ImportError:
         if settings.DEBUG:
-            raise template.TemplateSyntaxError, "Error in {% markdown %} filter: The Python markdown library isn't installed."
-        return force_unicode(value)
+            raise template.TemplateSyntaxError('Error in markdown filter: Markdown could not be imported.')
+        else:
+            # Try to salvage this; whatever we do, we shouldn't
+            # return potentially unsafe HTML.
+            from django.utils.html import escape, linebreaks
+            return linebreaks(escape(value))
     else:
-        return force_unicode(markdown.markdown(smart_str(value)))
+        extensions = [e for e in arg.split(",") if e]
+        if len(extensions) > 0 and extensions[0] == "safe":
+            extensions = extensions[1:]
+            safe_mode = True
+        else:
+            safe_mode = False
+        return force_unicode(markdown.markdown(value, extensions, safe_mode=safe_mode))
 
 def restructuredtext(value):
     try:
