JaceWei commited on
Commit
5ee8cc4
Β·
1 Parent(s): ba73199
Files changed (1) hide show
  1. app.py +90 -19
app.py CHANGED
@@ -141,13 +141,64 @@ def _prepare_workspace(logs):
141
  # ---------------------
142
  # Helpers for new features (post-processing)
143
  # ---------------------
144
- def _parse_rgb(hex):
145
- try:
146
- hex = hex.lstrip('#')
147
- return tuple(int(hex[i:i+2], 16) for i in (0, 2, 4))
148
- except Exception:
149
  return None
150
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  def _apply_meeting_logo(OUTPUT_DIR: Path, meeting_logo_file, logs):
152
  """Replace output/poster_latex_proj/logos/right_logo.png if meeting_logo_file provided."""
153
  if not meeting_logo_file:
@@ -176,7 +227,7 @@ def _apply_meeting_logo(OUTPUT_DIR: Path, meeting_logo_file, logs):
176
  return False
177
 
178
  def _apply_theme_rgb(OUTPUT_DIR: Path, rgb_tuple, logs):
179
- """Replace \\definecolor{nipspurple}{RGB}{r,g,b} in poster_output.tex if rgb_tuple provided."""
180
  if not rgb_tuple:
181
  return False
182
 
@@ -187,20 +238,33 @@ def _apply_theme_rgb(OUTPUT_DIR: Path, rgb_tuple, logs):
187
 
188
  try:
189
  content = tex_path.read_text(encoding="utf-8")
190
- pattern = r"(\\definecolor\{nipspurple\}\{RGB\}\{)\s*\d+\s*,\s*\d+\s*,\s*\d+\s*(\})"
191
- new_vals = f"{rgb_tuple[0]},{rgb_tuple[1]},{rgb_tuple[2]}"
192
- new_content, n = re.subn(pattern, r"\1" + new_vals + r"\2", content, flags=re.MULTILINE)
 
 
 
 
 
 
 
 
 
 
 
193
  if n > 0:
194
  tex_path.write_text(new_content, encoding="utf-8")
195
- logs.append(f"🎨 Theme color updated: themecolor = {{{new_vals}}} in {tex_path.relative_to(OUTPUT_DIR)}")
196
  return True
197
  else:
198
- logs.append("⚠️ Theme RGB not applied: definecolor for 'themecolor' not found.")
199
  return False
 
200
  except Exception as e:
201
  logs.append(f"⚠️ Failed to update theme RGB: {e}")
202
  return False
203
 
 
204
  def _apply_left_logo(OUTPUT_DIR: Path, logo_files, logs):
