diff --git a/notifications_utils/formatters.py b/notifications_utils/formatters.py
index 652fa61de..446e9fb08 100644
--- a/notifications_utils/formatters.py
+++ b/notifications_utils/formatters.py
@@ -7,7 +7,7 @@
import bleach
import mistune
import smartypants
-from flask import Markup
+from flask import Markup, current_app
from notifications_utils.sanitise_text import SanitiseSMS
@@ -33,12 +33,20 @@
EN_CLOSE = r"\[\[/en\]\]" # matches [[/en]]
RTL_OPEN = r"\[\[rtl\]\]" # matches [[rtl]]
RTL_CLOSE = r"\[\[/rtl\]\]" # matches [[/rtl]]
+CALLOUT_OPEN = r"\[\[callout\]\]" # matches [[callout]]
+CALLOUT_CLOSE = r"\[\[/callout\]\]" # matches [[/callout]]
+CTA_OPEN = r"\[\[cta\]\]" # matches [[cta]]
+CTA_CLOSE = r"\[\[/cta\]\]" # matches [[/cta]]
FR_OPEN_LITERAL = "[[fr]]"
FR_CLOSE_LITERAL = "[[/fr]]"
EN_OPEN_LITERAL = "[[en]]"
EN_CLOSE_LITERAL = "[[/en]]"
RTL_OPEN_LITERAL = "[[rtl]]"
RTL_CLOSE_LITERAL = "[[/rtl]]"
+CALLOUT_OPEN_LITERAL = "[[callout]]"
+CALLOUT_CLOSE_LITERAL = "[[/callout]]"
+CTA_OPEN_LITERAL = "[[cta]]"
+CTA_CLOSE_LITERAL = "[[/cta]]"
BR_TAG = r"
"
@@ -488,8 +496,42 @@ def double_emphasis(self, text):
def emphasis(self, text):
return f"{text}"
+ def table(self, header, body):
+ # If the feature flag is off, return the content with the tags unprocessed. This allows us to add table tags to
+ # content without them being rendered as tables until we're ready to turn the feature flag on
+ try:
+ if not current_app.config.get("FF_EMAIL_TABLES", False):
+ return ""
+ except RuntimeError:
+ return ""
+ return (
+ '
{link_styled_content}' + else: + # Leave unprocessed if not exactly one link + return match.group(0) + + result = cta_pattern.sub(replace_cta, result) + return result + + return _content + + +def remove_cta_tags(_content: str) -> str: + """Remove the tags from content. This fn is for use in the email + preheader, since this is plain text not html""" + return remove_tags(_content, CTA_OPEN, CTA_CLOSE) + + def remove_tags(_content: str, *tags) -> str: """Remove the tags in parameters from content. diff --git a/notifications_utils/template.py b/notifications_utils/template.py index 03643862e..9dfd3fd7e 100644 --- a/notifications_utils/template.py +++ b/notifications_utils/template.py @@ -11,11 +11,15 @@ from notifications_utils.columns import Columns from notifications_utils.field import Field from notifications_utils.formatters import ( + add_callout_divs, + add_cta_buttons, add_language_divs, add_prefix, add_rtl_divs, add_trailing_newline, autolink_sms, + escape_callout_tags, + escape_cta_tags, escape_html, escape_lang_tags, escape_rtl_tags, @@ -28,6 +32,8 @@ notify_email_preheader_markdown, notify_letter_preview_markdown, notify_plain_text_email_markdown, + remove_callout_divs, + remove_cta_tags, remove_empty_lines, remove_language_divs, remove_nested_list_padding, @@ -423,6 +429,8 @@ def preheader(self): .then(notify_email_preheader_markdown) .then(remove_language_divs) .then(remove_rtl_divs) + .then(remove_callout_divs) + .then(remove_cta_tags) .then(do_nice_typography) .split() )[: self.PREHEADER_LENGTH_IN_CHARACTERS].strip() @@ -857,10 +865,14 @@ def get_html_email_body(template_content, template_values, redact_missing_person .then(add_trailing_newline) .then(escape_lang_tags) .then(escape_rtl_tags) + .then(escape_callout_tags) + .then(escape_cta_tags) .then(notify_email_markdown) .then(remove_nested_list_padding) .then(add_language_divs) .then(add_rtl_divs) + .then(add_callout_divs) + .then(add_cta_buttons) .then(do_nice_typography) ) diff --git a/tests/test_formatters.py b/tests/test_formatters.py index 7f862af5c..7aaeea7a2 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -557,11 +557,41 @@ def test_multiple_newlines_get_truncated(markdown_function, expected): assert markdown_function("before\n\n\n\n\n\nafter") == expected -@pytest.mark.parametrize( - "markdown_function", (notify_letter_preview_markdown, notify_email_markdown, notify_plain_text_email_markdown) -) -def test_table(markdown_function): - assert markdown_function("col | col\n" "----|----\n" "val | val\n") == ("") +def test_table_feature_off(): + markdown_input = "col | col\n" "----|----\n" "val | val\n" + + assert notify_letter_preview_markdown(markdown_input) == "" + + # Tables are gated behind FF_EMAIL_TABLES — off by default (no app context) + email_result = notify_email_markdown(markdown_input) + assert "