This is a documentation file for Code Highlighter's developers.
This section describes how to setup your development environment.
This project requires the following tools:
-
Install the required Python version:
pyenv install
-
Set up Poetry:
poetry install
-
Install Lefthook:
lefthook install
Anki code highlighter comes in bundled with the highlight.js JavaScript
package. The JS package's files are included in assets
, e.g.,
assets/_ch-highlight.js
contains the single-file implementation of
highlight.js.
To update highlight.js:
- Set
HLJS_VERSION
intools/hljs.py
. - Run
python tools/hljs.py
.
Anki code hightlighter comes in bundled with the Pygments library, and its version is tracked as a Git submodule inside this repository.
To update Pygments, go to the submodule and pull the desired version. For example:
cd pydeps/pygments
git fetch
git checkout 2.18.0
In assets/_ch-pygment-solarized.css
I keep the stylesheet for code formatted
with pygments plus a few lines for general styles. I generated the style there with
dev/bin/pygutils.py
with some minor adjustments by hand:
- There are some tech debt lines relevant for all
<pre><code>
tags. - I have added some custom styles for borders.
- Run unit tests and mypy with
just test
. - Test supported Anki versions (2.1.49 and latest) by packaging the plugin and importing the plugin into the lowest and the newest support Anki.
- Create a release commit.
- Bump up the package version in
codehighlighter/manifest.json
andpyproject.toml
. - Tag the release commit
git tag vx.y.z && git push origin vx.y.z
.
- Bump up the package version in
- Use the
dev/bin/package
tool to createcodehighlighter.ankiaddon
. - Create a GitHub release:
gh release create vx.y.z codehighlighter.ankiaddon
. - Share the package on Anki.
This section discuss some design decisions made for this plugin.
One fundamental abstraction is that of highlighter. A highlighter is essentially a function that produces an HTML representing a highlighted code snippet given the following:
- A string with the unmarked code snippet.
- A language that code snippet represents.
- Additional styling options.
For code clarity and modularity, I keep such pure highlighters in separate
modules (hljs
and pygments
). A highlighter does not implement any logic
related to Anki including sanitising input from HTML markup.
The asset files start with an underscore, because then Anki ignores them (source).
This plugin saves its assets directly in the global assets
directory.
- The only way to share files across desktop and mobile seems to be through
collection.media
. - Anki does not support file directories in
collection.media
.
Loading files from Internet has the disadvantage of making my Anki solving experience depend on Internet, which I don't think is reasonable on mobile.
The plugin instruments all card templates by default, because that's what most
people will want. It requires zero-effort from a user to get to what they want,
which is being able to highlight code. It's non-intrusive, the added styles
should not interfere with users' preexisting settings as they are namespaced by
a class (hljs
or pygments
).
I've added each highlight.js language as a separate script to assets/, and then used another JS script to dynamically load languages. This method led to visible lag in rendering as the number of languages grew, so I abandoned this.
I've then tried detecting which languages are used in the card. I had a bug, where I did not properly account for language aliases. I've abandoned this way, because I figured that it would way more fool-proof to just use a single highlight.js bundle that has all languages. Loading that single file seems to be fast.
This package sets up a specific Python version to keep the dev environment in sync with what Anki uses. To update this Python version, you need to:
- If in the Poetry venv, deactivate it and remove it.
- Update Python spec in
.python-version
andpyproject.toml
. - Install the new Python version with
pyenv install
. - Install the new virtual environment with
poetry install
.