Skip to content

Commit

Permalink
Merge pull request #162 from Christoph-Koschel/patch-1
Browse files Browse the repository at this point in the history
Escape special Markdown characters
  • Loading branch information
alstr authored Sep 7, 2023
2 parents c90d4c3 + b11a016 commit 41e6824
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 3 deletions.
6 changes: 5 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,8 @@ inputs:
GITHUB_URL:
description: 'Base url of GitHub API'
required: false
default: ${{ github.api_url }}
default: ${{ github.api_url }}
ESCAPE:
description: 'Escape all special Markdown characters'
required: false
default: true
25 changes: 24 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,9 @@ class TodoParser(object):
ORG_PROJECTS_PATTERN = re.compile(r'(?<=org projects:\s).+')

def __init__(self):
# Determine if the Issues should be escaped.
self.should_escape = os.getenv('INPUT_ESCAPE', 'true') == 'true'

# Load any custom identifiers, otherwise use the default.
custom_identifiers = os.getenv('INPUT_IDENTIFIERS')
self.identifiers = ['TODO']
Expand Down Expand Up @@ -530,7 +533,10 @@ def _extract_issue_if_exists(self, comment, marker, code_block):
elif org_projects:
issue.org_projects.extend(org_projects)
elif len(cleaned_line):
issue.body.append(cleaned_line)
if self.should_escape:
issue.body.append(self._escape_markdown(cleaned_line))
else:
issue.body.append(cleaned_line)

if issue is not None and issue.identifier is not None and self.identifiers_dict is not None:
for identifier_dict in self.identifiers_dict:
Expand All @@ -541,6 +547,23 @@ def _extract_issue_if_exists(self, comment, marker, code_block):

return issue

@staticmethod
def _escape_markdown(comment):
# All basic characters according to: https://www.markdownguide.org/basic-syntax
must_escaped = ['\\', '<', '>', '#', '`', '*', '_', '[', ']', '(', ')', '!', '+', '-', '.', '|', '{', '}', '~', '=']

escaped = ''

# Linear Escape Algorithm, because the algorithm ends in an infinite loop when using the function 'replace',
# which tries to replace all backslashes with duplicate backslashes, i.e. also the already other escaped
# characters.
for c in comment:
if c in must_escaped:
escaped += '\\' + c
else:
escaped += c
return escaped

def _get_line_status(self, comment):
"""Return a Tuple indicating whether this is an addition/deletion/unchanged, plus the cleaned comment."""
addition_search = self.ADDITION_PATTERN.search(comment)
Expand Down
19 changes: 19 additions & 0 deletions tests/test_escape.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
diff --git a/tests/ExampleFile.java b/tests/ExampleFile.java
index d340f6a..29b54da 100644
--- a/tests/ExampleFile.java
+++ b/tests/ExampleFile.java
@@ -1,13 +1,5 @@
package com.mydomain.myapp;

public class JavaTests {
- // TODO: Some Java
- // # Some title
- // <SomeTag>

- /*
- TODO: Definitely some Java
- # Another title
- <AnotherTag>
- */
}
\ No newline at end of file
25 changes: 24 additions & 1 deletion tests/test_todo_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def test_clojure_issues(self):

def test_nix_issues(self):
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'nix'), 2)

def test_xaml_issues(self):
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'xml'), 2)

Expand Down Expand Up @@ -204,3 +204,26 @@ def test_multiple_ignores(self):
# Includes 2 tests for Crystal.
self.assertEqual(count_issues_for_file_type(self.raw_issues, 'ruby'), 5)
os.environ['INPUT_IGNORE'] = ''

class EscapeMarkdownTest(unittest.TestCase):
def test_simple_escape(self):
os.environ['INPUT_ESCAPE'] = 'true'
parser = TodoParser()
with open('syntax.json', 'r') as syntax_json:
parser.syntax_dict = json.load(syntax_json)
diff_file = open('tests/test_escape.diff', 'r')

# I had no other idea to make these checks dynamic.
self.raw_issues = parser.parse(diff_file)
self.assertEqual(len(self.raw_issues), 2)

issue = self.raw_issues[0]
self.assertEqual(len(issue.body), 2)
self.assertEqual(issue.body[0], '\\# Some title')
self.assertEqual(issue.body[1], '\\<SomeTag\\>')

issue = self.raw_issues[1]
self.assertEqual(len(issue.body), 2)
self.assertEqual(issue.body[0], '\\# Another title')
self.assertEqual(issue.body[1], '\\<AnotherTag\\>')

0 comments on commit 41e6824

Please sign in to comment.