Blogging With Math

By David Buchanan, 26th December 2023

In my previous blog post, I mentioned some big-O notation and simple math expressions like 264. My blog engine didn't have proper math syntax support, so I was stuck writing things like 2<sup>64</sup>, and leaving my big-O functions in plaintext, e.g. O(nlogn).

Not anymore! After a very simple patch to my markdown renderer, I can now write 264 as $2^{64}$, or even O(nlogn) as $O(n\log{n})$. Not only does this look better, its easier for me to type in. And if I really want to push the boat out, I can write fancy equations:

x=b±b24ac2a

ex=n=0xnn!

Neat! And this is all the code it needed, most of which is unrelated to math support itself:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import mistune
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.styles import get_style_by_name
from pygments.formatters import HtmlFormatter
from latex2mathml.converter import convert as convertlatex


class HighlightAndMathRenderer(mistune.HTMLRenderer):
	def __init__(self, *args, **kwargs):
		super().__init__(*args, **kwargs, escape=False)

	def block_code(self, code, info=None):
		if not info:
			return f'\n<pre>{mistune.escape(code)}</pre>\n'
		lexer = get_lexer_by_name(info, stripall=True)
		formatter = HtmlFormatter(
			linenos=True,
			cssclass="source",
			style=get_style_by_name("monokai")
		)
		return highlight(code, lexer, formatter)

	def block_math(self, text):
		return "<p>" + convertlatex(text, display="block") + "</p>"

	def inline_math(self, text):
		return convertlatex(text, display="inline")

renderer = HighlightAndMathRenderer()
md = mistune.create_markdown(
	renderer=renderer,
	escape=False,
	plugins=["math"]
)

I'm using mistune as my markdown renderer library, with a custom HTML renderer subclass, HighlightAndMathRenderer. Most of the logic here is actually for the code syntax highlighting, powered by pygments. The math input support is provided by mistune's default math plugin, which I customised by overriding default HTML output functions in my subclass. I use the latex2mathml library to convert the LaTeX syntax into MathML output, and it all Just Works.

There's nothing too clever going on here, just plugging some libraries together, but I was surprised by how easy it was. I didn't even need to make any changes to my CSS, the math comes out looking exactly how I'd like.

Maybe one day I'll publish the code behind my blog engine, there's not much to it, but it was written in a hurry by a version of me who was even worse at software development, so it needs a good refactor and cleanup first.