--- title: Release Notes for v2.0 --- Python-Markdown 2.0 Release Notes ================================= We are happy to release Python-Markdown 2.0, which has been over a year in the making. We have rewritten significant portions of the code, dramatically extending the extension API, increased performance, and added numerous extensions to the distribution (including an extension that mimics PHP Markdown Extra), all while maintaining backward compatibility with the end user API in version 1.7. Python-Markdown supports Python versions 2.3, 2.4, 2.5, and 2.6. We have even released a version converted to Python 3.0! Backwards-incompatible Changes ------------------------------ While Python-Markdown has experienced numerous internal changes, those changes should only affect extension authors. If you have not written your own extensions, then you should not need to make any changes to your code. However, you may want to ensure that any third party extensions you are using are compatible with the new API. The new extension API is fully [documented](../extensions/api.md) in the docs. Below is a summary of the significant changes: What's New in Python-Markdown 2.0 --------------------------------- Thanks to the work of Artem Yunusov as part of GSoC 2008, Python-Markdown uses ElementTree internally to build the (X)HTML document from markdown source text. This has resolved various issues with the older home-grown NanoDOM and made notable increases in performance. Artem also refactored the Inline Patterns to better support nested patterns which has resolved many inconsistencies in Python-Markdown's parsing of the markdown syntax. The core parser had been completely rewritten, increasing performance and, for the first time, making it possible to override/add/change the way block level content is parsed. Python-Markdown now parses markdown source text more closely to the other popular implementations (Perl, PHP, etc.) than it ever has before. With the exception of a few minor insignificant differences, any difference should be considered a bug, rather than a limitation of the parser. The option to return HTML4 output as apposed to XHTML has been added. In addition, extensions should be able to easily add additional output formats. As part of implementing markdown in the Dr. Project project (a Trac fork), among other things, David Wolever refactored the "extension" keyword so that it accepts either the extension names as strings or instances of extensions. This makes it possible to include multiple extensions in a single module. Numerous extensions are included in the distribution by default. See [available_extensions](../extensions/index.md) for a complete list. See the [Change Log](index.md) for a full list of changes. --- title: Release Notes for v2.1 --- Python-Markdown 2.1 Release Notes ================================= We are pleased to release Python-Markdown 2.1 which makes many improvements on 2.0. In fact, we consider 2.1 to be what 2.0 should have been. While 2.1 consists mostly of bug fixes, bringing Python-Markdown more inline with other implementations, some internal improvements were made to the parser, a few new built-in extensions were added, and HTML5 support was added. Python-Markdown supports Python versions 2.4, 2.5, 2.6, 2.7, 3.1, and 3.2 out of the box. In fact, the same code base installs on Python 3.1 and 3.2 with no extra work by the end user. Backwards-incompatible Changes ------------------------------ While Python-Markdown has received only minor internal changes since the last release, there are a few backward-incompatible changes to note: What's New in Python-Markdown 2.1 --------------------------------- Three new extensions were added. [Attribute Lists](../extensions/attr_list.md), which was inspired by Maruku's feature of the same name, [Newline to Break](../extensions/nl2br.md), which was inspired by GitHub Flavored Markdown, and Smart Strong, which fills a hole in the Extra extension. HTML5 is now supported. All this really means is that new block level elements introduced in the HTML5 spec are now properly recognized as raw HTML. As valid HTML5 can consist of either HTML4 or XHTML1, there is no need to add a new HTML5 serializers. That said, `html5` and `xhtml5` have been added as aliases of the `html4` and `xhtml1` serializers respectively. An XHTML serializer has been added. Previously, ElementTree's XML serializer was being used for XHTML output. With the new serializer we are able to avoid more invalid output like empty elements (i.e., `

