Skip to content

Releases: EveryInc/hands-on-deck

deckhand 2.0.0 — the create path

09 Jun 20:45

Choose a tag to compare

deckhand 1.x edited decks. deckhand 2.0 designs them.

The create path: write the slide as a webpage

Agents are bad at inventing slide layouts shape-by-shape — and world-class at HTML/CSS. html2patch.py closes that gap: the agent writes the slide as HTML, a headless browser renders it purely as a measuring engine, and every measured box and computed style compiles into an ordinary deck.py patch.

python html2patch.py slide.html --deck deck.pptx --layout Blank -o patch.json
python deck.py deck.pptx apply patch.json -o out.pptx --render img/

The output is a patch, not a second file format — and that's the whole architecture:

  • One writer. A compiled slide is born with the same shape ids, lint coverage, fix loop, and diff as any edit. The agent can nudge one box seconds after creating it, with an ordinary op.
  • Creates into your template. The patch can add-slide with a layout from your branded master and place the HTML-measured shapes onto it. Free-form design inside an existing deck — the thing generate-a-new-file architectures structurally cannot do.
  • Drift is caught, not hoped away. Browsers and PowerPoint wrap text slightly differently; the post-apply linter re-measures the real deck and reports any overflow with the exact fix.
  • Compiled, not approximated. CSS gradients → native gradient fills. Tables keep per-cell fills and measured column widths. object-fit: cover → a true picture crop. <ol> numbers, rotation rotates, text-transform applies, CSS padding → text insets, partial borders → accent lines, writing-mode → vertical text.

Stress-tested against the browser pixel-by-pixel across five fixture suites, and head-to-head against the best-known HTML-to-PPTX engine on its own constraint set: closer to the browser's render (RMS 24.3 vs 29.5) — and where that engine reported success while silently dropping an entire table and garbling nested lists, deckhand carried both.

Design record: docs/html2patch-spec.md. Clean-room implementation — no code shared with any other HTML-to-PPTX tool.

deck.py grew the keys the compiler needed (yours to use too)

  • set-style / add-shape: insets:[l,t,r,b] (text-frame margins in inches), adjustments:[…] (true corner radii), shadow:false (kills the theme's inherited drop shadow, including the effectRef some renderers apply anyway), fill:"none" (hollow shapes)
  • add-picture: crop:[l,t,r,b] source fractions — fill a box without distortion
  • add-table: name, color, fill / per-cell fills grid, col_widths, first_row:false + banding:false to neutralize theme table styling
  • Text model: bullet:"number" for auto-numbered paragraphs alongside bullet:true
  • Lint fix: explicit zero text-frame margins no longer treated as "unset" (falsy-zero bug that caused phantom overflow reports)

Upgrading

No breaking changes to existing ops — 2.0 marks the new creation surface, not a compatibility break. The create path needs one optional extra: pip install playwright && playwright install chromium. Core deckhand stays pip install python-pptx Pillow.

25 end-to-end tests, CI on ubuntu with LibreOffice + Chromium.


🤖 Generated with Claude Code