Pi66

merodi
A markdown-based static site generator.
git clone https://git.pi66.xyz/merodi

← back to log

feat: add LaTeX math rendering

author: pi66
date: 2026-06-27 01:58
hash: b9f52040913a9d304a91f66c307637131e2cc099

Diffstat:

M

pyproject.toml
1 +

M

src/build.py
47 +++++++++++++++++++-----------
 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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
diff --git a/pyproject.toml b/pyproject.toml
index a7777c8..e97e171 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -11,6 +11,7 @@ dependencies = [
     "watchdog",
    "PyGObject",
    "pymdown-extensions",
+   "latex2mathml"
 ]

 [project.scripts]
diff --git a/src/build.py b/src/build.py
index 32f2f71..7e7c45c 100644
--- a/src/build.py
+++ b/src/build.py
@@ -1,5 +1,6 @@
-import importlib.util
 import re
+import importlib.util
+import latex2mathml.converter

 from jinja2 import Environment, FileSystemLoader
 from markdown import markdown
@@ -47,6 +48,16 @@ def html_filter(html_content:str):
     result = re.sub(r'(}}\s*)\[[^\]]*\]', r'\1', result)
     return result

+def render_math(md_content: str) -> str:
+    def block(m):
+        return latex2mathml.converter.convert(m.group(1))
+    def inline(m):
+        return latex2mathml.converter.convert(m.group(1))
+    
+    md_content = re.sub(r'\<math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mrow><mi>\</mi></mrow></math>(.+?)\<math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mrow><mi>\</mi></mrow></math>', block, md_content, flags=re.DOTALL)
+    md_content = re.sub(r'\<math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mrow><mo stretchy="false">&#x00028;</mo><mo>&#x0002E;</mo><mo>&#x0002B;</mo><mo>&#x0003F;</mo><mo stretchy="false">&#x00029;</mo><mi>\</mi></mrow></math>', inline, md_content)
+    return md_content
+
 def jinja_handler(file, html_content, config=None):
     try:
         env = Environment( loader=FileSystemLoader(config.templates)) if config else Environment()
@@ -66,24 +77,24 @@ def compile_md_to_html(md_file:str, html_dest:str, config =None):
     """Convert a Markdown file to HTML, applying filters and Jinja2 processing, and save to dest."""
     info(f"Building {GRAY(md_file)}...")
     md_content = read_file(md_file)
+    math_rendered = render_math(md_content)
     raw_html_content = markdown(
-        md_content,
-extensions = [
-    "extra",
-    "md_in_html",
-    "pymdownx.highlight",
-    "pymdownx.inlinehilite",
-    "pymdownx.superfences",
-    "pymdownx.tilde",
-    "pymdownx.mark",
-    "pymdownx.betterem",
-    "pymdownx.magiclink",
-    "pymdownx.keys",
-    "pymdownx.arithmatex",
-    "pymdownx.details",
-    "pymdownx.tabbed",
-    "pymdownx.critic",
-]
+        math_rendered,
+        extensions = [
+            "extra",
+            "md_in_html",
+            "pymdownx.highlight",
+            "pymdownx.inlinehilite",
+            "pymdownx.superfences",
+            "pymdownx.tilde",
+            "pymdownx.mark",
+            "pymdownx.betterem",
+            "pymdownx.magiclink",
+            "pymdownx.keys",
+            "pymdownx.details",
+            "pymdownx.tabbed",
+            "pymdownx.critic",
+        ]
     )
     filtered_html = html_filter(raw_html_content)
     html_content = jinja_handler(md_file, filtered_html, config)