Hello community, here is the log from the commit of package python3-mistune for openSUSE:Factory checked in at 2015-07-19 11:45:51 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python3-mistune (Old) and /work/SRC/openSUSE:Factory/.python3-mistune.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python3-mistune" Changes: -------- --- /work/SRC/openSUSE:Factory/python3-mistune/python3-mistune.changes 2015-06-23 11:57:47.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.python3-mistune.new/python3-mistune.changes 2015-07-19 11:45:52.000000000 +0200 @@ -1,0 +2,9 @@ +Sat Jul 18 23:48:03 UTC 2015 - a...@gmx.de + +- update to version 0.7: + * Fix the breaking change in version 0.6 with options: + parse_inline_html and parse_block_html + * Breaking change: remove parse_html option for explicit + * Change option escape default value to True for security reason + +------------------------------------------------------------------- Old: ---- mistune-0.6.tar.gz New: ---- mistune-0.7.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python3-mistune.spec ++++++ --- /var/tmp/diff_new_pack.xP1pDn/_old 2015-07-19 11:45:53.000000000 +0200 +++ /var/tmp/diff_new_pack.xP1pDn/_new 2015-07-19 11:45:53.000000000 +0200 @@ -17,7 +17,7 @@ Name: python3-mistune -Version: 0.6 +Version: 0.7 Release: 0 Summary: The fastest markdown parser in pure Python License: BSD-3-Clause ++++++ mistune-0.6.tar.gz -> mistune-0.7.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-0.6/CHANGES.rst new/mistune-0.7/CHANGES.rst --- old/mistune-0.6/CHANGES.rst 2015-06-17 08:15:43.000000000 +0200 +++ new/mistune-0.7/CHANGES.rst 2015-07-18 14:35:33.000000000 +0200 @@ -3,6 +3,16 @@ Here is the full history of mistune. +Version 0.7 +~~~~~~~~~~~ + +Released on Jul. 18, 2015 + +* Fix the breaking change in version 0.6 with options: **parse_inline_html** and **parse_block_html** +* Breaking change: remove **parse_html** option for explicit +* Change option **escape** default value to ``True`` for security reason + + Version 0.6 ~~~~~~~~~~~ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-0.6/PKG-INFO new/mistune-0.7/PKG-INFO --- old/mistune-0.6/PKG-INFO 2015-06-17 08:27:36.000000000 +0200 +++ new/mistune-0.7/PKG-INFO 2015-07-18 15:20:19.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: mistune -Version: 0.6 +Version: 0.7 Summary: The fastest markdown parser in pure Python Home-page: https://github.com/lepture/mistune Author: Hsiaoming Yang @@ -9,7 +9,8 @@ Description: Mistune ======= - The fastest markdown parser in pure Python, inspired by marked_. + The fastest markdown parser in pure Python with renderer features, + inspired by marked_. .. image:: https://img.shields.io/pypi/wheel/mistune.svg?style=flat :target: https://pypi.python.org/pypi/mistune/ @@ -46,12 +47,6 @@ $ pip install mistune - If pip is not available, try easy_install:: - - $ easy_install mistune - - Cython Feature - ~~~~~~~~~~~~~~ Mistune can be faster, if you compile with cython:: @@ -67,10 +62,48 @@ import mistune - mistune.markdown('I am using **markdown**') - # output: <p>I am using <strong>markdown</strong></p> + mistune.markdown('I am using **mistune markdown parser**') + # output: <p>I am using <strong>mistune markdown parser</strong></p> + + If you care about performance, it is better to re-use the Markdown instance: + + .. code:: python + + import mistune + + markdown = mistune.Markdown() + markdown('I am using **mistune markdown parser**') + + Mistune has enabled all features by default. You don't have to configure + anything. But there are options for you to change the parser behaviors. + + + Options + ------- + + Here is a list of all options that will affect the rendering results, + configure them with ``mistune.Renderer``: + + .. code:: python + + renderer = mistune.Renderer(escape=True, hard_wrap=True) + # use this renderer instance + markdown = mistune.Markdown(renderer=renderer) + markdown(text) + + * **escape**: if set to *False*, all raw html tags will not be escaped. + * **hard_wrap**: if set to *True*, it will has GFM line breaks feature. + * **use_xhtml**: if set to *True*, all tags will be in xhtml, for example: ``<hr />``. + * **parse_block_html**: parse text only in block level html. + * **parse_inline_html**: parse text only in inline level html. + + When using the default renderer, you can use one of the following shortcuts:: + + mistune.markdown(text, escape=True, hard_wrap=True) + + markdown = mistune.Markdown(escape=True, hard_wrap=True) + markdown(text) - Mistune has all features by default. You don't have to configure anything. Renderer -------- @@ -87,7 +120,7 @@ from pygments.lexers import get_lexer_by_name from pygments.formatters import HtmlFormatter - class MyRenderer(mistune.Renderer): + class HighlightRenderer(mistune.Renderer): def block_code(self, code, lang): if not lang: return '\n<pre><code>%s</code></pre>\n' % \ @@ -96,10 +129,11 @@ formatter = HtmlFormatter() return highlight(code, lexer, formatter) - renderer = MyRenderer() - md = mistune.Markdown(renderer=renderer) - print(md.render('Some Markdown text.')) + renderer = HighlightRenderer() + markdown = mistune.Markdown(renderer=renderer) + print(markdown('```python\nassert 1 == 1\n```')) + Find more renderers in `mistune-contrib`_. Block Level ~~~~~~~~~~~ @@ -135,34 +169,18 @@ linebreak() newline() link(link, title, content) - tag(html) strikethrough(text) text(text) + inline_html(text) + Footnotes + ~~~~~~~~~ - Options - ------- - - Here is a list of all options that will affect the rendering results: - - .. code:: python - - renderer = mistune.Renderer(escape=True) - md = mistune.Markdown(renderer=renderer) - md.render(text) - - * **escape**: if set to *True*, all raw html tags will be escaped. - * **hard_wrap**: if set to *True*, it will has GFM line breaks feature. - * **use_xhtml**: if set to *True*, all tags will be in xhtml, for example: ``<hr />``. - * **parse_html**: parse text in block level html. - - When using the default renderer, you can use one of the following shorthands:: - - mistune.markdown(text, escape=True) - - md = mistune.Markdown(escape=True) - md.render(text) + Here is a list of renderers related to footnotes:: + footnote_ref(key, index) + footnote_item(key, text) + footnotes(text) Lexers ------ @@ -180,33 +198,23 @@ import copy from mistune import Renderer, InlineGrammar, InlineLexer - class MyRenderer(Renderer): + class WikiLinkRenderer(Renderer): def wiki_link(self, alt, link): return '<a href="%s">%s</a>' % (link, alt) - - class MyInlineGrammar(InlineGrammar): - # it would take a while for creating the right regex - wiki_link = re.compile( - r'\[\[' # [[ - r'([\s\S]+?\|[\s\S]+?)' # Page 2|Page 2 - r'\]\](?!\])' # ]] - ) - - - class MyInlineLexer(InlineLexer): - default_rules = copy.copy(InlineLexer.default_rules) - - # Add wiki_link parser to default rules - # you can insert it any place you like - default_rules.insert(3, 'wiki_link') - - def __init__(self, renderer, rules=None, **kwargs): - if rules is None: - # use the inline grammar - rules = MyInlineGrammar() - - super(MyInlineLexer, self).__init__(renderer, rules, **kwargs) + class WikiLinkInlineLexer(InlineLexer): + def enable_wiki_link(self): + # add wiki_link rules + self.rules.wiki_link = re.compile( + r'\[\[' # [[ + r'([\s\S]+?\|[\s\S]+?)' # Page 2|Page 2 + r'\]\](?!\])' # ]] + ) + + # Add wiki_link parser to default rules + # you can insert it some place you like + # but place matters, maybe 3 is not good + self.default_rules.insert(3, 'wiki_link') def output_wiki_link(self, m): text = m.group(1) @@ -219,8 +227,10 @@ .. code:: python - renderer = MyRenderer() - inline = MyInlineLexer(renderer) + renderer = WikiLinkRenderer() + inline = WikiLinkInlineLexer(renderer) + # enable the feature + inline.enable_wiki_link() markdown = Markdown(renderer, inline=inline) markdown('[[Link Text|Wiki Link]]') @@ -228,14 +238,23 @@ the whole mechanism. But you won't do the trick a lot. - Contribution - ------------ + Contribution & Extensions + ------------------------- Mistune itself doesn't accept any extension. It will always be a simple one file script. If you want to add features, you can head over to `mistune-contrib`_. + Here are some extensions already in `mistune-contrib`_: + + * Math/MathJax features + * Highlight Code Renderer + * TOC table of content features + * MultiMarkdown Metadata parser + + Get inspired with the contrib repository. + .. _`mistune-contrib`: https://github.com/lepture/mistune-contrib Platform: any diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-0.6/README.rst new/mistune-0.7/README.rst --- old/mistune-0.6/README.rst 2015-06-11 16:01:16.000000000 +0200 +++ new/mistune-0.7/README.rst 2015-07-18 14:41:33.000000000 +0200 @@ -1,7 +1,8 @@ Mistune ======= -The fastest markdown parser in pure Python, inspired by marked_. +The fastest markdown parser in pure Python with renderer features, +inspired by marked_. .. image:: https://img.shields.io/pypi/wheel/mistune.svg?style=flat :target: https://pypi.python.org/pypi/mistune/ @@ -38,12 +39,6 @@ $ pip install mistune -If pip is not available, try easy_install:: - - $ easy_install mistune - -Cython Feature -~~~~~~~~~~~~~~ Mistune can be faster, if you compile with cython:: @@ -59,10 +54,48 @@ import mistune - mistune.markdown('I am using **markdown**') - # output: <p>I am using <strong>markdown</strong></p> + mistune.markdown('I am using **mistune markdown parser**') + # output: <p>I am using <strong>mistune markdown parser</strong></p> + +If you care about performance, it is better to re-use the Markdown instance: + +.. code:: python + + import mistune + + markdown = mistune.Markdown() + markdown('I am using **mistune markdown parser**') + +Mistune has enabled all features by default. You don't have to configure +anything. But there are options for you to change the parser behaviors. + + +Options +------- + +Here is a list of all options that will affect the rendering results, +configure them with ``mistune.Renderer``: + +.. code:: python + + renderer = mistune.Renderer(escape=True, hard_wrap=True) + # use this renderer instance + markdown = mistune.Markdown(renderer=renderer) + markdown(text) + +* **escape**: if set to *False*, all raw html tags will not be escaped. +* **hard_wrap**: if set to *True*, it will has GFM line breaks feature. +* **use_xhtml**: if set to *True*, all tags will be in xhtml, for example: ``<hr />``. +* **parse_block_html**: parse text only in block level html. +* **parse_inline_html**: parse text only in inline level html. + +When using the default renderer, you can use one of the following shortcuts:: + + mistune.markdown(text, escape=True, hard_wrap=True) + + markdown = mistune.Markdown(escape=True, hard_wrap=True) + markdown(text) -Mistune has all features by default. You don't have to configure anything. Renderer -------- @@ -79,7 +112,7 @@ from pygments.lexers import get_lexer_by_name from pygments.formatters import HtmlFormatter - class MyRenderer(mistune.Renderer): + class HighlightRenderer(mistune.Renderer): def block_code(self, code, lang): if not lang: return '\n<pre><code>%s</code></pre>\n' % \ @@ -88,10 +121,11 @@ formatter = HtmlFormatter() return highlight(code, lexer, formatter) - renderer = MyRenderer() - md = mistune.Markdown(renderer=renderer) - print(md.render('Some Markdown text.')) + renderer = HighlightRenderer() + markdown = mistune.Markdown(renderer=renderer) + print(markdown('```python\nassert 1 == 1\n```')) +Find more renderers in `mistune-contrib`_. Block Level ~~~~~~~~~~~ @@ -127,34 +161,18 @@ linebreak() newline() link(link, title, content) - tag(html) strikethrough(text) text(text) + inline_html(text) +Footnotes +~~~~~~~~~ -Options -------- - -Here is a list of all options that will affect the rendering results: - -.. code:: python - - renderer = mistune.Renderer(escape=True) - md = mistune.Markdown(renderer=renderer) - md.render(text) - -* **escape**: if set to *True*, all raw html tags will be escaped. -* **hard_wrap**: if set to *True*, it will has GFM line breaks feature. -* **use_xhtml**: if set to *True*, all tags will be in xhtml, for example: ``<hr />``. -* **parse_html**: parse text in block level html. - -When using the default renderer, you can use one of the following shorthands:: - - mistune.markdown(text, escape=True) - - md = mistune.Markdown(escape=True) - md.render(text) +Here is a list of renderers related to footnotes:: + footnote_ref(key, index) + footnote_item(key, text) + footnotes(text) Lexers ------ @@ -172,33 +190,23 @@ import copy from mistune import Renderer, InlineGrammar, InlineLexer - class MyRenderer(Renderer): + class WikiLinkRenderer(Renderer): def wiki_link(self, alt, link): return '<a href="%s">%s</a>' % (link, alt) - - class MyInlineGrammar(InlineGrammar): - # it would take a while for creating the right regex - wiki_link = re.compile( - r'\[\[' # [[ - r'([\s\S]+?\|[\s\S]+?)' # Page 2|Page 2 - r'\]\](?!\])' # ]] - ) - - - class MyInlineLexer(InlineLexer): - default_rules = copy.copy(InlineLexer.default_rules) - - # Add wiki_link parser to default rules - # you can insert it any place you like - default_rules.insert(3, 'wiki_link') - - def __init__(self, renderer, rules=None, **kwargs): - if rules is None: - # use the inline grammar - rules = MyInlineGrammar() - - super(MyInlineLexer, self).__init__(renderer, rules, **kwargs) + class WikiLinkInlineLexer(InlineLexer): + def enable_wiki_link(self): + # add wiki_link rules + self.rules.wiki_link = re.compile( + r'\[\[' # [[ + r'([\s\S]+?\|[\s\S]+?)' # Page 2|Page 2 + r'\]\](?!\])' # ]] + ) + + # Add wiki_link parser to default rules + # you can insert it some place you like + # but place matters, maybe 3 is not good + self.default_rules.insert(3, 'wiki_link') def output_wiki_link(self, m): text = m.group(1) @@ -211,8 +219,10 @@ .. code:: python - renderer = MyRenderer() - inline = MyInlineLexer(renderer) + renderer = WikiLinkRenderer() + inline = WikiLinkInlineLexer(renderer) + # enable the feature + inline.enable_wiki_link() markdown = Markdown(renderer, inline=inline) markdown('[[Link Text|Wiki Link]]') @@ -220,12 +230,21 @@ the whole mechanism. But you won't do the trick a lot. -Contribution ------------- +Contribution & Extensions +------------------------- Mistune itself doesn't accept any extension. It will always be a simple one file script. If you want to add features, you can head over to `mistune-contrib`_. +Here are some extensions already in `mistune-contrib`_: + +* Math/MathJax features +* Highlight Code Renderer +* TOC table of content features +* MultiMarkdown Metadata parser + +Get inspired with the contrib repository. + .. _`mistune-contrib`: https://github.com/lepture/mistune-contrib diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-0.6/mistune.egg-info/PKG-INFO new/mistune-0.7/mistune.egg-info/PKG-INFO --- old/mistune-0.6/mistune.egg-info/PKG-INFO 2015-06-17 08:27:35.000000000 +0200 +++ new/mistune-0.7/mistune.egg-info/PKG-INFO 2015-07-18 15:20:17.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: mistune -Version: 0.6 +Version: 0.7 Summary: The fastest markdown parser in pure Python Home-page: https://github.com/lepture/mistune Author: Hsiaoming Yang @@ -9,7 +9,8 @@ Description: Mistune ======= - The fastest markdown parser in pure Python, inspired by marked_. + The fastest markdown parser in pure Python with renderer features, + inspired by marked_. .. image:: https://img.shields.io/pypi/wheel/mistune.svg?style=flat :target: https://pypi.python.org/pypi/mistune/ @@ -46,12 +47,6 @@ $ pip install mistune - If pip is not available, try easy_install:: - - $ easy_install mistune - - Cython Feature - ~~~~~~~~~~~~~~ Mistune can be faster, if you compile with cython:: @@ -67,10 +62,48 @@ import mistune - mistune.markdown('I am using **markdown**') - # output: <p>I am using <strong>markdown</strong></p> + mistune.markdown('I am using **mistune markdown parser**') + # output: <p>I am using <strong>mistune markdown parser</strong></p> + + If you care about performance, it is better to re-use the Markdown instance: + + .. code:: python + + import mistune + + markdown = mistune.Markdown() + markdown('I am using **mistune markdown parser**') + + Mistune has enabled all features by default. You don't have to configure + anything. But there are options for you to change the parser behaviors. + + + Options + ------- + + Here is a list of all options that will affect the rendering results, + configure them with ``mistune.Renderer``: + + .. code:: python + + renderer = mistune.Renderer(escape=True, hard_wrap=True) + # use this renderer instance + markdown = mistune.Markdown(renderer=renderer) + markdown(text) + + * **escape**: if set to *False*, all raw html tags will not be escaped. + * **hard_wrap**: if set to *True*, it will has GFM line breaks feature. + * **use_xhtml**: if set to *True*, all tags will be in xhtml, for example: ``<hr />``. + * **parse_block_html**: parse text only in block level html. + * **parse_inline_html**: parse text only in inline level html. + + When using the default renderer, you can use one of the following shortcuts:: + + mistune.markdown(text, escape=True, hard_wrap=True) + + markdown = mistune.Markdown(escape=True, hard_wrap=True) + markdown(text) - Mistune has all features by default. You don't have to configure anything. Renderer -------- @@ -87,7 +120,7 @@ from pygments.lexers import get_lexer_by_name from pygments.formatters import HtmlFormatter - class MyRenderer(mistune.Renderer): + class HighlightRenderer(mistune.Renderer): def block_code(self, code, lang): if not lang: return '\n<pre><code>%s</code></pre>\n' % \ @@ -96,10 +129,11 @@ formatter = HtmlFormatter() return highlight(code, lexer, formatter) - renderer = MyRenderer() - md = mistune.Markdown(renderer=renderer) - print(md.render('Some Markdown text.')) + renderer = HighlightRenderer() + markdown = mistune.Markdown(renderer=renderer) + print(markdown('```python\nassert 1 == 1\n```')) + Find more renderers in `mistune-contrib`_. Block Level ~~~~~~~~~~~ @@ -135,34 +169,18 @@ linebreak() newline() link(link, title, content) - tag(html) strikethrough(text) text(text) + inline_html(text) + Footnotes + ~~~~~~~~~ - Options - ------- - - Here is a list of all options that will affect the rendering results: - - .. code:: python - - renderer = mistune.Renderer(escape=True) - md = mistune.Markdown(renderer=renderer) - md.render(text) - - * **escape**: if set to *True*, all raw html tags will be escaped. - * **hard_wrap**: if set to *True*, it will has GFM line breaks feature. - * **use_xhtml**: if set to *True*, all tags will be in xhtml, for example: ``<hr />``. - * **parse_html**: parse text in block level html. - - When using the default renderer, you can use one of the following shorthands:: - - mistune.markdown(text, escape=True) - - md = mistune.Markdown(escape=True) - md.render(text) + Here is a list of renderers related to footnotes:: + footnote_ref(key, index) + footnote_item(key, text) + footnotes(text) Lexers ------ @@ -180,33 +198,23 @@ import copy from mistune import Renderer, InlineGrammar, InlineLexer - class MyRenderer(Renderer): + class WikiLinkRenderer(Renderer): def wiki_link(self, alt, link): return '<a href="%s">%s</a>' % (link, alt) - - class MyInlineGrammar(InlineGrammar): - # it would take a while for creating the right regex - wiki_link = re.compile( - r'\[\[' # [[ - r'([\s\S]+?\|[\s\S]+?)' # Page 2|Page 2 - r'\]\](?!\])' # ]] - ) - - - class MyInlineLexer(InlineLexer): - default_rules = copy.copy(InlineLexer.default_rules) - - # Add wiki_link parser to default rules - # you can insert it any place you like - default_rules.insert(3, 'wiki_link') - - def __init__(self, renderer, rules=None, **kwargs): - if rules is None: - # use the inline grammar - rules = MyInlineGrammar() - - super(MyInlineLexer, self).__init__(renderer, rules, **kwargs) + class WikiLinkInlineLexer(InlineLexer): + def enable_wiki_link(self): + # add wiki_link rules + self.rules.wiki_link = re.compile( + r'\[\[' # [[ + r'([\s\S]+?\|[\s\S]+?)' # Page 2|Page 2 + r'\]\](?!\])' # ]] + ) + + # Add wiki_link parser to default rules + # you can insert it some place you like + # but place matters, maybe 3 is not good + self.default_rules.insert(3, 'wiki_link') def output_wiki_link(self, m): text = m.group(1) @@ -219,8 +227,10 @@ .. code:: python - renderer = MyRenderer() - inline = MyInlineLexer(renderer) + renderer = WikiLinkRenderer() + inline = WikiLinkInlineLexer(renderer) + # enable the feature + inline.enable_wiki_link() markdown = Markdown(renderer, inline=inline) markdown('[[Link Text|Wiki Link]]') @@ -228,14 +238,23 @@ the whole mechanism. But you won't do the trick a lot. - Contribution - ------------ + Contribution & Extensions + ------------------------- Mistune itself doesn't accept any extension. It will always be a simple one file script. If you want to add features, you can head over to `mistune-contrib`_. + Here are some extensions already in `mistune-contrib`_: + + * Math/MathJax features + * Highlight Code Renderer + * TOC table of content features + * MultiMarkdown Metadata parser + + Get inspired with the contrib repository. + .. _`mistune-contrib`: https://github.com/lepture/mistune-contrib Platform: any diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-0.6/mistune.egg-info/SOURCES.txt new/mistune-0.7/mistune.egg-info/SOURCES.txt --- old/mistune-0.6/mistune.egg-info/SOURCES.txt 2015-06-17 08:27:36.000000000 +0200 +++ new/mistune-0.7/mistune.egg-info/SOURCES.txt 2015-07-18 15:20:18.000000000 +0200 @@ -13,6 +13,7 @@ mistune.egg-info/top_level.txt tests/bench.py tests/test_cases.py +tests/test_extra.py tests/test_subclassing.py tests/fixtures/data/math-paragraph.md tests/fixtures/data/math.md diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-0.6/mistune.py new/mistune-0.7/mistune.py --- old/mistune-0.6/mistune.py 2015-06-17 08:16:02.000000000 +0200 +++ new/mistune-0.7/mistune.py 2015-07-18 14:38:39.000000000 +0200 @@ -11,7 +11,7 @@ import re import inspect -__version__ = '0.6' +__version__ = '0.7' __author__ = 'Hsiaoming Yang <m...@lepture.com>' __all__ = [ 'BlockGrammar', 'BlockLexer', @@ -24,12 +24,16 @@ _key_pattern = re.compile(r'\s+') _escape_pattern = re.compile(r'&(?!#?\w+;)') _newline_pattern = re.compile(r'\r\n|\r') -_inline_tag = ( - r'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|' - r'var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|' - r'span|br|wbr|ins|del|img|font' -) -_block_tag = r'(?!(?:%s)\b)\w+(?!:/|[^\w\s@]*@)\b' % _inline_tag +_inline_tags = [ + 'a', 'em', 'strong', 'small', 's', 'cite', 'q', 'dfn', 'abbr', 'data', + 'time', 'code', 'var', 'samp', 'kbd', 'sub', 'sup', 'i', 'b', 'u', 'mark', + 'ruby', 'rt', 'rp', 'bdi', 'bdo', 'span', 'br', 'wbr', 'ins', 'del', + 'img', 'font', +] +_pre_tags = ['pre', 'script', 'style'] +_valid_end = r'(?!:/|[^\w\s@]*@)\b' +_valid_attr = r'''"[^"]*"|'[^']*'|[^'">]''' +_block_tag = r'(?!(?:%s)\b)\w+%s' % ('|'.join(_inline_tags), _valid_end) def _pure_pattern(regex): @@ -138,8 +142,8 @@ block_html = re.compile( r'^ *(?:%s|%s|%s) *(?:\n{2,}|\s*$)' % ( r'<!--[\s\S]*?-->', - r'<(%s)[\s\S]+?<\/\1>' % _block_tag, - r'''<%s(?:"[^"]*"|'[^']*'|[^'">])*?>''' % _block_tag, + r'<(%s)((?:%s)*?)>([\s\S]+?)<\/\1>' % (_block_tag, _valid_attr), + r'<%s(?:%s)*?>' % (_block_tag, _valid_attr), ) ) table = re.compile( @@ -397,13 +401,22 @@ return item def parse_block_html(self, m): - pre = m.group(1) in ['pre', 'script', 'style'] - text = m.group(0) - self.tokens.append({ - 'type': 'block_html', - 'pre': pre, - 'text': text - }) + tag = m.group(1) + if not tag: + text = m.group(0) + self.tokens.append({ + 'type': 'close_html', + 'text': text + }) + else: + attr = m.group(2) + text = m.group(3) + self.tokens.append({ + 'type': 'open_html', + 'tag': tag, + 'extra': attr, + 'text': text + }) def parse_paragraph(self, m): text = m.group(1).rstrip('\n') @@ -421,8 +434,8 @@ inline_html = re.compile( r'^(?:%s|%s|%s)' % ( r'<!--[\s\S]*?-->', - r'<(%s)[\s\S]+?<\/\1>' % _inline_tag, - r'''<(?:%s)(?:"[^"]*"|'[^']*'|[^'">])*?>''' % _inline_tag, + r'<(\w+%s)((?:%s)*?)>([\s\S]+?)<\/\1>' % (_valid_end, _valid_attr), + r'<\w+%s(?:%s)*?>' % (_valid_end, _valid_attr), ) ) autolink = re.compile(r'^<([^ >]+(@|:)[^ >]+)>') @@ -476,6 +489,11 @@ 'double_emphasis', 'emphasis', 'code', 'linebreak', 'strikethrough', 'text', ] + inline_html_rules = [ + 'escape', 'autolink', 'url', 'link', 'reflink', + 'nolink', 'double_emphasis', 'emphasis', 'code', + 'linebreak', 'strikethrough', 'text', + ] def __init__(self, renderer, rules=None, **kwargs): self.renderer = renderer @@ -491,8 +509,11 @@ self._in_link = False self._in_footnote = False - def __call__(self, text): - return self.output(text) + kwargs.update(self.renderer.options) + self._parse_inline_html = kwargs.get('parse_inline_html') + + def __call__(self, text, rules=None): + return self.output(text, rules) def setup(self, links, footnotes): self.footnote_index = 0 @@ -553,7 +574,20 @@ return self.renderer.autolink(link, False) def output_inline_html(self, m): - return self.renderer.inline_html(m.group(0)) + tag = m.group(1) + if self._parse_inline_html and tag in _inline_tags: + text = m.group(3) + if tag == 'a': + self._in_link = True + text = self.output(text, rules=self.inline_html_rules) + self._in_link = False + else: + text = self.output(text, rules=self.inline_html_rules) + extra = m.group(2) or '' + html = '<%s%s>%s</%s>' % (tag, extra, text, tag) + else: + html = m.group(0) + return self.renderer.inline_html(html) def output_footnote(self, m): key = _keyify(m.group(1)) @@ -883,8 +917,9 @@ """The Markdown parser. :param renderer: An instance of ``Renderer``. + :param inline: An inline lexer class or instance. + :param block: A block lexer class or instance. """ - def __init__(self, renderer=None, inline=None, block=None, **kwargs): if not renderer: renderer = Renderer(**kwargs) @@ -909,6 +944,9 @@ self.footnotes = [] self.tokens = [] + # detect if it should parse text in block html + self._parse_block_html = kwargs.get('parse_block_html') + def __call__(self, text): return self.parse(text) @@ -1070,12 +1108,19 @@ self.inline._in_footnote = False return self.renderer.placeholder() - def output_block_html(self): + def output_close_html(self): text = self.token['text'] - if self.options.get('parse_html') and not self.token.get('pre'): - text = self.inline(text) return self.renderer.block_html(text) + def output_open_html(self): + text = self.token['text'] + tag = self.token['tag'] + if self._parse_block_html and tag not in _pre_tags: + text = self.inline(text, rules=self.inline.inline_html_rules) + extra = self.token.get('extra') or '' + html = '<%s%s>%s</%s>' % (tag, extra, text, tag) + return self.renderer.block_html(html) + def output_paragraph(self): return self.renderer.paragraph(self.inline(self.token['text'])) @@ -1083,11 +1128,14 @@ return self.renderer.paragraph(self.tok_text()) -def markdown(text, **kwargs): +def markdown(text, escape=True, **kwargs): """Render markdown formatted text to html. :param text: markdown formatted text content. - :param escape: if set to True, all html tags will be escaped. + :param escape: if set to False, all html tags will not be escaped. :param use_xhtml: output with xhtml tags. + :param hard_wrap: if set to True, it will has GFM line breaks feature. + :param parse_block_html: parse text only in block level html. + :param parse_inline_html: parse text only in inline level html. """ - return Markdown(**kwargs)(text) + return Markdown(escape=escape, **kwargs)(text) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-0.6/tests/test_cases.py new/mistune-0.7/tests/test_cases.py --- old/mistune-0.6/tests/test_cases.py 2015-05-28 05:51:58.000000000 +0200 +++ new/mistune-0.7/tests/test_cases.py 2015-07-12 05:48:00.000000000 +0200 @@ -54,139 +54,3 @@ folder, names = listdir('normal') for key in names: yield render, folder, key - - -def test_escape(): - ret = mistune.markdown('<div>**foo**</div>', escape=True) - assert '>' in ret - - ret = mistune.markdown('this **foo** is <b>bold</b>', escape=True) - assert '>' in ret - - -def test_linebreak(): - ret = mistune.markdown('this **foo** \nis me') - assert '<br>' not in ret - - ret = mistune.markdown('this **foo** \nis me', hard_wrap=True) - assert '<br>' in ret - - -def test_safe_links(): - ret = mistune.markdown('javascript ![foo](<javascript:alert>) alert') - assert 'src=""' in ret - ret = mistune.markdown('javascript [foo](<javascript:alert>) alert') - assert 'href=""' in ret - - -def test_skip_style(): - ret = mistune.markdown( - 'foo\n<style>body{color:red}</style>', skip_style=True - ) - assert ret == '<p>foo</p>\n' - - -def test_use_xhtml(): - ret = mistune.markdown('foo\n\n----\n\nbar') - assert '<hr>' in ret - ret = mistune.markdown('foo\n\n----\n\nbar', use_xhtml=True) - assert '<hr />' in ret - - ret = mistune.markdown('foo \nbar', use_xhtml=True) - assert '<br />' in ret - - ret = mistune.markdown('![foo](bar "title")', use_xhtml=True) - assert '<img src="bar" alt="foo" title="title" />' in ret - - -def test_block_html(): - ret = mistune.markdown('<div>**foo**</div>') - assert '<strong>' not in ret - ret = mistune.markdown('<div>**foo**</div>', parse_html=True) - assert '<strong>' in ret - - -def test_trigger_more_cases(): - markdown = mistune.Markdown( - inline=mistune.InlineLexer, - block=mistune.BlockLexer, - skip_html=True - ) - ret = markdown.render('foo[^foo]\n\n[^foo]: foo\n\n[^foo]: bar\n') - assert 'bar' not in ret - - -def test_custom_lexer(): - import copy - - class MyInlineGrammar(mistune.InlineGrammar): - # it would take a while for creating the right regex - wiki_link = re.compile( - r'\[\[' # [[ - r'([\s\S]+?\|[\s\S]+?)' # Page 2|Page 2 - r'\]\](?!\])' # ]] - ) - - class MyInlineLexer(mistune.InlineLexer): - default_rules = copy.copy(mistune.InlineLexer.default_rules) - default_rules.insert(3, 'wiki_link') - - def __init__(self, renderer, rules=None, **kwargs): - if rules is None: - rules = MyInlineGrammar() - - super(MyInlineLexer, self).__init__(renderer, rules, **kwargs) - - def output_wiki_link(self, m): - text = m.group(1) - alt, link = text.split('|') - return '<a href="%s">%s</a>' % (link, alt) - - markdown = mistune.Markdown(inline=MyInlineLexer) - ret = markdown('[[Link Text|Wiki Link]]') - assert '<a href' in ret - - -def test_token_tree(): - """Tests a Renderer that returns a list from the placeholder method.""" - - class CustomRenderer(mistune.Renderer): - def placeholder(self): - return [] - - def __getattribute__(self, name): - """Saves the arguments to each Markdown handling method.""" - found = CustomRenderer.__dict__.get(name) - if found: - return object.__getattribute__(self, name) - - def fake_method(*args, **kwargs): - return [(name, args, kwargs)] - return fake_method - - with open(os.path.join(root, 'fixtures', 'data', 'tree.md')) as f: - content = f.read() - - expected = [ - ('header', ([('text', ('Title here',), {})], 2, 'Title here'), {}), - ('paragraph', ([('text', ('Some text.',), {})],), {}), - ('paragraph', - ([('text', ('In two paragraphs. And then a list.',), {})],), - {}), - ('list', - ([('list_item', ([('text', ('foo',), {})],), {}), - ('list_item', - ([('text', ('bar',), {}), - ('list', - ([('list_item', ([('text', ('meep',), {})],), {}), - ('list_item', ([('text', ('stuff',), {})],), {})], - True), - {})],), - {})], - False), - {}) - ] - - processor = mistune.Markdown(renderer=CustomRenderer()) - found = processor.render(content) - assert expected == found, "Expected:\n%r\n\nFound:\n%r" % (expected, found) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-0.6/tests/test_extra.py new/mistune-0.7/tests/test_extra.py --- old/mistune-0.6/tests/test_extra.py 1970-01-01 01:00:00.000000000 +0100 +++ new/mistune-0.7/tests/test_extra.py 2015-07-13 09:41:24.000000000 +0200 @@ -0,0 +1,81 @@ +import mistune + + +def test_escape(): + ret = mistune.markdown('<div>**foo**</div>', escape=True) + assert '>' in ret + + ret = mistune.markdown('this **foo** is <b>bold</b>', escape=True) + assert '>' in ret + + +def test_linebreak(): + ret = mistune.markdown('this **foo** \nis me') + assert '<br>' not in ret + + ret = mistune.markdown('this **foo** \nis me', hard_wrap=True) + assert '<br>' in ret + + +def test_safe_links(): + ret = mistune.markdown('javascript ![foo](<javascript:alert>) alert') + assert 'src=""' in ret + ret = mistune.markdown('javascript [foo](<javascript:alert>) alert') + assert 'href=""' in ret + + +def test_skip_style(): + ret = mistune.markdown( + 'foo\n<style>body{color:red}</style>', skip_style=True + ) + assert ret == '<p>foo</p>\n' + + +def test_use_xhtml(): + ret = mistune.markdown('foo\n\n----\n\nbar') + assert '<hr>' in ret + ret = mistune.markdown('foo\n\n----\n\nbar', use_xhtml=True) + assert '<hr />' in ret + + ret = mistune.markdown('foo \nbar', use_xhtml=True) + assert '<br />' in ret + + ret = mistune.markdown('![foo](bar "title")', use_xhtml=True) + assert '<img src="bar" alt="foo" title="title" />' in ret + + +def test_parse_inline_html(): + ret = mistune.markdown( + '<div>**foo**</div>', parse_inline_html=True, escape=False + ) + assert '<strong>' not in ret + ret = mistune.markdown( + '<span>**foo**</span>', parse_inline_html=True, escape=False + ) + assert '<span><strong>' in ret + + +def test_parse_block_html(): + ret = mistune.markdown( + '<div>**foo**</div>', parse_block_html=True, escape=False + ) + assert '<div><strong>' in ret + ret = mistune.markdown( + '<span>**foo**</span>', parse_block_html=True, escape=False + ) + assert '<strong>' not in ret + + +def test_trigger_more_cases(): + markdown = mistune.Markdown( + inline=mistune.InlineLexer, + block=mistune.BlockLexer, + skip_html=True + ) + ret = markdown.render('foo[^foo]\n\n[^foo]: foo\n\n[^foo]: bar\n') + assert 'bar' not in ret + + +def test_not_escape_block_tags(): + text = '<h1>heading</h1> text' + assert text in mistune.markdown(text, escape=False) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mistune-0.6/tests/test_subclassing.py new/mistune-0.7/tests/test_subclassing.py --- old/mistune-0.6/tests/test_subclassing.py 2015-03-31 13:58:35.000000000 +0200 +++ new/mistune-0.7/tests/test_subclassing.py 2015-06-19 17:18:45.000000000 +0200 @@ -2,6 +2,7 @@ import os import re +import copy import mistune root = os.path.dirname(__file__) @@ -73,7 +74,7 @@ ) -class CustomRenderer(mistune.Renderer): +class MathRenderer(mistune.Renderer): def block_math(self, text): return '$$%s$$' % text @@ -92,7 +93,7 @@ else: text = filename - rv = MarkdownWithMath(renderer=CustomRenderer()).render(text) + rv = MarkdownWithMath(renderer=MathRenderer()).render(text) assert text in rv @@ -109,3 +110,82 @@ def test_math_paragraph(): # https://github.com/ipython/ipython/issues/6724 assert_data('math-paragraph.md') + + +class WikiInlineGrammar(mistune.InlineGrammar): + # it would take a while for creating the right regex + wiki_link = re.compile( + r'\[\[' # [[ + r'([\s\S]+?\|[\s\S]+?)' # Page 2|Page 2 + r'\]\](?!\])' # ]] + ) + + +class WikiInlineLexer(mistune.InlineLexer): + default_rules = copy.copy(mistune.InlineLexer.default_rules) + default_rules.insert(3, 'wiki_link') + + def __init__(self, renderer, rules=None, **kwargs): + if rules is None: + rules = WikiInlineGrammar() + + super(WikiInlineLexer, self).__init__(renderer, rules, **kwargs) + + def output_wiki_link(self, m): + text = m.group(1) + alt, link = text.split('|') + return '<a href="%s">%s</a>' % (link, alt) + + +def test_custom_lexer(): + markdown = mistune.Markdown(inline=WikiInlineLexer) + ret = markdown('[[Link Text|Wiki Link]]') + assert '<a href' in ret + + +class TokenTreeRenderer(mistune.Renderer): + # options is required + options = {} + + def placeholder(self): + return [] + + def __getattribute__(self, name): + """Saves the arguments to each Markdown handling method.""" + found = TokenTreeRenderer.__dict__.get(name) + if found is not None: + return object.__getattribute__(self, name) + + def fake_method(*args, **kwargs): + return [(name, args, kwargs)] + return fake_method + + +def test_token_tree(): + """Tests a Renderer that returns a list from the placeholder method.""" + with open(os.path.join(root, 'fixtures', 'data', 'tree.md')) as f: + content = f.read() + + expected = [ + ('header', ([('text', ('Title here',), {})], 2, 'Title here'), {}), + ('paragraph', ([('text', ('Some text.',), {})],), {}), + ('paragraph', + ([('text', ('In two paragraphs. And then a list.',), {})],), + {}), + ('list', + ([('list_item', ([('text', ('foo',), {})],), {}), + ('list_item', + ([('text', ('bar',), {}), + ('list', + ([('list_item', ([('text', ('meep',), {})],), {}), + ('list_item', ([('text', ('stuff',), {})],), {})], + True), + {})],), + {})], + False), + {}) + ] + + processor = mistune.Markdown(renderer=TokenTreeRenderer()) + found = processor.render(content) + assert expected == found, "Expected:\n%r\n\nFound:\n%r" % (expected, found)