[object Object]

← back to Crazy News Channel

cartoon pages: share one page template between approve.py and the Shadow Man export (TK-12247)

afee2fe2932db3c017760cfdf35bf08a2480a49e · 2026-09-25 11:43:10 -0700 · Steve

approve.py now renders cartoons/<date>-<slug>.html from daily-cartoons/cartoon-page.template.html;
output verified byte-identical to the previous inline f-string on a scratch copy.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XizSgLiFuNbjY418z94Ewq

Files touched

Diff

commit afee2fe2932db3c017760cfdf35bf08a2480a49e
Author: Steve <steve@designerwallcoverings.com>
Date:   Fri Sep 25 11:43:10 2026 -0700

    cartoon pages: share one page template between approve.py and the Shadow Man export (TK-12247)
    
    approve.py now renders cartoons/<date>-<slug>.html from daily-cartoons/cartoon-page.template.html;
    output verified byte-identical to the previous inline f-string on a scratch copy.
    
    Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01XizSgLiFuNbjY418z94Ewq
---
 daily-cartoons/approve.py                 | 18 +++++++++++++-----
 daily-cartoons/cartoon-page.template.html |  5 +++++
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/daily-cartoons/approve.py b/daily-cartoons/approve.py
index f13bd8b..8b6f49b 100755
--- a/daily-cartoons/approve.py
+++ b/daily-cartoons/approve.py
@@ -16,6 +16,14 @@ import build_review
 
 CART = os.path.join(C.SITE, "cartoons")
 
+TEMPLATE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "cartoon-page.template.html")
+
+def render_page(**fields):
+    """Fill cartoon-page.template.html ({{key}} placeholders, single pass). Values must already be
+    HTML-escaped (media/source are pre-built markup)."""
+    tpl = open(TEMPLATE, encoding="utf-8").read().rstrip("\n")
+    return re.sub(r"\{\{(\w+)\}\}", lambda mo: fields[mo.group(1)], tpl)
+
 def story_exists(sid):
     for f in ("stories-data.js", "real-news-data.js"):
         p = os.path.join(C.SITE, f)
@@ -53,11 +61,11 @@ def main():
     src_url, src_title = m.get("story_url"), m.get("story_title")
     src_html = (f'<p class="src"><a href="{e(src_url)}" target="_blank" rel="noopener noreferrer">Source: {e(src_title or "linked article")}</a></p>'
                 if src_url else "")
-    open(os.path.join(CART, base + ".html"), "w").write(f'''<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">
-<meta name="viewport" content="width=device-width,initial-scale=1"><title>{e(m["title"])}</title>
-<link rel="stylesheet" href="../assets/style.css"></head>
-<body class="cartoon-page-simple"><p><a href="index.html">← Cartoon Desk</a></p>{media}<h1>{e(m["title"])}</h1>
-<p class="cap">&ldquo;{e(m["caption"])}&rdquo;</p>{src_html}<p><small>AI-generated editorial cartoon in classic editorial-ink style. Invented figures only.</small></p></body></html>''')
+    # TK-12247: the page markup lives in daily-cartoons/cartoon-page.template.html, shared with the
+    # Inkwell Shadow Man export so every single-image cartoon page is rendered from ONE template.
+    open(os.path.join(CART, base + ".html"), "w").write(render_page(
+        title=e(m["title"]), media=media, caption=e(m["caption"]), source=src_html,
+        credit="AI-generated editorial cartoon in classic editorial-ink style. Invented figures only."))
     mf = os.path.join(CART, "manifest.js"); src = open(mf).read()
     mm = re.search(r"(window\.P24_CARTOONS\s*=\s*)(\[[\s\S]*\])(\s*;\s*)$", src)
     arr = json.loads(mm.group(2)); arr = [x for x in arr if x.get("id") != a.slug]
diff --git a/daily-cartoons/cartoon-page.template.html b/daily-cartoons/cartoon-page.template.html
new file mode 100644
index 0000000..e781f84
--- /dev/null
+++ b/daily-cartoons/cartoon-page.template.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1"><title>{{title}}</title>
+<link rel="stylesheet" href="../assets/style.css"></head>
+<body class="cartoon-page-simple"><p><a href="index.html">← Cartoon Desk</a></p>{{media}}<h1>{{title}}</h1>
+<p class="cap">&ldquo;{{caption}}&rdquo;</p>{{source}}<p><small>{{credit}}</small></p></body></html>
\ No newline at end of file

← 95c7f77 auto-data-snapshot: 2026-09-25T11:23:40 (3 data files) — .cl  ·  back to Crazy News Channel  ·  p24: attach 2 Shadow Man cartoons to their articles — Money b0563b7 →