Highlights
Animated images survive export again (fixes a v2.12.0 regression)
v2.12.0's native-PPTX media size cap re-encoded every raster image through PIL, which silently flattened animated GIFs to their first frame — in the exported PPTX and in svg_final embeds, with no warning. All three optimize paths now detect multi-frame images (is_animated: covers GIF / animated WebP / APNG) and pass the original bytes through untouched, so animations play in the exported deck exactly as authored. Static images keep the full compression and size-cap behavior. Oversized animated assets are kept as-is with a console warning — animations are exempt from size limits. (#209)
project init no longer double-suffixes
project_manager.py init re-appended _<format>_<date> even when the given name already carried it — the natural operation when pasting an existing project directory name for a rebuild. A name already ending with the same-format suffix is now used as-is; a different-format suffix still appends (an explicit canvas switch). (#210)
source-to-md: batch and directory conversion
source_to_md.py now accepts multiple files, directories, and URLs in one call, unified behind a single conversion dispatcher; converted web pages are named by their page title.
Guidance & docs
- Path B (host-native image tools): fixed-resolution hosts generate at the nearest native tier, record actual pixels in the resource list, and never upsample to fake the requested size (#210)
- Overlay & Masking: new slice-crop displacement rule — text over images must sit on the scrim's opaque plateau, never start inside the gradient transition band (#210)
- Stale v2.12 cross-references fixed across
references/(#209);sources/content-type read policy documented; UTF-8 console-encoding boilerplate completed on the last remaining CLI script
Credits: @shenqili for the v2.12 review (#209), the 13-deck dogfood report (#210), and PRs #212–#215.