Skip to content

Commit 1edd96b

Browse files
committed
Fix unescaping of HTML characters <> in CodeHilite.
Previously, we'd unescape both `&amp;gt;` and `&gt;` to the same string because we were running the &amp; => & replacement first. By changing the order of this replacement, we now convert: `&amp;gt; &gt;` => `&gt; >` as expected. Fixes #988.
1 parent ee85eb5 commit 1edd96b

File tree

4 files changed

+28
-1
lines changed

4 files changed

+28
-1
lines changed

.spell-dict

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ Treeprocessors
132132
tuple
133133
tuples
134134
unescape
135+
unescaping
135136
unittest
136137
unordered
137138
untrusted

docs/change_log/release-3.3.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ The following bug fixes are included in the 3.3 release:
5555

5656
* Fix issues with complex emphasis (#979).
5757
* Limitations of `attr_list` extension are Documented (#965).
58+
* Fix unescaping of HTML characters <> in CodeHilite (#990).
5859

5960
[spec]: https://www.w3.org/TR/html5/text-level-semantics.html#the-code-element
6061
[fenced_code]: ../extensions/fenced_code_blocks.md

markdown/extensions/codehilite.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,11 @@ class HiliteTreeprocessor(Treeprocessor):
225225

226226
def code_unescape(self, text):
227227
"""Unescape code."""
228-
text = text.replace("&amp;", "&")
229228
text = text.replace("&lt;", "<")
230229
text = text.replace("&gt;", ">")
230+
# Escaped '&' should be replaced at the end to avoid
231+
# conflicting with < and >.
232+
text = text.replace("&amp;", "&")
231233
return text
232234

233235
def run(self, root):

tests/test_syntax/extensions/test_code_hilite.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,29 @@ def testDoubleEscape(self):
564564
extensions=['codehilite']
565565
)
566566

567+
def testEntitiesIntact(self):
568+
if has_pygments:
569+
expected = (
570+
'<div class="codehilite"><pre>'
571+
'<span></span>'
572+
'<code>&lt; &amp;lt; and &gt; &amp;gt;'
573+
'\n</code></pre></div>'
574+
)
575+
else:
576+
expected = (
577+
'<pre class="codehilite"><code class="language-text">'
578+
'&lt; &amp;lt; and &gt; &amp;gt;\n'
579+
'</code></pre>'
580+
)
581+
self.assertMarkdownRenders(
582+
(
583+
'\t:::text\n'
584+
'\t< &lt; and > &gt;'
585+
),
586+
expected,
587+
extensions=['codehilite']
588+
)
589+
567590
def testHighlightAmps(self):
568591
if has_pygments:
569592
expected = (

0 commit comments

Comments
 (0)