`) which can choke browsers. Improved support for Python 3.x. Now when running `setupy.py install` in Python 3.1 or greater the 2to3 tool is run automatically. Note that Python 3.0 is not supported due to a bug in its 2to3 tool. If you must use Python-Markdown with Python 3.0, it is suggested you manually use Python 3.1's 2to3 tool to do a conversion. Methods on instances of the Markdown class that do not return results can now be changed allowing one to do `md.reset().convert(moretext)`. The Markdown class was refactored so that a subclass could define its own `build_parser` method which would build a completely different parser. In other words, one could use the basic machinery in the markdown library to build a parser of a different markup language without the overhead of building the markdown parser and throwing it away. Import statements within markdown have been improved so that third party libraries can embed the markdown library if they desire (licensing permitting). Added support for Python's `-m` command line option. You can run the markdown package as a command line script. Do `python -m markdown [options] [args]`. Note that this is only fully supported in Python 2.7+. Python 2.5 & 2.6 require you to call the module directly (`markdown.__main__`) rather than the package (`markdown`). This does not work in Python 2.4. The command line script has been renamed to `markdown_py` which avoids all the various problems we had with previous names. Also improved the command line script to accept input on `stdin`. The testing framework has been completely rebuilt using the Nose testing framework. This provides a number of benefits including the ability to better test the built-in extensions and other options available to change the parsing behavior. See the Test Suite documentation for details. Various bug fixes have been made, which are too numerous to list here. See the [commit log](https://github.com/Python-Markdown/markdown/commits/master) for a complete history of the changes. --- title: Release Notes for v2.2 --- Python-Markdown 2.2 Release Notes ================================= We are pleased to release Python-Markdown 2.2 which makes improvements on 2.1. While 2.2 is primarily a bug fix release, some internal improvements were made to the parser, and a few security issues were resolved. Python-Markdown supports Python versions 2.5, 2.6, 2.7, 3.1, and 3.2 out of the box. Backwards-incompatible Changes ------------------------------ While Python-Markdown has received only minor internal changes since the last release, there are a few backward-incompatible changes to note: What's New in Python-Markdown 2.2 --------------------------------- The docs were refactored and can now be found at `http://packages.python.org/Markdown/`. The docs are now maintained in the Repository and are generated by the `setup.py build_docs` command. The [Sane_Lists](../extensions/sane_lists.md) extension was added. The Sane Lists Extension alters the behavior of the Markdown List syntax to be less surprising by not allowing the mixing of list types. In other words, an ordered list will not continue when an unordered list item is encountered and vice versa. Markdown now excepts a full path to an extension module. In other words, your extensions no longer need to be in the primary namespace (and start with `mdx_`) for Markdown to find them. Just do `Markdown(extension=['path.to.some.module'])`. As long as the provided module contains a compatible extension, the extension will be loaded. The BlockParser API was slightly altered to allow `blockprocessor.run` to return `True` or `False` which provides more control to the block processor loop from within any Blockprocessor instance. Various bug fixes have been made. See the [commit log](https://github.com/Python-Markdown/markdown/commits/master) for a complete history of the changes. --- title: Release Notes for v2.3 --- Python-Markdown 2.3 Release Notes ================================= We are pleased to release Python-Markdown 2.3 which adds one new extension, removes a few old (obsolete) extensions, and now runs on both Python 2 and Python 3 without running the 2to3 conversion tool. See the list of changes below for details. Python-Markdown supports Python versions 2.6, 2.7, 3.1, 3.2, and 3.3. Backwards-incompatible Changes ------------------------------ [CodeHilite Extension]: ../extensions/code_hilite.md [PyTidyLib]: http://countergram.github.io/pytidylib/ What's New in Python-Markdown 2.3 --------------------------------- [Admonition Extension]: ../extensions/admonition.md [rST]: http://docutils.sourceforge.net/docs/ref/rst/directives.html#specific- admonitions --- title: Release Notes for v2.4 --- Python-Markdown 2.4 Release Notes ================================= We are pleased to release Python-Markdown 2.4 which adds one new extension and fixes various bugs. See the list of changes below for details. Python-Markdown supports Python versions 2.6, 2.7, 3.1, 3.2, and 3.3. Backwards-incompatible Changes ------------------------------ [CodeHilite Extension]: ../extensions/code_hilite.md What's New in Python-Markdown 2.4 --------------------------------- [Dmitry Shachnev]: https://github.com/mitya57 [Smarty Extension]: ../extensions/smarty.md [SmartyPants]: https://daringfireball.net/projects/smartypants/ [Table of Contents Extension]: ../extensions/toc.md [Sphinx]: http://sphinx-doc.org/ [Markdown Inside HTML Blocks]: ../extensions/md_in_html.md [ryneeverett]: https://github.com/ryneeverett ```.python hl_lines="1 3" # This line will be emphasized. # This one won't. # This one will be also emphasized. ``` Thanks to [A. Jesse Jiryu Davis] for implementing this feature. [Fenced Code Extension]: ../extensions/fenced_code_blocks.md [A. Jesse Jiryu Davis]: https://github.com/ajdavis --- title: Release Notes for v2.5 --- Python-Markdown 2.5 Release Notes ================================= We are pleased to release Python-Markdown 2.5 which adds a few new features and fixes various bugs. See the list of changes below for details. Python-Markdown version 2.5 supports Python versions 2.7, 3.2, 3.3, and 3.4. Backwards-incompatible Changes ------------------------------ [CodeHilite Extension]: ../extensions/code_hilite.md [linenums]: ../extensions/code_hilite.md#usage If your code previously looked like this: html = markdown.markdown(text, same_mode=True) Then it is recommended that you change your code to read something like this: import bleach html = bleach.clean(markdown.markdown(text)) If you are not interested in sanitizing untrusted text, but simply desire to escape raw HTML, then that can be accomplished through an extension which removes HTML parsing: from markdown.extensions import Extension class EscapeHtml(Extension): def extendMarkdown(self, md, md_globals): del md.preprocessors['html_block'] del md.inlinePatterns['html'] html = markdown.markdown(text, extensions=[EscapeHtml()]) As the HTML would not be parsed with the above Extension, then the serializer will escape the raw HTML, which is exactly what happens now when `safe_mode="escape"`. [Bleach]: https://bleach.readthedocs.io/ html = markdown.markdown(text, ['extra']) Then it is recommended that you change it to read something like this: html = markdown.markdown(text, extensions=['extra']) !!! Note This change is being made as a result of deprecating `"safe_mode"` as the `safe_mode` argument was one of the positional arguments. When that argument is removed, the two arguments following it will no longer be at the correct position. It is recommended that you always use keywords when they are supported for this reason. markdown.markdown(text, extensions=['extra']) You should change your code to the following: markdown.markdown(text, extensions=['markdown.extensions.extra']) The same applies to the command line: $ python -m markdown -x markdown.extensions.extra input.txt See the [documentation](../library.md#extensions) for a full explanation of the current behavior. What's New in Python-Markdown 2.5 --------------------------------- [Smarty Extension]: ../extensions/smarty.md [Martin Altmayer]:https://github.com/MartinAltmayer Additionally, a Class may be specified in the name. The class must be at the end of the name (which uses dot notation from PYTHONPATH) and be separated by a colon from the module. Therefore, if you were to import the class like this: from path.to.module import SomeExtensionClass Then the named extension would comprise this string: "path.to.module:SomeExtensionClass" This allows multiple extensions to be implemented within the same module and still accessible when the user is not able to import the extension directly (perhaps from a template filter or the command line). This also means that extension modules are no longer required to include the `makeExtension` function which returns an instance of the extension class. However, if the user does not specify the class name (she only provides `"path.to.module"`) the extension will fail to load without the `makeExtension` function included in the module. Extension authors will want to document carefully what is required to load their extensions. [ex]: ../library.md#extensions Extension authors are encouraged to review the new methods available on the `markdown.extnesions.Extension` class for handling configuration and adjust their code going forward. The included extensions provide a model for best practices. See the [API] documentation for a full explanation. [ec]: ../library.md#extension_configs [API]: ../extensions/api.md#configsettings [cli]: ../cli.md#using-extensions [YAML]: https://yaml.org/ [JSON]: https://json.org/ [PyYAML]: https://pyyaml.org/ [ae]: ../extensions/admonition.md --- title: Release Notes for v2.6 --- # Python-Markdown 2.6 Release Notes We are pleased to release Python-Markdown 2.6 which adds a few new features and fixes various bugs. See the list of changes below for details. Python-Markdown version 2.6 supports Python versions 2.7, 3.2, 3.3, and 3.4 as well as PyPy. ## Backwards-incompatible Changes ### `safe_mode` Deprecated Both `safe_mode` and the associated `html_replacement_text` keywords are deprecated in version 2.6 and will raise a **`DeprecationWarning`**. The `safe_mode` and `html_replacement_text` keywords will be ignored in the next release. The so-called "safe mode" was never actually "safe" which has resulted in many people having a false sense of security when using it. As an alternative, the developers of Python-Markdown recommend that any untrusted content be passed through an HTML sanitizer (like [Bleach]) after being converted to HTML by markdown. In fact, [Bleach Whitelist] provides a curated list of tags, attributes, and styles suitable for filtering user-provided HTML using bleach. If your code previously looked like this: ```python html = markdown.markdown(text, safe_mode=True) ``` Then it is recommended that you change your code to read something like this: ```python import bleach from bleach_whitelist import markdown_tags, markdown_attrs html = bleach.clean(markdown.markdown(text), markdown_tags, markdown_attrs) ``` If you are not interested in sanitizing untrusted text, but simply desire to escape raw HTML, then that can be accomplished through an extension which removes HTML parsing: ```python from markdown.extensions import Extension class EscapeHtml(Extension): def extendMarkdown(self, md, md_globals): del md.preprocessors['html_block'] del md.inlinePatterns['html'] html = markdown.markdown(text, extensions=[EscapeHtml()]) ``` As the HTML would not be parsed with the above Extension, then the serializer will escape the raw HTML, which is exactly what happens now when `safe_mode="escape"`. [Bleach]: https://bleach.readthedocs.io/ [Bleach Whitelist]: https://github.com/yourcelf/bleach-whitelist ### Positional Arguments Deprecated Positional arguments on the `markdown.Markdown()` class are deprecated as are all except the `text` argument on the `markdown.markdown()` wrapper function. Using positional arguments will raise a **`DeprecationWarning`** in 2.6 and an error in the next release. Only keyword arguments should be used. For example, if your code previously looked like this: ```python html = markdown.markdown(text, [SomeExtension()]) ``` Then it is recommended that you change it to read something like this: ```python html = markdown.markdown(text, extensions=[SomeExtension()]) ``` !!! Note This change is being made as a result of deprecating `"safe_mode"` as the `safe_mode` argument was one of the positional arguments. When that argument is removed, the two arguments following it will no longer be at the correct position. It is recommended that you always use keywords when they are supported for this reason. ### "Shortened" Extension Names Deprecated In previous versions of Python-Markdown, the built-in extensions received special status and did not require the full path to be provided. Additionally, third party extensions whose name started with `"mdx_"` received the same special treatment. This behavior is deprecated and will raise a **`DeprecationWarning`** in version 2.6 and an error in the next release. Ensure that you always use the full path to your extensions. For example, if you previously did the following: ```python markdown.markdown(text, extensions=['extra']) ``` You should change your code to the following: ```python markdown.markdown(text, extensions=['markdown.extensions.extra']) ``` The same applies to the command line: ```python python -m markdown -x markdown.extensions.extra input.txt ``` Similarly, if you have used a third party extension (for example `mdx_math`), previously you might have called it like this: ```python markdown.markdown(text, extensions=['math']) ``` As the `"mdx"` prefix will no longer be appended, you will need to change your code as follows (assuming the file `mdx_math.py` is installed at the root of your PYTHONPATH): ```python markdown.markdown(text, extensions=['mdx_math']) ``` Extension authors will want to update their documentation to reflect the new behavior. See the [documentation](../library.md#extensions) for a full explanation of the current behavior. ### Extension Configuration as Part of Extension Name Deprecated The previously documented method of appending the extension configuration options as a string to the extension name is deprecated and will raise a **`DeprecationWarning`** in version 2.6 and an error in 2.7. The [`extension_configs`](../library.md#extension_configs) keyword should be used instead. See the [documentation](../library.md#extension_configs) for a full explanation of the current behavior. ### HeaderId Extension Pending Deprecation The HeaderId Extension is pending deprecation and will raise a **`PendingDeprecationWarning`** in version 2.6. The extension will be deprecated in the next release and raise an error in the release after that. Use the [Table of Contents][TOC] Extension instead, which offers most of the features of the HeaderId Extension and more (support for meta data is missing). Extension authors who have been using the `slugify` and `unique` functions defined in the HeaderId Extension should note that those functions are now defined in the Table of Contents extension and should adjust their import statements accordingly (`from markdown.extensions.toc import slugify, unique`). ### The `configs` Keyword is Deprecated Positional arguments and the `configs` keyword on the `markdown.extension.Extension` class (and its subclasses) are deprecated. Each individual configuration option should be passed to the class as a keyword/value pair. For example. one might have previously initiated an extension subclass like this: ```python ext = SomeExtension(configs={'somekey': 'somevalue'}) ``` That code should be updated to pass in the options directly: ```python ext = SomeExtension(somekey='somevalue') ``` Extension authors will want to note that this affects the `makeExtension` function as well. Previously it was common for the function to be defined as follows: ```python def makeExtension(configs=None): return SomeExtension(configs=configs) ``` Extension authors will want to update their code to the following instead: ```python def makeExtension(**kwargs): return SomeExtension(**kwargs) ``` Failing to do so will result in a **`DeprecationWarning`** and will raise an error in the next release. See the [Extension API][mext] documentation for more information. In the event that an `markdown.extension.Extension` subclass overrides the `__init__` method and implements its own configuration handling, then the above may not apply. However, it is recommended that the subclass still calls the parent `__init__` method to handle configuration options like so: ```python class SomeExtension(markdown.extension.Extension): def __init__(**kwargs): # Do pre-config stuff here # Set config defaults self.config = { 'option1' : ['value1', 'description1'], 'option2' : ['value2', 'description2'] } # Set user defined configs super(MyExtension, self).__init__(**kwargs) # Do post-config stuff here ``` Note the call to `super` to get the benefits of configuration handling from the parent class. See the [documentation][config] for more information. [config]: ../extensions/api.md#configsettings [mext]: ../extensions/api.md#dot_notation ## What's New in Python-Markdown 2.6 ### Official Support for PyPy Official support for [PyPy] has been added. While Python-Markdown has most likely worked on PyPy for some time, it is now officially supported and tested on PyPy. [PyPy]: https://pypy.org/ ### YAML Style Meta-Data The [Meta-Data] Extension now includes optional support for [YAML] style meta-data. By default, the YAML deliminators are recognized, however, the actual data is parsed as previously. This follows the syntax of [MultiMarkdown], which inspired this extension. Alternatively, if the `yaml` option is set, then the data is parsed as YAML. As the `yaml` option was buggy, it was removed in 2.6.1. It is suggested that a preprocessor (like [docdata]) or a third party extension be used if you want true YAML support. See [Issue #390][#390] for a full explanation. [MultiMarkdown]: https://fletcherpenney.net/multimarkdown/#metadata [Meta-Data]: ../extensions/meta_data.md [YAML]: https://yaml.org/ [#390]: [docdata]: https://github.com/waylan/docdata ### Table of Contents Extension Refactored The [Table of Contents][TOC] Extension has been refactored and some new features have been added. See the documentation for a full explanation of each feature listed below: [TOC]: ../extensions/toc.md ### Pygments can now be disabled The [CodeHilite][ch] Extension has gained a new configuration option: `use_pygments`. The option is `True` by default, however, it allows one to turn off Pygments code highlighting (set to `False`) while preserving the language detection features of the extension. Note that Pygments language guessing is not used as that would 'use Pygments'. If a language is defined for a code block, it will be assigned to the `` tag as a class in the manner suggested by the [HTML5 spec][spec] (alternate output will not be entertained) and could potentially be used by a JavaScript library in the browser to highlight the code block. [ch]: ../extensions/code_hilite.md [spec]: https://www.w3.org/TR/html5/text-level-semantics.html#the-code-element ### Miscellaneous Test coverage has been improved including running [flake8]. While those changes will not directly effect end users, the code is being better tested which will benefit everyone. [flake8]: https://flake8.readthedocs.io/en/latest/ Various bug fixes have been made. See the [commit log](https://github.com/Python-Markdown/markdown/commits/master) for a complete history of the changes.