Skip to content

Commit ac9d701

Browse files
committed
fix: correctly escape internal/external links in README
1 parent e177609 commit ac9d701

File tree

4 files changed

+58
-16
lines changed

4 files changed

+58
-16
lines changed

scripts/CSES/README.template.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Accepted solutions of [CSES problemset](https://cses.fi/problemset).
66

77
{% for category, problems in categories.items() %}
88

9-
- [{{ category }}](#{{ category | lower | replace(' ', '-') }})
9+
- [{{ category }}](#{{ category | escape_internal_link }})
1010
{% endfor %}
1111

1212
---
@@ -29,7 +29,7 @@ Accepted solutions of [CSES problemset](https://cses.fi/problemset).
2929
{{ problem.id }}
3030
</td>
3131
<td>
32-
<a href="{{ category | replace(' ', '%20') }}/{{ problem.id }}%20-%20{{ problem.title | replace(' ', '%20') }}.cpp">
32+
<a href="{{ category | escape_external_link }}/{{ problem.id }}%20-%20{{ problem.title | escape_external_link }}.cpp">
3333
💻 {{ problem.title }}
3434
</a>
3535
</td>

scripts/CSES/generate.py

+26-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
import os
21
import logging
2+
import os
3+
import re
4+
import urllib.parse
35

4-
from jinja2 import Template
6+
from jinja2 import Environment, FileSystemLoader
57

68
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
79

810
CSES_SOLUTIONS_DIR = 'solutions/CSES'
9-
TEMPLATE_FILE = 'scripts/CSES/README.template.md'
11+
TEMPLATE_FILE = 'README.template.md'
12+
TEMPLATE_DIR = 'scripts/CSES'
1013

1114
def generate_data_from_folder(path):
1215
data = {}
@@ -33,11 +36,29 @@ def generate_data_from_folder(path):
3336

3437
return data
3538

39+
def escape_internal_link(text):
40+
# Trim leading/trailing spaces
41+
text = text.strip()
42+
# Convert to lowercase
43+
text = text.lower()
44+
# Remove characters that are not word characters, hyphens, or spaces
45+
text = re.sub(r'[^\w\- ]+', '', text)
46+
# Replace spaces with hyphens
47+
text = re.sub(r'\s', '-', text.strip())
48+
# Remove trailing hyphens
49+
text = re.sub(r'\-+$', '', text)
50+
return text
51+
52+
def escape_external_link(text):
53+
return urllib.parse.quote(text)
54+
3655
if __name__ == '__main__':
3756
# Load the template
3857
logging.info('Loading the template')
39-
with open(TEMPLATE_FILE, 'r') as file:
40-
template = Template(file.read())
58+
env = Environment(loader=FileSystemLoader(TEMPLATE_DIR))
59+
env.filters['escape_internal_link'] = escape_internal_link
60+
env.filters['escape_external_link'] = escape_external_link
61+
template = env.get_template(TEMPLATE_FILE)
4162

4263
# Generate the data from the folder structure
4364
logging.info('Starting content generation')

scripts/France-IOI/README.template.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ Accepted solutions of [France-IOI problemset](https://www.france-ioi.org/algo/ch
55
## Table of Contents
66

77
{% for level, chapters in levels.items() %}
8-
- [{{ level }}](#{{ level | lower | replace(' ', '-') }})
8+
- [{{ level }}](#{{ level | escape_internal_link }})
99
{% for chapter, problems in chapters.items() %}
10-
- [{{ chapter }}](#{{ chapter | lower | replace(' ', '-') }})
10+
- [{{ chapter }}](#{{ chapter | escape_internal_link }})
1111
{% endfor %}
1212
{% endfor %}
1313

@@ -22,15 +22,15 @@ Accepted solutions of [France-IOI problemset](https://www.france-ioi.org/algo/ch
2222
### {{ chapter }}
2323

2424
{% for problem in content.problems %}
25-
1. <a href="{{ level | replace(' ', '%20') }}/{{ chapter | replace(' ', '%20') }}/{{ problem.title | replace(' ', '%20') }}.{{ problem.extension }}"> 💻 {{ problem.title }} </a>
25+
1. <a href="{{ level | escape_external_link }}/{{ chapter | escape_external_link }}/{{ problem.title | escape_external_link }}.{{ problem.extension }}"> 💻 {{ problem.title }} </a>
2626
{% endfor %}
2727

2828
{% for part in content.parts %}
2929

3030
1. **{{ part.part }}**
3131

3232
{% for subproblem in part.problems %}
33-
1. <a href="{{ level | replace(' ', '%20') }}/{{ chapter | replace(' ', '%20') }}/{{ part.part | replace(' ', '%20') }}/{{ subproblem.title | replace(' ', '%20') }}.{{ subproblem.extension }}"> 💻 {{ subproblem.title }} </a>
33+
1. <a href="{{ level | escape_external_link }}/{{ chapter | escape_external_link }}/{{ part.part | escape_external_link }}/{{ subproblem.title | escape_external_link }}.{{ subproblem.extension }}"> 💻 {{ subproblem.title }} </a>
3434
{% endfor %}
3535

3636
{% endfor %}

scripts/France-IOI/generate.py

+26-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
import os
21
import logging
2+
import os
3+
import re
4+
import urllib.parse
35

4-
from jinja2 import Template
6+
from jinja2 import Environment, FileSystemLoader
57

68
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
79

810
FRANCE_IOI_SOLUTIONS_DIR = 'solutions/France-IOI'
9-
TEMPLATE_FILE = 'scripts/France-IOI/README.template.md'
11+
TEMPLATE_FILE = 'README.template.md'
12+
TEMPLATE_DIR = 'scripts/France-IOI'
1013

1114
def generate_data_from_folder(path):
1215
data = {}
@@ -59,11 +62,29 @@ def generate_data_from_folder(path):
5962

6063
return data
6164

65+
def escape_internal_link(text):
66+
# Trim leading/trailing spaces
67+
text = text.strip()
68+
# Convert to lowercase
69+
text = text.lower()
70+
# Remove characters that are not word characters, hyphens, or spaces
71+
text = re.sub(r'[^\w\- ]+', '', text)
72+
# Replace spaces with hyphens
73+
text = re.sub(r'\s', '-', text.strip())
74+
# Remove trailing hyphens
75+
text = re.sub(r'\-+$', '', text)
76+
return text
77+
78+
def escape_external_link(text):
79+
return urllib.parse.quote(text)
80+
6281
if __name__ == '__main__':
6382
# Load the template
6483
logging.info('Loading the template')
65-
with open(TEMPLATE_FILE, 'r') as file:
66-
template = Template(file.read())
84+
env = Environment(loader=FileSystemLoader(TEMPLATE_DIR))
85+
env.filters['escape_internal_link'] = escape_internal_link
86+
env.filters['escape_external_link'] = escape_external_link
87+
template = env.get_template(TEMPLATE_FILE)
6788

6889
# Generate the data from the folder structure
6990
logging.info('Starting content generation')

0 commit comments

Comments
 (0)