0
+Utilities for text-to-HTML conversion.
0
+def textile(text, **kwargs):
0
+ Applies Textile conversion to a string, and returns the HTML.
0
+ This is simply a pass-through to the ``textile`` template filter
0
+ included in ``django.contrib.markup``, which works around issues
0
+ PyTextile has with Unicode strings. If you're not using Django but
0
+ want to use Textile with ``MarkupFormatter``, you'll need to
0
+ supply your own Textile filter.
0
+ from django.contrib.markup.templatetags.markup import textile
0
+def markdown(text, **kwargs):
0
+ Applies Markdown conversion to a string, and returns the HTML.
0
+ return markdown.markdown(text, **kwargs)
0
+def restructuredtext(text, **kwargs):
0
+ Applies reStructuredText conversion to a string, and returns the
0
+ from docutils import core
0
+ parts = core.publish_parts(source=text,
0
+ writer_name='html4css1',
0
+ return parts['fragment']
0
+DEFAULT_MARKUP_FILTERS = {
0
+ 'restructuredtext': restructuredtext
0
+class MarkupFormatter(object):
0
+ Generic markup formatter which can handle multiple text-to-HTML
0
+ Conversion is handled by filter functions registered with an
0
+ instance; a set of default filters is provided which cover
0
+ Markdown, reStructuredText and Textile (though using one of these
0
+ requires the appropriate module to be available on your system --
0
+ e.g., using the reST filter requires you to have ``docutils``
0
+ New filters can be added by registering them with an instance;
0
+ simply define a function which performs the conversion you want,
0
+ and use the ``register`` method to add it; ``register`` expects
0
+ 1. The name to associate with the filter.
0
+ 2. The actual filter function.
0
+ So, for example, you might define a new filter function called
0
+ ``my_filter``, and register it like so::
0
+ formatter = MarkupFormatter()
0
+ formatter.register('my_filter', my_filter)
0
+ Instances are callable, so applying the conversion to a string is
0
+ my_html = formatter(my_string, filter_name='my_filter')
0
+ The filter to use for conversion is determined in either of two
0
+ 1. If the keyword argument ``filter_name`` is supplied, it will be
0
+ used as the filter name.
0
+ 2. Absent an explicit argument, the filter name will be taken from
0
+ the ``MARKUP_FILTER`` setting in your Django settings file (see
0
+ Additionally, arbitrary keyword arguments can be supplied, and
0
+ they will be passed on to the filter function.
0
+ Reading default bahavior from a Django setting
0
+ ==============================================
0
+ The Django setting ``MARKUP_FILTER`` can be used to specify
0
+ default behavior; if used, its value should be a 2-tuple:
0
+ * The first element should be the name of a filter.
0
+ * The second element should be a dictionary to use as keyword
0
+ arguments for that filter.
0
+ So, for example, to have the default behavior apply Markdown with
0
+ safe mode enabled, you would add this to your Django settings
0
+ MARKUP_FILTER = ('markdown', { 'safe_mode': True })
0
+ The filter named in this setting does not have to be from the
0
+ default set; as long as you register a filter of that name before
0
+ trying to use the formatter, it will work.
0
+ To have the default behavior apply no conversion whatsoever, set
0
+ ``MARKUP_FILTER`` like so::
0
+ MARKUP_FILTER = (None, {})
0
+ When the ``filter_name`` keyword argument is supplied, the
0
+ ``MARKUP_FILTER`` setting is ignored entirely -- neither a filter
0
+ name nor any keyword arguments will be read from it. This means
0
+ that, by always supplying ``filter_name`` explicitly, it is
0
+ possible to use this formatter without configuring or even
0
+ Django and template autoescaping
0
+ ================================
0
+ Django's template system defaults to escaping the output of
0
+ template variables, which can interfere with functions intended to
0
+ return HTML. ``MarkupFormatter`` does not in any way tamper with
0
+ Django's autoescaping, so pasing the results of formatting
0
+ directly to a Django template will result in that text being
0
+ If you need to use ``MarkupFormatter`` for items which will be
0
+ passed to a Django template as variables, use the function
0
+ ``django.utils.safestring.mark_safe`` to tell Django's template
0
+ system not to escape that text.
0
+ For convenience, a Django template filter is included (in
0
+ ``templatetags/generic_markup.py``) which applies
0
+ ``MarkupFormatter`` to a string and marks the result as not
0
+ requiring autoescaping.
0
+ Using the default behavior, with the filter name and arguments
0
+ taken from the ``MARKUP_FILTER`` setting::
0
+ formatter = MarkupFormatter()
0
+ my_string = 'Lorem ipsum dolor sit amet.\n\nConsectetuer adipiscing elit.'
0
+ my_html = formatter(my_string)
0
+ Explicitly naming the filter to use::
0
+ my_html = formatter(my_string, filter_name='markdown')
0
+ Passing keyword arguments::
0
+ my_html = formatter(my_string, filter_name='markdown', safe_mode=True)
0
+ Perform no conversion (return the text as-is)::
0
+ my_html = formatter(my_string, filter_name=None)
0
+ for filter_name, filter_func in DEFAULT_MARKUP_FILTERS.items():
0
+ self.register(filter_name, filter_func)
0
+ def register(self, filter_name, filter_func):
0
+ Registers a new filter for use.
0
+ self._filters[filter_name] = filter_func
0
+ def __call__(self, text, **kwargs):
0
+ Applies text-to-HTML conversion to a string, and returns the
0
+ if 'filter_name' in kwargs:
0
+ filter_name = kwargs['filter_name']
0
+ del kwargs['filter_name']
0
+ from django.conf import settings
0
+ filter_name, filter_kwargs = settings.MARKUP_FILTER
0
+ if filter_name is None:
0
+ if filter_name not in self._filters:
0
+ raise ValueError("'%s' is not a registered markup filter. Registered filters are: %s." % (filter_name,
0
+ ', '.join(self._filters.iterkeys())))
0
+ filter_func = self._filters[filter_name]
0
+ filter_kwargs.update(**kwargs)
0
+ return filter_func(text, **filter_kwargs)
0
+# Unless you need to have multiple instances of MarkupFormatter lying
0
+# around, or want to subclass it, the easiest way to use it is to
0
+# import this instance.
0
+formatter = MarkupFormatter()