diff --git a/check50/renderer/_renderers.py b/check50/renderer/_renderers.py
index 0ddc252a..0d42244b 100644
--- a/check50/renderer/_renderers.py
+++ b/check50/renderer/_renderers.py
@@ -14,11 +14,56 @@ def to_html(slug, results, version):
content = f.read()
template = jinja2.Template(
- content, autoescape=jinja2.select_autoescape(enabled_extensions=("html",)))
- html = template.render(slug=slug, results=results, version=version)
+ content, autoescape=jinja2.select_autoescape(enabled_extensions=("html",))
+ )
+
+ html = template.render(
+ slug=slug,
+ results=results,
+ version=version,
+ fmt_special_chars=_fmt_special_chars,
+ color="808080" # RGB (128, 128, 128)
+ )
return html
+def _fmt_special_chars(txt, color):
+ """Converts a plaintext string into a string of HTML elements that highlights special chars."""
+ def highlight_char(char, color):
+ """Highlights and escapes a char."""
+ return f"{repr(char)[1:-1]}"
+
+ # We'd like to interpret whitespace (ws) as HTML in only these specific cases:
+ ws_to_html = {
+ "\n": "
",
+ " ": " ",
+ }
+ fmtted_txt = []
+
+ for i, char in enumerate(txt):
+ is_last = i == len(txt) - 1
+
+ if not char.isprintable() and char not in ws_to_html:
+ # Most special invisible characters, excluding those in ws_to_html, are highlighted
+ fmtted_txt.append(highlight_char(char, color))
+ elif char in ws_to_html:
+ # If there's a trailing whitespace character, we highlight it
+ if is_last:
+ # Spaces aren't normally highlightable, so we convert to nbsp.
+ if char == ' ':
+ char = ws_to_html[char]
+
+ fmtted_txt.append(highlight_char(char, color))
+ else:
+ # Certain special chars are interpreted in HTML, without escaping or highlighting
+ fmtted_txt.append(ws_to_html[char])
+ else:
+ # Non-special characters are unchanged
+ fmtted_txt.append(char)
+
+ # Return the text as a string of plaintext + html elements
+ return ''.join(fmtted_txt)
+
def to_json(slug, results, version):
return json.dumps({"slug": slug, "results": results, "version": version}, indent=4)
diff --git a/check50/renderer/templates/results.html b/check50/renderer/templates/results.html
index 6a51efa8..40b58d7f 100644
--- a/check50/renderer/templates/results.html
+++ b/check50/renderer/templates/results.html
@@ -86,7 +86,7 @@