Feature Summary
Test.
This blog is powered by Pelican, with a custom theme and a few custom Python-Markdown extensions. This is a brief overview of those features and how they work.
Code
Code is highlighted via codehilite and pygments; this is provided by the
bundled markdown.extensions.codehilite
.
const std = @import("std");
pub fn main() void {
std.log.debug("Hello, World!");
}
Fonts
The fonts are Latin Modern and text is justified and hyphenated to give that LaTeX feel. However there are some issues around the font weight, and I'm not satisfied with some browsers' text wrapping algorithms. I may rework this in the future.
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
— Tim Peters, The Zen of Python
Math
The blog has a custom Python-Markdown extension that compiles
to MathML
during static site generation. There's no client-side render step
like MathJax or KaTeX, so (as long as fonts are cached) math is instant.
With that, this markup:
[[ \iint_\Sigma \nabla \cross \mathbf F \cdot d \Sigma
= \oint_{\partial \Sigma} \mathbf F \cdot d \Gamma ]]
Or [(
\int_M d\tilde\varphi = \int_{\partial M} \tilde\varphi
)], as the differential geometers say.
Compiles to this static html:
Or , as the differential geometers say.
From experience, TEMML produces the best-looking MathML
of the few
options I considered. I don't have the bandwidth to write my own Python
renderer, so TEMML it is! However TEMML is a NodeJS module, so to invoke it
from Pelican I use JSPyBridge. I've been impressed at how seamless it is.
To be clear: this is Python:
from javascript import require
temml = require('./temml.cjs')
mathml = temml.renderToString(r'\int_M d\tilde\varphi')
Figures
I also have a Python-Markdown extension to execute certain Python code
blocks and embed any matplotlib.pyplot
figures in the page. Just set the
language to py figure
!
For example, if I create a code block - ripped from the matplotlib 3d
samples - with language py
, it appears as:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
__ZOOM = 0.25
ax = plt.figure(figsize=(10, 8)).add_subplot(projection='3d')
X, Y, Z = axes3d.get_test_data(0.05)
ax.plot_surface(X, Y, Z, edgecolor='black', color='white', lw=0.5,
rstride=8, cstride=8, alpha=0.5, shade=False)
ax.contour(X, Y, Z, zdir='x', offset=40, colors='black')
ax.contour(X, Y, Z, zdir='y', offset=-40, colors='black')
ax.axis('off')
ax.set(xlim=(-40, 40), ylim=(-40, 40), zlim=(-100, 100),
xlabel='X', ylabel='Y', zlabel='Z')
But changing the language to py figure
, it appears as:
The site supports both light and dark themes, but the figures are only generated
in light theme (black-on-transparent). To support dark theme, I use some CSS
filtering on img.figure
to invert brightness appropriately.
@media (prefers-color-scheme: light) {
html {
background: #ffffff;
color: #222222;
}
}
@media (prefers-color-scheme: dark) {
html {
background: #222222;
color: #eeeeee;
}
img.figure {
filter: brightness(calc(13 / 15)) invert() hue-rotate(180deg);
}
}
The brightnes(calc(13 / 15))
filter is to be sure the inverted background and
foreground colors match.