docs(P3a): inline images for self-contained HTML (REQ-268)
New scripts/inline_images.py (stdlib only: base64, re, mimetypes) — base64-embeds all relative-path <img src='assets/...'> images into the rendered HTML so it's redistributable without the assets/ folder. MIME-sniffs by extension (.png->image/png, .svg->image/svg+xml, etc). render_slides.sh Step 3 invokes it after the MARP HTML render, before staging. Verified: 2 images inlined, 0 file-path refs remaining. ---ci--- project: acdl phase: 3 milestone: v1.23 status: execute phase_role: execution ---/ci---
This commit is contained in:
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
"""scripts/inline_images.py — base64-embed all relative-path images in an
|
||||
HTML file so it becomes self-contained (redistributable without the
|
||||
assets/ folder).
|
||||
|
||||
Usage: python scripts/inline_images.py <html-path>
|
||||
|
||||
Stdlib only (base64, re, mimetypes, sys, pathlib).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import mimetypes
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
IMG_SRC_RE = re.compile(
|
||||
r'(<img\b[^>]*\bsrc=")(assets/[^"]+)("[^>]*>)',
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
|
||||
def _mime_for(path: Path) -> str:
|
||||
ext = path.suffix.lower()
|
||||
if ext == ".svg":
|
||||
return "image/svg+xml"
|
||||
guessed, _ = mimetypes.guess_type(str(path))
|
||||
return guessed or "application/octet-stream"
|
||||
|
||||
|
||||
def inline(html_path: Path) -> int:
|
||||
html = html_path.read_text(encoding="utf-8")
|
||||
repo_root = html_path.parent.parent.parent
|
||||
|
||||
count = 0
|
||||
|
||||
def replacer(match: re.Match[str]) -> str:
|
||||
nonlocal count
|
||||
prefix, rel_src, suffix = match.group(1), match.group(2), match.group(3)
|
||||
img_path = html_path.parent / rel_src
|
||||
if not img_path.exists():
|
||||
print(f" WARNING: image not found: {rel_src}", file=sys.stderr)
|
||||
return match.group(0)
|
||||
mime = _mime_for(img_path)
|
||||
data = base64.b64encode(img_path.read_bytes()).decode("ascii")
|
||||
count += 1
|
||||
return f'{prefix}data:{mime};base64,{data}{suffix}'
|
||||
|
||||
new_html = IMG_SRC_RE.sub(replacer, html)
|
||||
|
||||
if count > 0:
|
||||
html_path.write_text(new_html, encoding="utf-8")
|
||||
|
||||
return count
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: python scripts/inline_images.py <html-path>", file=sys.stderr)
|
||||
return 1
|
||||
html_path = Path(sys.argv[1])
|
||||
if not html_path.exists():
|
||||
print(f"ERROR: {html_path} not found", file=sys.stderr)
|
||||
return 1
|
||||
count = inline(html_path)
|
||||
print(f"Inlined {count} image(s) into {html_path}", file=sys.stderr)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -2,7 +2,8 @@
|
||||
# scripts/render_slides.sh — render the Nova presentation deck end-to-end:
|
||||
# 1. Mermaid .mmd → .png (S&P-themed via sp-theme.json)
|
||||
# 2. Marp .md → .html + .pptx (S&P-themed via inline style: block in frontmatter)
|
||||
# 3. Stage all rendered artifacts to git.
|
||||
# 3. Inline images → base64-embed all images in the HTML (self-contained).
|
||||
# 4. Stage all rendered artifacts to git.
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/render_slides.sh [deck-name]
|
||||
@@ -71,7 +72,13 @@ echo " PPTX → $PPTX"
|
||||
npx --yes @marp-team/marp-cli@4.5.0 --allow-local-files "$SRC" -o "$PPTX" 2>&1 | tail -3
|
||||
echo ""
|
||||
|
||||
# --- Step 3: stage ---
|
||||
echo "=== Step 3: Staging rendered artifacts ==="
|
||||
# --- Step 3: inline images into HTML (base64-embed for redistribution) ---
|
||||
# REQ-268: makes the HTML self-contained (no assets/ folder needed).
|
||||
echo "=== Step 3: Inlining images into HTML ==="
|
||||
python3 scripts/inline_images.py "$HTML" 2>&1
|
||||
echo ""
|
||||
|
||||
# --- Step 4: stage ---
|
||||
echo "=== Step 4: Staging rendered artifacts ==="
|
||||
git add "$PNG_DIR"/*.png "$HTML" "$PPTX" 2>/dev/null || true
|
||||
echo "=== Done: staged $(ls "$PNG_DIR"/*.png 2>/dev/null | wc -l) PNGs + $HTML + $PPTX ==="
|
||||
|
||||
Reference in New Issue
Block a user