Files
Quentin 3271fee5cc init: WordFileParse docx→HTML 解析服务(含 Word EQ 域公式修复)
服务:Spring Boot 3.2 + docx4j 8.3.9,POST /api/v3/server_office_file/file/parse
      接受 .docx,返回 HTML(公式 → LaTeX,图片 → RustFS 外链)

公式支持三类来源:
- OMML(Word 2007+ 公式)      → Python omml_mathml2latex
- MathType OLE 对象            → Ruby mathtype2mathml → MathML → LaTeX
- Word EQ 域(老教辅主力)      → EqToLatexUtil(本次新增)

本次改动:
1. 新增 java-svc/.../core/EqToLatexUtil.java:
   移植自 jby backend-services office-core,EQ 语法 → LaTeX
   (\f→\dfrac、\r→\sqrt、\i→\int/\sum/\prod、\s→^{}/_{}、\b→\left\right、
     \a→array、\x→\boxed/\overline、\o\al 堆叠、圈码、化学符号、极限、连等式)
   品牌标记 JBYU* → WPU*,与采集端一致
2. CtoMathFinder:接上 EQ 分支(原为 not-ported 桩),域代码经
   EqToLatexUtil.convert 转 LaTeX 写入 eqLatexMap(WPEQNUM 占位符)
3. WordParseUtil.dealPlaceholder:EQ 的 LaTeX 同样加 \( \) 包裹
   (原先因 WPEQNUM 例外不加包裹,前端/MathJax 不渲染)

修前症状:教辅 Word 里分式/方程组/上下标整段丢失(如 {−1/3, 1} 变成 {-,1})
修后实测:46 份教辅 2908 处 EQ 域全部还原,公式总数 2954 处、零未包裹残留

安全:application.yml(含 RustFS 密钥)不入库,提供 application.yml.example;
      OssService 的 @Value 默认密钥已清空
2026-09-29 09:43:13 +08:00

