From ac9d70138565b2e9c8cfe6242bd431bbeab85eb4 Mon Sep 17 00:00:00 2001 From: Omar Besbes <86571415+omar-besbes@users.noreply.github.com> Date: Sat, 12 Oct 2024 01:30:09 +0100 Subject: [PATCH] fix: correctly escape internal/external links in README --- scripts/CSES/README.template.md | 4 ++-- scripts/CSES/generate.py | 31 ++++++++++++++++++++++----- scripts/France-IOI/README.template.md | 8 +++---- scripts/France-IOI/generate.py | 31 ++++++++++++++++++++++----- 4 files changed, 58 insertions(+), 16 deletions(-) diff --git a/scripts/CSES/README.template.md b/scripts/CSES/README.template.md index 181f101..d439370 100644 --- a/scripts/CSES/README.template.md +++ b/scripts/CSES/README.template.md @@ -6,7 +6,7 @@ Accepted solutions of [CSES problemset](https://cses.fi/problemset). {% for category, problems in categories.items() %} -- [{{ category }}](#{{ category | lower | replace(' ', '-') }}) +- [{{ category }}](#{{ category | escape_internal_link }}) {% endfor %} --- @@ -29,7 +29,7 @@ Accepted solutions of [CSES problemset](https://cses.fi/problemset). {{ problem.id }} - + 💻 {{ problem.title }} diff --git a/scripts/CSES/generate.py b/scripts/CSES/generate.py index af69cce..9190a40 100644 --- a/scripts/CSES/generate.py +++ b/scripts/CSES/generate.py @@ -1,12 +1,15 @@ -import os import logging +import os +import re +import urllib.parse -from jinja2 import Template +from jinja2 import Environment, FileSystemLoader logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') CSES_SOLUTIONS_DIR = 'solutions/CSES' -TEMPLATE_FILE = 'scripts/CSES/README.template.md' +TEMPLATE_FILE = 'README.template.md' +TEMPLATE_DIR = 'scripts/CSES' def generate_data_from_folder(path): data = {} @@ -33,11 +36,29 @@ def generate_data_from_folder(path): return data +def escape_internal_link(text): + # Trim leading/trailing spaces + text = text.strip() + # Convert to lowercase + text = text.lower() + # Remove characters that are not word characters, hyphens, or spaces + text = re.sub(r'[^\w\- ]+', '', text) + # Replace spaces with hyphens + text = re.sub(r'\s', '-', text.strip()) + # Remove trailing hyphens + text = re.sub(r'\-+$', '', text) + return text + +def escape_external_link(text): + return urllib.parse.quote(text) + if __name__ == '__main__': # Load the template logging.info('Loading the template') - with open(TEMPLATE_FILE, 'r') as file: - template = Template(file.read()) + env = Environment(loader=FileSystemLoader(TEMPLATE_DIR)) + env.filters['escape_internal_link'] = escape_internal_link + env.filters['escape_external_link'] = escape_external_link + template = env.get_template(TEMPLATE_FILE) # Generate the data from the folder structure logging.info('Starting content generation') diff --git a/scripts/France-IOI/README.template.md b/scripts/France-IOI/README.template.md index 68da95e..616be29 100644 --- a/scripts/France-IOI/README.template.md +++ b/scripts/France-IOI/README.template.md @@ -5,9 +5,9 @@ Accepted solutions of [France-IOI problemset](https://www.france-ioi.org/algo/ch ## Table of Contents {% for level, chapters in levels.items() %} -- [{{ level }}](#{{ level | lower | replace(' ', '-') }}) +- [{{ level }}](#{{ level | escape_internal_link }}) {% for chapter, problems in chapters.items() %} - - [{{ chapter }}](#{{ chapter | lower | replace(' ', '-') }}) + - [{{ chapter }}](#{{ chapter | escape_internal_link }}) {% endfor %} {% endfor %} @@ -22,7 +22,7 @@ Accepted solutions of [France-IOI problemset](https://www.france-ioi.org/algo/ch ### {{ chapter }} {% for problem in content.problems %} -1. 💻 {{ problem.title }} +1. 💻 {{ problem.title }} {% endfor %} {% for part in content.parts %} @@ -30,7 +30,7 @@ Accepted solutions of [France-IOI problemset](https://www.france-ioi.org/algo/ch 1. **{{ part.part }}** {% for subproblem in part.problems %} - 1. 💻 {{ subproblem.title }} + 1. 💻 {{ subproblem.title }} {% endfor %} {% endfor %} diff --git a/scripts/France-IOI/generate.py b/scripts/France-IOI/generate.py index a281502..da7f590 100644 --- a/scripts/France-IOI/generate.py +++ b/scripts/France-IOI/generate.py @@ -1,12 +1,15 @@ -import os import logging +import os +import re +import urllib.parse -from jinja2 import Template +from jinja2 import Environment, FileSystemLoader logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') FRANCE_IOI_SOLUTIONS_DIR = 'solutions/France-IOI' -TEMPLATE_FILE = 'scripts/France-IOI/README.template.md' +TEMPLATE_FILE = 'README.template.md' +TEMPLATE_DIR = 'scripts/France-IOI' def generate_data_from_folder(path): data = {} @@ -59,11 +62,29 @@ def generate_data_from_folder(path): return data +def escape_internal_link(text): + # Trim leading/trailing spaces + text = text.strip() + # Convert to lowercase + text = text.lower() + # Remove characters that are not word characters, hyphens, or spaces + text = re.sub(r'[^\w\- ]+', '', text) + # Replace spaces with hyphens + text = re.sub(r'\s', '-', text.strip()) + # Remove trailing hyphens + text = re.sub(r'\-+$', '', text) + return text + +def escape_external_link(text): + return urllib.parse.quote(text) + if __name__ == '__main__': # Load the template logging.info('Loading the template') - with open(TEMPLATE_FILE, 'r') as file: - template = Template(file.read()) + env = Environment(loader=FileSystemLoader(TEMPLATE_DIR)) + env.filters['escape_internal_link'] = escape_internal_link + env.filters['escape_external_link'] = escape_external_link + template = env.get_template(TEMPLATE_FILE) # Generate the data from the folder structure logging.info('Starting content generation')