NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #2912 most downloaded on PyPI
A fast, extensible Markdown parser in pure Python.
Last release 2 months ago
11 Jul 2026
Release timing varies
gaps range from 2 months to 2.5 years
Nearly every release is documented
notes for 32 of 33 stable releases
Nothing withdrawn
no release was ever pulled
9 years old
33 releases · first in 2017
Incorrect escaping of $ and other reserved chars in links ( #248 ).
$ and other reserved chars in links (#248).<http://example.com/@user/1234> being rendered as <a href="mailto:...">...</a> (#260).HtmlRenderer: Escape characters in image src.MarkdownRenderer: Fix type annotations (#265, #267).JiraRenderer: Escape pipes in table cells (#270).MarkdownRenderer: Escape pipes in table cells (#274).MarkdownRenderer: Preserve line break before/after HTML span during word-wrap (#275).GithubWiki: Reduce backtracking in wiki links (#276).remove_token() against duplicate removal (#281).HtmlRenderer: Escape mailto autolink hrefs (#283).Full Changelog: v1.5.1...v1.6.0
Special thanks to @nijel as the most active contributor in this release!
One column per quarter.
Parsing slow when there are many table-like lines on input ( #254 ).
LaTeXRenderer : Render thematic break on a new line ( #224 ).
Add parent attribute/property ( #71 via #206 ).
Add parent attribute/property (#71 via #206).
COMPATIBILITY REMARKS:
children attribute changed to property, existing code needs to be changed like this:
-hasattr(token, 'children')
+token.children is not None
# ...
-'children' in vars(token)
+token.children is not None
# ...
-getattr(token, 'children', [])
+token.children or []Add line numbers ( line_number attribute) on all block tokens during parsing ( #188 ).
line_number attribute) on all block tokens during parsing (#188).HtmlRenderer: Option to skip HTML tokens parsing (#74 via #204). Just pass process_html_tokens=False to the renderer's constructor.LaTeXRenderer: Add AMS packages for Math (#207).MarkdownRenderer: Penultimate lines of multiline fragments being ignored (#201).MathJaxRenderer: Output inline math (in: $...$) correctly (out: \(...\)) (#195).MarkdownRenderer: Keep the original content spacing after the list marker (#196 via #197).
COMPATIBILITY REMARKS:
normalize_whitespace=True to the renderer's constructor (#202).ListItem's tokens directly via its constructor, you need to pass it a new parameter called indentation (number of spaces before the item marker):
-def __init__(self, parse_buffer, prepend, leader):
+def __init__(self, parse_buffer, indentation, prepend, leader):For contributors:
In v1.2.0, due to #182 , using HTMLRenderer (the old class name) directly from the mistletoe package stopped working.
HTMLRenderer (the old class name) directly from the mistletoe package stopped working.FileWrapper 's methods anchor/reset are DEPRECATED, use a more versatile get_pos/set_pos approach instead ( #186 ).
FileWrapper's methods anchor/reset are DEPRECATED, use a more versatile get_pos/set_pos approach instead (#186).LaTeXRenderer: Escape special characters in URLs of generated links (#114 via #190).mistletoe.block_token.Table.interrupt_paragraph to false if you need the old behavior.PygmentsRenderer no longer throws a ClassNotFound error if there is a code language specified which is not supported by the Pygments highlighter (#183). If you still need to get the error, simply pass fail_on_unsupported_language=True to the renderer's constructor.HTMLRenderer are marked as deprecated.For contributors:
assertEqual() calls in all the tests (#185).Scheme renderer's __main__ section turned into a proper unit test (#189).check_interrupts_paragraph(cls, lines) -> bool method.MarkdownRenderer - the long awaited renderer for outputting parsed AST back to the Markdown syntax ( #4 , #162 ). 🎉 For this, parsing was extended to
MarkdownRenderer - the long awaited renderer for outputting parsed AST back to the Markdown syntax (#4, #162). 🎉HTMLRenderer should escape double and/or single quotes (#176).Token.__repr__() no longer outputs class attributes (#172).Scheme (scheme.py) work again (7883f58).HTMLRenderer not escaping single quotes by default (#176).ASTRenderer no longer outputs all token attributes, but only those listed in Token.repr_attributes (#172).Special thanks go to @anderskaplan as the most active contributor of this release. 💪
Do include package "mistletoe.contrib" in the built artifacts ( #177 ).
Fixed:
Updated:
WARNING - Backwards compatibility changes:
WARNING - Backwards compatibility changes:
contrib folder got moved under the mistletoe folder / package. So if you reference a renderer from that folder, you need to reference it as mistletoe.contrib.<renderer> now.' '.join(re.split('[ \n]+', content.strip())), or re.sub('[ \n]+', ' ', content.strip())).Added:
JIRARenderer: Support link title notation, i.e. [label](url "title") gets transformed to [label|url|title] (#161)Fixed:
traverse() function actually work with various input parameters:
Footnotes) more strict - spec compliant (#132)Updated:
WARNING - Backwards compatibility changes:
WARNING - Backwards compatibility changes:
html module (available since Python 3.4) is no longer includedHTMLRenderer: single quote is no longer rendered as ', but as ' (see #115; let us know if you would need the old behavior)BaseRenderer.__getattr__() is removed and replaced by explicit render_*() methods definitions for clearer API (#133)Added:
__repr__() methods to all token classes (#140)Fixed:
LaTeXRenderer - refactored globally (#135)| (#149)pytest (#142)Others:
Failure to parse paragraph containing just "[" (#130) (a side-effect of the fix of #124 in v0.8.1)
Fixed:
Others:
Documentation (#122 - covering #56, #99 and some other basic topics)
Added:
Fixed:
Testing:
Fixed incorrect handling of loose list (#54, #65, thanks @Rogdham and @Vallentin)
Fixed:
FileWrapper backstep after StopIteration (#58, thanks @Rogdham)Testing:
only matching the first instance of InlineCode (#50, thanks @huettenhain);
Fixed:
InlineCode (#50, thanks @huettenhain);Performance:
ParseToken.append_child.Warning: this is a release that breaks backwards compatibility in non-trivial ways (hopefully for the last time!) Read the full release notes if you a
Warning: this is a release that breaks backwards compatibility in non-trivial ways (hopefully for the last time!) Read the full release notes if you are updating from a previous version.
Features:
span_tokenizer.tokenize.Fixed:
ASTRenderer crashes on tables with headers (#48, thanks @timfox456!)Where I break backwards compatibility:
Previously span-level tokens need to have their children attribute manually specified. This is no longer the case, as the children attribute will automatically be set based on the class variable parse_group, which correspond to the regex match group in which child tokens might occur.
As an example, previously GithubWiki is implemented as this:
from mistletoe.span_token import SpanToken, tokenize_inner
import re
class GithubWiki(SpanToken):
pattern = re.compile(r'...')
def __init__(self, match_obj):
super().__init__(match_obj)
# alternatively, self.children = tokenize_inner(match_obj.group(1))
self.target = match_obj.group(2)
Now we can write:
from mistletoe.span_token import SpanToken
import re
class GithubWiki(SpanToken):
pattern = re.compile(r'...')
parse_inner = True # default value, can be omitted
parse_group = 1 # default value, can be omitted
precedence = 5 # default value, can be omitted
def __init__(self, match_obj):
self.target = match_obj.group(2)
If we have a span token that does not need further parsing, we can write:
class Foo(SpanToken):
pattern = re.compile(r'(foo)')
parse_inner = False
def __init__(self, match_obj):
self.content = match_obj.group(1)
See the readme for more details.
removed _children attribute, using children directly; (potentially breaking change?)
Features:
CodeFence;BlockCode;HTMLBlock;HTMLSpan;AutoLink;InlineCode;Heading;SetextHeading;LineBreak;Quote;Footnotes can be defined in any block-level containers.Fixes:
FileWrapper._index should not go below -1.Development:
SetextHeading;block_tokenizer.MismatchException;_children attribute, using children directly; (potentially breaking change?)Separator to ThematicBreak;FootnoteBlock to Footnote;tokenize and tokenize_inner returns lists of tokens;CommonMark compliant CodeFence (#41);
Features:
CodeFence (#41);InlineCode;InlineCode;Fixed:
Separator needs at least three characters;Paragraph.read (#43, thanks @NatTupper);block_token.until function;language-".added Pygments renderer to contrib (#35, thanks to @Bridouz);
Features:
contrib (#35, thanks to @Bridouz);HTMLSpan now supports comments (#37);Fixes:
Performance:
FileWrapper.normalize;Breaking changes:
BlockToken.start does not advance file iterator.Special shout-out to @joncass for raising the unattributed issues above, and giving me the motivation to finally fix the list implementation!
Note that this is a release with major changes. If you notice any rough edges (as there will certainly be), please do not hesitate to open an issue.
added default render methods for all tokens;
Features:
reset_tokens function to block_token and span_token;BlockToken.read to return any iterable;Fixes:
AttributeError when accessing RawText.children (#31, thanks @jabdoa2);span_token.Link (#32, thanks @DMRobertson);Image and FootnoteImage (#33, thanks @joncass).md2jira: read from stdin if no input file is given (#27, thanks @alexkolson!);
Features:
mistletoe.markdown is given a string;Fixes:
... plus various refactors and documentation improvements.
shortened mistletoe.markdown keyword argument name (renderer_cls to renderer);
Features:
mistletoe.markdown keyword argument name (renderer_cls to renderer);Fixed:
CodeFence (#24);Development:
docs directory;contrib/md2jira.py was importing from the wrong directory (#20, thanks to @cctile);
Fixed:
contrib/md2jira.py was importing from the wrong directory (#20, thanks to @cctile);lstlisting environment should not be escaped (#23, thanks to @liuq).added JIRA Markdown support (thanks to @cctile);
Features:
Strong / Emphasis elements must open with non-whitespace characters;Heading;Fixed:
render_table crashing when iterating token.children (#12);FootnoteLink engulfing trailing spaces (#14);Paragraph.read not stopping before CodeFence (#15);Development:
plugins directory into contrib (thanks to @huettenhain);Lastly, I miss cheeseburgers. 🍔
BlockToken is a hell lot more flexible now;
Features:
BlockToken is a hell lot more flexible now;add_token accepts an additional position argument;Paragraph tokens.Fixed:
ASTRenderer fails to serialize FootnoteAnchor.Where I broke backwards compatibility:
BlockToken now has start and read methods, instead of match method. This allows for much more granular control of parsing when defining custom block-level tokens.Heading and SetextHeading are now different token classes, though their renderer functions are still the same.CodeFence and BlockCode are now different token classes, though their renderer functions are still the same.What has been in my life for the past few weeks:
❄️
added support for empty or self-closing HTMLSpan;
Features:
--renderer flag for command line usage;token.children now has idempotent behavior!Development:
Merry Christmas! 🎄
removed argument footnotes from render functions;
Features:
footnotes from render functions;Development:
Now for a beer emoji: 🍺
auto-closes unclosed code fences;
Features:
Fixed:
render_image function missing argument;span-level token constructors now accept match objects;
Features:
Development:
added table-of-contents plugin;
Features:
Fixed:
Relicensed under MIT.
added support for footnote-style images and links;
Features:
Development:
Fixed:
This release is mainly to celebrate that I shaved. Other than that:
This release is mainly to celebrate that I shaved. Other than that:
Block-level token support:
Span-level token support:
Output format support:
Lastly, hello world!
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →