Skip to content

acn-slide-gen — Pipeline

/acn-slide-gen:generate runs a deterministic 6-phase pipeline. Each phase consumes the previous phase’s output. The pipeline drives toward a self-contained Python script that python-pptx executes against the chosen flavor’s template.

flowchart LR
    P0["Phase 0<br/>Decrypt"] --> P1["Phase 1<br/>Inspect Template"]
    P1 --> P2["Phase 2<br/>Reason About Layout"]
    P2 --> P3["Phase 3<br/>Parse Content"]
    P3 --> P4["Phase 4<br/>Generate Python Script"]
    P4 --> P5["Phase 5<br/>Verify Output"]

Resolve the source PPTX path and confirm it’s readable.

  • New Deck Mode: look up --flavor in the registry, resolve to template.pptx
  • Modify Mode: use the <deck.pptx> argument directly
  • Locate a venv (.venv-pptx/.venv/ → any with python-pptx), or fall back to creating /tmp/.venv-pptx
  • Run ${CLAUDE_PLUGIN_ROOT}/scripts/decrypt_pptx.py "<path>" and handle exit codes 0/1/2/3 (decrypted / not-found / password-fail / DRM-blocked)

Extract shape geometry and theme tokens.

  • inspect_slide.py "<path>" <slide_number> --json → shape inventory with EMU coordinates and properties
  • inspect_theme.py "<path>" --json → theme color and font tokens
  • Read the active flavor’s brand.md for branding rules

Classify each shape into a semantic role: brand-label, section-label, title, description, content-card, divider-line, footer-banner, footer-item, background-shape, image, unknown. Tag each as static, parameterized, or repeating. New Deck Mode also catalogs all available layouts and maps content sections (# → cover, ## no body → divider, ## with body → content).

Map markdown to layout zones.

  • ## heading → slide boundary + title zone
  • First short line after heading → section-label
  • Paragraphs → description
  • ### sub-sections / bullets → content-cards or footer-items
  • Bold-prefixed bullets (**Title**: description) split into card title + body
  • Image input: read via Claude vision, infer headings, bullets, and sections, map to zones
  • Overflow: split across multiple slides, append (1/2), (2/2) suffixes
  • Underflow: leave card slots unfilled (don’t insert empty shapes)

Write a self-contained script to /tmp/slide_gen_<timestamp>.py that:

  • Defines EMU constants from Phase 1 coordinates
  • One xml_<role>() f-string function per shape role
  • Uses schemeClr references — never hardcoded RGB — so shapes inherit theme color
  • Strict border rule: never use <a:ln><a:solidFill/></a:ln> (empty solidFill inherits theme line color and produces unintended outlines); explicit color inside <a:solidFill> when a border is intended
  • Helpers: _uid(), _esc(), _ext() for IDs, escaping, creation IDs
  • build_slide() assembles shapes onto slide.shapes._spTree
  • reorder_slides() if --after is specified

Branding compliance is verified pre-write against the flavor’s brand.md (fonts, colors, sentence-case headlines, left-aligned text, highlight rules, layout selection, color proportions).

After the script runs, confirm slide count, per-slide shape count, and (if --after was used) slide ordering. Branding spot-check on cover layout, structural markers, and one content slide’s font and color compliance against brand.md.

The generated script is preserved at /tmp/slide_gen_*.py for debugging and reuse.

Three Python helpers ship in ${CLAUDE_PLUGIN_ROOT}/scripts/:

  • decrypt_pptx.py — strip DRM from password-protected files; exit codes signal status
  • inspect_slide.py — dump layout geometry and shape properties to JSON
  • inspect_theme.py — extract theme color and font tokens

The scripts are flavor-agnostic. Flavor specifics live in assets/flavors/<flavor>/brand.md — see Flavors.