169 lines
7.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Pattern-based replacements and regex patterns for LaTeX processing.
This module provides regex patterns for:
- Spacing cleanup and normalization
- Delimiter marker cleanup
- LaTeX structure fixes
- Assignment operator normalization
"""
# Assignment operator normalization (line 5529-5530)
ASSIGNMENT_OPERATOR_REPLACEMENTS = [
('∶ =', ':='), # U+2236 RATIO with space and equals
(': =', ':='), # Colon with space and equals
]
# ========================================================================
# Pattern-Based Replacements (Regex Patterns)
# ========================================================================
# Spacing cleanup patterns (consolidated from lines 1289, 1292-1293, 1296, 5566-5567)
SPACING_CLEANUP_PATTERNS = [
# Reduce excessive spaces (line 1289)
(r' {3,}', ' ', 'Reduce 3+ spaces to double space'),
# Remove spaces before delimiters (lines 1292-1293)
(r'\\left\s+\\{', r'\\left\\{', 'Remove space before left brace'),
(r'\\right\s+\\}', r'\\right\\}', 'Remove space before right brace'),
# Remove space between command and braces (line 1296)
(r'\\([a-zA-Z]+)\s+\{', r'\\\1{', 'Remove space between command and opening brace'),
# Add space after set operations when not followed by braces (lines 5566-5567)
(r'\\cap(?![{])', r'\\cap ', 'Add space after \\cap'),
(r'\\cup(?![{])', r'\\cup ', 'Add space after \\cup'),
]
# Delimiter marker cleanup patterns (consolidated from lines 1491-1502, 5433-5447)
# These clean up __DELIM__ markers left from OMML processing
DELIMITER_CLEANUP_PATTERNS = [
# Paired delimiters with content (line 5433)
(r'__DELIM__(.+?)__DELIM__', r'\1', 'Remove paired __DELIM__ markers'),
# Corrupted paired delimiters (lines 5436-5438)
(r'__DELIM_(.+?)__DELIM_', r'\1', 'Remove corrupted paired markers (single underscore)'),
(r'__DELIM__(.+?)__DELIM_', r'\1', 'Remove mixed paired markers (full+corrupted)'),
(r'__DELIM_(.+?)__DELIM__', r'\1', 'Remove mixed paired markers (corrupted+full)'),
# Orphaned markers with single character (lines 5441-5444)
(r'__DELIM__(.)', r'\1', 'Remove orphaned opening marker with character'),
(r'(.)__DELIM__', r'\1', 'Remove orphaned closing marker with character'),
(r'__DELIM_(.)', r'\1', 'Remove corrupted opening marker with character'),
(r'(.)__DELIM_', r'\1', 'Remove corrupted closing marker with character'),
# Standalone markers (lines 5445-5447)
(r'__DELIM__', '', 'Remove any remaining full markers'),
(r'__DELIM_', '', 'Remove any remaining corrupted markers'),
(r'_DELIM__', '', 'Remove reverse corrupted markers'),
# Specific delimiter characters (lines 1491-1497)
(r'__DELIM[_]*\([_]*', '(', 'Clean opening paren markers'),
(r'[_]*\)__DELIM[_]*', ')', 'Clean closing paren markers'),
(r'__DELIM[_]*\[[_]*', '[', 'Clean opening bracket markers'),
(r'[_]*\]__DELIM[_]*', ']', 'Clean closing bracket markers'),
(r'__DELIM[_]*\{[_]*', '{', 'Clean opening brace markers'),
(r'[_]*\}__DELIM[_]*', '}', 'Clean closing brace markers'),
(r'__DELIM[_]*\|[_]*', '|', 'Clean pipe markers (absolute value)'),
# Fragments (lines 1500-1502)
(r'LIM__', '', 'Remove LIM__ fragment'),
(r'LIM_', '', 'Remove LIM_ fragment'),
]
# Simple structure fix patterns (these don't need complex logic)
SIMPLE_STRUCTURE_FIX_PATTERNS = [
# Convert \overset{\dot}{X} to \dot{X} (lines 5570-5571)
(r'\\overset\{\\dot\}\{([a-zA-Z0-9])\}', r'\\dot{\1}', 'Simplify dot overset to \\dot command'),
(r'\\overset\{\.\}\{([a-zA-Z0-9])\}', r'\\dot{\1}', 'Simplify literal dot overset to \\dot command'),
# Fix array column specification (line 5574)
(r'\\begin\{array\{([^}]+)\}\}', r'\\begin{array}{\1}', 'Fix array column specification braces'),
# Convert incorrect fraction to reaction arrow (line 5579)
(r'\\dfrac\{\\underline\{([^}]+)\}\}\{\}', r'\\xlongequal[\\quad]{\1}', 'Convert underline fraction to reaction arrow'),
# Fix nested underset with underbrace (lines 5744-5747)
(r'\\underset\{([^{}]+)\}\{\\underset\{\\underbrace\}\{([^{}]+)\}\}', r'\\underbrace{\2}_{\1}', 'Fix nested underset underbrace pattern'),
# Fix overset with \hat over numbers to \overline (lines 5753-5756)
(r'\\overset\{\\hat\}\{(\\mathrm\{)?(\d+)\}?\}', r'\\overline{\2}', 'Convert hat overset to overline for numbers'),
# Fix underset with textemdash patterns (lines 5802-5823)
(r'\\underset\{\\textemdash\}\{\\underset\{\\textemdash\}\{([^{}]+)\}\}', r'\\underline{\\underline{\1}}', 'Convert nested textemdash underset to double underline'),
(r'\\underset\{\\textemdash\}\{\\underline\{([^{}]+)\}\}', r'\\underline{\\underline{\1}}', 'Convert textemdash underset with underline to double underline'),
(r'\\underset\{\\textemdash\}\{([^{}]+)\}', r'\\underline{\1}', 'Convert textemdash underset to underline'),
]
# ========================================================================
# Additional Symbol Classification Data
# ========================================================================
# Mathematical symbols for classification
MATH_SYMBOLS_SET = {
"↑", "↓", "→", "←", "↔", "×", "⋅", "·", "÷", "∕", "−", # Added U+2212 MINUS SIGN
"∩", "∪", "⊂", "⊃", "⊆", "⊇", "∈", "∉", "∋", "∌",
"≤", "≥", "≠", "≈", "≅", "≡", "≢", "∼", "≃", "≄",
"≜", "≝", "≞", "≟", "≦", "≧", "≨", "≩", "≲", "≳", "≴", "≵", "≶", "≷", "≸", "≹",
"≺", "≻", "⪯", "⪰", "∝", "⊥",
"∥", "∦", "±", "∓", "∗", "∘", "∙", "√", "∞",
"∂", "∇", "∆", "∫", "∬", "∭", "∮", "∯", "∰",
"∑", "∏", "∐", "⋃", "⋂", "⋁", "⋀", "⨁", "⨂", "⨄",
"∀", "∃", "∄", "⊢", "⊣", "⊤", "⊥", "¬", "∧", "∨",
"⟨", "⟩", "⌊", "⌋", "⌈", "⌉", "⏞", "⏟", "∠", "∁"
}
# Summation symbols for specific processing
SUMMATION_SYMBOLS = {
'∑': 'sum',
'∏': 'prod',
'∫': 'integral',
'Σ': 'sum',
'Π': 'prod'
}
# Font family to LaTeX command mapping
FONT_TO_LATEX = {
'Times New Roman': 'mathrm', # Roman/upright text
'Times': 'mathrm', # Times font variant
'Cambria Math': None, # Default math font (no special formatting)
'Cambria': None, # Cambria variant
'Arial': 'mathsf', # Sans-serif
'Helvetica': 'mathsf', # Helvetica sans-serif
'Courier New': 'mathtt', # Typewriter/monospace
'Courier': 'mathtt', # Courier variant
'Computer Modern': None, # LaTeX default math font
'Latin Modern Math': None, # Modern LaTeX math font
}
# Large operators that should use \limits in display mode
LARGE_OPERATORS = [
"\\sum", "\\prod", "\\int", "\\iint", "\\iiint", "\\oint",
"\\bigcup", "\\bigcap", "\\bigvee", "\\bigwedge",
"\\bigoplus", "\\bigotimes", "\\biguplus", "\\coprod",
"\\lim", "\\limsup", "\\liminf", "\\sup", "\\inf",
"\\max", "\\min"
]
# Unicode large operators for detection
LARGE_OPERATORS_UNICODE = [
"∑", "Σ", # Summation
"∏", "Π", # Product
"∫", # Integral
"∮", # Contour integral
"∬", # Double integral
"∭", # Triple integral
"⋂", # Intersection
"⋃", # Union
"⋁", # Logical OR
"⋀", # Logical AND
"⊕", # Direct sum
"⊗", # Tensor product
"⊎", # Multiset sum
"⨁", # Large direct sum
"⨂", # Large tensor product
"⨃", # Large union with plus
"⨆", # Large square union
"⨄", # Large union with plus
]