Metadata-Version: 2.5
Name: markdown-pptx
Version: 1.5.0
Summary: Convert constrained Markdown slide decks into editable PowerPoint presentations.
Project-URL: Homepage, https://github.com/pseudosavant/markdown-pptx
Project-URL: Repository, https://github.com/pseudosavant/markdown-pptx
Project-URL: Issues, https://github.com/pseudosavant/markdown-pptx/issues
Project-URL: Releases, https://github.com/pseudosavant/markdown-pptx/releases
Author: John Paul Ellis
License-Expression: MIT
License-File: LICENSE
Keywords: cli,markdown,powerpoint,pptx,presentation,slides
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Office/Business :: Office Suites
Classifier: Topic :: Software Development :: Documentation
Classifier: Topic :: Text Processing :: Markup
Requires-Python: >=3.11
Requires-Dist: httpx>=0.27
Requires-Dist: markdown-it-py>=3.0
Requires-Dist: mdit-py-plugins>=0.5
Requires-Dist: packaging>=24.0
Requires-Dist: pillow>=10.0
Requires-Dist: ps-python-pptx==1.2.0
Requires-Dist: pygments>=2.18
Requires-Dist: pywin32>=311; sys_platform == 'win32'
Requires-Dist: pyyaml>=6.0
Description-Content-Type: text/markdown

# markdown-pptx

`markdown-pptx` turns constrained Markdown into editable PowerPoint `.pptx` presentations built from real PowerPoint layouts and placeholders. It is a strict, predictable CLI designed for both people and coding agents.

PowerPoint generation uses the [ps-python-pptx fork](https://github.com/pseudosavant/python-pptx). The converter uses public library APIs only. See the [API boundary](docs/public-api-capabilities.md) for the capability mapping.

## Prerequisite

`markdown-pptx` is designed to be used with [`uv`](https://docs.astral.sh/uv/getting-started/installation/). Install `uv` before continuing. The documented workflows and managed agent skill use `uvx` to run the tool without requiring a global installation.

## Quick start with an agent

Install the managed agent skill:

```powershell
uvx markdown-pptx skill install
```

Then use `$markdown-pptx` in Codex, Claude Code, or another agent harness that supports skills:

> Use $markdown-pptx to create a seven-slide presentation about our product launch. Use a clear narrative, include speaker notes, and save both the Markdown source and editable PowerPoint deck.

The skill teaches the agent how to inspect the format and templates, write valid slide Markdown, render the deck, and handle the result.

## Manage the agent skill

The standard location is `~/.agents/skills/markdown-pptx/SKILL.md`. Normal invocations of an installed CLI, including help and version output, automatically synchronize an already-installed managed skill to the running CLI version. Missing and unmanaged skills are left alone. Skill-management commands skip this automatic check.

Synchronization is local only. It does not query a package index, refresh uv's cache, or update the CLI. The running CLI version is the authority. PEP 440 version comparison prevents downgrades and leaves equal versions unchanged. The skill continues to instruct agents to use `uvx markdown-pptx`.

Each generated `SKILL.md` stores lifecycle data in its YAML `metadata` mapping:

```yaml
metadata:
  managed-by: markdown-pptx
  managed-version: "1.3.0"
  managed-content-sha256: "sha256:<64 lowercase hexadecimal characters>"
```

The version above is illustrative. The generated value exactly matches `uvx markdown-pptx --version`. The SHA-256 hash covers the entire UTF-8 file with LF line endings and only the hash value replaced by `""`. Verification preserves the original YAML formatting and normalizes CRLF and CR line endings. This detects modifications. It is not a signature or security boundary. No sidecar files are used.

An older managed skill updates only when its own stored hash verifies. Modified files and valid-version files with missing or malformed hashes are preserved. The legacy HTML managed marker remains recognized. Legacy skills without a version migrate as version 0. Managed skills with missing or invalid version metadata receive a fresh replacement as a recovery step, without hash verification. A conflicting `managed-by` value always prevents replacement.

Inspect the path, ownership, versions, integrity, and automatic synchronization eligibility without changing anything:

```powershell
uvx markdown-pptx skill status
uvx markdown-pptx skill status --json
```

A normal explicit install creates a missing skill or updates a pristine older one. It refuses to overwrite modified or unverifiable managed content with valid version metadata. To restore the bundled skill and discard those edits:

```powershell
uvx markdown-pptx skill install --force
```

Install-time `--force` still refuses unmanaged skills and never downgrades a newer version. Removal accepts current and legacy managed skills. Its existing `--force` option also permits removing unmanaged content and extra files in the selected skill directory:

```powershell
uvx markdown-pptx skill remove
```

All three commands accept `--skills-dir PATH`. Custom locations require explicit updates because normal CLI invocations inspect only the standard location. Local source checkouts, local direct-source installs, and editable builds do not synchronize automatically. Unidentifiable installation origins are skipped conservatively. An installed wheel remains eligible. Explicit commands such as `uvx --from . markdown-pptx skill install` still work during development.

Automatic replacements are atomic and recheck the installed file before replacement. Maintenance failures do not change the primary command's exit status. Update notices and preservation warnings go to stderr, so documented JSON results on stdout stay valid. Changes affect future agent skill loading and may not change instructions already loaded into a running agent session.

## What it creates

Markdown stays readable, while the generated presentation remains easy to edit in PowerPoint.

![Rendered PowerPoint slide example](https://github.com/user-attachments/assets/99859d77-ca0b-4f4c-9dee-ac2be729a0e9)

## Use the CLI directly

Render a deck without installing the package globally:

```powershell
uvx markdown-pptx deck.md deck.pptx
```

Inspect the supported format or the layouts in the default template:

```powershell
uvx markdown-pptx --syntax
uvx markdown-pptx --examples list
uvx markdown-pptx --examples two-content
uvx markdown-pptx --list-layouts
```

To install the command as a persistent tool instead:

```powershell
uv tool install markdown-pptx
```

The examples below continue to use `uvx markdown-pptx` so they work without a global installation.

## How the format works

The document model has four core rules:

1. Optional document front matter may appear only at the beginning of the file.
2. Each ATX `# H1` or Setext H1 starts exactly one slide.
3. Optional slide front matter may appear only immediately after its H1 heading.
4. Everything until the next H1 belongs to that slide.

A minimal two-slide deck looks like this:

```markdown
# Quarterly review
---
layout: Title Slide
---

Acme Corporation

# Highlights
---
layout: Title and Content
---

- Revenue grew 18%
- Customer retention reached 94%
- Two new products launched
```

Render it with:

```powershell
uvx markdown-pptx deck.md deck.pptx
```

If no `--template` is provided, the packaged default template is used.

## Use a PowerPoint template

Inspect a template before writing the deck, then use only the layouts it provides:

```powershell
uvx markdown-pptx --list-masters --template theme.pptx
uvx markdown-pptx --list-layouts --template theme.pptx --master 2
uvx markdown-pptx deck.md deck.pptx --template theme.pptx --master 2
```

All embedded slide masters are retained in the output. This keeps every layout group available in PowerPoint after the deck is generated.

The effective master is selected in this order:

1. The slide-level `master` value
2. The CLI `--master` option
3. The first embedded master

Master selectors may be 1-based indices or exact unique master or theme names. Indices are the most reliable choice because template names can be blank or duplicated. Layout names are resolved only within the effective master.

The renderer uses real placeholders for slide titles and bodies. Missing placeholders, duplicate layout names, and ambiguous placeholder mappings are errors. It does not invent free-positioned text boxes to compensate for an incompatible template.

## Customize a deck

Document front matter sets deck-wide defaults:

| Key | Purpose |
| --- | --- |
| `aspect_ratio` | Select `16:9` or `4:3` |
| `fonts` | Set body and heading fonts |
| `color_scheme` | Start from a preset or define PowerPoint theme colors |
| `background` | Set a solid color, gradient, image, or no background |
| `title_color` | Set the default title color |
| `body_color` | Set the default body and subtitle color |

Slide front matter controls an individual slide:

| Key | Purpose |
| --- | --- |
| `master` | Override the default slide master |
| `layout` | Select a layout from the effective master |
| `background` | Override the document background |
| `title_color` | Override the document title color |
| `body_color` | Override the document body color |
| `hide_background_graphics` | Hide inherited master graphics |
| `notes` | Add speaker notes to the PowerPoint notes pane |
| `table` | Set native PowerPoint table-style flags |

Run `uvx markdown-pptx --syntax` for the complete schema, accepted values, and examples.

### Theme colors

Use `color_scheme` to recolor theme-aware template content throughout the presentation:

```yaml
---
color_scheme:
  preset: Office
  dark_1: "#10263F"
  light_1: "#F9F9F9"
  accent_1: "#1D6FA8"
  accent_2: "#5AA9E6"
title_color: "var(--dark-1)"
body_color: "var(--dark-2)"
---
```

Colors accept hex, RGB, HSL, and PowerPoint theme references such as `var(--accent-1)`. Set `preset: null` and provide all 12 theme slots for a fully custom palette. Theme-aware template objects follow the resulting palette, while hard-coded RGB colors and images do not.

When a template should provide the colors, use `--ignore-document-colors`, `--ignore-slide-colors`, or both. These options do not change images, layouts, or content.

### Tables

Write standard Markdown pipe tables and put PowerPoint styling options in slide front matter:

```markdown
# Quarterly summary
---
layout: Title and Content
table:
  header_row: true
  total_row: true
  first_column: true
  banded_rows: true
---

| Region | Revenue |
| --- | ---: |
| North | $50,000 |
| Total | $50,000 |
```

Table flags control native PowerPoint styling. They do not calculate totals or change the Markdown table structure. A slide may use `table` metadata only when it contains at least one table. The flags apply to both tables on a Two Content slide.

### Images and paths

Local image paths are resolved relative to the Markdown file. Remote HTTP and HTTPS images are enabled by default. Use `--no-remote-images` for offline builds or untrusted Markdown. Download assets ahead of time and use local paths when reproducible builds matter.

When reading Markdown from stdin, provide an output path and a base directory for relative assets:

```powershell
uvx markdown-pptx --input - --output deck.pptx --base-dir ./assets
```

## Layouts and supported content

The built-in template provides these common layouts. Supplied templates may use different names and placeholders.

| Layout | Body behavior |
| --- | --- |
| `Title Slide` | Body text is placed in the subtitle placeholder |
| `Section Header` | Body text is placed in the subtitle or body placeholder |
| `Title and Content` | Accepts text flow, one image, or one table |
| `Two Content` | One thematic break separates left and right content. Each side accepts text flow, one image, or one table |
| `Title Only` | Does not accept body content |
| `Blank` | Requires an empty title and empty body |

Supported Markdown includes:

- Paragraphs
- Bullet and ordered lists, nested up to three levels, with continuation paragraphs and empty items
- Task lists with static checked and unchecked boxes
- ATX or Setext H1 slide headings and H2 through H6 headings within a slide
- Emphasis, strong text, strikethrough, superscript, subscript, inline code, and links
- Hard line breaks from two trailing spaces or a trailing backslash
- Fenced code blocks with editable syntax coloring for recognized languages
- Plain indented code blocks
- Blockquotes with nested text, headings, lists, and code
- Pipe tables
- Local and remote standalone images, including linked images

Soft line breaks become spaces so ordinary source wrapping does not force a line break on the slide. Use a hard line break when the visual line must end. A Setext heading uses `===` for H1 or `---` for H2 on the next line. Setext has no H3 through H6 form. Slide front matter must still immediately follow the slide heading.

Inline formatting stays editable in PowerPoint, including formatting nested inside links. Task boxes are static symbols. Fenced code uses the first language label for syntax coloring when Pygments recognizes it. Unknown labels produce plain editable code. Image alt text and optional titles are stored in the picture metadata. A link around a standalone image makes the picture clickable.

HTML comments and tags are ignored. Text between tags stays visible as plain text. Script and style content is omitted.

The intentionally unsupported set includes:

- Thematic breaks outside the single Two Content separator
- Footnotes
- Images mixed into text paragraphs
- Arbitrary positioning
- Layered backgrounds
- Animations

### Theme syntax colors

Fenced code keeps its existing Pygments colors by default. Set `code_highlighting` in document front matter or override it on a slide:

```yaml
code_highlighting: theme-dark
background: "#FFFFFF"
```

| Value | Behavior |
| --- | --- |
| `default` | Existing Pygments palette. No background analysis |
| `theme-dark` | Dark code colors for a light background |
| `theme-light` | Light code colors for a dark background |

A slide inherits the document setting. Explicit `default` restores the original palette on that slide. These modes apply to code blocks, including plain blocks with no recognized language. Inline code keeps its ordinary text formatting. Theme modes override `body_color` within code blocks.

| Code role | Theme slot |
| --- | --- |
| Ordinary names, punctuation, operators | Dark 1 for `theme-dark`, Light 1 for `theme-light` |
| Comments | Same base color, italic |
| Keywords and HTML tags | Accent 1, bold |
| Strings, numbers, constants | Accent 2 |
| Functions, types, classes, built-ins, HTML attributes | Accent 3 |

The three accent roles stay fixed across languages and slides. Dark 1 and Light 1 provide the theme's primary text colors without consuming an accent. Each color receives the smallest native brightness adjustment needed to reach a **4.5:1 contrast ratio**, using the [WCAG relative luminance formula](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html). Colors that already meet the target remain unchanged. Comments meet the same target as other tokens.

The output uses editable PowerPoint theme references. Changing the theme in PowerPoint changes these colors too, but does not rerun contrast analysis. Regenerate the deck after a theme change to recalculate the adjustments.

Analysis runs once per content placeholder that contains code. Two Content areas are analyzed separately. Solid backgrounds use their resolved color. Image backgrounds use the visible source region behind the placeholder, including cover cropping, with at most 256 pixels on the longest side. A luminance histogram discards 1% at each tail and uses the remaining range. Decoded images are cached for the render. Supported gradients use a 16 by 16 grid across the placeholder.

Image and gradient results are estimates. They do not guarantee contrast at every glyph. Template graphics layered over backgrounds, complex placeholder fills, and unsupported background effects are not fully rendered. When background inspection fails, the opposite theme text color is used as an explicit assumption and a warning is reported. A high-contrast background may make the target impossible. The renderer retains the requested light or dark variant, uses its maximum contrast, and reports the failure. It does not add a panel or switch variants.

Plain CLI output sends warnings to stderr. JSON render output includes a `code_highlighting` array with slide and placeholder identifiers, analysis method, sample count, estimated minimum contrast, warnings, and `target_met`. That value is `null` when the background had to be assumed. The default palette produces no analysis entries.

The color-ignore flags remove the existing document or slide color overrides. They retain `code_highlighting`, which then uses the remaining template colors and backgrounds.

Use `markdown-pptx --examples theme-code` for a complete authoring example.

Run `uv run python scripts/benchmark_code_colors.py` to compare the image range analysis with an average-only baseline. Both use the same crop and sample size. On the development machine, the 1080p and 4K cases took about 6 milliseconds per area, about 1.2 to 1.5 times the baseline. Image decoding is measured separately and cached during rendering. These are local measurements, not performance guarantees.

### Two content areas

Select `Two Content` explicitly and put exactly one top-level thematic break between the left and right content:

```markdown
# Compare options
---
layout: Two Content
---

## First option

- Small scope
- Quick feedback

***

## Second option

- Broader scope
- More preparation
```

Each side follows the same content rules as `Title and Content`. Text beside an image or table is supported. Mixing text and an image or table within one side is rejected. Either side can be empty, but the separator is still required.

Prefer `***` surrounded by blank lines. CommonMark `---` and `___` thematic breaks also work. A `---` directly below paragraph text is a Setext H2 underline. YAML front matter remains valid only immediately after the slide heading. Breaks inside code fences remain literal code. Nested breaks and more than one break are rejected.

The selected template layout must contain exactly two body/content placeholders with non-overlapping horizontal bounds. Content follows their position from left to right, regardless of placeholder index. No divider line or extra text boxes are created. Layouts with three or more content areas are unsupported.

### Discover authoring examples

The CLI includes complete Markdown documents covering every supported metadata key and Markdown feature:

```powershell
uvx markdown-pptx --examples
uvx markdown-pptx --examples list
uvx markdown-pptx --examples two-content
uvx markdown-pptx --examples tables --json
```

`--examples` prints the full annotated catalog. `--examples list` lists topic names and descriptions. `--examples NAME` prints only the selected document's raw Markdown, suitable for saving as a `.md` file. `--json` returns structured entries with descriptions, asset requirements, and Markdown source. The list form omits the source to keep discovery compact. Each example is a separate document. Image examples require the assets described in their requirements.

Use `--help` to discover commands, `--syntax` to inspect the format contract, and `--examples` to learn authoring. Use `--list-layouts --template theme.pptx --json` to check a template's actual layout compatibility. These commands work without installing a skill.

## Automation and image export

### Structured results and overwrite safety

Use `--json` for agent and automation workflows:

```powershell
uvx markdown-pptx deck.md deck.pptx --json
```

Successful JSON includes the output path, slide count, and template master details. Failures include a stable error code and relevant input, line, slide, or partial-output context.

The CLI refuses to overwrite an existing presentation or colliding generated image. Add `--force` only when replacing generated output is intended:

```powershell
uvx markdown-pptx deck.md deck.pptx --force --json
```

### Export slide images on Windows

On Windows, the CLI can use an installed desktop copy of Microsoft PowerPoint to export PNG or JPEG previews after generating the editable presentation:

```powershell
uvx markdown-pptx deck.md deck.pptx --export-images png --slides 1,3-5 --image-width 1600 --json
```

Image export requires Windows, an interactive desktop session, and an installed, licensed, initialized PowerPoint application. The default output directory is `<pptx-name>-images`. PNG is recommended for text and diagrams.

The editable `.pptx` is retained if image export fails. With `--json`, the partial output path is reported in `error.details.pptx_output`.

## Reference

Useful discovery and metadata commands:

```powershell
uvx markdown-pptx --help
uvx markdown-pptx --syntax
uvx markdown-pptx --list-color-schemes
uvx markdown-pptx --list-masters --template theme.pptx
uvx markdown-pptx --list-layouts --template theme.pptx --master 2
uvx markdown-pptx --about
uvx markdown-pptx --version
```

Exit codes:

| Code | Meaning |
| ---: | --- |
| `0` | Success |
| `2` | Usage or input error |
| `3` | Markdown or front-matter parse error |
| `4` | Template or layout error |
| `5` | Image or other asset error |
| `6` | Unsupported Markdown content |
| `7` | PowerPoint rendering error |
| `8` | Unexpected internal error |

## Examples

- [Sample source deck](sample/showcase.md)
- [Sample rendered deck](sample/showcase.pptx)
- [Sample multi-master template](sample/showcase-template.pptx)
- [Sample local image](sample/showcase-local.png)

Regenerate the showcase from the repository checkout:

```powershell
uvx --refresh --from . markdown-pptx sample/showcase.md sample/showcase.pptx --template sample/showcase-template.pptx --force
```

## Development

Install the development environment and run the checks:

```powershell
uv sync --locked --all-groups
uv run pytest
uv run ruff check .
uv run ruff format --check .
```

The real PowerPoint export smoke test is optional and requires desktop PowerPoint:

```powershell
$env:MARKDOWN_PPTX_TEST_POWERPOINT="1"
uv run pytest tests/test_powerpoint_integration.py
```

Build and validate distributable packages:

```powershell
uv build
uv run twine check dist/*
```

CI runs `tests/wheel_smoke.py` with an isolated installed wheel. It checks version discovery, generated skill metadata, automatic synchronization, and inspection output. Run `uv run python tests/wheel_smoke.py --expect-local` to check development-build exclusion and explicit installation. Both the smoke checks and pytest use temporary skill directories.
