Usage

Markup-Types

django-markupmirror comes with five default markup types (or converters). You Can create and register your own converters and unregister the default ones if you prefer.

Default Markup Types

The markup-types available by default are:

plaintext
class markupmirror.markup.plaintext.PlainTextMarkup

Markup transformer for plain-text content.

This uses Django’s urlize and linebreaks utitlies to convert URLs in the text to clickable links and linebreaks to <p> and <br /> elements respectively.

html
class markupmirror.markup.html.HtmlMarkup

Markup pseudo-transformer for HTML content.

This does not transform anything and thus is potentially harmful. Use with care.

markdown
class markupmirror.markup.markdown_.MarkdownMarkup

Markup transformer for Markdown content.

restructuredtext
class markupmirror.markup.restructuredtext.ReStructuredTextMarkup

Markup transformer for reStructuredText content.

textile
class markupmirror.markup.textile_.TextileMarkup

Markup transformer for Textile content.

The Markup Pool

The markup pool is the main access point to markup converters. They are registered with the pool, and retrieved from it.

markupmirror.markup.base.markup_pool

Instance of MarkupPool for public use.

class markupmirror.markup.base.MarkupPool

Pool for markup converters.

Each markup class, subclassing markupmirror.markup.base.BaseMarkup, must register to this pool using register_markup defined below.

markups

List registered markup types.

Defaults to the MARKUPMIRROR_MARKUP_TYPES defined in settings.

First access loads and registeres the configured markup converters with this pool.

register_markup(markup)

Registers a markup converter class.

markup must be a subclass of BaseMarkup and may not be registered already.

load_markup(markup)

Import markup converter class from specified path.

If already an object, then return as is otherwise, import it first.

load_requirements(markup)

See that we can import everything in the requires field.

Return list of [(requirement, error), ...] for all the requirements that couldn’t be fullfilled

unregister_markup(markup_name)

Unregisters a markup converter with the name markup_name. Fails silently if no converter was registered by that name.

Alternatively you can also use the del operator:

del markup_pool['restructuredtext']
has_markup(markup_name)

Tests if a markup converter with the name markup_name is already registered with the markup pool.

Alternatively you can also use the in operator, like with a dictionary:

if 'restructuredtext' in markup_pool:
    pass
get_markup(markup_name)

Returns one markup converter by name. Raises KeyError if no converter was registered by markup_name.

Alternatively you can also use the [] accessor, like with a dictionary:

markup = markup_pool['restructuredtext']

Create your own Markup Type

You can easily create your own markup converters for any purpose. The converter only needs to inherit from BaseMarkup and implement the convert method.

class markupmirror.markup.base.BaseMarkup

Basic interface for markup converter classes.

An example converter could look like this:

class ExampleMarkup(BaseMarkup):

    def convert(self, markup):
        return markup.replace("example", "markup")
classmethod get_name()

Returns lowercase markup name, without the “Markup” part.

Class naming convention is <Markup-Type>Markup.

convert(markup, *args, **kwargs)

Main conversion method. Must be implemented in subclasses.

before_convert(markup, *args, **kwargs)

Called before convert. Can be used to separate the main conversion through a third-party library (e.g. Markdown) from additional logic.

after_convert(markup, *args, **kwargs)

Called after convert. Similar to before_convert.

__call__(markup, *args, **kwargs)

Main entry point. Calls before_convert, convert and after_convert in that order.

Note

If convert, before_convert or after_convert accept *args and **kwargs which can be exploited to pass the request or a model instance into the conversion process.

It may also have a requires dictionary attribute that defines named requirements by their full import path.

When the markup type is registered, these requires will be resolved and made available through the requirement attribute (also a dictionary) of the markup class.

For example:

from markupmirror.markup.base import BaseMarkup

class ExampleMarkup(BaseMarkup):

    requires = {
        'wikimarkup': wikimarkup.parse',
    }

    def convert(self, markup):
        return self.requirements['wikimarkup'](markup)

If any requirements can’t be resolved then the markupmirror logger will emit a warning complaining about this and the markup type is not registered.

Register and unregister Markup Types

The default markup types provided by django-markupmirror are registered during initialization. If you want to remove any of these, you can use the MarkupPool.unregister_markup method:

from markupmirror.markup.base import markup_pool

markup_pool.unregister_markup('plaintext')  # is equal to
del markup_pool['textile']

To register new markup converters, pass the markup class to the MarkupPool.register_markup method:

from markupmirror.markup.base import markup_pool, BaseMarkup

class ExampleMarkup(BaseMarkup):

    def convert(self, markup):
        return markup.replace("markup", "example")

markup_pool.register_markup(ExampleMarkup)

This would make the ExampleMarkup converter available through the key example, derived from its class name:

example_markup = markup_pool['example']

Registration via settings.py

You may also control what markup types are registered on initialisation via the following two settings in your project’s settings.py:

MARKUPMIRROR_IGNORE_DEFAULT_TYPES
Whether to ignore all default markup types
MARKUPMIRROR_MARKUP_TYPES

Dictionary of key to markup type.

Where markup type is either an subclass of BaseMarkup or a dot seperated import path to a subclass of BaseMarkup.

These will be merged on top of the default markup types.

Using the MarkupMirrorField

After you have configured markupmirror in your settings and added your custom markup converters, the only thing left to do is to use the MarkupMirrorField in your models.

A field with fixed markup type would have to provide a markup_type:

from django.db import models
from markupmirror.fields import MarkupMirrorField

class MyModel(models.Model):
    content = MarkupMirrorField(markup_type='markdown')

To provide a selectbox for the users to select the content’s markup type manually, use default_markup_type instead:

class MyModel(models.Model):
    content = MarkupMirrorField(default_markup_type='plaintext')

If you provide neither markup_type nor default_markup_type, the MARKUPMIRROR_DEFAULT_MARKUP_TYPE setting will be used as default.

For reference, see the MarkupMirrorField and Markup classes:

class markupmirror.fields.MarkupMirrorField(verbose_name=None, name=None, markup_type=None, default_markup_type=None, escape_html=False, **kwargs)

Field to store markup content.

The MarkupMirrorField adds three fields to the model it is used in.

  • One field for the raw markup content (<field_name>).
  • One field for the rendered HTML content (<field_name>_rendered).
  • One field that specifies the markup type (<field_name>_markup_type).

The field can be used with a fixed markup_type or a default_markup_type, which displays an additional selection widget for the available markup types. However, only one of markup_type and default_markup_type can be provided.

If neither is provided, the setting MARKUPMIRROR_DEFAULT_MARKUP_TYPE is used as default_markup_type instead.

class markupmirror.fields.Markup(instance, field_name, rendered_field_name, markup_type_field_name)

Wrapper class for markup content output.

Stores the names of the associated field, the rendered field and the markup_type field to make assignment possible.

When accessing the value of a MarkupField, a Markup instance will be returned. This provides a few methods to access the raw and rendered markup, and the markup type of the saved content.

raw

The raw markup content.

markup_type

Markup type of the current markup content.

rendered

Returns the rendered markup content (read only). This is only available after Model.save has been called.

__unicode__()

Allows display via templates to work without safe filter. Same as rendered.