This page is a live test bench for the code-block rendering used across the whole site. Every snippet below is plain HTML inside <pre><code class="language-xxx">; the colours, tokens and the Copy button are added in the browser by Prism.js and the shared copy-code.js script. The sections after the samples explain how that pipeline works, how to add a new language, and the mistakes that most often break highlighting.
Python, SQL, Bash and Go samples follow. If any of them render as plain grey text, the matching prism-<lang>.min.js component is missing from the page head.
def greet(name):
print(f"Hello, {name}!")
def add(a, b):
return a + b
if __name__ == "__main__":
greet("World")
result = add(5, 3)
print(f"5 + 3 = {result}")
SELECT name, age
FROM users
WHERE age > 18
ORDER BY age DESC;
#!/bin/bash
echo "Hello, World!"
mkdir new_directory
cd new_directory
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
func add(a int, b int) int {
return a + b
}
Syntax highlighting is purely presentational: it splits source text into lexical categories such as keywords, strings, comments, numbers and operators, then colours each category so the reader can parse structure at a glance. It does not execute, validate or compile the code. On this site, highlighting is performed client-side by Prism.js, a small library whose core is a few kilobytes and whose languages ship as separate grammar files. Each page loads the core plus the grammars it needs, and every <pre> block also receives a Copy button from the shared /static/copy-code.js script, so readers can paste examples straight into a terminal or notebook.
Because highlighting happens in the browser, the stored HTML stays clean and diff-friendly. The source of each example is exactly the text a reader copies; there are no colour spans in the file that could leak into the clipboard.
When the page finishes parsing, Prism scans the document for code elements whose class contains language-. For each one it looks up the grammar registered under that name, for example Prism.languages.sql. A grammar is an ordered object of regular expressions. Prism walks the text, and for each token type in order it tries its pattern against the remaining unclaimed text. Matched slices become token objects; unmatched slices stay as plain strings. Nested grammars (for example interpolation inside a Python f-string) are handled by recursing into a token's inside grammar.
The token tree is then serialised back to HTML as <span class="token keyword"> and similar elements, and the result replaces the original text content of the code element. The theme stylesheet maps each .token.* class to a colour. Swapping themes therefore changes only CSS, never the page markup.
Order matters. Comments and strings are listed before keywords in almost every grammar so that a word like SELECT inside a quoted string, or a # inside a string literal, is not mis-coloured. When highlighting looks wrong, the cause is usually that a construct the grammar does not know about (a heredoc, a raw string, a dollar-quoted SQL body) let a later pattern claim text it should not have.
Every block on the site follows one shape: an outer <pre>, an inner <code> carrying the language class, and HTML-escaped content. The escaping is not optional. A literal < in a Bash redirect or a Go generic must be written as <, otherwise the browser parses it as a tag before Prism ever sees it, and part of the example silently disappears.
| Language | Class | Grammar file |
|---|---|---|
| Python | language-python | prism-python.min.js |
| SQL | language-sql | prism-sql.min.js |
| Bash / shell | language-bash | prism-bash.min.js |
| Go | language-go | prism-go.min.js |
| YAML | language-yaml | prism-yaml.min.js |
| Java / Scala / C / C++ | language-java etc. | one file each |
Suppose a page needs a JSON example. The core is already present, so only the grammar file and the class are required. Add the component script after prism.min.js in the head (components depend on the core and some depend on others; C++ requires C, for instance), then mark the block.
# verify which Prism components a page loads
grep -o 'prism-[a-z]*\.min\.js' page.html | sort -u
# find code blocks whose language has no matching component
python3 - <<'PY'
import re, sys
html = open("page.html").read()
used = set(re.findall(r'class="language-([a-z]+)"', html))
loaded = set(re.findall(r'prism-([a-z]+)\.min\.js', html))
print("missing grammars:", sorted(used - loaded - {"none"}))
PY
The script compares the languages referenced by blocks with the grammars loaded in the head and prints any gap. A block whose language is missing still renders, just without colour, so this check catches problems that a quick visual scan can miss on a long page.
| Approach | Strengths | Costs |
|---|---|---|
| Client-side (Prism, highlight.js) | Clean source HTML, no build step, theme swap is CSS only | JS must load; brief unstyled flash; per-page grammar list to maintain |
| Build-time (Pygments, Shiki) | Zero runtime JS, works with scripts disabled, very accurate grammars | Needs a build pipeline; colour spans baked into HTML |
| None (plain pre) | Simplest, smallest | Harder to read long examples |
For a hand-edited static site with no build step, client-side highlighting is the pragmatic choice. A site generated by a static-site builder would usually prefer build-time highlighting to remove the JavaScript dependency.
<, > and & inside code.lang-python or python alone is ignored; it must be language-python.<code> renders as an empty first line; it is harmless but visible.