diff --git a/templates/tests/test_unicode_decimals.html b/templates/tests/test_unicode_decimals.html new file mode 100644 index 0000000000..caa7a27f1f --- /dev/null +++ b/templates/tests/test_unicode_decimals.html @@ -0,0 +1,5 @@ +header + +{{ render_markdown_path("zerver/tests/markdown/test_unicode_decimals.md", {"unescape_rendered_html": unescape_rendered_html}) }} + +footer diff --git a/templates/zerver/tests/markdown/test_unicode_decimals.md b/templates/zerver/tests/markdown/test_unicode_decimals.md new file mode 100644 index 0000000000..c60c140460 --- /dev/null +++ b/templates/zerver/tests/markdown/test_unicode_decimals.md @@ -0,0 +1 @@ +{} diff --git a/zerver/templatetags/app_filters.py b/zerver/templatetags/app_filters.py index 0d356592dc..ddda2b0bf5 100644 --- a/zerver/templatetags/app_filters.py +++ b/zerver/templatetags/app_filters.py @@ -1,4 +1,5 @@ import os +from html import unescape from typing import Any, Dict, List, Optional import markdown @@ -141,4 +142,13 @@ def render_markdown_path(markdown_file_path: str, html = md_engine.convert(markdown_string) rendered_html = jinja.from_string(html).render(context) + if context.get('unescape_rendered_html', False): + # In some exceptional cases (such as our Freshdesk webhook docs), + # code blocks in some of our Markdown templates have characters such + # as '{' encoded as '{' to prevent clashes with Jinja2 syntax, + # but the encoded form never gets decoded because the text ends up + # inside a
 tag. So here, we explicitly "unescape" such characters
+        # if 'unescape_rendered_html' is True.
+        rendered_html = unescape(rendered_html)
+
     return mark_safe(rendered_html)
diff --git a/zerver/tests/test_templates.py b/zerver/tests/test_templates.py
index 4e5d7e80a9..0272d4d782 100644
--- a/zerver/tests/test_templates.py
+++ b/zerver/tests/test_templates.py
@@ -216,6 +216,22 @@ class TemplateTestCase(ZulipTestCase):
         self.assertEqual(content_sans_whitespace,
                          'headerHello!

Thisissomeboldtext.

footer') + def test_encoded_unicode_decimals_in_markdown_template(self) -> None: + template = get_template("tests/test_unicode_decimals.html") + context = {'unescape_rendered_html': False} + content = template.render(context) + + content_sans_whitespace = content.replace(" ", "").replace('\n', '') + self.assertEqual(content_sans_whitespace, + 'header

{}

footer') + + context = {'unescape_rendered_html': True} + content = template.render(context) + + content_sans_whitespace = content.replace(" ", "").replace('\n', '') + self.assertEqual(content_sans_whitespace, + 'header

{}

footer') + def test_markdown_nested_code_blocks(self) -> None: template = get_template("tests/test_markdown.html") context = { diff --git a/zerver/views/integrations.py b/zerver/views/integrations.py index e614bc4aa6..64a6a2325f 100644 --- a/zerver/views/integrations.py +++ b/zerver/views/integrations.py @@ -146,6 +146,14 @@ def integration_doc(request: HttpRequest, integration_name: str=REQ(default=None context['hubot_docs_url'] = integration.hubot_docs_url if isinstance(integration, EmailIntegration): context['email_gateway_example'] = settings.EMAIL_GATEWAY_EXAMPLE + if integration.name == 'freshdesk': + # In our Freshdesk docs, some nested code blocks have characters such + # as '{' encoded as '{' to prevent clashes with Jinja2 syntax, + # but the encoded form never gets rendered because the text ends up + # inside a
 tag. So here, we explicitly set a directive that
+        # a particular template should be "unescaped" before being displayed.
+        # Note that this value is used by render_markdown_path.
+        context['unescape_rendered_html'] = True
 
     doc_html_str = render_markdown_path(integration.doc, context)