JS6969 commited on
Commit
2d95095
·
verified ·
1 Parent(s): d3f75c2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +79 -29
app.py CHANGED
@@ -281,30 +281,39 @@ def load_journal() -> dict:
281
  # ────────────────────────────────────────────────────────
282
  # Shape Aliases (compile/cache/apply)
283
  # ────────────────────────────────────────────────────────
284
- def _compile_shape_aliases_from_file():
285
  s = load_settings()
286
- if not s.get("shape_aliases_enabled", True):
287
- return []
288
- compiled = []
289
- for item in s.get("shape_aliases", []):
290
- shape = (item.get("shape") or "").strip()
291
- name = (item.get("name") or "").strip()
292
- if not shape or not name:
 
 
 
 
 
 
 
293
  continue
294
- pat = rf"\b{re.escape(shape)}(?:-?shaped)?\b"
295
- compiled.append((re.compile(pat, flags=re.I), name))
296
- return compiled
297
-
298
- _SHAPE_ALIASES = _compile_shape_aliases_from_file()
299
-
300
- def _refresh_shape_aliases_cache():
301
- global _SHAPE_ALIASES
302
- _SHAPE_ALIASES = _compile_shape_aliases_from_file()
 
 
 
 
 
 
303
 
304
- def apply_shape_aliases(caption: str) -> str:
305
- for pat, name in _SHAPE_ALIASES:
306
- caption = pat.sub(f"({name})", caption)
307
- return caption
308
 
309
  # ────────────────────────────────────────────────────────
310
  # Logo loader
@@ -606,14 +615,55 @@ with gr.Blocks(css=BASE_CSS, title="CaptionForge") as demo:
606
  max_side = gr.Slider(256, MAX_SIDE_CAP, settings.get("max_side", min(896, MAX_SIDE_CAP)), step=32, label="Max side (resize)")
607
 
608
  # Shape Aliases UI (Accordion)
609
- with gr.Accordion("Shape Aliases", open=False):
610
- enable_aliases = gr.Checkbox(label="Enable shape alias replacements", value=True)
611
- alias_table = gr.Dataframe(
612
- headers=["shape (literal token)", "name to insert"],
613
- datatype=["str","str"],
614
- row_count=(1, "dynamic"),
615
- wrap=True,
616
- interactive=True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
617
  )
618
  save_aliases_btn = gr.Button("Save aliases")
619
  save_status = gr.Markdown()
 
281
  # ────────────────────────────────────────────────────────
282
  # Shape Aliases (compile/cache/apply)
283
  # ────────────────────────────────────────────────────────
284
+ def get_shape_alias_rows_ui_defaults():
285
  s = load_settings()
286
+ rows = [[it.get("shape",""), it.get("name","")] for it in s.get("shape_aliases", [])]
287
+ enabled = bool(s.get("shape_aliases_enabled", True))
288
+ # Always show at least one empty row
289
+ if not rows:
290
+ rows = [["", ""]]
291
+ return rows, enabled
292
+
293
+ def save_shape_alias_rows(enabled, df_rows):
294
+ cfg = load_settings()
295
+ cfg["shape_aliases_enabled"] = bool(enabled)
296
+
297
+ cleaned = []
298
+ for r in (df_rows or []):
299
+ if not r:
300
  continue
301
+ shape = (r[0] or "").strip()
302
+ name = (r[1] or "").strip()
303
+ if shape and name:
304
+ cleaned.append({"shape": shape, "name": name})
305
+
306
+ cfg["shape_aliases"] = cleaned
307
+ save_settings(cfg)
308
+ _refresh_shape_aliases_cache()
309
+
310
+ # Normalize table after save (keep one empty row at the end)
311
+ normalized = [[it["shape"], it["name"]] for it in cleaned] + [["", ""]]
312
+ return (
313
+ "✅ Saved shape alias options.",
314
+ gr.update(value=normalized, row_count=(max(1, len(normalized)), "dynamic"))
315
+ )
316
 
 
 
 
 
317
 
318
  # ────────────────────────────────────────────────────────
319
  # Logo loader
 
615
  max_side = gr.Slider(256, MAX_SIDE_CAP, settings.get("max_side", min(896, MAX_SIDE_CAP)), step=32, label="Max side (resize)")
616
 
617
  # Shape Aliases UI (Accordion)
618
+ with gr.Tab("Shape Aliases"):
619
+ gr.Markdown(
620
+ "### 🔷 Shape Aliases\n"
621
+ "Tell CaptionForge to replace literal **shape tokens** it sees in captions with your preferred **name**.\n\n"
622
+ "**How to use:**\n"
623
+ "1) In the left column, type the exact shape token (e.g., `diamond`, `heart`, `oval`).\n"
624
+ "2) In the right column, type the replacement name you want inserted (e.g., `starkey-emblem`).\n"
625
+ "3) Click **Save**.\n\n"
626
+ "Tips: rows with either side blank are ignored; you can add as many rows as you like."
627
+ )
628
+
629
+ init_rows, init_enabled = get_shape_alias_rows_ui_defaults()
630
+
631
+ enable_aliases = gr.Checkbox(
632
+ label="Enable shape alias replacements",
633
+ value=init_enabled,
634
+ info="Turn all replacements on/off without deleting your list."
635
+ )
636
+
637
+ alias_table = gr.Dataframe(
638
+ headers=["shape (literal token)", "name to insert"],
639
+ value=init_rows, # <-- set value at creation time
640
+ col_count=(2, "fixed"), # <-- lock to 2 columns
641
+ row_count=(max(1, len(init_rows)), "dynamic"), # user can add rows
642
+ datatype=["str", "str"],
643
+ type="array", # <-- treat rows as lists (most reliable for editing)
644
+ interactive=True
645
+ )
646
+
647
+ with gr.Row():
648
+ add_row_btn = gr.Button("+ Add row", variant="secondary")
649
+ clear_btn = gr.Button("Clear", variant="secondary")
650
+ save_btn = gr.Button("💾 Save", variant="primary")
651
+
652
+ save_status = gr.Markdown("")
653
+
654
+ # Button logic
655
+ def _add_row(cur):
656
+ cur = (cur or []) + [["", ""]]
657
+ # keep dynamic rows in sync
658
+ return gr.update(value=cur, row_count=(max(1, len(cur)), "dynamic"))
659
+
660
+ def _clear_rows():
661
+ return gr.update(value=[["", ""]], row_count=(1, "dynamic"))
662
+
663
+ add_row_btn.click(_add_row, inputs=[alias_table], outputs=[alias_table])
664
+ clear_btn.click(_clear_rows, inputs=None, outputs=[alias_table])
665
+ save_btn.click(save_shape_alias_rows, inputs=[enable_aliases, alias_table], outputs=[save_status, alias_table])
666
+
667
  )
668
  save_aliases_btn = gr.Button("Save aliases")
669
  save_status = gr.Markdown()