File size: 2,474 Bytes
6981282
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import hashlib
import subprocess
import tempfile
from dataclasses import dataclass
from functools import lru_cache
from pathlib import Path


@dataclass
class CompilationResult:
    success: bool
    pdf_data: bytes = b""
    error_log: str = ""


def _compute_hash(content: str) -> str:
    return hashlib.md5(content.encode()).hexdigest()


@lru_cache(maxsize=128)
def _cached_compile(content_hash: str, latex_content: str) -> tuple[bool, bytes, str]:
    with tempfile.TemporaryDirectory() as tmpdir:
        tmppath = Path(tmpdir)
        tex_file = tmppath / "document.tex"
        tex_file.write_text(latex_content)
        
        try:
            result = subprocess.run(
                [
                    "pdflatex",
                    "-interaction=nonstopmode",
                    "-halt-on-error",
                    "-output-directory", str(tmppath),
                    str(tex_file)
                ],
                capture_output=True,
                text=True,
                timeout=30
            )
            
            pdf_file = tmppath / "document.pdf"
            if pdf_file.exists():
                return (True, pdf_file.read_bytes(), "")
            else:
                log_file = tmppath / "document.log"
                error_log = log_file.read_text() if log_file.exists() else result.stdout
                return (False, b"", _extract_errors(error_log))
                
        except subprocess.TimeoutExpired:
            return (False, b"", "Compilation timed out after 30 seconds")
        except FileNotFoundError:
            return (False, b"", "pdflatex not found. Please install TeX Live.")
        except Exception as e:
            return (False, b"", f"Compilation error: {str(e)}")


def _extract_errors(log: str) -> str:
    lines = log.split("\n")
    error_lines = []
    capture = False
    for line in lines:
        if line.startswith("!"):
            capture = True
        if capture:
            error_lines.append(line)
            if line.strip() == "" and error_lines:
                capture = False
        if len(error_lines) > 50:
            break
    return "\n".join(error_lines) if error_lines else log[-2000:]


def compile_latex(latex_content: str) -> CompilationResult:
    content_hash = _compute_hash(latex_content)
    success, pdf_data, error_log = _cached_compile(content_hash, latex_content)
    return CompilationResult(success=success, pdf_data=pdf_data, error_log=error_log)