diff options
| author | Baptiste Mispelon <bmispelon@gmail.com> | 2025-05-31 00:32:30 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-30 23:32:30 +0100 |
| commit | 253cc2a4499cfe0935c4e4462a3562a4650df317 (patch) | |
| tree | 8cc6e2c7b0774bec548773c8175b22f17be9f476 /blog | |
| parent | c68e183cc0b04ee435d87ff10cec9a1d402291d0 (diff) | |
Fixed escaping of alt text in ContentFormat.img() (#2036)
* Fixed escaping of alt text in ContentFormat.img()
* Simpler approach
Diffstat (limited to 'blog')
| -rw-r--r-- | blog/models.py | 3 | ||||
| -rw-r--r-- | blog/tests.py | 40 |
2 files changed, 42 insertions, 1 deletions
diff --git a/blog/models.py b/blog/models.py index 0083dd22..988c607e 100644 --- a/blog/models.py +++ b/blog/models.py @@ -8,6 +8,7 @@ from django.test import RequestFactory from django.utils import timezone from django.utils.cache import _generate_cache_header_key from django.utils.formats import date_format +from django.utils.html import format_html from django.utils.translation import gettext_lazy as _ from django_hosts.resolvers import get_host, reverse, reverse_host from docutils.core import publish_parts @@ -73,7 +74,7 @@ class ContentFormat(models.TextChoices): CF = type(self) return { CF.REST: f".. image:: {url}\n :alt: {alt_text}", - CF.HTML: f'<img src="{url}" alt="{alt_text}">', + CF.HTML: format_html('<img src="{}" alt="{}">', url, alt_text), CF.MARKDOWN: f"", }[self] diff --git a/blog/tests.py b/blog/tests.py index 60a0e511..15c6a4b9 100644 --- a/blog/tests.py +++ b/blog/tests.py @@ -297,3 +297,43 @@ class ImageUploadTestCase(TestCase): r"http://www\.djangoproject\.localhost:8000" r"/m/blog/images/2005/07/test(_\w+)?\.png", ) + + def test_alt_text_html_escape(self): + testdata = [ + (ContentFormat.HTML, 'te"st', '<img src="." alt="te"st">'), + (ContentFormat.HTML, "te<st>", '<img src="." alt="te<st>">'), + (ContentFormat.MARKDOWN, 'te"st', '<img src="." alt="te"st">'), + (ContentFormat.MARKDOWN, "te[st]", '<img src="." alt="te[st]">'), + (ContentFormat.MARKDOWN, "te{st}", '<img src="." alt="te{st}">'), + (ContentFormat.MARKDOWN, "te<st>", '<img src="." alt="te<st>">'), + (ContentFormat.MARKDOWN, "test*", '<img src="." alt="test*">'), + (ContentFormat.MARKDOWN, "test_", '<img src="." alt="test_">'), + (ContentFormat.MARKDOWN, "test`", '<img src="." alt="test`">'), + (ContentFormat.MARKDOWN, "test+", '<img src="." alt="test+">'), + (ContentFormat.MARKDOWN, "test-", '<img src="." alt="test-">'), + (ContentFormat.MARKDOWN, "test.", '<img src="." alt="test.">'), + (ContentFormat.MARKDOWN, "test!", '<img src="." alt="test!">'), + (ContentFormat.MARKDOWN, "te\nst", '<img src="." alt="te\nst">'), + (ContentFormat.REST, 'te"st', '<img src="." alt="te"st">'), + (ContentFormat.REST, "te[st]", '<img src="." alt="te[st]">'), + (ContentFormat.REST, "te{st}", '<img src="." alt="te{st}">'), + (ContentFormat.REST, "te<st>", '<img src="." alt="te<st>">'), + (ContentFormat.REST, "te:st", '<img src="." alt="te:st">'), + (ContentFormat.REST, "test*", '<img src="." alt="test*">'), + (ContentFormat.REST, "test_", '<img src="." alt="test_">'), + (ContentFormat.REST, "test`", '<img src="." alt="test`">'), + (ContentFormat.REST, "test+", '<img src="." alt="test+">'), + (ContentFormat.REST, "test-", '<img src="." alt="test-">'), + (ContentFormat.REST, "test.", '<img src="." alt="test.">'), + (ContentFormat.REST, "test!", '<img src="." alt="test!">'), + ] + for cf, alt_text, expected in testdata: + # RST doesn't like an empty src, so we use . instead + img_tag = cf.img(url=".", alt_text=alt_text) + if cf is ContentFormat.MARKDOWN: + expected = f"<p>{expected}</p>" + with self.subTest(cf=cf, alt_text=alt_text): + self.assertHTMLEqual( + ContentFormat.to_html(cf, img_tag), + expected, + ) |
