From 0940eba0dee9ea51c23d7a55bfd6319ebba2f9d2 Mon Sep 17 00:00:00 2001 From: Prowler Bot Date: Wed, 29 Jul 2026 10:56:03 +0200 Subject: [PATCH] fix(sdk): render inline code with valid ADF marks (#12213) Co-authored-by: Hugo Pereira Brito <101209179+HugoPBrito@users.noreply.github.com> --- .../changelog.d/jira-adf-metadata.fixed.md | 1 + prowler/lib/outputs/jira/jira.py | 4 +- tests/lib/outputs/jira/jira_test.py | 46 ++++++++++++++++++- 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 prowler/changelog.d/jira-adf-metadata.fixed.md diff --git a/prowler/changelog.d/jira-adf-metadata.fixed.md b/prowler/changelog.d/jira-adf-metadata.fixed.md new file mode 100644 index 0000000000..c227c4a473 --- /dev/null +++ b/prowler/changelog.d/jira-adf-metadata.fixed.md @@ -0,0 +1 @@ +Jira descriptions with inline code nested in bold or italic Markdown now render as valid ADF diff --git a/prowler/lib/outputs/jira/jira.py b/prowler/lib/outputs/jira/jira.py index 601120cdfc..9fb4c7d6ad 100644 --- a/prowler/lib/outputs/jira/jira.py +++ b/prowler/lib/outputs/jira/jira.py @@ -203,7 +203,9 @@ class MarkdownToADFConverter: if token_type == "text": result.extend(self._text_to_nodes(token.content, marks_stack)) elif token_type == "code_inline": - marks = self._clone_marks(marks_stack) + marks = self._clone_marks( + [mark for mark in marks_stack if mark["type"] == "link"] + ) marks.append({"type": "code"}) result.append(self._create_text_node(token.content, marks)) elif token_type in {"softbreak", "hardbreak"}: diff --git a/tests/lib/outputs/jira/jira_test.py b/tests/lib/outputs/jira/jira_test.py index f38c1ba376..9abd2d26a1 100644 --- a/tests/lib/outputs/jira/jira_test.py +++ b/tests/lib/outputs/jira/jira_test.py @@ -23,11 +23,55 @@ from prowler.lib.outputs.jira.exceptions.exceptions import ( JiraSendFindingsResponseError, JiraTestConnectionError, ) -from prowler.lib.outputs.jira.jira import Jira +from prowler.lib.outputs.jira.jira import Jira, MarkdownToADFConverter TEST_DATETIME = "2023-01-01T12:01:01+00:00" +class TestMarkdownToADFConverter: + def setup_method(self): + self.converter = MarkdownToADFConverter() + + def test_inline_code_nested_in_strong_has_only_code_mark(self): + result = self.converter.convert("**before `code` after**") + + assert result[0]["content"] == [ + {"type": "text", "text": "before ", "marks": [{"type": "strong"}]}, + {"type": "text", "text": "code", "marks": [{"type": "code"}]}, + {"type": "text", "text": " after", "marks": [{"type": "strong"}]}, + ] + + def test_inline_code_nested_in_emphasis_has_only_code_mark(self): + result = self.converter.convert("*before `code` after*") + + assert result[0]["content"] == [ + {"type": "text", "text": "before ", "marks": [{"type": "em"}]}, + {"type": "text", "text": "code", "marks": [{"type": "code"}]}, + {"type": "text", "text": " after", "marks": [{"type": "em"}]}, + ] + + def test_inline_code_in_link_preserves_link_and_code_marks(self): + result = self.converter.convert("[`code`](https://example.com)") + + assert result[0]["content"][0]["marks"] == [ + {"type": "link", "attrs": {"href": "https://example.com"}}, + {"type": "code"}, + ] + + def test_inline_code_in_emphasized_link_preserves_link_and_code_marks(self): + result = self.converter.convert("*[`code`](https://example.com)*") + + assert result[0]["content"][0]["marks"] == [ + {"type": "link", "attrs": {"href": "https://example.com"}}, + {"type": "code"}, + ] + + def test_standalone_inline_code_has_code_mark(self): + result = self.converter.convert("`code`") + + assert result[0]["content"][0]["marks"] == [{"type": "code"}] + + class TestJiraIntegration: @pytest.fixture(autouse=True) @patch.object(Jira, "get_auth", return_value=None)