Repository: Python-Markdown/markdown
Pull request #696 (2018-07-31 15:32:18)

smart_emphasis keyword > legacy_em extension.
The smart_strong extension has been removed and its behavior is now the
default (smart em and smart strong are the default). The legacy_em
extension restores legacy behavior (no smart em or smart strong).

This completes the removal of keywords.  All parser behavior is now
modified by extensions, not by keywords on the Markdown class.

This adapts 8dcfb14f and d4ff60c5 from the md3 branch.


Patch:
diff --git a/markdown/core.py b/markdown/core.py
index 2144f00..d25f20d 100644
--- a/markdown/core.py
+++ b/markdown/core.py
@@ -47,11 +47,6 @@ class Markdown(object):
 
     doc_tag = "div"     # Element used to wrap document - later removed
 
-    option_defaults = {
-        'tab_length':            4,
-        'smart_emphasis':        True,
-    }
-
     output_formats = {
         'html':   to_html_string,
         'xhtml':  to_xhtml_string,
@@ -73,13 +68,10 @@ class Markdown(object):
             * "xhtml": Outputs XHTML style tags. Default.
             * "html": Outputs HTML style tags.
         * tab_length: Length of tabs in the source. Default: 4
-        * smart_emphasis: Treat `_connected_words_` intelligently Default: True
 
         """
 
-        # Loop through kwargs and assign defaults
-        for option, default in self.option_defaults.items():
-            setattr(self, option, kwargs.get(option, default))
+        self.tab_length = kwargs.get('tab_length', 4)
 
         self.ESCAPED_CHARS = ['\\', '`', '*', '_', '{', '}', '[', ']',
                               '(', ')', '>', '#', '+', '-', '.', '!']
diff --git a/markdown/extensions/extra.py b/markdown/extensions/extra.py
index 19b9db0..e498a74 100644
--- a/markdown/extensions/extra.py
+++ b/markdown/extensions/extra.py
@@ -37,7 +37,6 @@ from .. import util
 import re
 
 extensions = [
-    'smart_strong',
     'fenced_code',
     'footnotes',
     'attr_list',
diff --git a/markdown/extensions/legacy_em.py b/markdown/extensions/legacy_em.py
new file mode 100644
index 0000000..5cc0f6d
--- /dev/null
+++ b/markdown/extensions/legacy_em.py
@@ -0,0 +1,30 @@
+'''
+Legacy Em Extension for Python-Markdown
+=======================================
+
+This extention provides legacy behavior for _connected_words_.
+
+Copyright 2015-2018 The Python Markdown Project
+
+License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
+
+'''
+
+from __future__ import absolute_import
+from __future__ import unicode_literals
+from . import Extension
+from ..inlinepatterns import SimpleTagInlineProcessor
+
+EMPHASIS_RE = r'(\*|_)(.+?)\1'
+STRONG_RE = r'(\*{2}|_{2})(.+?)\1'
+
+
+class LegacyEmExtension(Extension):
+    """ Add legacy_em extension to Markdown class."""
+
+    def extendMarkdown(self, md, md_globals):
+        """ Modify inline patterns. """
+        md.inlinePatterns.register(SimpleTagInlineProcessor(STRONG_RE, 'strong'), 'strong', 40)
+        md.inlinePatterns.register(SimpleTagInlineProcessor(EMPHASIS_RE, 'em'), 'emphasis', 30)
+        md.inlinePatterns.deregister('strong2')
+        md.inlinePatterns.deregister('emphasis2')
diff --git a/markdown/extensions/smart_strong.py b/markdown/extensions/smart_strong.py
deleted file mode 100644
index e7a15d9..0000000
--- a/markdown/extensions/smart_strong.py
+++ /dev/null
@@ -1,37 +0,0 @@
-'''
-Smart_Strong Extension for Python-Markdown
-==========================================
-
-This extension adds smarter handling of double underscores within words.
-
-See <https://Python-Markdown.github.io/extensions/smart_strong>
-for documentation.
-
-Original code Copyright 2011 [Waylan Limberg](http://achinghead.com)
-
-All changes Copyright 2011-2014 The Python Markdown Project
-
-License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
-
-'''
-
-from __future__ import absolute_import
-from __future__ import unicode_literals
-from . import Extension
-from ..inlinepatterns import SimpleTagInlineProcessor
-
-SMART_STRONG_RE = r'(?<!\w)(_{2})(?!_)(.+?)(?<!_)\1(?!\w)'
-STRONG_RE = r'(\*{2})(.+?)\1'
-
-
-class SmartEmphasisExtension(Extension):
-    """ Add smart_emphasis extension to Markdown class."""
-
-    def extendMarkdown(self, md, md_globals):
-        """ Modify inline patterns. """
-        md.inlinePatterns.register(SimpleTagInlineProcessor(STRONG_RE, 'strong'), 'strong', 40)
-        md.inlinePatterns.register(SimpleTagInlineProcessor(SMART_STRONG_RE, 'strong'), 'strong2', 10)
-
-
-def makeExtension(**kwargs):  # pragma: no cover
-    return SmartEmphasisExtension(**kwargs)
diff --git a/markdown/inlinepatterns.py b/markdown/inlinepatterns.py
index 8d49d07..e4af53e 100644
--- a/markdown/inlinepatterns.py
+++ b/markdown/inlinepatterns.py
@@ -95,10 +95,8 @@ def build_inlinepatterns(md, **kwargs):
     inlinePatterns.register(DoubleTagInlineProcessor(STRONG_EM_RE, 'em,strong'), 'strong_em', 50)
     inlinePatterns.register(SimpleTagInlineProcessor(STRONG_RE, 'strong'), 'strong', 40)
     inlinePatterns.register(SimpleTagInlineProcessor(EMPHASIS_RE, 'em'), 'emphasis', 30)
-    if md.smart_emphasis:
-        inlinePatterns.register(SimpleTagInlineProcessor(SMART_EMPHASIS_RE, 'em'), 'emphasis2', 20)
-    else:
-        inlinePatterns.register(SimpleTagInlineProcessor(EMPHASIS_2_RE, 'em'), 'emphasis2', 20)
+    inlinePatterns.register(SimpleTagInlineProcessor(SMART_STRONG_RE, 'strong'), 'strong2', 20)
+    inlinePatterns.register(SimpleTagInlineProcessor(SMART_EMPHASIS_RE, 'em'), 'emphasis2', 10)
     return inlinePatterns
 
 
@@ -119,7 +117,13 @@ ESCAPE_RE = r'\\(.)'
 EMPHASIS_RE = r'(\*)([^\*]+)\1'
 
 # **strong**
-STRONG_RE = r'(\*{2}|_{2})(.+?)\1'
+STRONG_RE = r'(\*{2})(.+?)\1'
+
+# __smart__strong__
+SMART_STRONG_RE = r'(?<!\w)(_{2})(?!_)(.+?)(?<!_)\1(?!\w)'
+
+# _smart_emphasis_
+SMART_EMPHASIS_RE = r'(?<!\w)(_)(?!_)(.+?)(?<!_)\1(?!\w)'
 
 # ***strongem*** or ***em*strong**
 EM_STRONG_RE = r'(\*|_)\1{2}(.+?)\1(.*?)\1{2}'
@@ -127,12 +131,6 @@ EM_STRONG_RE = r'(\*|_)\1{2}(.+?)\1(.*?)\1{2}'
 # ***strong**em*
 STRONG_EM_RE = r'(\*|_)\1{2}(.+?)\1{2}(.*?)\1'
 
-# _smart_emphasis_
-SMART_EMPHASIS_RE = r'(?<!\w)(_)(?!_)(.+?)(?<!_)\1(?!\w)'
-
-# _emphasis_
-EMPHASIS_2_RE = r'(_)(.+?)\1'
-
 # [text](url) or [text](<url>) or [text](url "title")
 LINK_RE = NOIMG + r'\['
 
diff --git a/setup.py b/setup.py
index c81e4f9..f906389 100755
--- a/setup.py
+++ b/setup.py
@@ -96,12 +96,12 @@ setup(
             'meta = markdown.extensions.meta:MetaExtension',
             'nl2br = markdown.extensions.nl2br:Nl2BrExtension',
             'sane_lists = markdown.extensions.sane_lists:SaneListExtension',
-            'smart_strong = markdown.extensions.smart_strong:SmartEmphasisExtension',
             'smarty = markdown.extensions.smarty:SmartyExtension',
             'tables = markdown.extensions.tables:TableExtension',
             'toc = markdown.extensions.toc:TocExtension',
             'wikilinks = markdown.extensions.wikilinks:WikiLinkExtension',
             'legacy_attrs = markdown.extensions.legacy_attrs:LegacyAttrExtension',
+            'legacy_em = markdown.extensions.legacy_em:LegacyEmExtension',
         ]
     },
     classifiers=[


Test patch:
diff --git a/tests/misc/em_strong_complex.html b/tests/misc/em_strong_complex.html
index 3befa70..65faddf 100644
--- a/tests/misc/em_strong_complex.html
+++ b/tests/misc/em_strong_complex.html
@@ -1,7 +1,7 @@
 <p><em><strong>test test</strong> test test</em></p>
 <p><strong><em>test test</em> test test</strong></p>
 <p><strong><em>test</em></strong></p>
-<p><strong>test</strong>_</p>
+<p><strong>test</strong></p>
 <p><strong><em>test</em> test</strong>_</p>
 <p><strong><em>test</em> test</strong></p>
 <p><em>test_test test_test</em></p>
diff --git a/tests/misc/em_strong_complex.txt b/tests/misc/em_strong_complex.txt
index 66f4ff1..0425971 100644
--- a/tests/misc/em_strong_complex.txt
+++ b/tests/misc/em_strong_complex.txt
@@ -4,7 +4,7 @@ ___test test_ test test__
 
 ___test___
 
-__test___
+__test__
 
 ___test_ test___
 
diff --git a/tests/misc/underscores.html b/tests/misc/underscores.html
index 54bd9f9..72d51b8 100644
--- a/tests/misc/underscores.html
+++ b/tests/misc/underscores.html
@@ -1,6 +1,6 @@
 <p>THIS_SHOULD_STAY_AS_IS</p>
 <p>Here is some <em>emphasis</em>, ok?</p>
 <p>Ok, at least <em>this</em> should work.</p>
-<p>THIS<strong>SHOULD</strong>STAY</p>
+<p>THIS__SHOULD__STAY</p>
 <p>Here is some <strong>strong</strong> stuff.</p>
 <p>THIS<strong><em>SHOULD</em></strong>STAY?</p>
\ No newline at end of file
diff --git a/tests/options/html4.html b/tests/options/html4.html
deleted file mode 100644
index 7c88ad7..0000000
--- a/tests/options/html4.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<p>A test of the most<br>
-basic of html/xhtml differences.</p>
\ No newline at end of file
diff --git a/tests/options/html4.txt b/tests/options/html4.txt
deleted file mode 100644
index fddaf8e..0000000
--- a/tests/options/html4.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-A test of the most  
-basic of html/xhtml differences.
\ No newline at end of file
diff --git a/tests/options/no-smart-emphasis.html b/tests/options/no-smart-emphasis.html
deleted file mode 100644
index c4f1381..0000000
--- a/tests/options/no-smart-emphasis.html
+++ /dev/null
@@ -1,1 +0,0 @@
-<p><em>connected</em>words_</p>
\ No newline at end of file
diff --git a/tests/options/no-smart-emphasis.txt b/tests/options/no-smart-emphasis.txt
deleted file mode 100644
index cf500b5..0000000
--- a/tests/options/no-smart-emphasis.txt
+++ /dev/null
@@ -1,1 +0,0 @@
-_connected_words_
\ No newline at end of file
diff --git a/tests/test_apis.py b/tests/test_apis.py
index c813e56..b5c7733 100644
--- a/tests/test_apis.py
+++ b/tests/test_apis.py
@@ -695,6 +695,18 @@ class testSerializers(unittest.TestCase):
             '<p>foo</p>'
         )
 
+    def testXHTMLOutput(self):
+        self.assertEqual(
+            markdown.markdown('foo  \nbar', output_format='xhtml'),
+            '<p>foo<br />\nbar</p>'
+        )
+
+    def testHTMLOutput(self):
+        self.assertEqual(
+            markdown.markdown('foo  \nbar', output_format='html'),
+            '<p>foo<br>\nbar</p>'
+        )
+
 
 class testAtomicString(unittest.TestCase):
     """ Test that AtomicStrings are honored (not parsed). """
diff --git a/tests/test_legacy.py b/tests/test_legacy.py
index 976a84e..f4e807e 100644
--- a/tests/test_legacy.py
+++ b/tests/test_legacy.py
@@ -41,14 +41,6 @@ class TestMisc(LegacyTestCase):
     location = os.path.join(parent_test_dir, 'misc')
 
 
-class TestOptions(LegacyTestCase):
-    location = os.path.join(parent_test_dir, 'options')
-
-    html4 = Kwargs(output_format='html4')
-
-    no_smart_emphasis = Kwargs(smart_emphasis=False)
-
-
 class TestPhp(LegacyTestCase):
     """
     Notes on "excluded" tests:
diff --git a/tests/test_syntax/extensions/test_legacy_em.py b/tests/test_syntax/extensions/test_legacy_em.py
new file mode 100644
index 0000000..ddb2079
--- /dev/null
+++ b/tests/test_syntax/extensions/test_legacy_em.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+"""
+Python Markdown
+
+A Python implementation of John Gruber's Markdown.
+
+Documentation: https://python-markdown.github.io/
+GitHub: https://github.com/Python-Markdown/markdown/
+PyPI: https://pypi.org/project/Markdown/
+
+Started by Manfred Stienstra (http://www.dwerg.net/).
+Maintained for a few years by Yuri Takhteyev (http://www.freewisdom.org).
+Currently maintained by Waylan Limberg (https://github.com/waylan),
+Dmitry Shachnev (https://github.com/mitya57) and Isaac Muse (https://github.com/facelessuser).
+
+Copyright 2007-2018 The Python Markdown Project (v. 1.7 and later)
+Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
+Copyright 2004 Manfred Stienstra (the original version)
+
+License: BSD (see LICENSE.md for details).
+"""
+
+from __future__ import unicode_literals
+from markdown.test_tools import TestCase
+
+
+class TestLegacyEm(TestCase):
+    def test_legacy_emphasis(self):
+        self.assertMarkdownRenders(
+            '_connected_words_',
+            '<p><em>connected</em>words_</p>',
+            extensions=['legacy_em']
+        )
+
+    def test_legacy_strong(self):
+        self.assertMarkdownRenders(
+            '__connected__words__',
+            '<p><strong>connected</strong>words__</p>',
+            extensions=['legacy_em']
+        )