205
  """
206
  Use the first institutional logo uploaded by the user:
@@ -477,16 +541,23 @@ def run_pipeline(arxiv_url, pdf_file, openai_key, logo_files, meeting_logo_file,
477
 
478
  # ====== Zip output (run-local) ======
479
  try:
480
- with zipfile.ZipFile(ZIP_PATH, 'w', zipfile.ZIP_DEFLATED) as zipf:
481
- for root, dirs, files in os.walk(OUTPUT_DIR):
482
- for file in files:
483
- file_path = Path(root) / file
484
- arcname = file_path.relative_to(OUTPUT_DIR)
485
- zipf.write(file_path, arcname=arcname)
486
- logs.append(f"βœ… Zipped output β†’ {ZIP_PATH.relative_to(WORK_DIR)}")
 
 
 
 
 
 
 
487
  except Exception as e:
488
  logs.append(f"❌ Failed to create zip: {e}")
489
-
490
  # ====== Prepare Overleaf base64 payload (optional) ======
491
  overleaf_zip_b64 = ""
492
  try:
 
141
  # ---------------------
142
  # Helpers for new features (post-processing)
143
  # ---------------------
144
+ def _parse_rgb(val):
145
+ """Return (R, G, B) as ints in [0,255] from '#RRGGBB', 'rgb(...)', 'rgba(...)', 'r,g,b', [r,g,b], or (r,g,b)."""
146
+ if val is None:
 
 
147
  return None
148
 
149
+ import re
150
+
151
+ def clamp255(x):
152
+ try:
153
+ return max(0, min(255, int(round(float(x)))))
154
+ except Exception:
155
+ return None
156
+
157
+ s = str(val).strip()
158
+
159
+ # list/tuple
160
+ if isinstance(val, (list, tuple)) and len(val) >= 3:
161
+ r, g, b = [clamp255(val[0]), clamp255(val[1]), clamp255(val[2])]
162
+ if None not in (r, g, b):
163
+ return (r, g, b)
164
+
165
+ # hex: #RGB or #RRGGBB
166
+ if s.startswith("#"):
167
+ hx = s[1:].strip()
168
+ if len(hx) == 3:
169
+ hx = "".join(c*2 for c in hx)
170
+ if len(hx) == 6 and re.fullmatch(r"[0-9A-Fa-f]{6}", hx):
171
+ return tuple(int(hx[i:i+2], 16) for i in (0, 2, 4))
172
+
173
+ # rgb/rgba(...)
174
+ m = re.match(r"rgba?\(\s*([^)]+)\)", s, flags=re.IGNORECASE)
175
+ if m:
176
+ parts = [p.strip() for p in m.group(1).split(",")]
177
+ if len(parts) >= 3:
178
+ def to_int(p):
179
+ if p.endswith("%"):
180
+ # percentage to 0-255
181
+ return clamp255(float(p[:-1]) * 255.0 / 100.0)
182
+ return clamp255(p)
183
+ r, g, b = to_int(parts[0]), to_int(parts[1]), to_int(parts[2])
184
+ if None not in (r, g, b):
185
+ return (r, g, b)
186
+
187
+ # 'r,g,b'
188
+ if "," in s:
189
+ parts = [p.strip() for p in s.split(",")]
190
+ if len(parts) >= 3:
191
+ def to_int(p):
192
+ if p.endswith("%"):
193
+ return clamp255(float(p[:-1]) * 255.0 / 100.0)
194
+ return clamp255(p)
195
+ r, g, b = to_int(parts[0]), to_int(parts[1]), to_int(parts[2])
196
+ if None not in (r, g, b):
197
+ return (r, g, b)
198
+
199
+ return None
200
+
201
+
202
  def _apply_meeting_logo(OUTPUT_DIR: Path, meeting_logo_file, logs):
203
  """Replace output/poster_latex_proj/logos/right_logo.png if meeting_logo_file provided."""
204
  if not meeting_logo_file:
 
227
  return False
228
 
229
  def _apply_theme_rgb(OUTPUT_DIR: Path, rgb_tuple, logs):
230
+ """Update \\definecolor{<name>}{RGB}{r,g,b} or {HTML}{RRGGBB} in poster_output.tex."""
231
  if not rgb_tuple:
232
  return False
233
 
 
238
 
239
  try:
240
  content = tex_path.read_text(encoding="utf-8")
241
+ r, g, b = rgb_tuple
242
+ # names we might use in template
243
+ name_pattern = r"(?:nipspurple|neuripspurple|themecolor)"
244
+
245
+ # 1) Try RGB form
246
+ rgb_pat = rf"(\\definecolor\{{{name_pattern}\}}\{{RGB\}}\{{)\s*\d+\s*,\s*\d+\s*,\s*\d+\s*(\}})"
247
+ new_content, n = re.subn(rgb_pat, rf"\1{r},{g},{b}\2", content, flags=re.MULTILINE)
248
+
249
+ if n == 0:
250
+ # 2) Try HTML form: \definecolor{name}{HTML}{5E2E91}
251
+ from_str = f"{r:02X}{g:02X}{b:02X}"
252
+ html_pat = rf"(\\definecolor\{{{name_pattern}\}}\{{HTML\}}\{{)[0-9A-Fa-f]{{6}}(\}})"
253
+ new_content, n = re.subn(html_pat, rf"\1{from_str}\2", content, flags=re.MULTILINE)
254
+
255
  if n > 0:
256
  tex_path.write_text(new_content, encoding="utf-8")
257
+ logs.append(f"🎨 Theme color updated to RGB {{{r},{g},{b}}} in {tex_path.relative_to(OUTPUT_DIR)}")
258
  return True
259
  else:
260
+ logs.append("ℹ️ No \\definecolor target found.")
261
  return False
262
+
263
  except Exception as e:
264
  logs.append(f"⚠️ Failed to update theme RGB: {e}")
265
  return False
266
 
267
+
268
  def _apply_left_logo(OUTPUT_DIR: Path, logo_files, logs):
269
  """
270
  Use the first institutional logo uploaded by the user:
 
541
 
542
  # ====== Zip output (run-local) ======
543
  try:
544
+ target_dir = OUTPUT_DIR / "poster_latex_proj"
545
+
546
+ if not target_dir.exists():
547
+ logs.append("❌ poster_latex_proj folder not found")
548
+ else:
549
+ with zipfile.ZipFile(ZIP_PATH, 'w', zipfile.ZIP_DEFLATED) as zipf:
550
+ for root, dirs, files in os.walk(target_dir):
551
+ for file in files:
552
+ file_path = Path(root) / file
553
+ arcname = file_path.relative_to(target_dir) # only relative to subfolder
554
+ zipf.write(file_path, arcname=arcname)
555
+
556
+ logs.append(f"βœ… Zipped poster_latex_proj β†’ {ZIP_PATH.relative_to(WORK_DIR)}")
557
+
558
  except Exception as e:
559
  logs.append(f"❌ Failed to create zip: {e}")
560
+
561
  # ====== Prepare Overleaf base64 payload (optional) ======
562
  overleaf_zip_b64 = ""
563
  try: