How to Add Syntax Highlighting to Pure Blog
This guide walks through adding server-side syntax highlighting to Pure Blog using highlight.php — a PHP port of highlight.js. Because highlighting happens on the server, no JavaScript is required.
You will need four things:
- The highlight.php library files copied into your site.
- An entry in
config/update-ignoreto protect them from being overwritten on updates. - An
on_render_markdownhook that runs the highlighter over fenced code blocks. - A CSS theme file linked in your post pages.
Step 1: Get the library
Download the latest release from github.com/scrivo/highlight.php. Inside the zip you'll find a src/ directory containing two folders: Highlight and HighlightUtilities.
Copy both into your site's lib/ directory so the structure looks like this:
lib/
Highlight/
Autoloader.php
Highlighter.php
... (languages, etc.)
HighlightUtilities/
functions.php
...
Also copy the LICENSE file from the repo root into lib/Highlight/LICENSE.txt to satisfy the BSD 3-Clause licence terms.
Step 2: Protect the library from updates
Pure Blog's update system will overwrite files in the site root. Add the library directories to config/update-ignore so they're preserved:
lib/Highlight
lib/HighlightUtilities
Step 3: Add the hook
The on_render_markdown filter fires on the rendered HTML of every post and page, before it's returned to the browser. Add the following to config/hooks.php:
require_once __DIR__ . '/../lib/Highlight/Autoloader.php';
spl_autoload_register('\\Highlight\\Autoloader::load');
function on_render_markdown(string $html): string
{
return preg_replace_callback(
'/<pre><code class="language-([a-zA-Z0-9_+\-]+)">(.*?)<\/code><\/pre>/s',
function (array $m): string {
$lang = $m[1];
$code = html_entity_decode($m[2], ENT_QUOTES | ENT_HTML5, 'UTF-8');
try {
$highlighter = new \Highlight\Highlighter();
$result = $highlighter->highlight($lang, $code);
return '<pre><code class="hljs language-'
. htmlspecialchars($result->language, ENT_QUOTES, 'UTF-8') . '">'
. $result->value
. '</code></pre>';
} catch (\Exception $e) {
return $m[0];
}
},
$html
) ?? $html;
}
The hook matches fenced code blocks that Parsedown has already rendered to <pre><code class="language-xxx">, decodes the HTML entities back to raw code, runs the highlighter, and returns the highlighted markup. If the language isn't recognised it falls back to the original block unchanged.
Step 4: Add the CSS
The highlight.php repo includes pre-built CSS themes in its styles/ directory. Copy the theme you want into content/css/ in your site.
A good starting point is to use atom-one-light for light mode and atom-one-dark for dark mode, combined into a single file using @media (prefers-color-scheme: dark).
Save this as content/css/syntax.css.
Link the stylesheet
Since syntax highlighting is only needed on post pages, add a <link> tag via Admin → Settings → Head Inject (Posts):
<link rel="stylesheet" href="/content/css/syntax.css">
Alternatively, if you want it on all pages, you can paste the CSS directly into content/css/custom.css and Pure Blog will inline it automatically.
That's it — fenced code blocks with a language identifier will now be highlighted server-side with no JavaScript required.
How to use syntax highlighting with markdown
To trigger highlighting, use a fenced code block with a language identifier:
```php
function hello(): string
{
return 'Hello, world!';
}
```
The language name must match one of the identifiers supported by highlight.js — common ones include php, javascript, python, css, html, bash, sql, json, and yaml. A full list is available in the lib/Highlight/languages/ directory of your site (each filename without .json is a valid identifier).
If you omit the language identifier, Parsedown renders the block without a language-xxx class and the hook leaves it untouched — it will render as a plain unstyled code block.