Lincoln Atkinson wrote a post about TeX math typesetting in Hugo (archive) where he described a solution that could do TeX math typesetting with and without Javascript enabled.
I have improved slightly upon his method, creating a simple Python script to download the equation images prior to publication and serving them from the local web server.
Why?
The primary reason was that I wanted a missing noscript
equation to be an error at compile time instead of just a dead link.
When going to the codecogs website at the time of writing, I see the following in a little box:
Licence Details
Registered use: CLOUD
Expiration date: 31-12-2020
What does that mean? I have no idea. It might mean that service transistions to a new backend at the start of 2021, or it might mean that the service completely shuts down.
How?
Lincoln created a shortcode1 that inserts an image with src=latex.codecogs.com/gif.latex?
followed by the equation to render, ending with title=
(the "
are removed by Hugo).
Knowing this it is possible to create a script that finds all instances of the codecogs.com
sources, downloads the equation as a file and replaces the src=
attribute with the local file.
The benefits of this approach is that the noscript equations still work before the script is run, it’s just fetched from codecogs.com
instead of locally.
Script
Running the script in the directory that contains the public
folder will download equations, place them next to the .html
file and replace the src=
attribute.
#!/user/bin/env python3
from pathlib import Path
import requests
import urllib
EXTENSION = "svg"
LATEX_URL = f"https://latex.codecogs.com/{EXTENSION}.latex?"
LATEX_INLINE = f"https://latex.codecogs.com/{EXTENSION}.latex?\inline&space;"
for path in Path('public').rglob('*.html'):
contents = Path(path).read_text();
while (LATEX_INLINE in contents) or (LATEX_URL in contents):
latex_url = ""
if LATEX_INLINE in contents:
latex_url = LATEX_INLINE
elif LATEX_URL in contents:
latex_url = LATEX_URL
else:
continue
print("PATH: " + str(path))
index = contents.find(latex_url)
end = contents.find(" title=", index)
equation = contents[index + len(latex_url):end]
url = contents[index:end]
f = requests.get(url).content
with open(path.parent.joinpath(equation + f".{EXTENSION}"), 'wb') as w:
w.write(f)
print(f"\tReplacing {url} with {urllib.parse.quote(equation)}.{EXTENSION}")
contents = contents.replace(url, urllib.parse.quote(equation) + f".{EXTENSION}")
with open(path, 'w') as w:
w.write(contents)
Future work
Ideally the equations would be done entirely at compile time without external dependencies.
Currently it does not seem possible to do entirely in HTML, since the math requires some fonts that are not installed by default on most platforms.
A LaTeX to SVG tool could be used, but would break the hugo serve
tool since it does not seem possible to insert arbitrary commands in that process.
Think of it like a function for Hugo that inserts text and can take parameters. ↩︎