Push Bot commited on
Commit
abc742b
·
1 Parent(s): db0616f

Lenient compile: add sanitizer for TikZ nodes & bullets; call sanitizer; keep latexmk -f and accept PDF even on errors

Browse files
Files changed (1) hide show
  1. app.py +58 -0
app.py CHANGED
@@ -72,6 +72,58 @@ def _write_logs(log_path: Path, logs):
72
  except Exception:
73
  pass
74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  def _on_rm_error(func, path, exc_info):
76
  # fix "PermissionError: [Errno 13] Permission denied" for readonly files
77
  os.chmod(path, stat.S_IWRITE)
@@ -429,6 +481,9 @@ def _compile_poster_pdf(OUTPUT_DIR: Path, logs):
429
  def _has(bin_name):
430
  return _sh.which(bin_name) is not None
431
 
 
 
 
432
  # Most-tolerant: prefer latexmk with XeLaTeX and force (-f), then XeLaTeX, then LuaLaTeX
433
  if _has("latexmk"):
434
  cmd = ["latexmk", "-xelatex", "-pdf", "-f", "-interaction=nonstopmode", "-file-line-error", tex_path.name]
@@ -496,6 +551,9 @@ def _compile_tex_to_pdf(tex_path: Path, logs):
496
  import shutil as _sh, subprocess as _sp
497
  def _has(bin_name):
498
  return _sh.which(bin_name) is not None
 
 
 
499
  # Prefer XeLaTeX (Overleaf-like), then LuaLaTeX, then latexmk (forced XeLaTeX)
500
  if _has("xelatex"):
501
  cmd = ["xelatex", "-interaction=nonstopmode", "-file-line-error", tex_path.name]
 
72
  except Exception:
73
  pass
74
 
75
+ def _sanitize_tex_lenient(tex_path: Path, logs):
76
+ """Best-effort, non-invasive fixes to let compilation proceed.
77
+ - Ensure TikZ \node lines have trailing ';' and an empty label '{}' if missing.
78
+ - Replace Unicode bullets with \textbullet{}.
79
+ Operates in-place on the run-local copy only.
80
+ """
81
+ try:
82
+ text = tex_path.read_text(encoding="utf-8")
83
+ lines = text.splitlines()
84
+ changed = False
85
+ cnt_semicolon = 0
86
+ cnt_emptylabel = 0
87
+ cnt_bullet = 0
88
+ new_lines = []
89
+ for line in lines:
90
+ orig = line
91
+ # Replace bullets
92
+ if "\\•" in line or "•" in line:
93
+ line = line.replace("\\•", r"\\textbullet{}")
94
+ line = line.replace("•", r"\\textbullet{}")
95
+ if line != orig:
96
+ cnt_bullet += 1
97
+ orig = line
98
+ # Fix TikZ node syntax (line-based heuristic)
99
+ if "\\node" in line:
100
+ # Ensure semicolon at end of command line
101
+ stripped = line.rstrip()
102
+ if not stripped.endswith(";"):
103
+ line = stripped + ";"
104
+ cnt_semicolon += 1
105
+ # Add empty label '{}' before the first trailing ';' if no braces after ')'
106
+ try:
107
+ close_paren = line.rfind(")")
108
+ if close_paren != -1:
109
+ tail = line[close_paren+1:]
110
+ semi = tail.find(";")
111
+ if semi != -1:
112
+ between = tail[:semi]
113
+ if "{" not in between:
114
+ line = line[:close_paren+1] + " {}" + tail
115
+ cnt_emptylabel += 1
116
+ except Exception:
117
+ pass
118
+ new_lines.append(line)
119
+ if new_lines != lines:
120
+ tex_path.write_text("\n".join(new_lines), encoding="utf-8")
121
+ logs.append(
122
+ f"🧯 Lenient sanitizer: +semicolon={cnt_semicolon}, +emptylabel={cnt_emptylabel}, bullets_fixed={cnt_bullet}"
123
+ )
124
+ except Exception as e:
125
+ logs.append(f"⚠️ sanitizer skipped: {e}")
126
+
127
  def _on_rm_error(func, path, exc_info):
128
  # fix "PermissionError: [Errno 13] Permission denied" for readonly files
129
  os.chmod(path, stat.S_IWRITE)
 
481
  def _has(bin_name):
482
  return _sh.which(bin_name) is not None
483
 
484
+ # Apply lenient sanitizer on the main tex before compile
485
+ _sanitize_tex_lenient(tex_path, logs)
486
+
487
  # Most-tolerant: prefer latexmk with XeLaTeX and force (-f), then XeLaTeX, then LuaLaTeX
488
  if _has("latexmk"):
489
  cmd = ["latexmk", "-xelatex", "-pdf", "-f", "-interaction=nonstopmode", "-file-line-error", tex_path.name]
 
551
  import shutil as _sh, subprocess as _sp
552
  def _has(bin_name):
553
  return _sh.which(bin_name) is not None
554
+ # Apply lenient sanitizer on the main tex before compile
555
+ _sanitize_tex_lenient(tex_path, logs)
556
+
557
  # Prefer XeLaTeX (Overleaf-like), then LuaLaTeX, then latexmk (forced XeLaTeX)
558
  if _has("xelatex"):
559
  cmd = ["xelatex", "-interaction=nonstopmode", "-file-line-error", tex_path.name]