md2star.pptx_assemble module

Seam-D PPTX assembler: build a deck directly on the AI-selected layouts.

md2star.pptx_layout decides, per slide, which of a designer template’s named layouts best carries that slide’s content. This module is what actually uses that decision: for every slide it instantiates the chosen layout (not a fixed handful of curated backgrounds) from the real template and overlays guaranteed-legible content, so the deck’s visual variety follows the AI’s per-slide reasoning instead of a hand-picked round-robin.

Design choice, carried over from the PoC that proved it out: fighting a designer layout’s own placeholders is fragile (their colours and geometry vary wildly, some are dark-on-dark, some clutter a small box next to a big void). Instead each slide keeps the chosen layout’s background (its true branding) and places our own guaranteed-safe text/image boxes in it, sized from the layout’s actual placeholder geometry when the catalog recorded one (title / body / picture), and a sensible fractional default otherwise — so it degrades gracefully for template layouts the catalog under-described.

Text colour is not hard-coded white: with an arbitrary designer layout now in play (not just a curated dark subset), a slide’s background can be light, so the assembler reads the layout’s own background colour and switches to a dark foreground when needed. This is the correctness gap the curated-background PoC never had to close.

The target-matching Ralph Eyeball Loop (eyeball_slides()) closes the verification gap the same way md2star.reverse_diagrams does for diagrams: render the assembled slide, show it and the chosen layout’s own catalog thumbnail to a vision model, and apply bounded, spec-level fixes (shrink text, trim bullets, grow an undersized image) rather than ever hand- editing the picture.

Author

[Warith HARCHAOUI](https://linkedin.com/in/warith-harchaoui/)

class md2star.pptx_assemble.AssembleResult(pptx_path: 'Path', placed: 'int', total: 'int')[source]

Bases: object

Parameters:
placed: int
pptx_path: Path
total: int
md2star.pptx_assemble.add_code(slide, code, box, *, font)[source]
Parameters:
Return type:

None

md2star.pptx_assemble.add_image(slide, img, *, box)[source]
Parameters:
Return type:

None

md2star.pptx_assemble.add_text(slide, blocks, box, *, color, center=False, middle=False)[source]

Overlay a text box. blocks = list of (text, pt_size, bold, font).

Parameters:
Return type:

None

md2star.pptx_assemble.assemble(slides, catalog, template, out_path, *, image_base_dir=None, render_mermaid=None, default_layout=None)[source]

Build a real .pptx directly on each slide’s AI-selected layout.

For every slide, instantiate slides[i].chosen_layout from template (falling back to default_layout, or the template’s first layout, when the pick is missing or unknown) and overlay title/body/image/code content sized from that layout’s own placeholder geometry when the catalog recorded one. Per-slide overrides (written by eyeball_slides()) bound font size, bullet count and image growth.

Returns:

The output path plus how many of the slides were placed without error (a per-slide exception is logged and skipped, never aborts the deck).

Return type:

AssembleResult

Parameters:
md2star.pptx_assemble.clear_slides(prs)[source]

Drop every slide the template ships with, keeping layouts/masters.

Parameters:

prs (Presentation)

Return type:

None

md2star.pptx_assemble.content_box(prs, info)[source]
Parameters:
Return type:

tuple[float, float, float, float]

md2star.pptx_assemble.eyeball_slides(slides, catalog, template, out_path, *, indices=None, max_iterations=1, chat=None, render_template=None, render_deck=None, image_base_dir=None, render_mermaid=None, default_layout=None)[source]

Target-matching Ralph Eyeball Loop over an assembled deck.

Assembles (or re-uses an already-assembled) deck, renders it, and for each of indices (default: every slide) shows a vision model both the candidate render and the chosen layout’s own catalog thumbnail. On a mismatch it writes a bounded overrides entry back onto the slide (shrink text, cap bullets, grow an undersized image — never touches the picture itself) and re-assembles, up to max_iterations passes. Any transport/render failure leaves the current best assembly untouched.

render_deck renders the assembled output deck itself (default: md2star.pptx_layout.render_deck_pages(), LibreOffice + poppler); injectable so the loop is testable offline without either installed.

Parameters:
Return type:

AssembleResult

md2star.pptx_assemble.fallback_bullets(body, cap)[source]

Trimmed bullet text, used when no AI summary was computed for a slide.

Parameters:
Return type:

list[str]

md2star.pptx_assemble.image_box(prs, info)[source]
Parameters:
Return type:

tuple[float, float, float, float]

md2star.pptx_assemble.is_content(features)[source]
Parameters:

features (list[str])

Return type:

bool

md2star.pptx_assemble.is_dark_layout(layout)[source]

True/False for a resolvable solid background, else None.

Return type:

bool | None

md2star.pptx_assemble.layout_index(prs)[source]

Map every distinct layout name to its SlideLayout object.

Parameters:

prs (Presentation)

Return type:

dict[str, object]

md2star.pptx_assemble.parse_code(body)[source]

First non-Mermaid fenced block (the slide’s primary code sample, if any).

Parameters:

body (str)

Return type:

str | None

md2star.pptx_assemble.parse_image(body, base_dir)[source]
Parameters:
  • body (str)

  • base_dir (Path | None)

Return type:

Path | None

md2star.pptx_assemble.parse_mermaid(body)[source]
Parameters:

body (str)

Return type:

str | None

md2star.pptx_assemble.template_fonts(template)[source]

Derive the template’s own DESIGN fonts: {family, display, body}.

Reads every explicit typeface="..." on slide/layout shapes (not the theme, which carries Office’s long CJK fallback list) and picks the most- common non-system face as body, its heaviest same-family weight as display (titles). Falls back to Arial when the template declares no explicit design font. Read-only: unlike the PoC this is derived from, this never downloads or installs fonts — a missing font degrades to whatever substitute PowerPoint/LibreOffice picks, exactly like every other best-effort AI/rendering feature in this package.

Parameters:

template (Path)

Return type:

dict[str, str]

md2star.pptx_assemble.title_box(prs, info, *, divider=False)[source]
Parameters:
Return type:

tuple[float, float, float, float]