|
1 """ |
|
2 Set of "markup" template filters for Django. These filters transform plain text |
|
3 markup syntaxes to HTML; currently there is support for: |
|
4 |
|
5 * Textile, which requires the PyTextile library available at |
|
6 http://dealmeida.net/projects/textile/ |
|
7 |
|
8 * Markdown, which requires the Python-markdown library from |
|
9 http://www.freewisdom.org/projects/python-markdown |
|
10 |
|
11 * ReStructuredText, which requires docutils from http://docutils.sf.net/ |
|
12 |
|
13 In each case, if the required library is not installed, the filter will |
|
14 silently fail and return the un-marked-up text. |
|
15 """ |
|
16 |
|
17 from django import template |
|
18 from django.conf import settings |
|
19 from django.utils.encoding import smart_str, force_unicode |
|
20 from django.utils.safestring import mark_safe |
|
21 |
|
22 register = template.Library() |
|
23 |
|
24 def textile(value): |
|
25 try: |
|
26 import textile |
|
27 except ImportError: |
|
28 if settings.DEBUG: |
|
29 raise template.TemplateSyntaxError, "Error in {% textile %} filter: The Python textile library isn't installed." |
|
30 return force_unicode(value) |
|
31 else: |
|
32 return mark_safe(force_unicode(textile.textile(smart_str(value), encoding='utf-8', output='utf-8'))) |
|
33 textile.is_safe = True |
|
34 |
|
35 def markdown(value, arg=''): |
|
36 """ |
|
37 Runs Markdown over a given value, optionally using various |
|
38 extensions python-markdown supports. |
|
39 |
|
40 Syntax:: |
|
41 |
|
42 {{ value|markdown:"extension1_name,extension2_name..." }} |
|
43 |
|
44 To enable safe mode, which strips raw HTML and only returns HTML |
|
45 generated by actual Markdown syntax, pass "safe" as the first |
|
46 extension in the list. |
|
47 |
|
48 If the version of Markdown in use does not support extensions, |
|
49 they will be silently ignored. |
|
50 |
|
51 """ |
|
52 try: |
|
53 import markdown |
|
54 except ImportError: |
|
55 if settings.DEBUG: |
|
56 raise template.TemplateSyntaxError, "Error in {% markdown %} filter: The Python markdown library isn't installed." |
|
57 return force_unicode(value) |
|
58 else: |
|
59 # markdown.version was first added in 1.6b. The only version of markdown |
|
60 # to fully support extensions before 1.6b was the shortlived 1.6a. |
|
61 if hasattr(markdown, 'version'): |
|
62 extensions = [e for e in arg.split(",") if e] |
|
63 if len(extensions) > 0 and extensions[0] == "safe": |
|
64 extensions = extensions[1:] |
|
65 safe_mode = True |
|
66 else: |
|
67 safe_mode = False |
|
68 |
|
69 # Unicode support only in markdown v1.7 or above. Version_info |
|
70 # exist only in markdown v1.6.2rc-2 or above. |
|
71 if getattr(markdown, "version_info", None) < (1,7): |
|
72 return mark_safe(force_unicode(markdown.markdown(smart_str(value), extensions, safe_mode=safe_mode))) |
|
73 else: |
|
74 return mark_safe(markdown.markdown(force_unicode(value), extensions, safe_mode=safe_mode)) |
|
75 else: |
|
76 return mark_safe(force_unicode(markdown.markdown(smart_str(value)))) |
|
77 markdown.is_safe = True |
|
78 |
|
79 def restructuredtext(value): |
|
80 try: |
|
81 from docutils.core import publish_parts |
|
82 except ImportError: |
|
83 if settings.DEBUG: |
|
84 raise template.TemplateSyntaxError, "Error in {% restructuredtext %} filter: The Python docutils library isn't installed." |
|
85 return force_unicode(value) |
|
86 else: |
|
87 docutils_settings = getattr(settings, "RESTRUCTUREDTEXT_FILTER_SETTINGS", {}) |
|
88 parts = publish_parts(source=smart_str(value), writer_name="html4css1", settings_overrides=docutils_settings) |
|
89 return mark_safe(force_unicode(parts["fragment"])) |
|
90 restructuredtext.is_safe = True |
|
91 |
|
92 register.filter(textile) |
|
93 register.filter(markdown) |
|
94 register.filter(restructuredtext) |