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 默认密钥已清空
This commit is contained in:
168
scripts/omml_mathml2latex/data/patterns.py
Normal file
168
scripts/omml_mathml2latex/data/patterns.py
Normal file
@@ -0,0 +1,168 @@
|
||||
"""
|
||||
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
|
||||
]
|
||||
Reference in New Issue
Block a user