服务: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 默认密钥已清空
169 lines
7.7 KiB
Python
169 lines
7.7 KiB
Python
"""
|
||
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
|
||
]
|