skilldrop-cli 0.11.9 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/loops/build/evals/eval_queries.json +30 -0
- package/loops/build/evals/evals.json +27 -0
- package/loops/design/evals/eval_queries.json +30 -0
- package/loops/design/evals/evals.json +26 -0
- package/loops/discover/evals/eval_queries.json +30 -0
- package/loops/discover/evals/evals.json +26 -0
- package/loops/operate/evals/eval_queries.json +30 -0
- package/loops/operate/evals/evals.json +25 -0
- package/loops/ship-a-draft/evals/eval_queries.json +30 -0
- package/loops/ship-a-draft/evals/evals.json +25 -0
- package/model-routing.json +1 -1
- package/package.json +1 -1
- package/skills/deck-builder/SKILL.md +160 -93
- package/skills/deck-builder/evals/eval_queries.json +12 -32
- package/skills/deck-builder/evals/evals.json +23 -0
- package/skills/deck-builder/examples/templated-brand-deck.md +148 -0
- package/skills/deck-builder/manifest.json +5 -5
- package/skills/deck-builder/reference.md +88 -0
- package/skills/deck-builder/scripts/build_deck.py +863 -140
- package/skills/deck-builder/templates/deck-spec.json +69 -1
|
@@ -1,34 +1,14 @@
|
|
|
1
1
|
[
|
|
2
|
-
{
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
},
|
|
6
|
-
{
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
{
|
|
15
|
-
"query": "I need a real deck file, not an outline",
|
|
16
|
-
"should_trigger": true
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"query": "Just outline the slides — I'll build the deck myself",
|
|
20
|
-
"should_trigger": false
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
"query": "Write a one-page summary for executives",
|
|
24
|
-
"should_trigger": false
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"query": "Which audience archetype should I target and what are its rules?",
|
|
28
|
-
"should_trigger": false
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"query": "Critique the deck I already made",
|
|
32
|
-
"should_trigger": false
|
|
33
|
-
}
|
|
2
|
+
{ "query": "Build me a PowerPoint from this content", "should_trigger": true },
|
|
3
|
+
{ "query": "Generate a .pptx deck for this exec presentation", "should_trigger": true },
|
|
4
|
+
{ "query": "Turn this into actual slides I can present, with our brand colors", "should_trigger": true },
|
|
5
|
+
{ "query": "I need a real deck file, not an outline", "should_trigger": true },
|
|
6
|
+
{ "query": "Build the deck on our corporate template — marketing rejects anything else", "should_trigger": true },
|
|
7
|
+
{ "query": "Use our .potx master for this QBR deck", "should_trigger": true },
|
|
8
|
+
{ "query": "Put these quarterly numbers on a slide as a chart", "should_trigger": true },
|
|
9
|
+
{ "query": "Just outline the slides — I'll build the deck myself", "should_trigger": false },
|
|
10
|
+
{ "query": "Write a one-page summary for executives", "should_trigger": false },
|
|
11
|
+
{ "query": "Which audience archetype should I target and what are its rules?", "should_trigger": false },
|
|
12
|
+
{ "query": "Critique the deck I already made", "should_trigger": false },
|
|
13
|
+
{ "query": "Extract the text out of this existing .pptx so I can email it", "should_trigger": false }
|
|
34
14
|
]
|
|
@@ -6,12 +6,35 @@
|
|
|
6
6
|
"prompt": "Build a .pptx from this content for an exec audience, using our brand palette (navy/white).",
|
|
7
7
|
"assertions": [
|
|
8
8
|
"A real .pptx file is produced, not an outline",
|
|
9
|
+
"Audience, format and design are confirmed in a single setup block rather than as a trickle of separate questions",
|
|
9
10
|
"The title slide carries a real title, subtitle, presenter, and date — never left blank",
|
|
10
11
|
"Section dividers appear sparingly, at most one every 4-5 content slides",
|
|
11
12
|
"Big-number layouts use only numbers the user supplied; no statistic is invented for emphasis",
|
|
12
13
|
"Bullet density matches the stated audience rather than a fixed default",
|
|
13
14
|
"The requested palette is applied rather than the default theme"
|
|
14
15
|
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"id": 2,
|
|
19
|
+
"prompt": "Build the Q3 QBR deck on our corporate template at ~/brand/acme-master.potx — 25 minutes, live, partner audience.",
|
|
20
|
+
"assertions": [
|
|
21
|
+
"The template's layouts are listed with --list-layouts before the spec is written, rather than layout names being guessed",
|
|
22
|
+
"The spec sets `template` and a `layout_map` covering at least title, section, content and closing",
|
|
23
|
+
"A palette is still collected, because the template does not colour charts, tables or big numbers",
|
|
24
|
+
"`aspect` is not fought with — the template's own slide size is accepted and stated",
|
|
25
|
+
"Slide count is derived from the 25-minute budget at roughly 2 minutes per slide"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": 3,
|
|
30
|
+
"prompt": "Here are our renewal rates for the last three quarters (88%, 91%, 94%) and the SLA table from the contract. Put them in the deck.",
|
|
31
|
+
"assertions": [
|
|
32
|
+
"The three comparable figures become a `chart` slide, not a bullet list",
|
|
33
|
+
"The chart carries a `takeaway` sentence and a `source`",
|
|
34
|
+
"The SLA data becomes a `table` slide rather than aligned bullets",
|
|
35
|
+
"No figure appears that the user did not supply",
|
|
36
|
+
"Any build warning (missing image, short series) is reported to the user with its path rather than left in the file"
|
|
37
|
+
]
|
|
15
38
|
}
|
|
16
39
|
]
|
|
17
40
|
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Example: Q3 partner QBR on the company's own PowerPoint template
|
|
2
|
+
|
|
3
|
+
**Prompt the user gave:** *"Make the Q3 QBR deck for Northwind. Use our corporate template at
|
|
4
|
+
`~/brand/acme-master.potx` — it's mandatory, marketing rejects anything else. 25 minutes, live,
|
|
5
|
+
with the partner's CTO and two of their architects in the room. Renewal rate went 88 → 91 → 94%
|
|
6
|
+
over the last three quarters, ticket volume is down 31%, and we want to land the co-sell
|
|
7
|
+
expansion ask. Brand colours are #0B3D6B and #E8A33D."*
|
|
8
|
+
|
|
9
|
+
## Step 1 — Setup block, answered in one pass
|
|
10
|
+
|
|
11
|
+
| Input | Value | How it was resolved |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| Content | Renewal trend, ticket volume, expansion ask | Supplied |
|
|
14
|
+
| Audience | `partner` | Stated ("partner's CTO and architects") |
|
|
15
|
+
| Format | Live, 25 min → 12–14 slides | Stated; slide count derived at ~2 min/slide |
|
|
16
|
+
| Aspect | From the template | `aspect` ignored — the `.potx` is 16:9 |
|
|
17
|
+
| Design | `~/brand/acme-master.potx` + brand hexes | Template for chrome, palette for charts |
|
|
18
|
+
| Embeds | Renewal trend (chart), SLA table | Three comparable figures ⇒ chart, not bullets |
|
|
19
|
+
|
|
20
|
+
The palette is still collected: the template does not colour charts, tables or big numbers.
|
|
21
|
+
`primary: #0B3D6B`, `accent: #E8A33D`; `secondary`, `background` and `text` derived per
|
|
22
|
+
[`reference.md`](../reference.md#color-palette-principles) and called out to the user.
|
|
23
|
+
|
|
24
|
+
## Step 2 — Read the template's layouts before writing the spec
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
python3 "${CLAUDE_SKILL_DIR}/scripts/build_deck.py" --list-layouts ~/brand/acme-master.potx
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
acme-master.potx — slide size 13.33in x 7.50in
|
|
32
|
+
[0] Acme Cover
|
|
33
|
+
[1] Acme Section Break
|
|
34
|
+
[2] Acme Title and Body
|
|
35
|
+
[3] Acme Two Column
|
|
36
|
+
[4] Acme Statement
|
|
37
|
+
[5] Acme Full Bleed Image
|
|
38
|
+
[6] Blank
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The names are the template's, not PowerPoint's defaults — which is exactly why the map is read
|
|
42
|
+
from the file rather than guessed.
|
|
43
|
+
|
|
44
|
+
## Step 3 — The deck spec
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"title": "Northwind QBR — Q3 FY26",
|
|
49
|
+
"audience": "partner",
|
|
50
|
+
"template": "~/brand/acme-master.potx",
|
|
51
|
+
"layout_map": {
|
|
52
|
+
"title": "Acme Cover",
|
|
53
|
+
"section": "Acme Section Break",
|
|
54
|
+
"content": "Acme Title and Body",
|
|
55
|
+
"two_column": "Acme Two Column",
|
|
56
|
+
"big_number": "Acme Statement",
|
|
57
|
+
"quote": "Acme Statement",
|
|
58
|
+
"chart": "Acme Statement",
|
|
59
|
+
"table": "Acme Statement",
|
|
60
|
+
"image": "Acme Full Bleed Image",
|
|
61
|
+
"closing": "Acme Statement"
|
|
62
|
+
},
|
|
63
|
+
"palette": {
|
|
64
|
+
"primary": "#0B3D6B",
|
|
65
|
+
"secondary": "#4A6E94",
|
|
66
|
+
"accent": "#E8A33D",
|
|
67
|
+
"background": "#FFFFFF",
|
|
68
|
+
"text": "#222222"
|
|
69
|
+
},
|
|
70
|
+
"slides": [
|
|
71
|
+
{
|
|
72
|
+
"layout": "title",
|
|
73
|
+
"title": "Northwind × Acme — Q3 business review",
|
|
74
|
+
"subtitle": "Renewals, service quality, and the FY27 co-sell ask",
|
|
75
|
+
"presenter": "Jane Roe, Partner Director",
|
|
76
|
+
"date": "2026-09-30",
|
|
77
|
+
"notes": "Thank them for the quarter before the first slide. Name the ask now so it isn't a surprise at slide 12."
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"layout": "chart",
|
|
81
|
+
"title": "Renewal rate has climbed every quarter this year",
|
|
82
|
+
"takeaway": "Three consecutive quarters of improvement — the joint success plan is what changed.",
|
|
83
|
+
"chart": {
|
|
84
|
+
"type": "line",
|
|
85
|
+
"categories": ["Q1 FY26", "Q2 FY26", "Q3 FY26"],
|
|
86
|
+
"series": [{ "name": "Renewal rate (%)", "values": [88, 91, 94] }],
|
|
87
|
+
"number_format": "0\"%\""
|
|
88
|
+
},
|
|
89
|
+
"source": "Northwind CS dashboard, 30 Sep 2026",
|
|
90
|
+
"notes": "Let them claim the win — ask their CTO what drove Q2. The answer is usually the thing to double down on in FY27."
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"layout": "big_number",
|
|
94
|
+
"title": "Support load is down as adoption is up",
|
|
95
|
+
"number": "-31%",
|
|
96
|
+
"caption": "Ticket volume vs. Q3 FY25, on 2.4× the seat count",
|
|
97
|
+
"notes": "The pairing is the point: more users, fewer tickets. Pause after saying it."
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"layout": "table",
|
|
101
|
+
"title": "SLA performance against contract",
|
|
102
|
+
"columns": ["Metric", "Contracted", "Q3 actual", "Status"],
|
|
103
|
+
"rows": [
|
|
104
|
+
["Availability", "99.9%", "99.97%", "Met"],
|
|
105
|
+
["P1 response", "15 min", "9 min", "Met"],
|
|
106
|
+
["P1 resolution", "4 hrs", "3h 10m", "Met"],
|
|
107
|
+
["Change failure", "< 5%", "6.2%", "Missed"]
|
|
108
|
+
],
|
|
109
|
+
"caption": "Change-failure remediation plan on the next slide.",
|
|
110
|
+
"notes": "Do not skip the missed row. Naming it before they do is what makes the other three credible."
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"layout": "closing",
|
|
114
|
+
"title": "Ask: co-sell motion for FY27, two named accounts each",
|
|
115
|
+
"subtitle": "Kick-off 15 Oct, joint pipeline review monthly",
|
|
116
|
+
"notes": "Land on the ask. Get the kick-off date agreed in the room, not in follow-up email."
|
|
117
|
+
}
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
*(Abridged — the full deck is 13 slides; the four above are the ones that show the new layouts.)*
|
|
123
|
+
|
|
124
|
+
## Step 4 — Build
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
python3 "${CLAUDE_SKILL_DIR}/scripts/build_deck.py" /tmp/northwind-qbr.json -o ./out/northwind-qbr.pptx
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
template: dropped 2 sample slide(s), kept masters and layouts
|
|
132
|
+
wrote ./out/northwind-qbr.pptx (13 slides, template)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
No warnings, so nothing to report. Had the SLA table's diagram been an `.svg`, the build would
|
|
136
|
+
have drawn a placeholder box and warned — which gets reported to the user with the path, not
|
|
137
|
+
quietly shipped.
|
|
138
|
+
|
|
139
|
+
## What the template bought
|
|
140
|
+
|
|
141
|
+
| Without the template | With it |
|
|
142
|
+
|---|---|
|
|
143
|
+
| Calibri, generated-looking cover | Acme's typeface, cover, and logo on every slide |
|
|
144
|
+
| Palette-coloured title bars | The master's own chrome |
|
|
145
|
+
| Marketing sends it back | Passes brand review unchanged |
|
|
146
|
+
|
|
147
|
+
The palette still did real work: the line chart, the `-31%`, and the table header are brand
|
|
148
|
+
colours because `palette` was collected *alongside* the template, not instead of it.
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deck-builder",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Generate a real PowerPoint (.pptx) file from content,
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Generate a real PowerPoint (.pptx) file from content, audience, and either a brand template or a color palette — with charts, tables and images, not only bullets. Slide count, density and layout are tuned to the audience: execs, boards, technical reviewers, sales prospects, investors, internal teams. Use when the user wants an actual editable .pptx rather than an outline, wants their corporate template or brand colours applied, or says \"build the deck\", \"make it a pptx\", \"use our template\".",
|
|
5
5
|
"entrypoint": "SKILL.md",
|
|
6
6
|
"deps": {
|
|
7
7
|
"npm": [],
|
|
8
8
|
"pip": ["python-pptx==1.0.2"]
|
|
9
9
|
},
|
|
10
10
|
"env": { "required": [], "optional": [] },
|
|
11
|
-
"related": ["audience-profile", "slide-outliner"],
|
|
11
|
+
"related": ["audience-profile", "slide-outliner", "doc-critique"],
|
|
12
12
|
"install": {
|
|
13
13
|
"pip": "python3 -m pip install -r requirements.txt"
|
|
14
14
|
},
|
|
15
|
-
"tags": ["powerpoint", "pptx", "deck", "presentation", "stakeholder-communication"],
|
|
16
|
-
"model": { "tier": "standard", "rationale": "
|
|
15
|
+
"tags": ["powerpoint", "pptx", "deck", "presentation", "template", "charts", "stakeholder-communication"],
|
|
16
|
+
"model": { "tier": "standard", "rationale": "Shapes content, maps a brand template's layouts, and runs a script. Judgment, not hard reasoning." }
|
|
17
17
|
}
|
|
@@ -29,6 +29,8 @@ These are bundled in [`templates/palettes.json`](templates/palettes.json) and se
|
|
|
29
29
|
| `vibrant` | Internal / sales / pitch decks — energetic |
|
|
30
30
|
| `dark-mode` | Engineering audiences who prefer dark, or for live demos |
|
|
31
31
|
| `editorial` | Long-form / read-ahead decks with lots of text |
|
|
32
|
+
| `forest` | Calm, nature-leaning — sustainability, long-horizon programmes |
|
|
33
|
+
| `sunset` | Warm, narrative-leaning — story-first sales and internal decks |
|
|
32
34
|
|
|
33
35
|
## Layout → content matching
|
|
34
36
|
|
|
@@ -40,6 +42,9 @@ The biggest deck-design mistake is "everything is a bulleted content slide". Use
|
|
|
40
42
|
| A list of 2–6 related points | `content` | `two_column` (over-engineered) |
|
|
41
43
|
| A comparison (us vs. them, before vs. after) | `two_column` | `content` with sub-bullets |
|
|
42
44
|
| A pithy customer / SME quote | `quote` | `content` ("Customer says…") |
|
|
45
|
+
| 3+ comparable figures over time or category | `chart` | `content` with numbers in bullets |
|
|
46
|
+
| Row-and-column data, ≤ 12 rows | `table` | `two_column` faked with aligned bullets |
|
|
47
|
+
| An architecture / flow / screenshot | `image` | describing the diagram in prose |
|
|
43
48
|
| A topic break / new section | `section` | another title slide |
|
|
44
49
|
| First slide | `title` | jumping straight into `content` |
|
|
45
50
|
| Final slide with The Ask | `closing` | `content` titled "Thank you" |
|
|
@@ -90,3 +95,86 @@ Speaker notes should be *what's not on the slide*, not a redundant copy.
|
|
|
90
95
|
- **Don't use both italic and bold** in the same sentence for emphasis.
|
|
91
96
|
- **Don't mix serif and sans-serif** unless you really know what you're doing.
|
|
92
97
|
- **Slide numbers** — include them for decks > 10 slides; omit for short decks.
|
|
98
|
+
|
|
99
|
+
## Brand templates
|
|
100
|
+
|
|
101
|
+
A template is inherited, not imitated: `template` points the build at a `.pptx` or `.potx`, and
|
|
102
|
+
the deck is generated on that file's masters, theme fonts, theme colours, logos and slide size.
|
|
103
|
+
Sample slides shipped inside the template are dropped; its layouts are kept.
|
|
104
|
+
|
|
105
|
+
### The layout map
|
|
106
|
+
|
|
107
|
+
`layout_map` binds each logical layout to one of the template's layout names (or its index).
|
|
108
|
+
Discover them with `--list-layouts`. Matching is exact name first, then case-insensitive, then
|
|
109
|
+
substring — so `"content": "Title and Content"` and `"content": "title and content"` both hit.
|
|
110
|
+
|
|
111
|
+
| Logical layout | What to map it to | If unmapped |
|
|
112
|
+
|---|---|---|
|
|
113
|
+
| `title` | The template's title/cover layout | Built-in cover — **loses the brand**, always map it |
|
|
114
|
+
| `section` | Section header / divider | Built-in divider — always map it |
|
|
115
|
+
| `content` | Title and content / title and bullets | Built-in — always map it |
|
|
116
|
+
| `two_column` | Two content / comparison | Built-in two-column; acceptable |
|
|
117
|
+
| `closing` | Closing / thank-you / title-only | Built-in — always map it |
|
|
118
|
+
| `image` | Picture with caption (best), else title-only | Image drawn into the content area |
|
|
119
|
+
| `big_number`, `quote`, `table`, `chart` | Title-only | Drawn into the claimed content area; fine |
|
|
120
|
+
|
|
121
|
+
Placeholders are filled, not replaced — the run keeps the template's font, so the deck inherits
|
|
122
|
+
the brand's typography instead of Calibri. Placeholders left unfilled are deleted, so no
|
|
123
|
+
"Click to add text" ghosts survive. For `big_number`, `quote`, `table`, `chart` and `image`, the
|
|
124
|
+
largest empty body (or picture) placeholder is claimed for its rectangle and removed, so custom
|
|
125
|
+
content lands where the template intended content to go.
|
|
126
|
+
|
|
127
|
+
### Template gotchas
|
|
128
|
+
|
|
129
|
+
- **Slide size comes from the template.** `aspect` is ignored, with a warning. A 4:3 corporate
|
|
130
|
+
master produces a 4:3 deck — tell the user rather than silently letting it look cramped.
|
|
131
|
+
- **Charts and tables are drawn, not templated.** They take palette colours, not theme colours.
|
|
132
|
+
Supply brand hexes alongside the template so they match.
|
|
133
|
+
- **Slide numbers:** if the template's master already stamps them, the script does not add its
|
|
134
|
+
own.
|
|
135
|
+
- **A template that fails to open** is a hard error, never a silent fall-back to the built-in
|
|
136
|
+
design — a deck that quietly lost its branding is worse than a failed build.
|
|
137
|
+
|
|
138
|
+
## Charts
|
|
139
|
+
|
|
140
|
+
`chart` types: `column`, `bar`, `line`, `stacked_column`, `stacked_bar`, `pie`, `doughnut`.
|
|
141
|
+
|
|
142
|
+
| Question the slide answers | Type |
|
|
143
|
+
|---|---|
|
|
144
|
+
| How does this compare across categories? | `column` (≤ 7 categories) or `bar` (longer labels) |
|
|
145
|
+
| How has this moved over time? | `line` |
|
|
146
|
+
| What is the mix of a whole? | `pie`, and only with ≤ 5 slices |
|
|
147
|
+
| How does the mix change across categories? | `stacked_column` |
|
|
148
|
+
|
|
149
|
+
### Hard rules
|
|
150
|
+
|
|
151
|
+
- **Every chart carries a `takeaway`** — the sentence the audience should leave with, above the
|
|
152
|
+
plot. A chart without one makes the audience do the analysis live.
|
|
153
|
+
- **Every chart carries a `source`.** No source means the number is unverifiable, which on a
|
|
154
|
+
board deck means it is indefensible.
|
|
155
|
+
- **Never chart invented numbers.** If the user supplied three figures, chart three figures.
|
|
156
|
+
A forecast is labelled a forecast, in the series name.
|
|
157
|
+
- **`null` is the right value for a gap.** Padding a short series with zeroes draws a cliff that
|
|
158
|
+
didn't happen.
|
|
159
|
+
- **Pie charts cap at 5 slices.** More than that, use `bar` sorted descending.
|
|
160
|
+
- **One chart per slide.** Two charts is two slides, or a `two_column` with the takeaway split.
|
|
161
|
+
|
|
162
|
+
## Tables
|
|
163
|
+
|
|
164
|
+
- **≤ 12 data rows.** Past that it belongs in the appendix or an attached spreadsheet.
|
|
165
|
+
- **≤ 5 columns** at 16:9, ≤ 4 at 4:3. Wider than that and the font drops below readable.
|
|
166
|
+
- **Put the column the audience cares about last or first**, never buried in the middle.
|
|
167
|
+
- **Cells are values, not sentences.** A table cell running to two lines means the content is
|
|
168
|
+
prose and wants a `content` slide.
|
|
169
|
+
- Font size auto-shrinks past 7 and past 10 rows; header row takes `primary`, body rows zebra
|
|
170
|
+
against `#F2F4F8`.
|
|
171
|
+
|
|
172
|
+
## Images
|
|
173
|
+
|
|
174
|
+
- **Raster only.** `python-pptx` reads PNG/JPG/GIF/BMP/TIFF. SVG, EMF and PDF raise on import —
|
|
175
|
+
export to PNG at 2× the slide size before building.
|
|
176
|
+
- **Relative paths resolve against the spec file**, not the working directory.
|
|
177
|
+
- `position: "left"` / `"right"` pairs the image with bullets on the other half;
|
|
178
|
+
`"full"` (default) gives it the whole content area.
|
|
179
|
+
- A missing or unreadable image draws a bordered placeholder box naming the file, and warns.
|
|
180
|
+
That box is a build artefact, never a deliverable — resolve it before the deck is presented.
|