From d00af71a912ffc4b4152d0297083a6d7bbee611a Mon Sep 17 00:00:00 2001 From: Mikkeli Date: Thu, 13 Aug 2026 18:03:31 +0900 Subject: [PATCH] Prune card exports whose PNG is gone Deleting a character in the UI left _text/cards/.json behind, describing a card that no longer exists. A stale derived file is worse than a missing one because it reads as current -- which is the exact reason the pre-commit hook regenerates _text/ at all, so the script was failing its own premise. Found by testing a deletion rather than reading the code. The write path was obviously correct; the delete path had simply never been written. --- _text/cards/Aino Vihtanen.json | 4 ++-- characters/Aino Vihtanen.png | Bin 94141 -> 94173 bytes st-export.py | 12 ++++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/_text/cards/Aino Vihtanen.json b/_text/cards/Aino Vihtanen.json index 0e62f20..17700c6 100644 --- a/_text/cards/Aino Vihtanen.json +++ b/_text/cards/Aino Vihtanen.json @@ -1,6 +1,6 @@ { - "avatar": "none", - "chat": "Aino Vihtanen - 2026-08-12@16h09m13s142ms", + "avatar": "Aino Vihtanen.png", + "chat": "Aino Vihtanen - 2026-08-13@18h01m20s857ms", "create_date": "2026-08-12T16:09:13.167Z", "creatorcomment": "", "data": { diff --git a/characters/Aino Vihtanen.png b/characters/Aino Vihtanen.png index e4807ede5af88ba40593cab043634c537e0dfe7a..0db655efeef7523c402ab2f85836467c54a8b369 100644 GIT binary patch delta 1283 zcmeH`&#Kcv7{%K~T?xAI3Eb92nzV&kC^U^pC)`PCZ<|a81Ur-4n@N+lcoSoSP;ns$ zK8qj-UAb}NQ%GOMZ{mMlxN>)AH83;hJLkul52w!OQ|HC|_Nd!_a5TH^8@CU$AT4-h z2CE>}!eEecIVgE1}rOOk{+u`YA6@J3`2?}%mRBr)r$wKO;- zN&_^XJqhW2A7y^Qs8=gJGVb@VEG5hAM>Vhc$%7_ykUvK+dO6l=%sn2K#9zc zBL`K=gVG80I2M_mM2=rkV{G$vhR=03P{kX1FN>LOhFr&Yn{M!DtKy z2Td?F^rHGF$=^ZhsN&A->%7C*-7rYGvQa5Al#2-*Y_H^>>6zn~k#i}h$qW(#8E2{J zf1{`RlASq-lrBU{Lr)BnvY+80hkiIx&QzG delta 9334 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 diff --git a/st-export.py b/st-export.py index 2f9475a..b689dc4 100755 --- a/st-export.py +++ b/st-export.py @@ -92,6 +92,18 @@ def export_cards() -> int: json.dump(card, fh, indent=2, ensure_ascii=False, sort_keys=True) fh.write("\n") n += 1 + + # ⚠ PRUNE EXPORTS WHOSE SOURCE IS GONE. Without this, deleting a character in + # the UI left `_text/cards/.json` behind describing a card that no + # longer exists — and it reads as current, which is worse than absent. Found + # by testing a deletion rather than by reading the code: the write path was + # obviously correct and the delete path was simply never written. + live = {f[:-4] + ".json" for f in os.listdir(src) + if f.lower().endswith(".png") and not f.startswith("default_")} if os.path.isdir(src) else set() + for stale in sorted(set(os.listdir(dst)) - live): + if stale.endswith(".json"): + os.remove(os.path.join(dst, stale)) + print(f" pruned _text/cards/{stale} — its PNG is gone") return n