NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #1418 most downloaded on PyPI
A fast and complete Python implementation of Markdown
Last release 7 months ago
02 Mar 2026
Ships fairly regularly
a new release about every 3 months
Nearly every release is documented
notes for 60 of 60 stable releases
Nothing withdrawn
no release was ever pulled
18 years old
60 releases · first in 2008
[pull #639] Fix middle-word-em interfering with strongs
[pull #617] Add MarkdownFileLinks extra
One column per quarter.
[pull #616] make tables without body gfm compatible
[pull #605] Add support for Python 3.13, drop EOL 3.8
middle-word-em extra preventing strongs from being recognized (#606)[pull #590] Fix underscores within bold text getting emphasized
link-shortrefs extra (#597)[pull #519] Add support for custom extras
prepend arg to toc extra (#397)html, head and body tags being wrapped in <p> tags (#575)[pull #559] Allow cuddled tables
markdown-in-html not always splitting HTML tags into separate lines (#558)markdown-in-html extra (#565)[pull #547] Update markdown-in-html extra to handle markdown on same line as HTML
markdown-in-html extra to handle markdown on same line as HTML (#546)**) in one line (#541)[pull #524] Fix angles being escaped in style blocks (issue #523)
breaks extra with ability to hard break on backslashes (issue #525)code-friendly extra enabled_slugify to use utf-8 encoding (issue #534)[pull #520] Allow more relative links in safe mode (issue #517)
middle-word-em extra[pull #502] Replace deprecated optparse with argparse
<thead> tag to html-classes extraoptparse with argparse_uniform_outdent failing with empty strings (issue #505)imp module (issue #510)[pull #499] Fix images not being procesed correctly
[pull #483] Fix hashing nested HTML blocks
code-color extra[pull #477] Feature wavedrom support
[pull #466] Add optional dependencies to setup.py
setup.py[pull #439] Fix TypeError if html-classes extra is None
<strike> with <s> in strike extra_uniform_outdent_limit functionAssertionError with lazy numbered lists (issue #471)<ul> and <ol> tags to html-classes extra (#352)[pull #413] Fix meta indentation
<br> tags in lists using break-on-newline extra (issue #394)[pull #408] Fix for fenced code blocks issue #396
[pull #389] Tables extra: allow whitespace at the end of the underline row
fenced-code-blocks is loaded.[pull #377] Fixed bug breaking strings elements in metadata lists
language-LANG class[pull #356] Don't merge sequential quotes into a single blockquote
[pull #335] Added header support for wiki tables
[pull #317] Temporary fix to issue #150
[pull #306] Drop support for legacy Python versions
[pull #300] Replace a deprecated method
[pull #238] Fenced code blocks lang with leading space
[pull #243] task list extra visual changes
[pull #236] Fix for safe_mode links regression
[pull #204] toc extra Python 3 error
[pull #131] Markdown "spoiler" extra
New "tables" extra for table syntax that matches GFM and PHP-Markdown Extra . For example:
New "tables" extra for table syntax that matches GFM https://help.github.com/articles/github-flavored-markdown#tables and PHP-Markdown Extra https://michelf.ca/projects/php-markdown/extra/#table. For example:
| Header 1 | *Header* 2 |
| -------- | -------- |
| `Cell 1` | [Cell 2](http://example.com) link |
| Cell 3 | **Cell 4** |
See https://github.com/trentm/python-markdown2/blob/master/test/tm-cases/tables.text for examples and edge cases.
If you have documents using the 'wiki-tables' syntax and want to convert to the 'tables' syntax, there is a script to help with that here: https://github.com/trentm/python-markdown2/blob/master/tools/wiki-tables-to-tables.py
[issue #165] Fix an edge case in list parsing.
[pull #156] Footnotes XML compatibility.
[issue #142 pull #141] Fix parentheses and spaces in urls.
[issue #135] Fix fenced code blocks odd rendering.
["nofollow" extra, issue #74, pull #104] Add rel="nofollow" support (mostly by https://github.com/cdman):
["nofollow" extra, issue #74, pull #104] Add rel="nofollow" support
(mostly by https://github.com/cdman):
$ echo '[link](http://example)' | markdown2 -x nofollow
<p><a rel="nofollow" href="http://example">link</a></p>
Limitation: This can add a duplicate 'rel' attribute to raw HTML links in the input.
["toc" extra] Unescape Markdown special chars in TOC entries. See .
["toc" extra] Unescape Markdown special chars in TOC entries. See https://github.com/trentm/restdown/issues/15.
Now 'tox' testing support (by github.com/msabramo):
[sudo] pip install tox
tox
confirming that markdown2 works with jython (not sure which version) and pypy! Also added pypy to travis-ci testing (http://travis-ci.org/#!/trentm/python-markdown2).
[issue #90, backward incompatible change] Require a space between the '#' and a text for a title. I.e.:
[issue #90] Add a Markdown.preprocess(text) -> text hook for subclasses.
This is a match for the Markdown.postprocess(text) -> text hook added in
an earlier version. (by @joestump).
[issue #90, backward incompatible change] Require a space between the '#' and a text for a title. I.e.:
# This still works
#This doesn't work
##Nor this
This keeps comments, hash tags, and ticket numbers at the beginning of the line from turning into an h1. (by @joestump)
This is a backward incompatible change, however small, hence the version change to 2.0.0.
[issue #84, issue #87] Fix problems with fenced-code-blocks getting double-processed.
[issue #67] Fix an sub-ul inside a ol not working with an indent less than 4 spaces.
[issue #67] Fix an sub-ul inside a ol not working with an indent less
than 4 spaces.
Fix code blocks and fenced-code-blocks to work with a single leading newline at the start of the input.
[issue #86, 'fenced-code-blocks' extra] Fix fenced code blocks not being parsed out before other syntax elements, like headers.
[issue #83, 'fenced-code-blocks' and 'code-color' extras] Allow 'cssclass' code coloring option (passed to pygments) to be overridden (by https://github.com/kaishaku). E.g.:
import markdown2
html = markdown2.markdown(text,
extras={'fenced-code-blocks': {'cssclass': 'mycode'}})
[issue #64] Python 3 support! markdown2.py supports Python 2 and 3 in the same file without requiring install-time 2to3 transformation.
[issue #80] Jython 2.2.1 support fix (by github.com/clach04)
Deprecate code-color extra. Use the fenced-code-block extra and its cleaner mechanism for specifying the language, instead. This extra will be removed…
Deprecate code-color extra. Use the fenced-code-block extra and
its cleaner mechanism for specifying the language, instead. This extra
will be removed in v2.0 or so.
New fenced-code-blocks extra. It allows a code block to not have to be
indented by fencing it with '```' on a line before and after. Based on
[GFM](<http://github.github.com/github-flavored-markdown/).
Some code:
```
print "hi"
```
It includes support for code syntax highlighting as per GFM. This requires
the pygments Python module to be on the pythonpath.
```python
if True:
print "hi"
```
[issue #78, issue #77] Add "metadata" extra (github.com/slomo).
Drop "Makefile.py" (a mk thing) and simplify to "Makefile".
mk thing) and simplify to "Makefile".[issue #76] Ensure "smarty-pants" extra doesn't destroy image links and links with title text.
[issue #76] Ensure "smarty-pants" extra doesn't destroy image links and links with title text.
[issue #72] Support reading from stdin for command line tool like any well-behaved unix tool, e.g.:
$ echo '*hi*' | markdown2
<p><em>hi</em></p>
Thanks Ryan!
Drop this "1.0.1.*" version silliness. The idea was that the first three numbers tracked the Markdown.pl on which markdown2.py was originally based. I don't believe Markdown.pl really gets releases anymore tho, so pointless.
[Issue 66] Add "wiki-tables" extra for Google Code Wiki-style tables. See .
[Issue 57] Add html5 block tags (article, section, aside, et al; see "_html5tags" variable) to Markdown literal HTML block tag handling. Thanks Tim Gr
[Issue 57] Add html5 block tags (article, section, aside, et al; see "_html5tags" variable) to Markdown literal HTML block tag handling. Thanks Tim Gray!
[Issue 56] Fix setup.py install.
[Issue 54] Fix escaping of link title attributes. Thanks FND!
Tweak list matching to NOT make a ul for something like this:
- - - - - hi there
Before this change this would be a silly 5-deep nested li. See "not_quite_a_list" test case.
[Issue 52] Fix potential pathologically slow matching for <hr> markdown
("slow_hr" test case).
Add a Markdown.postprocess(text) -> text hook that is called near the end
of markdown conversion. By default this does no transformation. It is called
just before unescaping of special characters and unhashing of literal HTML
blocks.
["header-ids" and "toc" extras] Add "n" argument to
Markdown.header_id_from_text hook. This allows a subclass using this hook
to differentiate the header id based on the hN number (e.g. h1 diff that
h2). Also allow a None return value to not add an id to that header (and
exclude that header from the TOC).
Note: If you used this hook, this is an incompatible change to the call signature.
Add a "markdown-in-html" extra similar to (but limited) http://michelf.com/projects/php-markdown/extra/#markdown-attr. I.e. this:
<div markdown="1">
Yo **yo**!
</div>
becomes:
<div>
Yo <strong>yo</strong>!
</div>
[Issue 39] Test case fix for pygments 1.3.1 from thomas.moschny.
[Issue 42] Add "smarty-pants" extra for transforming plain ASCII
punctuation characters into smart typographic punctuation HTML entities.
Inspiration: http://daringfireball.net/projects/smartypants/
Implementation by Nikhil Chelliah. Also add \' and \" escape sequences
for forcing dumb quotes when this extra is in use.
Guard against using True instead of None as follows
markdown(..., extras={'header-ids': True}). None is wanted, but True
is commonly (at least I did it twice) used.
[Issue 36] Fix "cuddled-lists" extra handling for an looks-like-a-cuddled-list-but-is-indented block. See the "test/tm-cases/cuddled_list_indented.tex
[Issue 36] Fix "cuddled-lists" extra handling for an looks-like-a-cuddled-list-but-is-indented block. See the "test/tm-cases/cuddled_list_indented.text" test case.
Experimental new "toc" extra. The returned string from conversion will have
a toc_html attribute.
New "header-ids" extra that will add an id attribute to headers:
# My First Section
will become:
<h1 id="my-first-section">My First Section</h1>
An argument can be give for the extra, which will be used as a prefix for the ids:
$ cat foo.txt
# hi there
$ python markdown2.py foo.txt
<h1>hi there</h1>
$ python markdown2.py foo.txt -x header-ids
<h1 id="hi-there">hi there</h1>
$ python markdown2.py foo.txt -x header-ids=prefix
<h1 id="prefix-hi-there">hi there</h1>
Preliminary support for "html-classes" extra: takes a dict mapping HTML tag to the string value to use for a "class" attribute for that emitted tag. Currently just supports "pre" and "code" for code blocks.
[Issue 33] Implement a "cuddled-lists" extra that allows:
[Issue 33] Implement a "cuddled-lists" extra that allows:
I did these things:
* bullet1
* bullet2
* bullet3
to be converted to:
<p>I did these things:</p>
<ul>
<li>bullet1</li>
<li>bullet2</li>
<li>bullet3</li>
</ul>
[Issue 30] Fix a possible XSS via JavaScript injection in a carefully crafted image reference (usage of double-quotes in the URL).
[Issue 29] Fix security hole in the md5-hashing scheme for handling HTML chunks during processing.
[Issue 24] Set really long sentinel for max-length of link text to avoid problems with reasonably long ones.
[Issue 26] Fix bug where email auto linking wouldn't work for emails with underscores. E.g. Mail me: wouldn't work.
[Issue 26] Fix bug where email auto linking wouldn't work for emails with
underscores. E.g. Mail me: <foo_bar@example.com> wouldn't work.
Update MANIFEST.in to ensure bin/markdown2 gets included in sdist.
[Issue 23] Add support for passing options to pygments for the "code-color" extra. For example:
>>> markdown("...", extras={'code-color': {"noclasses": True}})
This formatter_opts dict is passed to the pygments HtmlCodeFormatter.
Patch from 'svetlyak.40wt'.
[Issue 21] Escape naked '>' characters, as is already done for '&' and '<' characters. Note that other markdown implementations (both Perl and PHP) do not do this. This results in differing output with two 3rd-party tests: "php-markdown-cases/Backslash escapes.text" and "markdowntest-cases/Amps and angle encoding.tags".
"link-patterns" extra: Add support for the href replacement being a callable, e.g.:
>>> link_patterns = [
... (re.compile("PEP\s+(\d+)", re.I),
... lambda m: "http://www.python.org/dev/peps/pep-%04d/" % int(m.group(1))),
... ]
>>> markdown2.markdown("Here is PEP 42.", extras=["link-patterns"],
... link_patterns=link_patterns)
u'<p>Here is <a href="http://www.python.org/dev/peps/pep-0042/">PEP 42</a>.</p>\n'
Fix syntax_color test for the latest Pygments.
sys.argv is defined at top-level code --
e.g. when used at a PostreSQL stored procedure. Fix that.Fix sys.path manipulation in setup.py so easy_install markdown2-*.tar.gz works. (Henry Precheur pointed out the problem.)
easy_install markdown2-*.tar.gz
works. (Henry Precheur pointed out the problem.)<p> -- i.e. treats them as a HTML
block tag.Fix bug in processing text with two HTML comments, where the first comment is cuddled to other content. See "test/tm-cases/two_comments.text". Noted b
License note updates to facilitate Thomas Moschny building a package for Fedora Core Linux. No functional change.
Add a proper setup.py and release to pypi: http://pypi.python.org/pypi/markdown2/
Fix Python 2.6 deprecation warning about the md5 module.
Fix Python 2.6 deprecation warning about the md5 module.
Pass XML processing instructions and one-liner tags. For example:
<?blah ...?>
<xi:include xmlns:xi="..." />
Limitations: they must be on one line. Test: pi_and_xinclude. Suggested by Wolfgang Machert.
Your coding agent can read these notes before it upgrades. Set up the MCP server →