Summary

This is a Python implementation of John Gruber's [Markdown](http://daringfireball.net/projects/markdown/). The current version of python-markdown implements all Markdown syntax features and fully passes [Markdown Test Suite 1.0](http://six.pairlist.net/pipermail/markdown-discuss/2004-December/000909.html). It also supports footnotes (see [this thread](http://six.pairlist.net/pipermail/markdown-discuss/2005-August/001480.html)) and attributes (see [this thread](http://six.pairlist.net/pipermail/markdown-discuss/2005-August/001486.html)). Python-Markdown defaults to ignoring middle-word emphasis through underscore, but this it can be switched off. (See [this thread](http://six.pairlist.net/pipermail/markdown-discuss/2005-October/001610.html) for discussion.) If you find something missing, [submit a bug report](http://sourceforge.net/tracker/?func=add&group_id=153041&atid=790198) or send me an email (qaramazov-at-gmail.com). Better yet, send me a patch.

Installation

[Download](http://sourceforge.net/project/showfiles.php?group_id=153041) the zip file and extract the files. If you want to install markdown as as a module into your python tree, run "python setup.py install" from a directory where you unzip the files.

Command Line Usage

To use markdown.py by itself, run it as python markdown.py or python markdown.py > If you are using Python 2.3 or higher, you can also use advanced command line options to specify encoding or to run extensions. $ python markdown.py usage: markdown.py INPUTFILE [options] options: -h, --help show this help message and exit -f OUTPUT_FILE, --file=OUTPUT_FILE write output to OUTPUT_FILE -e ENCODING, --encoding=ENCODING encoding for input and output files -q, --quiet suppress all messages -v, --verbose print info messages --noisy print debug messages -x EXTENSION, --extension=EXTENSION load extension EXTENSION For an extension to be ran this way it must be provided in a module named ``mdx_{extensionname}.py`` which should be in your python path, e.g. ``mdx_footnotes.py``. It can then be invoked as by name (the part after "mdx_"): python markdown.py -x footnotes text_with_footnotes.txt output.html If the extension supports config options (see below), you can also pass them in as well: python markdown.py -x "footnotes(PLACE_MARKER=~~~~~~~~)"

Using the Module

To use it as markdown as a module: import markdown html = markdown.markdown(your_text_string) Alternatively, if you want to pass more options: import markdown md = Markdown(text, extensions=['footnotes'], extension_configs= {'footnotes' : ('PLACE_MARKER','~~~~~~~~')} encoding='utf8') return md.toString() or, if you want to process multiple strings: md = Markdown(text=None) md.toString(text) Finally, if the extensions are fully compatible, you should be able to get a list of extensions and their config parameters: for x in md.getExtensions(): print x.name print x.oneliner print x.getConfigInfo()

Writing Extensions

The functionality of the script can be extended without changing the code, by inserting additional pre-processors, post-processors or inline patterns into Markdown's pipeline. **Pre-processors** operate on lines of source text and are run in the beginning. It is sufficient to write a class with a run() method that takes a list of text lines as a parameter and returns the same or a new list. An instance of the preprocessor can then be inserted into the markdown pipeline. Preprocessor classes must extend markdown.Preprocessor. class SamplePreprocessor (markdown.Preprocessor) : def run(self, lines) : for i in range(len(lines)) : if lines[i].startswith(SOMETHING) : lines[i] = do_something(lines[i]) return lines md_instance.preprocessors.insert(SOME_INDEX, SamplePreprocessor()) **Post-processors** operate on a NanoDom tree and run at the very end. They need to implement a "run" method that takes a pointer to a NanoDom document. Postprocessor classes must extend markdown.Postprocessor. class SamplePostprocessor (markdown.Postprocessor): def run(self, doc) : doc.documentElement.appendChild(doc.createElement("new")) md_instance.postprocessors.insert(SOME_INDEX, SamplePostprocessor()) Finally, **inline patterns** can be added. Each inline pattern includes a regular expression pattern and a method for turning a match object into a DOM fragment class MyCustomPattern (markdown.Pattern) : def handleMatch(self, m, doc) : el = doc.createElement('custom') el.setAttribute('stuff', m.group(3)) return el new_pattern = MyCustomPattern(r'your regular expression here') md_instance.inlinePatterns.insert(SOME_INDEX, new_pattern) Preprocessors, patterns and postprocessors need to then be wrapped together into an extension, which should be implemented as a class that extends markdown.Extension and should over-ride the ``extendMarkdown()`` method. ``extendMarkdown()`` is called during markdown construction, giving the extension a pointer to the markdown object (the ``md`` parameters) and markdown's global variables (``md_globals``), which in theory gives the extension an option of changing anything it cares to change. However, what it really should be doing is inserting preprocessors, postprocessors and patterns into the markdown pipeline: def extendMarkdown(self, md, md_globals) : self.md = md # Insert a preprocessor before ReferencePreprocessor index = md.preprocessors.index(md_globals['REFERENCE_PREPROCESSOR']) preprocessor = FootnotePreprocessor(self) preprocessor.md = md md.preprocessors.insert(index, preprocessor) If the extension uses any parameters that the use may want to change, they should be stored in self.config 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-riden from the command line or at the time Markdown is instantiated: 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 the run time, e.g. i += int(self.getConfig("SOME_PARAM")) Each extension should ideally be placed in its own module starting with ``mdx_`` prefix (e.g. ``mdx_footnotes.py``). The module must provide a module-level function called ``makeExtensions`` that takes as an optional parameter a list of configuration over-rides and returns an instance of the extension. E.g.: def makeExtension(configs=None) : return FootnoteExtension(configs=configs) See the implementation of footnote support (mdx_footnotes.py) for an example of using all three in combination to provide reasonably complex additional functionality. (I use a pre-processor to collect footnote definitions, an inline pattern to handle uses of footnotes inside the text and a post-processor to attach the HTML of the actual footnotes at the end of the document) Other extensions: * [Table-of-contents extension](extensions/mdx_toc.py) by Chris Clark (inserts a table of contents), upgraded by Yuri. * [Title extension](extensions/mdx_title.py) by Chris Clark (inserts a title element) * [WikiLinks](http://achinghead.com/archives/67/adding-wikilinks-to-markdown-in-python/) by Waylan Limberg (not yet upgraded)

Credits

* The first version of this script was written by [Manfred Stienstra](http://www.dwerg.net/), who is responsible for about a quarter of the code. * Daniel Krech provided the setup.py script. * G. Clark Haynes submitted a patch for indented lists. * Tiago Cogumbreiro submitted an email autolink fix. * Sergej Chodarev submitted a patch for treatment of `
` tags. * Chris Clark submitted a patch to handle `` syntax and a reg ex for "smart" emphasis (ignoring underscores within a word). * Steward Midwinter wrote command-line parser and cleaned up comments. * Many other people helped by reporting bugs.

License

The code is dual-licensed under [GPL](http://www.gnu.org/copyleft/gpl.html) and [BSD License](http://www.opensource.org/licenses/bsd-license.php). Other licensing arrangements can be discussed.

Contact Info

Email qaramazov [at] gmail.com if you have any questions or spot any bugs. (Feel free to write in English, Russian, Portuguese or Spanish.) Or subscribe to [python-markdown-discuss](http://lists.sourceforge.net/lists/listinfo/python-markdown-discuss).

Recent Changes

Oct 11, 2006: Releasing v. 1.6 with a whole bunch of changes (since May 15), including: - Fixed a bug that caused some text to be lost after comments. - Added exception for PHP tags when handling html blocks. - Incorporated Sergej Chodarev's patch to fix a problem with ampersand normalization and html blocks. - Switched to using optparse. Added proper support for unicode. - Fixed the