Skip to content

Commit 939a2fe

Browse files
committed
Improve standalone * and _ parsing.
The `NOT_STRONG_RE` regex matchs 1, 2, or 3 * or _ which are surrounded by white space to prevent them from being parsed as tokens. However, the surrounding white space should not be consumed by the regex, which is why lookhead and lookbehind assertions are used. As `^` cannot be matched in a lookbehind assertion, it is left outside the assertion, but as it is zero length, that should not matter. Tests added and/or updated to cover various edge cases. Fixes #1300.
1 parent e97ffeb commit 939a2fe

File tree

3 files changed

+50
-4
lines changed

3 files changed

+50
-4
lines changed

docs/change_log/index.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ title: Change Log
33
Python-Markdown Change Log
44
=========================
55

6+
*under development*: version 3.4.1 (a bug-fix release).
7+
8+
* Improve standalone * and _ parsing (#1300).
9+
610
July 15, 2022: version 3.4.1 (a bug-fix release).
711

812
* Fix an import issue with `importlib.util` (#1274).

markdown/inlinepatterns.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ def build_inlinepatterns(md, **kwargs):
154154
IMAGE_REFERENCE_RE = IMAGE_LINK_RE
155155

156156
# stand-alone * or _
157-
NOT_STRONG_RE = r'((^|\s)(\*|_)(\s|$))'
157+
NOT_STRONG_RE = r'((^|(?<=\s))(\*{1,3}|_{1,3})(?=\s|$))'
158158

159159
# <http://www.123.com>
160160
AUTOLINK_RE = r'<((?:[Ff]|[Hh][Tt])[Tt][Pp][Ss]?://[^<>]*)>'

tests/test_syntax/inline/test_emphasis.py

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,42 @@ def test_standalone_understore(self):
3636
'<p>_</p>'
3737
)
3838

39+
def test_standalone_asterisks_consecutive(self):
40+
self.assertMarkdownRenders(
41+
'Foo * * * *',
42+
'<p>Foo * * * *</p>'
43+
)
44+
45+
def test_standalone_understore_consecutive(self):
46+
self.assertMarkdownRenders(
47+
'Foo _ _ _ _',
48+
'<p>Foo _ _ _ _</p>'
49+
)
50+
51+
def test_standalone_asterisks_pairs(self):
52+
self.assertMarkdownRenders(
53+
'Foo ** ** ** **',
54+
'<p>Foo ** ** ** **</p>'
55+
)
56+
57+
def test_standalone_understore_pairs(self):
58+
self.assertMarkdownRenders(
59+
'Foo __ __ __ __',
60+
'<p>Foo __ __ __ __</p>'
61+
)
62+
63+
def test_standalone_asterisks_triples(self):
64+
self.assertMarkdownRenders(
65+
'Foo *** *** *** ***',
66+
'<p>Foo *** *** *** ***</p>'
67+
)
68+
69+
def test_standalone_understore_triples(self):
70+
self.assertMarkdownRenders(
71+
'Foo ___ ___ ___ ___',
72+
'<p>Foo ___ ___ ___ ___</p>'
73+
)
74+
3975
def test_standalone_asterisk_in_text(self):
4076
self.assertMarkdownRenders(
4177
'foo * bar',
@@ -72,10 +108,16 @@ def test_standalone_understores_with_newlines(self):
72108
'<p>foo\n_ bar _\nbaz</p>'
73109
)
74110

75-
def test_standalone_asterisks_at_end(self):
111+
def test_standalone_underscore_at_begin(self):
112+
self.assertMarkdownRenders(
113+
'_ foo_ bar',
114+
'<p>_ foo_ bar</p>'
115+
)
116+
117+
def test_standalone_asterisk_at_end(self):
76118
self.assertMarkdownRenders(
77-
'foo * bar *',
78-
'<p>foo * bar *</p>'
119+
'foo *bar *',
120+
'<p>foo *bar *</p>'
79121
)
80122

81123
def test_standalone_understores_at_begin_end(self):

0 commit comments

Comments
 (0)