From 85df7d016afa9f8c9f783c727c7000be2cd672ba Mon Sep 17 00:00:00 2001 From: Christoph Koschel Date: Sat, 8 Jul 2023 21:17:23 +0200 Subject: [PATCH] Enable issue escaping --- action.yml | 6 +++++- main.py | 25 ++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index 8ab5762..9591184 100644 --- a/action.yml +++ b/action.yml @@ -75,4 +75,8 @@ inputs: GITHUB_URL: description: 'Base url of GitHub API' required: false - default: ${{ github.api_url }} \ No newline at end of file + default: ${{ github.api_url }} + ESCAPE: + description: 'Escape all special Markdown characters' + required: false + default: true \ No newline at end of file diff --git a/main.py b/main.py index 0558149..cbc6f0a 100644 --- a/main.py +++ b/main.py @@ -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'] @@ -530,7 +533,10 @@ class TodoParser(object): 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: @@ -541,6 +547,23 @@ class TodoParser(object): 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)