Math and code
These plugins use external libraries to produce beautiful math and code rendering directly from your reST sources.
Math
For Pelican, download the m/math.py and latex2svg.py
files, put them including the m/
directory into one of your
PLUGIN_PATHS
and add m.math
package to your PLUGINS
in
pelicanconf.py
. This plugin assumes presence of
m.htmlsanity.
PLUGINS += ['m.htmlsanity', 'm.math'] M_MATH_RENDER_AS_CODE = False M_MATH_CACHE_FILE = 'm.math.cache'
For the Python doc theme, it’s enough to mention it in PLUGINS
. The
m.htmlsanity plugin is available always, no need to mention it explicitly:
PLUGINS += ['m.code']
For the Doxygen theme, this feature is builtin. Use either the @f[
command
for block-level math or the @f$
command for inline math. It’s possible to
add extra CSS classes by placing @m_class
in a paragraph before the actual
math block (or right before inline math), see the
Doxygen theme-specific commands
for more information. The M_MATH_CACHE_FILE
and
M_MATH_RENDER_AS_CODE
options are supported as well.
In addition you need some LaTeX distribution installed. Use your distribution package manager, for example on Ubuntu:
sudo apt install \ texlive-base \ texlive-latex-extra \ texlive-fonts-extra \ texlive-fonts-recommended
The plugin overrides the builtin docutils math directive and math interpreted text role and:
- Instead of relying on MathML or MathJax, converts input LaTeX math formula to a SVG file, which is then embedded directly to the page. All glyphs are converted to paths.
- Size is represented using CSS
em
units so the formula follows surrounding text size. - Adds a possibility to color the whole formula or parts of it using colors that follow the current theme.
- Adds a
<title>
containing the original formula to the generated<svg>
element for accessibility.
Put math blocks into the .. math::
directive; if you want to color the equations, add corresponding
CSS class via a :class:
option.
Inline math can be wrapped in the :math:
interpreted text role. If you
want to add additional CSS classes, derive a custom role from it.
The resulting SVG follows font size of surrounding text, so you can use math even outside of main page copy:
The xcolor
package is enabled by default together with names matching CSS
color classes. You can use it to highlight different parts of the formula:
The M_MATH_CACHE_FILE
setting (defaulting to m.math.cache
in the
site root directory) describes a file used for caching rendered LaTeX math
formulas for speeding up subsequent runs. Cached output that’s no longer needed
is periodically pruned and new formulas added to the file. Set it to None
to disable caching.
Math figure
See the m.components
plugin for details about code figures using the .. math-figure::
directive.
Code
For Pelican, download the m/code.py and ansilexer.py
files, put them including the m/
directory into one of your PLUGIN_PATHS
and add m.code
package to your PLUGINS
in pelicanconf.py
. This
plugin assumes presence of m.htmlsanity.
PLUGINS += ['m-htmlsanity', 'm.code'] M_CODE_FILTERS_PRE = [] M_CODE_FILTERS_POST = []
For the Python doc theme, it’s enough to mention it in PLUGINS
. The
m.htmlsanity plugin is available always, no need to mention it explicitly:
PLUGINS += ['m.code']
For the Doxygen theme, this feature is builtin. Use the @code{.ext}
command
either in a block or inline, the various @include
and @snippet
commands
support it as well. Language detection is done from the value of .ext
in
the @code
command and from the include/snippet filename for the others.
It’s possible to add extra CSS classes by placing @m_class
in a paragraph
before the actual code block (or right before inline code), see the
Doxygen theme-specific commands
for more information. There’s no possibility to highlight particular code
lines.
In addition you need to have Pygments installed. Get
it via pip
or your distribution package manager:
pip3 install Pygments
The plugin overrides the builtin docutils code directive and code interpreted text role, replaces Pelican code-block directive and:
- Wraps Pygments output in
<code>
element for inline code and<pre>
element for code blocks with.m-code
CSS class applied. - Removes useless CSS classes from the output.
- Adds a
:filters:
option. See Filters below.
Put code blocks into the .. code::
directive and specify the language via a parameter. Use :hl-lines:
option to highlight lines; if you want to add additional CSS classes, use the
:class:
option.
.. code:: c++ :hl-lines: 4 5 :class: m-inverted #include <iostream> int main() { std::cout << "Hello world!" << std::endl; return 0; }
#include <iostream> int main() { std::cout << "Hello world!" << std::endl; return 0; }
Omitting the language parameter renders a plain code block without any
highlighing. In that case the class:
option is still recognized (and the
.m-code
CSS class added as well) but :hl-lines:
is ignored.
The builtin include directive is also patched to use the improved code directive, and:
- Drops the rarely useful
:encoding:
,:literal:
and:name:
options - Adds a
:hl-lines:
option to have the same behavior as the.. code::
directive - Adds a
:start-on:
and:strip-prefix:
options, and improves:end-before:
. See Advanced file inclusion below.
Simply specify external code snippets filename and set the language using the
:code:
option. All options of the .. code::
directive are
supported as well.
.. include:: snippet.cpp :code: c++ :start-line: 2
int main() { std::cout << "Hello world!" << std::endl; return 0; }
For inline code highlighting, use :code:
interpreted text role. To
specify which language should be highlighted, derive a custom role from it.
Like with the .. code::
directive it’s possible to supply CSS classes
via the :class:
option, and if you omit the :language:
option you
get a plain inline code without any highlighting but :class:
still
applied, and the .m-code
CSS class added as well.
.. role:: cmake(code) :language: cmake .. role:: cpp(code) :language: cpp With the :cmake:`add_executable(foo bar.cpp)` CMake command you can create an executable from a file that contains just :cpp:`int main() { return 666; }` and nothing else.
With the add_executable(foo bar.cpp)
CMake command you can create
an executable from a file that contains just int main() { return 666; }
and nothing else.
Colored terminal output
Use the ansi
pseudo-language for highlighting
colored terminal output.
The plugin will take care of the rest like using the custom Pygments lexer and
assigning a proper CSS class. Because ANSI escape codes might cause problems
with some editors and look confusing when viewed via git diff
on the
terminal, it’s best to have the listings in external files and use
.. include::
:
.. include:: console.ansi :code: ansi
![mosra@don-perverzo m.css]$ ls CONTRIBUTING.rst CREDITS.rst doc plugins README.rst COPYING css documentation pelican-theme site ASan reports: =>0x0c287fff8030: 00[fc]fc fc fc fc fc fc fc fc fc fa fa fa fa fa
There’s support for the basic foreground and background color sets, 256 palette
colors using the \033[38;5;{p}m
or \033[48;5;{p}m
color sequences,
and 24bit colors using the \033[38;2;{r};{g};{b}m
and
\033[48;2;{r};{g};{b}m
color sequences. The non-bright basic foreground
colors can be independently brightened using the \033[1m
color sequence:
██ ██ ██ ██ ██ ▓▓ ▒▒ ░░ ▒▒ ▓▓ ██
Code figure
See the m.components
plugin for details about code figures using the .. code-figure::
directive.
Advanced file inclusion
Compared to the builtin include directive, the m.css-patched variant
additionally provides a :strip-prefix:
option that strips a prefix from
each included line. This can be used for example to remove excessive
indentation from code blocks. To avoid trailing whitespace, you can wrap the
value in quotes. Reusing the snippet from above, showing only the code inside
main()
:
.. include:: snippet.cpp :code: c++ :start-line: 3 :end-line: 5 :strip-prefix: ' '
std::cout << "Hello world!" << std::endl; return 0;
This isn’t limited to just whitespace though — since the .. include::
directive works for including reStructuredText as well, it can be used to embed
parts of self-contained python scripts on the page. Consider this file,
two-sins.py
:
""" This is a reST markup explaining the following code, compatible with `Sphinx Gallery <https://sphinx-gallery.github.io/>`_. """ # You can convert the file to a Jupyter notebook using the # sphx_glr_python_to_jupyter.py utility from Sphinx Gallery. import math sin = math.sin(0.13587) print(sin) #%% # And a sum with itself turns it into two sins, because the following holds: # # .. math:: # # 2 a = a + a # two_sins = sin + sin if two_sins != 2*sin: print("Assumptions broken. Restart the universe.")
Embedding it on a page, mixed together with other content (and unimportant
parts omitted), can look like below. The :start-on:
option can be used
to pin to a particular line (instead of skipping it like :start-after:
does) and an empty :end-before:
will include everything until the next
blank line. Finally, :strip-prefix:
strips the leading #
from the
comments embedded in Python code:
.. include:: two-sins.py :start-after: """ :end-before: """ .. code-figure:: .. include:: two-sins.py :start-on: sin = :end-before: :code: py 0.13545234412104434 .. include:: two-sins.py :start-on: # And a sum with itself :strip-prefix: '# ' :end-before: .. include:: two-sins.py :start-on: two_sins :code: py
This is a reST markup explaining the following code, compatible with Sphinx Gallery.
sin = math.sin(0.13587) print(sin)
0.13545234412104434
And a sum with itself turns it into two sins, because the following holds:
two_sins = sin + sin if two_sins != 2*sin: print("Assumptions broken. Restart the universe.")
Filters
It’s possible to supply filters that get applied both before and after a
code snippet is rendered using the M_CODE_FILTERS_PRE
and
M_CODE_FILTERS_POST
options. It’s a dict with keys being the lexer
name 1 and values being filter functions. Each function that gets string as
an input and is expected to return a modified string. In the following example,
all CSS code snippets have the hexadecimal color literals annotated with a
color swatch:
import re _css_colors_src = re.compile(r"""<span class="mh">#(?P<hex>[0-9a-f]{6})</span>""") _css_colors_dst = r"""<span class="mh">#\g<hex><span class="m-code-color" style="background-color: #\g<hex>;"></span></span>""" M_CODE_FILTERS_POST = { 'CSS': lambda code: _css_colors_src.sub(_css_colors_dst, code) }
.. code:: css p.green { color: #3bd267; }
p.green { color: #3bd267; }
In the above case, the filter gets applied globally to all code snippets of
given language. Sometimes it might be desirable to apply a filter only to
specific code snippet — in that case, the dict key is a tuple of
(lexer, filter)
where the second item is a filter name. This filter name
is then referenced from the :filters:
option of the .. code::
and
.. include::
directives as well as the inline :code:
text role.
Multiple filters can be specified when separated by spaces.
M_CODE_FILTERS_PRE = { ('C++', 'codename'): lambda code: code.replace('DirtyMess', 'P300::V1'), ('C++', 'fix_typography'): lambda code: code.replace(' :', ':'), }
.. code:: cpp :filters: codename fix_typography for(auto& a : DirtyMess::managedEntities()) { // ... }
for(auto& a: P300::V1::managedEntities()) { // ... }
- 1.
- ^ In order to have an unique mapping, the filters can’t use the aliases
— for example C++ code can be highlighted using either
c++
orcpp
as a language name and the dict would need to have an entry for each. An unique lexer name is thename
field used in the particular lexer source, you can also see the names in the language dropdown on the official website.