You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
595 lines
25 KiB
595 lines
25 KiB
Writing Extensions for Python-Markdown
|
|
======================================
|
|
|
|
Overview
|
|
--------
|
|
|
|
Python-Markdown includes an API for extension writers to plug their own
|
|
custom functionality and/or syntax into the parser. There are preprocessors
|
|
which allow you to alter the source before it is passed to the parser,
|
|
inline patterns which allow you to add, remove or override the syntax of
|
|
any inline elements, and postprocessors which allow munging of the
|
|
output of the parser before it is returned. If you really want to dive in,
|
|
there are also blockprocessors which are part of the core BlockParser.
|
|
|
|
As the parser builds an [ElementTree][] object which is later rendered
|
|
as Unicode text, there are also some helpers provided to ease manipulation of
|
|
the tree. Each part of the API is discussed in its respective section below.
|
|
Additionaly, reading the source of some [[Available Extensions]] may be helpful.
|
|
For example, the [[Footnotes]] extension uses most of the features documented
|
|
here.
|
|
|
|
* [Preprocessors][]
|
|
* [InlinePatterns][]
|
|
* [Treeprocessors][]
|
|
* [Postprocessors][]
|
|
* [BlockParser][]
|
|
* [Working with the ElementTree][]
|
|
* [Integrating your code into Markdown][]
|
|
* [extendMarkdown][]
|
|
* [OrderedDict][]
|
|
* [registerExtension][]
|
|
* [Config Settings][]
|
|
* [makeExtension][]
|
|
|
|
<h3 id="preprocessors">Preprocessors</h3>
|
|
|
|
Preprocessors munge the source text before it is passed into the Markdown
|
|
core. This is an excellent place to clean up bad syntax, extract things the
|
|
parser may otherwise choke on and perhaps even store it for later retrieval.
|
|
|
|
Preprocessors should inherit from ``markdown.preprocessors.Preprocessor`` and
|
|
implement a ``run`` method with one argument ``lines``. The ``run`` method of
|
|
each Preprocessor will be passed the entire source text as a list of Unicode
|
|
strings. Each string will contain one line of text. The ``run`` method should
|
|
return either that list, or an altered list of Unicode strings.
|
|
|
|
A pseudo example:
|
|
|
|
class MyPreprocessor(markdown.preprocessors.Preprocessor):
|
|
def run(self, lines):
|
|
new_lines = []
|
|
for line in lines:
|
|
m = MYREGEX.match(line)
|
|
if m:
|
|
# do stuff
|
|
else:
|
|
new_lines.append(line)
|
|
return new_lines
|
|
|
|
<h3 id="inlinepatterns">Inline Patterns</h3>
|
|
|
|
Inline Patterns implement the inline HTML element syntax for Markdown such as
|
|
``*emphasis*`` or ``[links](http://example.com)``. Pattern objects should be
|
|
instances of classes that inherit from ``markdown.inlinepatterns.Pattern`` or
|
|
one of its children. Each pattern object uses a single regular expression and
|
|
must have the following methods:
|
|
|
|
* **``getCompiledRegExp()``**:
|
|
|
|
Returns a compiled regular expression.
|
|
|
|
* **``handleMatch(m)``**:
|
|
|
|
Accepts a match object and returns an ElementTree element of a plain
|
|
Unicode string.
|
|
|
|
Note that any regular expression returned by ``getCompiledRegExp`` must capture
|
|
the whole block. Therefore, they should all start with ``r'^(.*?)'`` and end
|
|
with ``r'(.*?)!'``. When using the default ``getCompiledRegExp()`` method
|
|
provided in the ``Pattern`` you can pass in a regular expression without that
|
|
and ``getCompiledRegExp`` will wrap your expression for you. This means that
|
|
the first group of your match will be ``m.group(2)`` as ``m.group(1)`` will
|
|
match everything before the pattern.
|
|
|
|
For an example, consider this simplified emphasis pattern:
|
|
|
|
class EmphasisPattern(markdown.inlinepatterns.Pattern):
|
|
def handleMatch(self, m):
|
|
el = markdown.etree.Element('em')
|
|
el.text = m.group(3)
|
|
return el
|
|
|
|
As discussed in [Integrating Your Code Into Markdown][], an instance of this
|
|
class will need to be provided to Markdown. That instance would be created
|
|
like so:
|
|
|
|
# an oversimplified regex
|
|
MYPATTERN = r'\*([^*]+)\*'
|
|
# pass in pattern and create instance
|
|
emphasis = EmphasisPattern(MYPATTERN)
|
|
|
|
Actually it would not be necessary to create that pattern (and not just because
|
|
a more sophisticated emphasis pattern already exists in Markdown). The fact is,
|
|
that example pattern is not very DRY. A pattern for `**strong**` text would
|
|
be almost identical, with the exception that it would create a 'strong' element.
|
|
Therefore, Markdown provides a number of generic pattern classes that can
|
|
provide some common functionality. For example, both emphasis and strong are
|
|
implemented with separate instances of the ``SimpleTagPettern`` listed below.
|
|
Feel free to use or extend any of these Pattern classes.
|
|
|
|
**Generic Pattern Classes**
|
|
|
|
* **``SimpleTextPattern(pattern)``**:
|
|
|
|
Returns simple text of ``group(2)`` of a ``pattern``.
|
|
|
|
* **``SimpleTagPattern(pattern, tag)``**:
|
|
|
|
Returns an element of type "`tag`" with a text attribute of ``group(3)``
|
|
of a ``pattern``. ``tag`` should be a string of a HTML element (i.e.: 'em').
|
|
|
|
* **``SubstituteTagPattern(pattern, tag)``**:
|
|
|
|
Returns an element of type "`tag`" with no children or text (i.e.: 'br').
|
|
|
|
There may be other Pattern classes in the Markdown source that you could extend
|
|
or use as well. Read through the source and see if there is anything you can
|
|
use. You might even get a few ideas for different approaches to your specific
|
|
situation.
|
|
|
|
<h3 id="treeprocessors">Treeprocessors</h3>
|
|
|
|
Treeprocessors manipulate an ElemenTree object after it has passed through the
|
|
core BlockParser. This is where additional manipulation of the tree takes
|
|
place. Additionally, the InlineProcessor is a Treeprocessor which steps through
|
|
the tree and runs the InlinePatterns on the text of each Element in the tree.
|
|
|
|
A Treeprocessor should inherit from ``markdown.treeprocessors.Treeprocessor``,
|
|
over-ride the ``run`` method which takes one argument ``root`` (an Elementree
|
|
object) and returns either that root element or a modified root element.
|
|
|
|
A pseudo example:
|
|
|
|
class MyTreeprocessor(markdown.treeprocessors.Treeprocessor):
|
|
def run(self, root):
|
|
#do stuff
|
|
return my_modified_root
|
|
|
|
For specifics on manipulating the ElementTree, see
|
|
[Working with the ElementTree][] below.
|
|
|
|
<h3 id="postprocessors">Postprocessors</h3>
|
|
|
|
Postprocessors manipulate the document after the ElementTree has been
|
|
serialized into a string. Postprocessors should be used to work with the
|
|
text just before output.
|
|
|
|
A Postprocessor should inherit from ``markdown.postprocessors.Postprocessor``
|
|
and over-ride the ``run`` method which takes one argument ``text`` and returns
|
|
a Unicode string.
|
|
|
|
Postprocessors are run after the ElementTree has been serialized back into
|
|
Unicode text. For example, this may be an appropriate place to add a table of
|
|
contents to a document:
|
|
|
|
class TocPostprocessor(markdown.postprocessors.Postprocessor):
|
|
def run(self, text):
|
|
return MYMARKERRE.sub(MyToc, text)
|
|
|
|
<h3 id="blockparser">BlockParser</h3>
|
|
|
|
Sometimes, pre/tree/postprocessors and Inline Patterns aren't going to do what
|
|
you need. Perhaps you want a new type of block type that needs to be integrated
|
|
into the core parsing. In such a situation, you can add/change/remove
|
|
functionality of the core ``BlockParser``. The BlockParser is composed of a
|
|
number of Blockproccessors. The BlockParser steps through each block of text
|
|
(split by blank lines) and passes each block to the appropriate Blockprocessor.
|
|
That Blockprocessor parses the block and adds it to the ElementTree. The
|
|
[[Definition Lists]] extension would be a good example of an extension that
|
|
adds/modifies Blockprocessors.
|
|
|
|
A Blockprocessor should inherit from ``markdown.blockprocessors.BlockProcessor``
|
|
and implement both the ``test`` and ``run`` methods.
|
|
|
|
The ``test`` method is used by BlockParser to identify the type of block.
|
|
Therefore the ``test`` method must return a boolean value. If the test returns
|
|
``True``, then the BlockParser will call that Blockprocessor's ``run`` method.
|
|
If it returns ``False``, the BlockParser will move on to the next
|
|
BlockProcessor.
|
|
|
|
The **``test``** method takes two arguments:
|
|
|
|
* **``parent``**: The parent etree Element of the block. This can be useful as
|
|
the block may need to be treated differently if it is inside a list, for
|
|
example.
|
|
|
|
* **``block``**: A string of the current block of text. The test may be a
|
|
simple string method (such as ``block.startswith(some_text)``) or a complex
|
|
regular expression.
|
|
|
|
The **``run``** method takes two arguments:
|
|
|
|
* **``parent``**: A pointer to the parent etree Element of the block. The run
|
|
method will most likely attach additional nodes to this parent. Note that
|
|
nothing is returned by the method. The Elementree object is altered in place.
|
|
|
|
* **``blocks``**: A list of all remaining blocks of the document. Your run
|
|
method must remove (pop) the first block from the list (which it altered in
|
|
place - not returned) and parse that block. You may find that a block of text
|
|
legitimately contains multiple block types. Therefore, after processing the
|
|
first type, your processor can insert the remaining text into the beginning
|
|
of the ``blocks`` list for future parsing.
|
|
|
|
Please be aware that a single block can span multiple text blocks. For example,
|
|
The official Markdown syntax rules state that a blank line does not end a
|
|
Code Block. If the next block of text is also indented, then it is part of
|
|
the previous block. Therefore, the BlockParser was specifically designed to
|
|
address these types of situations. If you notice the ``CodeBlockProcessor``,
|
|
in the core, you will note that it checks the last child of the ``parent``.
|
|
If the last child is a code block (``<pre><code>...</code></pre>``), then it
|
|
appends that block to the previous code block rather than creating a new
|
|
code block.
|
|
|
|
Each BlockProcessor has the following utility methods available:
|
|
|
|
* **``lastChild(parent)``**:
|
|
|
|
Returns the last child of the given etree Element or ``None`` if it had no
|
|
children.
|
|
|
|
* **``detab(text)``**:
|
|
|
|
Removes one level of indent (four spaces by default) from the front of each
|
|
line of the given text string.
|
|
|
|
* **``looseDetab(text, level)``**:
|
|
|
|
Removes "level" levels of indent (defaults to 1) from the front of each line
|
|
of the given text string. However, this methods allows secondary lines to
|
|
not be indented as does some parts of the Markdown syntax.
|
|
|
|
Each BlockProcessor also has a pointer to the containing BlockParser instance at
|
|
``self.parser``, which can be used to check or alter the state of the parser.
|
|
The BlockParser tracks it's state in a stack at ``parser.state``. The state
|
|
stack is an instance of the ``State`` class.
|
|
|
|
**``State``** is a subclass of ``list`` and has the additional methods:
|
|
|
|
* **``set(state)``**:
|
|
|
|
Set a new state to string ``state``. The new state is appended to the end
|
|
of the stack.
|
|
|
|
* **``reset()``**:
|
|
|
|
Step back one step in the stack. The last state at the end is removed from
|
|
the stack.
|
|
|
|
* **``isstate(state)``**:
|
|
|
|
Test that the top (current) level of the stack is of the given string
|
|
``state``.
|
|
|
|
Note that to ensure that the state stack doesn't become corrupted, each time a
|
|
state is set for a block, that state *must* be reset when the parser finishes
|
|
parsing that block.
|
|
|
|
An instance of the **``BlockParser``** is found at ``Markdown.parser``.
|
|
``BlockParser`` has the following methods:
|
|
|
|
* **``parseDocument(lines)``**:
|
|
|
|
Given a list of lines, an ElementTree object is returned. This should be
|
|
passed an entire document and is the only method the ``Markdown`` class
|
|
calls directly.
|
|
|
|
* **``parseChunk(parent, text)``**:
|
|
|
|
Parses a chunk of markdown text composed of multiple blocks and attaches
|
|
those blocks to the ``parent`` Element. The ``parent`` is altered in place
|
|
and nothing is returned. Extensions would most likely use this method for
|
|
block parsing.
|
|
|
|
* **``parseBlocks(parent, blocks)``**:
|
|
|
|
Parses a list of blocks of text and attaches those blocks to the ``parent``
|
|
Element. The ``parent`` is altered in place and nothing is returned. This
|
|
method will generally only be used internally to recursively parse nested
|
|
blocks of text.
|
|
|
|
While is is not recommended, an extension could subclass or completely replace
|
|
the ``BlockParser``. The new class would have to provide the same public API.
|
|
However, be aware that other extensions may expect the core parser provided
|
|
and will not work with such a drastically different parser.
|
|
|
|
<h3 id="working_with_et">Working with the ElementTree</h3>
|
|
|
|
As mentioned, the Markdown parser converts a source document to an
|
|
[ElementTree][] object before serializing that back to Unicode text.
|
|
Markdown has provided some helpers to ease that manipulation within the context
|
|
of the Markdown module.
|
|
|
|
First, to get access to the ElementTree module import ElementTree from
|
|
``markdown`` rather than importing it directly. This will ensure you are using
|
|
the same version of ElementTree as markdown. The module is named ``etree``
|
|
within Markdown.
|
|
|
|
from markdown import etree
|
|
|
|
``markdown.etree`` tries to import ElementTree from any known location, first
|
|
as a standard library module (from ``xml.etree`` in Python 2.5), then as a third
|
|
party package (``Elementree``). In each instance, ``cElementTree`` is tried
|
|
first, then ``ElementTree`` if the faster C implementation is not available on
|
|
your system.
|
|
|
|
Sometimes you may want text inserted into an element to be parsed by
|
|
[InlinePatterns][]. In such a situation, simply insert the text as you normally
|
|
would and the text will be automatically run through the InlinePatterns.
|
|
However, if you do *not* want some text to be parsed by InlinePatterns,
|
|
then insert the text as an ``AtomicString``.
|
|
|
|
some_element.text = markdown.AtomicString(some_text)
|
|
|
|
Here's a basic example which creates an HTML table (note that the contents of
|
|
the second cell (``td2``) will be run through InlinePatterns latter):
|
|
|
|
table = etree.Element("table")
|
|
table.set("cellpadding", "2") # Set cellpadding to 2
|
|
tr = etree.SubElement(table, "tr") # Add child tr to table
|
|
td1 = etree.SubElement(tr, "td") # Add child td1 to tr
|
|
td1.text = markdown.AtomicString("Cell content") # Add plain text content
|
|
td2 = etree.SubElement(tr, "td") # Add second td to tr
|
|
td2.text = "*text* with **inline** formatting." # Add markup text
|
|
table.tail = "Text after table" # Add text after table
|
|
|
|
You can also manipulate an existing tree. Consider the following example which
|
|
adds a ``class`` attribute to ``<a>`` elements:
|
|
|
|
def set_link_class(self, element):
|
|
for child in element:
|
|
if child.tag == "a":
|
|
child.set("class", "myclass") #set the class attribute
|
|
set_link_class(child) # run recursively on children
|
|
|
|
For more information about working with ElementTree see the ElementTree
|
|
[Documentation](http://effbot.org/zone/element-index.htm)
|
|
([Python Docs](http://docs.python.org/lib/module-xml.etree.ElementTree.html)).
|
|
|
|
<h3 id="integrating_into_markdown">Integrating Your Code Into Markdown</h3>
|
|
|
|
Once you have the various pieces of your extension built, you need to tell
|
|
Markdown about them and ensure that they are run in the proper sequence.
|
|
Markdown accepts a ``Extension`` instance for each extension. Therefore, you
|
|
will need to define a class that extends ``markdown.Extension`` and over-rides
|
|
the ``extendMarkdown`` method. Within this class you will manage configuration
|
|
options for your extension and attach the various processors and patterns to
|
|
the Markdown instance.
|
|
|
|
It is important to note that the order of the various processors and patterns
|
|
matters. For example, if we replace ``http://...`` links with <a> elements, and
|
|
*then* try to deal with inline html, we will end up with a mess. Therefore,
|
|
the various types of processors and patterns are stored within an instance of
|
|
the Markdown class in [OrderedDict][]s. Your ``Extension`` class will need to
|
|
manipulate those OrderedDicts appropriately. You may insert instances of your
|
|
processors and patterns into the appropriate location in an OrderedDict, remove
|
|
a built-in instance, or replace a built-in instance with your own.
|
|
|
|
<h4 id="extendmarkdown">extendMarkdown</h4>
|
|
|
|
The ``extendMarkdown`` method of a ``markdown.Extension`` class accepts two
|
|
arguments:
|
|
|
|
* **``md``**:
|
|
|
|
A pointer to the instance of the Markdown class. You should use this to
|
|
access the [OrderedDict][]s of processors and patterns. They are found
|
|
under the following attributes:
|
|
|
|
* ``md.preprocessors``
|
|
* ``md.inlinePatterns``
|
|
* ``md.parser.blockprocessors``
|
|
* ``md.treepreprocessors``
|
|
* ``md.postprocessors``
|
|
|
|
Some other things you may want to access in the markdown instance are:
|
|
|
|
* ``md.htmlStash``
|
|
* ``md.output_formats``
|
|
* ``md.set_output_format()``
|
|
* ``md.registerExtension()``
|
|
|
|
* **``md_globals``**:
|
|
|
|
Contains all the various global variables within the markdown module.
|
|
|
|
Of course, with access to those items, theoretically you have the option to
|
|
changing anything through various [monkey_patching][] techniques. However, you
|
|
should be aware that the various undocumented or private parts of markdown
|
|
may change without notice and your monkey_patches may break with a new release.
|
|
Therefore, what you really should be doing is inserting processors and patterns
|
|
into the markdown pipeline. Consider yourself warned.
|
|
|
|
[monkey_patching]: http://en.wikipedia.org/wiki/Monkey_patch
|
|
|
|
A simple example:
|
|
|
|
class MyExtension(markdown.Extension):
|
|
def extendMarkdown(self, md, md_globals):
|
|
# Insert instance of 'mypattern' before 'references' pattern
|
|
md.inlinePatterns.add('mypattern', MyPattern(md), '<references')
|
|
|
|
<h4 id="ordereddict">OrderedDict</h4>
|
|
|
|
An OrderedDict is a dictionary like object that retains the order of it's
|
|
items. The items are ordered in the order in which they were appended to
|
|
the OrderedDict. However, an item can also be inserted into the OrderedDict
|
|
in a specific location in relation to the existing items.
|
|
|
|
Think of OrderedDict as a combination of a list and a dictionary as it has
|
|
methods common to both. For example, you can get and set items using the
|
|
``od[key] = value`` syntax and the methods ``keys()``, ``values()``, and
|
|
``items()`` work as expected with the keys, values and items returned in the
|
|
proper order. At the same time, you can use ``insert()``, ``append()``, and
|
|
``index()`` as you would with a list.
|
|
|
|
Generally speaking, within Markdown extensions you will be using the special
|
|
helper method ``add()`` to add additional items to an existing OrderedDict.
|
|
|
|
The ``add()`` method accepts three arguments:
|
|
|
|
* **``key``**: A string. The key is used for later reference to the item.
|
|
|
|
* **``value``**: The object instance stored in this item.
|
|
|
|
* **``location``**: Optional. The items location in relation to other items.
|
|
|
|
Note that the location can consist of a few different values:
|
|
|
|
* The special strings ``"_begin"`` and ``"_end"`` insert that item at the
|
|
beginning or end of the OrderedDict respectively.
|
|
|
|
* A less-than sign (``<``) followed by an existing key (i.e.:
|
|
``"<somekey"``) inserts that item before the existing key.
|
|
|
|
* A greater-than sign (``>``) followed by an existing key (i.e.:
|
|
``">somekey"``) inserts that item after the existing key.
|
|
|
|
Consider the following example:
|
|
|
|
>>> import markdown
|
|
>>> od = markdown.OrderedDict()
|
|
>>> od['one'] = 1 # The same as: od.add('one', 1, '_begin')
|
|
>>> od['three'] = 3 # The same as: od.add('three', 3, '>one')
|
|
>>> od['four'] = 4 # The same as: od.add('four', 4, '_end')
|
|
>>> od.items()
|
|
[("one", 1), ("three", 3), ("four", 4)]
|
|
|
|
Note that when building an OrderedDict in order, the extra features of the
|
|
``add`` method offer no real value and are not necessary. However, when
|
|
manipulating an existing OrderedDict, ``add`` can be very helpful. So let's
|
|
insert another item into the OrderedDict.
|
|
|
|
>>> od.add('two', 2, '>one') # Insert after 'one'
|
|
>>> od.values()
|
|
[1, 2, 3, 4]
|
|
|
|
Now let's insert another item.
|
|
|
|
>>> od.add('twohalf', 2.5, '<three') # Insert before 'three'
|
|
>>> od.keys()
|
|
["one", "two", "twohalf", "three", "four"]
|
|
|
|
Note that we also could have set the location of "twohalf" to be 'after two'
|
|
(i.e.: ``'>two'``). However, it's unlikely that you will have control over the
|
|
order in which extensions will be loaded, and this could affect the final
|
|
sorted order of an OrderedDict. For example, suppose an extension adding
|
|
'twohalf' in the above examples was loaded before a separate extension which
|
|
adds 'two'. You may need to take this into consideration when adding your
|
|
extension components to the various markdown OrderedDicts.
|
|
|
|
Once an OrderedDict is created, the items are available via key:
|
|
|
|
MyNode = od['somekey']
|
|
|
|
Therefore, to delete an existing item:
|
|
|
|
del od['somekey']
|
|
|
|
To change the value of an existing item (leaving location unchanged):
|
|
|
|
od['somekey'] = MyNewObject()
|
|
|
|
To change the location of an existing item:
|
|
|
|
t.link('somekey', '<otherkey')
|
|
|
|
<h4 id="registerextension">registerExtension</h4>
|
|
|
|
Some extensions may need to have their state reset between multiple runs of the
|
|
Markdown class. For example, consider the following use of the [[Footnotes]]
|
|
extension:
|
|
|
|
md = markdown.Markdown(extensions=['footnotes'])
|
|
html1 = md.convert(text_with_footnote)
|
|
md.reset()
|
|
html2 = md.convert(text_without_footnote)
|
|
|
|
Without calling ``reset``, the footnote definitions from the first document will
|
|
be inserted into the second document as they are still stored within the class
|
|
instance. Therefore the ``Extension`` class needs to define a ``reset`` method
|
|
that will reset the state of the extension (i.e.: ``self.footnotes = {}``).
|
|
However, as many extensions do not have a need for ``reset``, ``reset`` is only
|
|
called on extensions that are registered.
|
|
|
|
To register an extension, call ``md.registerExtension`` from within your
|
|
``extendMarkdown`` method:
|
|
|
|
|
|
def extendMarkdown(self, md, md_globals):
|
|
md.registerExtension(self)
|
|
# insert processors and patterns here
|
|
|
|
Then, each time ``reset`` is called on the Markdown instance, the ``reset``
|
|
method of each registered extension will be called as well. You should also
|
|
note that ``reset`` will be called on each registered extension after it is
|
|
initialized the first time. Keep that in mind when over-riding the extension's
|
|
``reset`` method.
|
|
|
|
<h4 id="configsettings">Config Settings</h4>
|
|
|
|
If an extension uses any parameters that the user may want to change,
|
|
those parameters should be stored in ``self.config`` of your
|
|
``markdown.Extension`` class in the following format:
|
|
|
|
self.config = {parameter_1_name : [value1, description1],
|
|
parameter_2_name : [value2, description2] }
|
|
|
|
When stored this way the config parameters can be over-ridden from the
|
|
command line or at the time Markdown is initiated:
|
|
|
|
markdown.py -x myextension(SOME_PARAM=2) inputfile.txt > output.txt
|
|
|
|
Note that parameters should always be assumed to be set to string
|
|
values, and should be converted at run time. For example:
|
|
|
|
i = int(self.getConfig("SOME_PARAM"))
|
|
|
|
<h4 id="makeextension">makeExtension</h4>
|
|
|
|
Each extension should ideally be placed in its own module starting
|
|
with the ``mdx_`` prefix (e.g. ``mdx_footnotes.py``). The module must
|
|
provide a module-level function called ``makeExtension`` that takes
|
|
an optional parameter consisting of a dictionary of configuration over-rides
|
|
and returns an instance of the extension. An example from the footnote
|
|
extension:
|
|
|
|
def makeExtension(configs=None) :
|
|
return FootnoteExtension(configs=configs)
|
|
|
|
By following the above example, when Markdown is passed the name of your
|
|
extension as a string (i.e.: ``'footnotes'``), it will automatically import
|
|
the module and call the ``makeExtension`` function initiating your extension.
|
|
|
|
You may have noted that the extensions packaged with Python-Markdown do not
|
|
use the ``mdx_`` prefix in their module names. This is because they are all
|
|
part of the ``markdown.extensions`` package. Markdown will first try to import
|
|
from ``markdown.extensions.extname`` and upon failure, ``mdx_extname``. If both
|
|
fail, Markdown will continue without the extension.
|
|
|
|
However, Markdown will also accept an already existing instance of an extension.
|
|
For example:
|
|
|
|
import markdown
|
|
import myextension
|
|
configs = {...}
|
|
myext = myextension.MyExtension(configs=configs)
|
|
md = markdown.Markdown(extensions=[myext])
|
|
|
|
This is useful if you need to implement a large number of extensions with more
|
|
than one residing in a module.
|
|
|
|
[Preprocessors]: #preprocessors
|
|
[InlinePatterns]: #inlinepatterns
|
|
[Treeprocessors]: #treeprocessors
|
|
[Postprocessors]: #postprocessors
|
|
[BlockParser]: #blockparser
|
|
[Working with the ElementTree]: #working_with_et
|
|
[Integrating your code into Markdown]: #integrating_into_markdown
|
|
[extendMarkdown]: #extendmarkdown
|
|
[OrderedDict]: #ordereddict
|
|
[registerExtension]: #registerextension
|
|
[Config Settings]: #configsettings
|
|
[makeExtension]: #makeextension
|
|
[ElementTree]: http://effbot.org/zone/element-index.htm
|