Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the preview formatting when a variable appears in a link url #344

Merged
merged 9 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/waffles/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ docopt==0.6.2
Flask==2.3.3
markupsafe==2.1.5
setuptools==75.6.0 # required for distutils in Python 3.12
git+https://github.com/cds-snc/[email protected].3#egg=notifications-utils
git+https://github.com/cds-snc/[email protected].4#egg=notifications-utils
16 changes: 15 additions & 1 deletion notifications_utils/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ class Field:
# * body of placeholder - potentially standard or conditional,
# * closing ))
placeholder_pattern = re.compile(r"\({2}" r"(?!\()" r"([\s\S]+?)" r"\){2}")
placeholder_pattern_for_link_url = re.compile(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is some heady code to come back and write! nicely done! 😮

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you AI 🤖 😄

r"(?<=\]\()" # Lookbehind for markdown link URL pattern
r"\({2}" # Match opening double parentheses
r"(?!\()" # Negative lookahead to enforce consumption of late parenthesis and not early ones
r"([\s\S]+?)" # Body of placeholder - potentially standard or conditional
r"\){2}" # Match closing double parentheses
)

placeholder_tag = "<mark class='placeholder'>(({}))</mark>"
conditional_placeholder_tag = "<mark class='placeholder-conditional'><span class='condition'>(({}??</span>{}))</mark>"
placeholder_tag_translated = "<span class='placeholder-no-brackets'>[{}]</span>"
Expand Down Expand Up @@ -109,6 +117,10 @@ def values(self):
def values(self, value):
self._values = Columns(value) if value else {}

def format_match_in_link_url(self, match):
placeholder = Placeholder.from_match(match)
return placeholder.name

def format_match(self, match):
placeholder = Placeholder.from_match(match)

Expand Down Expand Up @@ -155,7 +167,9 @@ def get_replacement_as_list(self, replacement):

@property
def _raw_formatted(self):
return re.sub(self.placeholder_pattern, self.format_match, self.sanitizer(self.content))
_sanitized_content = self.sanitizer(self.content)
sanitized_content = re.sub(self.placeholder_pattern_for_link_url, self.format_match_in_link_url, _sanitized_content)
return re.sub(self.placeholder_pattern, self.format_match, sanitized_content)

@property
def formatted(self):
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "notifications-utils"
version = "53.0.3"
version = "53.0.4"
description = "Shared python code for Notification - Provides logging utils etc."
authors = ["Canadian Digital Service"]
license = "MIT license"
Expand Down
71 changes: 71 additions & 0 deletions tests/test_template.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pytest
from bs4 import BeautifulSoup
from notifications_utils.template import get_html_email_body


Expand Down Expand Up @@ -40,6 +41,76 @@ def test_lang_tags_in_templates_good_content(good_content: str):
assert '<div lang="fr-ca">' in html


class TestVariablesInLinks:
@pytest.mark.parametrize(
"template_content,variable,expected_html",
[
("((variable))", {}, "((variable))"),
("((variable))", {"variable": "my content"}, "my content"),
],
)
def test_variable(self, template_content, variable, expected_html):
html = BeautifulSoup(str(get_html_email_body(template_content, variable)), "html.parser")
rendered_markdown = html.get_text()
assert rendered_markdown == expected_html

@pytest.mark.parametrize(
"template_content,variable,expected_link_text,expected_href",
[
(
"[link text with ((variable))](https://developer.mozilla.org/en-US/)",
{},
"link text with ((variable))",
"https://developer.mozilla.org/en-US/",
),
(
"[link text with ((variable))](https://developer.mozilla.org/en-US/)",
{"variable": "var"},
"link text with var",
"https://developer.mozilla.org/en-US/",
),
(
"[link with query param](https://developer.mozilla.org/en-US/search?q=asdf)",
{},
"link with query param",
"https://developer.mozilla.org/en-US/search?q=asdf",
),
("[link with variable as url](((url_var)))", {}, "link with variable as url", "url_var"),
(
"[link with variable as url](((url_var)))",
{"url_var": "replaced_variable"},
"link with variable as url",
"replaced_variable",
),
("[link with variable in url](((url_var))/en-US/)", {}, "link with variable in url", "url_var/en-US/"),
(
"[link with variable in url](((url_var))/en-US/)",
{"url_var": "replaced_variable"},
"link with variable in url",
"replaced_variable/en-US/",
),
(
"[link with variable and query param](((url_var))/en-US/search?q=asdf)",
{},
"link with variable and query param",
"url_var/en-US/search?q=asdf",
),
(
"[link with variable and query param](((url_var))/en-US/search?q=asdf)",
{"url_var": "replaced_variable"},
"link with variable and query param",
"replaced_variable/en-US/search?q=asdf",
),
],
)
def test_link_text_with_variable(self, template_content, variable, expected_link_text, expected_href):
html = BeautifulSoup(str(get_html_email_body(template_content, variable)), "html.parser")
href = html.select("a")[0].get_attribute_list("href")[0]
link_text = html.select("a")[0].get_text()
assert href == expected_href
assert link_text == expected_link_text


class TestRTLTags:
def test_rtl_tags_in_templates(self):
content = "[[rtl]]\nRTL content\n[[/rtl]]"
Expand Down
Loading