Skip to content

Commit 627faa4

Browse files
committed
fix: resolve MathJax rendering issues — config escaping, split math merge, arithmatex delimiter preservation
1 parent d1271f7 commit 627faa4

2 files changed

Lines changed: 19 additions & 6 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,5 @@ marimo/_static/
206206
marimo/_lsp/
207207
__marimo__/
208208
markdown2html_tailwind.py
209+
210+
.opencode

src/md2html_tailwind4/converter.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,12 @@ def _normalize_split_math_expressions(text):
363363
E.g.: $4.99 \\rightarrow $14.99 → $4.99 \\rightarrow 14.99$
364364
$4.99$ \\rightarrow $14.99$ → $4.99 \\rightarrow 14.99$
365365
"""
366+
def _merge_two_dollars(m):
367+
group3 = m.group(3)
368+
if group3.strip():
369+
return f"${m.group(1)}{m.group(2)} {group3}$"
370+
return m.group(0)
371+
366372
lines = text.split('\n')
367373
result = []
368374

@@ -373,12 +379,12 @@ def _normalize_split_math_expressions(text):
373379
dollar_count = line.count('$')
374380

375381
# If 2 dollars + LaTeX: $content \cmd $content → $content \cmd content$
376-
# Only merge when group 1 has real content before the command
382+
# Only merge when group 3 has actual non-whitespace content after second $.
377383
# (e.g. $4.99 \rightarrow $14.99) to avoid swallowing text after
378384
# a standalone $\cmd$ expression (e.g. $\rightarrow$ *italic*).
379385
if dollar_count == 2:
380386
line = re.sub(r'\$([^\$\\\s][^\$]*?)(\\[a-z]+[^\$]*?)\s*\$([^\$\n]*)',
381-
r'$\1\2 \3$', line)
387+
_merge_two_dollars, line)
382388
# If 3+ dollars + LaTeX: merge outer dollars
383389
elif dollar_count >= 3:
384390
# $content1$ \cmd $content2$ → $content1 \cmd content2$
@@ -442,10 +448,12 @@ def _is_image_with_caption_paragraph(p):
442448
if not has_image or 'em' not in names:
443449
return False
444450

445-
# Allow only image/link, caption (<em>), line breaks and whitespace text nodes.
451+
# Allow only image/link, caption (<em> without links), line breaks and whitespace text nodes.
446452
for child in meaningful:
447453
name = getattr(child, 'name', None)
448-
if name in ('img', 'em', 'br'):
454+
if name in ('img', 'br'):
455+
continue
456+
if name == 'em' and not child.find('a'):
449457
continue
450458
if name == 'a':
451459
a_children = [c for c in child.children if getattr(c, 'name', None) or str(c).strip()]
@@ -460,7 +468,10 @@ def _is_image_with_caption_paragraph(p):
460468
def _is_image_caption_paragraph(p):
461469
"""Return True if a paragraph is an image caption rendered as only emphasized text."""
462470
children = [c for c in p.children if getattr(c, 'name', None) or str(c).strip()]
463-
return bool(children) and all(getattr(c, 'name', None) == 'em' for c in children)
471+
if not children or not all(getattr(c, 'name', None) == 'em' for c in children):
472+
return False
473+
# An <em> that wraps a link is italic text, not a caption.
474+
return not any(child.find('a') for child in children)
464475

465476
@staticmethod
466477
def _ensure_list_spacing(text):
@@ -545,7 +556,7 @@ def _replace_common_latex_commands_in_text(soup):
545556

546557
for text_node in soup.find_all(string=True):
547558
parent = text_node.parent
548-
if parent and parent.name in skip_parents:
559+
if parent and (parent.name in skip_parents or (parent.name == 'span' and 'arithmatex' in parent.get('class', []))):
549560
continue
550561

551562
original = str(text_node)

0 commit comments

Comments
 (0)