Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
---
|
||||
name: powerpoint
|
||||
description: Create, read, edit .pptx decks with python-pptx.
|
||||
version: 1.1.0
|
||||
author: Nous Research
|
||||
license: MIT
|
||||
platforms: [linux, macos, windows]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [pptx, powerpoint, presentations, slides, office, python-pptx]
|
||||
category: productivity
|
||||
related_skills: [docx, xlsx, pdf]
|
||||
---
|
||||
|
||||
# Powerpoint Skill
|
||||
|
||||
Create, inspect, and edit PowerPoint (.pptx) presentations using the
|
||||
python-pptx library. Five helper scripts cover deck creation from a JSON
|
||||
spec, structured read-back, in-place edits, template-driven brand decks,
|
||||
and slide rendering — all offline, no PowerPoint installation required.
|
||||
|
||||
## When to Use
|
||||
|
||||
- The user asks to build a slide deck, report presentation, or pitch deck.
|
||||
- You need to extract text, notes, tables, chart data, or images from a
|
||||
.pptx someone shared.
|
||||
- You need to update an existing deck: replace text, refresh or patch
|
||||
chart data, swap a logo, duplicate/remove/reorder slides, set
|
||||
backgrounds, footers, hyperlinks, or speaker notes.
|
||||
- You must produce an on-brand deck from a company .pptx template.
|
||||
- Do NOT use this for .ppt (legacy binary) files — convert them first with
|
||||
`soffice --convert-to pptx old.ppt` if LibreOffice is available.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Python 3.10+ with `python-pptx` installed
|
||||
(`pip install python-pptx`).
|
||||
- Optional: LibreOffice (`soffice`) plus poppler (`pdftoppm` or
|
||||
`pdftocairo`) for rendering slides to PNGs and for PDF export.
|
||||
`pptx_render.py` detects both with `shutil.which` and degrades
|
||||
gracefully (reports `{"rendered": false, "missing": [...]}`, exit 0)
|
||||
when absent — all create/read/edit operations work without them.
|
||||
- Check availability via `terminal`:
|
||||
`python -c "import pptx; print(pptx.__version__)"` and `which soffice pdftoppm`.
|
||||
|
||||
## How to Run
|
||||
|
||||
All scripts live in `scripts/`, take `--help`, print JSON to stdout, and
|
||||
exit non-zero on failure. Run them with `terminal`:
|
||||
|
||||
```bash
|
||||
python scripts/pptx_create.py deck.json out.pptx
|
||||
python scripts/pptx_read.py deck.pptx --outline # full JSON outline
|
||||
python scripts/pptx_read.py deck.pptx --notes # speaker notes
|
||||
python scripts/pptx_read.py deck.pptx --images ./img # export pictures
|
||||
python scripts/pptx_edit.py deck.pptx --replace-text "Old Corp" "New Corp"
|
||||
python scripts/pptx_edit.py deck.pptx --chart-data update.json
|
||||
python scripts/pptx_edit.py deck.pptx --duplicate-slide 2
|
||||
python scripts/pptx_edit.py deck.pptx --remove-slide 3 --move-slide 2 0
|
||||
python scripts/pptx_from_template.py brand.pptx out.pptx --values vals.json
|
||||
python scripts/pptx_render.py deck.pptx --outdir ./render # slide PNGs
|
||||
```
|
||||
|
||||
Author JSON specs with `write_file`; inspect script output and generated
|
||||
JSON with `read_file`.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Task | Command |
|
||||
|---|---|
|
||||
| New deck from spec | `pptx_create.py spec.json out.pptx` |
|
||||
| 16:9 vs 4:3 | `"slide_size": "16:9"` or `"4:3"` in the spec |
|
||||
| Outline as JSON | `pptx_read.py deck.pptx --outline` |
|
||||
| Export images | `pptx_read.py deck.pptx --images DIR` |
|
||||
| Replace text | `pptx_edit.py deck.pptx --replace-text OLD NEW` |
|
||||
| Replace chart data | `pptx_edit.py deck.pptx --chart-data spec.json` |
|
||||
| Patch one series | same flag, spec with `"ops"` (see below) |
|
||||
| Swap picture | `pptx_edit.py deck.pptx --swap-image N NAME new.png` |
|
||||
| Duplicate slide | `pptx_edit.py deck.pptx --duplicate-slide N` |
|
||||
| Remove slide | `pptx_edit.py deck.pptx --remove-slide N` |
|
||||
| Reorder slide | `pptx_edit.py deck.pptx --move-slide FROM TO` |
|
||||
| Slide background | `pptx_edit.py deck.pptx --set-background N RRGGBB` |
|
||||
| Hyperlink runs | `pptx_edit.py deck.pptx --hyperlink N TEXT URL` |
|
||||
| Slide number on | `pptx_edit.py deck.pptx --enable-slide-number N` |
|
||||
| Footer text | `pptx_edit.py deck.pptx --set-footer N TEXT` |
|
||||
| Set notes | `pptx_edit.py deck.pptx --set-notes N TEXT` |
|
||||
| Append notes | `pptx_edit.py deck.pptx --append-notes N TEXT` |
|
||||
| Fill template | `pptx_from_template.py tpl.pptx out.pptx --values v.json` |
|
||||
| Render slide PNGs | `pptx_render.py deck.pptx --outdir DIR` |
|
||||
|
||||
## Procedure
|
||||
|
||||
### 1. Create a deck
|
||||
|
||||
Write a JSON spec (see `pptx_create.py --help` for the full format), then
|
||||
run `pptx_create.py`. Per slide you can set: `layout` (title,
|
||||
title_content, section, two_content, title_only, blank), `title`,
|
||||
`subtitle`, `bullets` (strings, or dicts with `level` 0-4, `size` pt,
|
||||
`bold`, `italic`, `font`, `color` hex, `link` URL for a hyperlink),
|
||||
`background` (solid hex), `footer` (text; enables the layout's footer
|
||||
placeholder), `slide_number` (true; enables the layout's slide-number
|
||||
placeholder), `images` (path + left/top/width/height in inches), `tables`
|
||||
(`rows` as list-of-lists), `shapes` (rectangle, rounded_rectangle, oval,
|
||||
diamond, right_arrow, chevron, with `fill` hex + optional `text`),
|
||||
`charts` (bar, bar_h, line, pie with `categories` + `series`), and
|
||||
`notes` (speaker notes).
|
||||
|
||||
### 2. Read a deck
|
||||
|
||||
`pptx_read.py deck.pptx --outline` returns slide size, layout inventory,
|
||||
and per slide: layout name, all shape texts, table cells, image inventory
|
||||
(filename/ext/bytes), chart categories/series/values, and speaker notes.
|
||||
Use `--images DIR` to dump embedded pictures to files, then
|
||||
`vision_analyze` on any exported image if you need to see its content.
|
||||
|
||||
### 3. Edit a deck
|
||||
|
||||
`pptx_edit.py` combines operations in one pass; use `--output` to keep the
|
||||
original. Text replacement scans slide shapes, table cells, and notes.
|
||||
Image swap retargets the picture's relationship id so position and size
|
||||
are preserved. Slide removal drops the relationship and the `<p:sldId>`
|
||||
entry; reorder moves the `<p:sldId>` element within `<p:sldIdLst>`
|
||||
(python-pptx has no public API for either — the script does the XML-level
|
||||
work). `--duplicate-slide N` appends an independent deep copy of slide N:
|
||||
shape XML plus image/media/hyperlink relationships are cloned and rIds
|
||||
remapped, so editing the copy never touches the original. Chart slides
|
||||
are refused (see Pitfalls). `--set-notes`/`--append-notes` edit speaker
|
||||
notes; `--set-background`, `--hyperlink`, `--enable-slide-number`, and
|
||||
`--set-footer` handle deck polish.
|
||||
|
||||
Chart updates take a JSON spec via `--chart-data`. Full replace:
|
||||
`{"slide": 0, "chart": 0, "categories": [...], "series": {...}}`. For
|
||||
surgical edits, pass `"ops"` instead — a list of
|
||||
`{"op": "update_series", "name": ..., "values": [...]}`,
|
||||
`add_series`, `remove_series`, `rename_category` (`from`/`to` or
|
||||
`index`), and `set_title`. python-pptx can only swap a chart's entire
|
||||
dataset (`replace_data`), so ops are implemented as read-existing →
|
||||
modify → replace; the per-part UX is a wrapper, and any chart data not
|
||||
expressible as categories + numeric series will be normalized by the
|
||||
round-trip.
|
||||
|
||||
### 4. Build from a template
|
||||
|
||||
`pptx_from_template.py` opens a brand .pptx, replaces every
|
||||
`{{token}}` from a values JSON across slides/tables/notes, and can append
|
||||
new slides that use the template's own layouts (by layout name or index)
|
||||
so they inherit the master's fonts and colors. Tip: to start from a
|
||||
template with zero slides, delete existing ones afterward with
|
||||
`pptx_edit.py --remove-slide`.
|
||||
|
||||
### 5. Visual verification
|
||||
|
||||
`pptx_render.py deck.pptx --outdir ./render` converts the deck to PDF
|
||||
with `soffice --headless` and splits it into one PNG per slide with
|
||||
`pdftoppm` (or `pdftocairo`). Output JSON lists the PNG paths — review
|
||||
each with `vision_analyze`. When either tool is missing the script exits
|
||||
0 with `{"rendered": false, "missing": [...]}` and guidance; fall back to
|
||||
the JSON outline from `pptx_read.py`, which verifies content and
|
||||
structure, just not visuals.
|
||||
|
||||
## Converting to PDF
|
||||
|
||||
If LibreOffice is installed, export the finished deck to PDF directly:
|
||||
|
||||
```bash
|
||||
soffice --headless --convert-to pdf --outdir ./out deck.pptx
|
||||
```
|
||||
|
||||
The output lands at `./out/deck.pdf`. Fonts not installed on the host are
|
||||
substituted, so render-verify (Procedure step 5) before shipping the PDF.
|
||||
There is no offline pure-Python .pptx→PDF path; if `soffice` is absent,
|
||||
say so rather than approximating.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- **Run splitting**: PowerPoint fragments paragraph text into runs at
|
||||
spell-check and edit boundaries. `--replace-text` first merges adjacent
|
||||
runs whose formatting is identical, so matches split across such runs
|
||||
are replaced with formatting fully preserved. Only when a match spans
|
||||
*genuinely differently-formatted* runs is the paragraph rewritten with
|
||||
the first run's formatting — verify those slides after replacement.
|
||||
- **Chart slides cannot be duplicated**: each chart relationship embeds a
|
||||
separate XLSX workbook part; cloning that graph reliably is not
|
||||
supported, so `--duplicate-slide` refuses chart slides cleanly instead
|
||||
of corrupting the deck. Rebuild the chart on a new slide instead.
|
||||
External-hyperlink and image/media rels are carried over; layout and
|
||||
notes rels are recreated fresh.
|
||||
- **Chart ops are a wrapper**: python-pptx replaces the whole dataset;
|
||||
`"ops"` round-trips existing plot data through `replace_data`, and
|
||||
changing chart *type* is not possible.
|
||||
- **Reordering is XML-level**: python-pptx has no supported reorder API.
|
||||
`--move-slide` manipulates `<p:sldIdLst>` directly; safe for ordinary
|
||||
decks but re-read the deck afterward to confirm.
|
||||
- **Copying slides between decks is unsupported** — duplication works
|
||||
only within one deck, where layouts and masters are shared.
|
||||
- Footer/slide-number enablement copies the placeholder from the slide's
|
||||
layout; on layouts without those placeholders, `--set-footer` fails
|
||||
with a clear message (add a textbox instead).
|
||||
- Hyperlinks apply to whole runs; `--hyperlink` links every run
|
||||
containing the given text on that slide.
|
||||
- The default python-pptx template is 4:3; the create script sets 16:9
|
||||
unless the spec says otherwise. Custom templates keep their own size.
|
||||
- Layout indexes vary by template. For brand templates, list layout names
|
||||
first: `pptx_read.py template.pptx --outline` (`layouts_available`).
|
||||
- `slide.shapes.title` is None on blank layouts — the create script
|
||||
handles this, but remember it when writing ad-hoc python-pptx code.
|
||||
- Always pass `encoding="utf-8"` when writing spec files; tokens like
|
||||
`{{city}}` may be filled with non-ASCII values.
|
||||
|
||||
## Verification
|
||||
|
||||
1. After any create/edit, run `pptx_read.py OUT.pptx --outline` and check
|
||||
slide count, texts, tables, notes, and chart values match intent.
|
||||
2. `--images DIR` then file-size check confirms pictures embedded.
|
||||
3. Render every slide with `pptx_render.py deck.pptx --outdir ./render`
|
||||
and review each PNG with `vision_analyze` — this catches overlapping
|
||||
shapes, truncated text, and color problems the outline cannot. If the
|
||||
render tools are missing, the script says so; rely on the outline.
|
||||
4. The bundled test suite is the full contract:
|
||||
`python -m pytest tests/ -q` (requires python-pptx + pytest).
|
||||
Reference in New Issue
Block a user