Syntax highlighting plugin for PicoCMS
Table of Contents
PicoPygments ∆
A PicoCMS plugin that adds Pygments syntax highlighting to code blocks that have a language definition.
Requirements ∆
You need
- to have PicoCMS up and running.
- the DOM module for PHP (possibly also the SimpeXML and XML modules; on Debian, these are packaged into
php-xml
. - Python3 and a Python3 version of Pygments. I tested with both
python3-pygments
from Debian stable repos (2.3.1) and a much newer, pip-installed version - both worked.
Tested on Debian buster (stable), PicoCMS 2.1.4 and PHP 7.3.
Installation ∆
There are two ways - cloning the git repository, or manually downloading the plugin.
Git clone ∆
- Change into your PicoCMS install's
/plugin
directory, open a terminal there. - Execute
git clone https://$site.org/ohnonot/PicoPygments
, where$site
is eitherframagit
ornotabug
.
If you follow a few simple rules, you can always cd PicoPygments; git pull
to the newest version:
- Don't edit any files inside the repository.
- Copy the
picopygments.yml
config file to your PicoCMS install's/config
directory. - Create custom files inside the repository that have the word
custom
in their name (see.gitignore
) and edit/config/picopygments.yml
to point to those. Currently this only applies to thestylesheet
configuration.
Manual download ∆
- Download the master.zip into your PicoCMS install's
/plugin
directory. - Extract it in place - you should now have a
PicoPygments
folder that immediately containsPicoPygments.php
and some other files. In other words, from your PicoCMS install's base directory, you should have/plugins/PicoPygments/PicoPygments.php
(and some other files and directories).
That should be enough.
As usual, you should copy the picopygments.yml
configuration file to your PicoCMS installation's /config
folder and make your adjustments there.
Configuration ∆
The plugin should be enabled by default, and its own caching should also work by default.
If you want to make sure, set debug: true
in your PicoCMS' config.yml
, you will see some messages at the top
of the page. After first loading a page all code blocks on that page should be cached, greatly reducing loading times.
They are cached with a unique filename representing the code itself and PicoPygments' configuration.
If anything changes there, new versions are generated.
Additionally you can explicitely disable PicoPygments for a particular page by adding picopygments: false
to its YAML header.
Styles, Colors, CSS ∆
Base16 ∆
If the page's already existing stylesheet declares the CSS variables --base00
through --base0f
in its :root
(see the TagBlog theme's README.md (mirror) for details), PicoPygments will automatically apply them.
This happens through the default css/base16var_with_fallback.css
stylesheet. If
these variables are not defined, then the fallbacks following them will be applied . They come from the Base16 Equilibrium Light scheme (and the TagBlog theme currently uses the same as fallback).
As the names of the variables suggest they should adhere to the [Base16 Styling Guidelines][bsg].
However, it is still possible to use a different stylesheet with the stylesheet
setting in picopygments.yml
.
Options are provided in the css/generated
folder.
BTW, you can preview many Pygments styles here, and most Base16 styles here.
Those Pygments styles that are not Base16 styles can be generated with scripts/styles.py
(be sure to read scripts/README.md
first).
Additional to colors, there's a _common.css
file with overrides for all styles.
Line numbers ∆
It is possible by editing the formatteroptions
configuration under the DANGER ZONE in /config/picopygments.yml
.
I have tried to integrate line numbers, but this introduces too many quirks and (what I consider) inconsistencies in Pygments' behaviour. They work fine as such, but possibly
- your code blocks will get even larger, with empty elements.
- the code block will look weird, with double borders etc (fixable with CSS).
- you have to decide if you want line numbers for either all code blocks or none.
Usage ∆
You have a markdown article with a fenced code block. If you append a language keyword to the opening fence, this plugin will become active. Example:
md## This is what I coded in Lua: ```lua -- try to find themes in $HOME themedir = os.getenv("HOME") .. '/.local/share/themes/' ```
will use Lua syntax highlighting for this block of code.
If you're unsure which language to choose for your code you can run the included guess.py
script,
enter the raw code in question, and Pygments will tell you what it thinks about it.
The plugin activates after PicoCMS has converted your Markdown articles to HTML, it replaces code
blocks therein if they have a language class, like this: <code class="language-lua">...</code>
.
PicoCMS uses Parsedown and Parsedown Extra which is supposed to implement
Markdown Extra, but I found that this particular feature is not as rich as outlined here:
- It won't handle more than one class added.
- If you don't use the simple syntax above, but try to add multiple classes or dots or brackets
(e.g.
~~~ .lua
,~~~{.lua .my-code}
,~~~{.lua #my-code}
etc.) the extra characters show up in the langauge class and you end up with something like<code class="language-{.lua">
.
This plugin sanitizes these strings, but multiple classes won't work.
Highlighting inline code (not a block of code) ∆
Neither Markdown Extra nor Parsedown Extra have a means to put a CSS class on inline code, but you can write it out as HTML in your Markdown text. Instead of
I typed `while true; do echo Yes; done` without looking.
you have to write
I typed <code class="language-bash">while true; do echo Yes; done</code> without looking.
Background ∆
The plugin does all its work server-side.
If you care about keeping your site javascript free, you might like this.
If not - I would recommend other solutions.
It is written in PHP, just like PicoCMS itself, but Pygments is written in Python and
there is no PHP version of it.
Therefore it needs to execute an external program with exec, which is just python3 -I
with an ad-hoc generated script
(it does not call the pygmentize
script included with python-pygmentize).
This increases loading times much more than any pure PHP solution (but IMO Pygments is still the best,
most up-to-date solution for non-javascript syntax highlighting).
To minimise this impact the plugin
- considers only code blocks that are marked with a language class (it does not guess at the language)
- executes
python
at most once per page (and not once per code block) - caches Pygments' output and prefers to re-use that.
So the best-case scenario is that all code blocks have been cached peviously and will be read
from (RAM)disk, and there's no need to call python at all.
I made some (unscientific, anecdotal) comparisons with Firefox' developer tools - the result is clear enough:
- Without internal caching this plugin adds between 66% and 91% to the loading time (the HTML of the page only, no assets like images or CSS).
- With internal caching (and all code blocks loaded from cache) the plugin adds between 2% and 5% to the loading time.
Get it here ∆
framagit.org/ohnonot/PicoPygments / notabug.org/ohnonot/PicoPygments