Skip to content

Commit

Permalink
fix: only HTML-escape URLs when rendering to HTML
Browse files Browse the repository at this point in the history
  • Loading branch information
mentalisttraceur committed Nov 1, 2024
1 parent 0772c78 commit f423704
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 6 deletions.
4 changes: 2 additions & 2 deletions src/mistune/directives/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def render_block_image(
height: Optional[str] = None,
**attrs: Any,
) -> str:
img = '<img src="' + src + '"'
img = '<img src="' + escape_text(src) + '"'
style = ''
if alt:
img += ' alt="' + escape_text(alt) + '"'
Expand All @@ -90,7 +90,7 @@ def render_block_image(

target = attrs.get('target')
if target:
href = escape_text(self.safe_url(target))
href = self.safe_url(target)
outer = '<a class="' + _cls + '" href="' + href + '">'
return outer + img + '</a>\n'
else:
Expand Down
6 changes: 3 additions & 3 deletions src/mistune/renderers/html.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,17 @@ def safe_url(self, url: str) -> str:
links, images, and etc.
"""
if self._allow_harmful_protocols is True:
return url
return escape_text(url)

_url = url.lower()
if self._allow_harmful_protocols and \
_url.startswith(tuple(self._allow_harmful_protocols)):
return url
return escape_text(url)

if _url.startswith(self.HARMFUL_PROTOCOLS) and \
not _url.startswith(self.GOOD_DATA_PROTOCOLS):
return '#harmful-link'
return url
return escape_text(url)

def text(self, text: str) -> str:
if self._escape:
Expand Down
2 changes: 1 addition & 1 deletion src/mistune/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def escape_url(link: str) -> str:
'!$&()*+,;=' # sub-delims - "'" (rfc3986)
'%' # leave already-encoded octets alone
)
return escape(quote(unescape(link), safe=safe))
return quote(unescape(link), safe=safe)


def safe_entity(s: str) -> str:
Expand Down
19 changes: 19 additions & 0 deletions tests/fixtures/fenced_image.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,22 @@
.
<a class="block-image align-left" href="https://lepture.com"><img src="picture.png" alt="description" width="100" height="50" /></a>
````````````````````````````````

## ampersand in source

```````````````````````````````` example
~~~{image} https://example.com/picture.png?foo=qux&test=me
~~~
.
<div class="block-image"><img src="https://example.com/picture.png?foo=qux&amp;test=me" /></div>
````````````````````````````````

## ampersand in target

```````````````````````````````` example
~~~{image} picture.png
:target: https://example.com/rickroll?a=1&b=2
~~~
.
<a class="block-image" href="https://example.com/rickroll?a=1&amp;b=2"><img src="picture.png" /></a>
````````````````````````````````
19 changes: 19 additions & 0 deletions tests/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,25 @@ def test_ast_output(self):
]
self.assertEqual(result, expected)

def test_ast_url(self):
md = mistune.create_markdown(escape=False, renderer=None)
label = 'hi &<>"'
url = 'https://example.com/foo?a=1&b=2'
text = '[{}]({})'.format(label, url)
result = md(text)
expected = [
{
'type': 'paragraph',
'children': [
{
'type': 'link',
'children': [{'type': 'text', 'raw': label}],
'attrs': {'url': url},
},
],
},
]
self.assertEqual(result, expected)

def test_emsp(self):
md = mistune.create_markdown(escape=False, hard_wrap=True)
Expand Down

0 comments on commit f423704

Please sign in to comment.