Skip to content

Commit 6d562d1

Browse files
JacobCoffeetheblairwhichprojectclaude
committed
feat: use Pygments for code sample syntax highlighting
Replace manual regex-based HTML formatting with Pygments PythonConsoleLexer for proper syntax highlighting of homepage code samples. Addresses reviewer feedback on #2538. - Add Pygments dependency - Clean up code samples to plain text (no hand-written HTML spans) - Map Pygments CSS classes (.c1, .go, .gp) in stylesheet - Fix HTML entity escaping (now handled by Pygments automatically) Co-Authored-By: Tim Hoffmann <tim.hoffmann@gmail.com> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 43c8e2a commit 6d562d1

3 files changed

Lines changed: 46 additions & 41 deletions

File tree

apps/codesamples/factories.py

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
import factory
66
from factory.django import DjangoModelFactory
7+
from pygments import highlight
8+
from pygments.formatters import HtmlFormatter
9+
from pygments.lexers import PythonConsoleLexer
710

811
from apps.codesamples.models import CodeSample
912
from apps.users.factories import UserFactory
@@ -26,22 +29,28 @@ class Meta:
2629
is_published = True
2730

2831

32+
def _highlight_python_console(code):
33+
"""Highlight a Python console code snippet using Pygments."""
34+
code = textwrap.dedent(code).strip()
35+
html = highlight(code, PythonConsoleLexer(), HtmlFormatter(nowrap=True))
36+
return f"<pre><code>{html}</code></pre>"
37+
38+
2939
def initial_data():
3040
"""Create the default set of homepage code samples."""
3141
code_samples = [
3242
(
33-
"""\
34-
<pre><code><span class=\"comment\"># Simple output (with Unicode)</span>
43+
"""
44+
# Simple output (with Unicode)
3545
>>> print("Hello, I'm Python!")
36-
<span class=\"output\">Hello, I'm Python!</span>
46+
Hello, I'm Python!
3747
38-
<span class=\"comment\"># Input, assignment</span>
39-
>>> name = input('What is your name?\n')
40-
<span class=\"output\">What is your name?
41-
Python</span>
48+
# Input, assignment
49+
>>> name = input('What is your name?\\n')
4250
>>> print(f'Hi, {name}.')
43-
<span class=\"output\">Hi, Python.</span></code>
44-
</pre>
51+
What is your name?
52+
Python
53+
Hi, Python.
4554
""",
4655
"""\
4756
<h1>Quick &amp; Easy to Learn</h1>
@@ -53,16 +62,16 @@ def initial_data():
5362
""",
5463
),
5564
(
56-
"""\
57-
<pre><code><span class=\"comment\"># Simple arithmetic</span>
65+
"""
66+
# Simple arithmetic
5867
>>> 1 / 2
59-
<span class=\"output\">0.5</span>
68+
0.5
6069
>>> 2 ** 3
61-
<span class=\"output\">8</span>
62-
>>> 17 / 3 <span class=\"comment\"># true division returns a float</span>
63-
<span class=\"output\">5.666666666666667</span>
64-
>>> 17 // 3 <span class=\"comment\"># floor division</span>
65-
<span class=\"output\">5</span></code></pre>
70+
8
71+
>>> 17 / 3 # true division returns a float
72+
5.666666666666667
73+
>>> 17 // 3 # floor division
74+
5
6675
""",
6776
"""\
6877
<h1>Intuitive Interpretation</h1>
@@ -76,16 +85,16 @@ def initial_data():
7685
""",
7786
),
7887
(
79-
"""\
80-
<pre><code><span class=\"comment\"># List comprehensions</span>
88+
"""
89+
# List comprehensions
8190
>>> fruits = ['Banana', 'Apple', 'Lime']
8291
>>> loud_fruits = [fruit.upper() for fruit in fruits]
8392
>>> print(loud_fruits)
84-
<span class=\"output\">['BANANA', 'APPLE', 'LIME']</span>
93+
['BANANA', 'APPLE', 'LIME']
8594
86-
<span class=\"comment\"># List and the enumerate function</span>
95+
# List and the enumerate function
8796
>>> list(enumerate(fruits))
88-
<span class=\"output\">[(0, 'Banana'), (1, 'Apple'), (2, 'Lime')]</span></code></pre>
97+
[(0, 'Banana'), (1, 'Apple'), (2, 'Lime')]
8998
""",
9099
"""\
91100
<h1>Compound Data Types</h1>
@@ -97,19 +106,15 @@ def initial_data():
97106
""",
98107
),
99108
(
100-
"""\
101-
<pre>
102-
<code>
103-
<span class=\"comment\"># For loop on a list</span>
109+
"""
110+
# For loop on a list
104111
>>> numbers = [2, 4, 6, 8]
105112
>>> product = 1
106113
>>> for number in numbers:
107114
... product = product * number
108115
...
109116
>>> print('The product is:', product)
110-
<span class=\"output\">The product is: 384</span>
111-
</code>
112-
</pre>
117+
The product is: 384
113118
""",
114119
"""\
115120
<h1>All the Flow You&rsquo;d Expect</h1>
@@ -122,21 +127,17 @@ def initial_data():
122127
""",
123128
),
124129
(
125-
"""\
126-
<pre>
127-
<code>
128-
<span class=\"comment\"># Write Fibonacci series up to n</span>
130+
"""
131+
# Write Fibonacci series up to n
129132
>>> def fib(n):
130133
... a, b = 0, 1
131-
... while a &lt; n:
134+
... while a < n:
132135
... print(a, end=' ')
133136
... a, b = b, a+b
134137
... print()
135138
...
136139
>>> fib(1000)
137-
<span class=\"output\">0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610</span>
138-
</code>
139-
</pre>
140+
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610
140141
""",
141142
"""\
142143
<h1>Functions Defined</h1>
@@ -151,7 +152,7 @@ def initial_data():
151152
return {
152153
"boxes": [
153154
CodeSampleFactory(
154-
code=textwrap.dedent(code),
155+
code=_highlight_python_console(code),
155156
copy=textwrap.dedent(copy),
156157
)
157158
for code, copy in code_samples

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ dependencies = [
2020
"docutils==0.21.2",
2121
"Markdown==3.7",
2222
"cmarkgfm==2024.11.20",
23+
"Pygments>=2.17",
2324
"Pillow==10.4.0",
2425
"psycopg2-binary==2.9.9",
2526
"python3-openid==3.2.0",

static/sass/style.css

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,10 +1529,13 @@ input#s,
15291529
.slide-code code {
15301530
display: inline-block;
15311531
color: #0d870d; }
1532-
.slide-code code .comment {
1533-
color: #666666; }
1534-
.slide-code code .output {
1532+
.slide-code code .c1 {
1533+
color: #666666;
1534+
font-style: normal; }
1535+
.slide-code code .go {
15351536
color: #dddddd; }
1537+
.slide-code code .gp {
1538+
color: #c65d09; }
15361539

15371540
.js .launch-shell, .no-js .launch-shell {
15381541
display: none; }

0 commit comments

Comments
 (0)