Skip to content

Commit 3b34767

Browse files
vorojarclaude
andcommitted
fix: convert complex LaTeX math expressions in OCR output to Unicode
Add _convert_math_interior() to handle expressions like $5^{\circ}$ → 5°, $$15^{\circ}\sim 20^{\circ}$$ → 15°∼20°. Also collapses spurious spaces between digits that GLM-OCR inserts in math mode. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 63fcd58 commit 3b34767

1 file changed

Lines changed: 43 additions & 2 deletions

File tree

server.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -527,18 +527,59 @@ def _replace_frac(m):
527527

528528
text = re.sub(r'\$\\frac\{([^}]+)\}\{([^}]+)\}\$', _replace_frac, text)
529529

530-
# 3. Simple $\command$ → Unicode (longest match first)
530+
# 3. Inline math $...$ and display math $$...$$ → convert interior then strip delimiters
531+
text = re.sub(r'\$\$(.+?)\$\$', lambda m: _convert_math_interior(m.group(1)), text, flags=re.DOTALL)
532+
text = re.sub(r'\$(.+?)\$', lambda m: _convert_math_interior(m.group(1)), text)
533+
534+
# 4. Simple $\command$ → Unicode (longest match first) — catch any remaining
531535
for latex_cmd, unicode_char in _LATEX_SIMPLE:
532536
token = f"${latex_cmd}$"
533537
if token in text:
534538
text = text.replace(token, unicode_char)
535539

536-
# 4. Remaining bare $\command$ patterns not in map — unwrap the $ delimiters
540+
# 5. Remaining bare $\command$ patterns not in map — unwrap the $ delimiters
537541
text = re.sub(r'\$\\([a-zA-Z]+)\$', lambda m: '\\' + m.group(1), text)
538542

539543
return text
540544

541545

546+
def _convert_math_interior(math: str) -> str:
547+
"""Convert LaTeX math content to Unicode plain text.
548+
Handles: ^{\\circ} → °, \\sim → ~, \\times → ×, etc.
549+
Collapses spurious spaces between digits: '1 5' → '15'.
550+
"""
551+
s = math.strip()
552+
553+
# ^{\circ} or ^\circ → ° (degree symbol)
554+
s = re.sub(r'\^\{\\circ\}', '°', s)
555+
s = re.sub(r'\^\\circ', '°', s)
556+
557+
# ^{...} superscript — for single char/digit, use Unicode superscript if possible
558+
# For complex content, just append it
559+
s = re.sub(r'\^\{([^}]+)\}', lambda m: m.group(1), s)
560+
s = re.sub(r'\^(\d)', lambda m: m.group(1), s)
561+
562+
# _{...} subscript — similar treatment
563+
s = re.sub(r'_\{([^}]+)\}', lambda m: m.group(1), s)
564+
s = re.sub(r'_(\d)', lambda m: m.group(1), s)
565+
566+
# Replace LaTeX commands with Unicode (longest match first)
567+
for latex_cmd, unicode_char in _LATEX_SIMPLE:
568+
if latex_cmd in s:
569+
s = s.replace(latex_cmd, unicode_char)
570+
571+
# Remove remaining braces
572+
s = s.replace('{', '').replace('}', '')
573+
574+
# Collapse spaces between digits: "1 5" → "15", "2 0" → "20"
575+
s = re.sub(r'(\d)\s+(\d)', r'\1\2', s)
576+
577+
# Clean up multiple spaces
578+
s = re.sub(r' {2,}', ' ', s)
579+
580+
return s.strip()
581+
582+
542583
def pdf_to_images(pdf_path: str, output_dir: Path) -> list[str]:
543584
"""Convert PDF pages to images in the specified directory"""
544585
output_dir.mkdir(parents=True, exist_ok=True)

0 commit comments

Comments
 (0)