from __future__ import annotations
import re
# ---------------------------------------------------------------------------
# Regex patterns
# ---------------------------------------------------------------------------
# Display math:
_MATH_DISPLAY = re.compile(
r'', re.DOTALL | re.IGNORECASE
)
# Inline math: (no display attribute, or display="inline")
_MATH_INLINE = re.compile(
r'',
re.DOTALL | re.IGNORECASE,
)
_BOLD = re.compile(r"<(?:b|strong)>(.*?)(?:b|strong)>", re.DOTALL | re.IGNORECASE)
_ITALIC = re.compile(r"<(?:i|em)>(.*?)(?:i|em)>", re.DOTALL | re.IGNORECASE)
_SUP = re.compile(r"(.*?)", re.DOTALL | re.IGNORECASE)
_SUB = re.compile(r"(.*?)", re.DOTALL | re.IGNORECASE)
_ANY_TAG = re.compile(r"<[^>]+>")
# Bare LaTeX command sequences (outside $ markers): \cmd{...} or \cmd
_BARE_LATEX = re.compile(
r"(? after all tags stripped
_LT = re.compile(r"<(?![a-zA-Z/])")
_GT = re.compile(r'(?')
def escape_typst_string(text: str) -> str:
"""Escape for embedding inside a Typst double-quoted string literal."""
return text.replace("\\", "\\\\").replace('"', '\\"').replace("\n", "\\n")
def to_typst_markup(text: str, *, is_equation: bool = False) -> str:
"""Convert hybrid HTML/LaTeX text to cmarker-friendly markdown with mitex math.
Args:
text: The translated_text field value (may contain HTML tags and LaTeX).
is_equation: True for EQUATION category elements — bare LaTeX gets wrapped.
Returns:
String safe for cmarker.render(..., math: mitex) in Typst.
"""
if not text:
return ""
# If not in equation mode, escape literal dollar signs that are outside of