pptx-kit 0.7.0 → 0.9.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,160 @@
1
1
  # pptx-kit
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - eeb8659: Validate authoring inputs at the API boundary so out-of-range values throw a
8
+ clear `RangeError` instead of silently emitting a schema-invalid `.pptx` that
9
+ PowerPoint marks corrupt and "repairs".
10
+
11
+ A generative schema-validation sweep surfaced a whole class of defects where a
12
+ caller-supplied number/string was serialized straight into a constrained
13
+ ECMA-376 attribute. These now reject (or, for GUIDs, normalize) at the boundary:
14
+
15
+ - Run formatting: `setShapeRunFormat` font `size` (ST_TextFontSize, 1..4000 pt)
16
+ and `spc` (ST_TextPoint). It also now accepts the 3-digit hex shorthand for
17
+ run `color` / `highlight`, matching `setShapeFill` / `setShapeStroke`.
18
+ - Tables: `setTableStyleId` / `addSlideTable` `styleId` (ST_Guid — a lowercase
19
+ GUID from `crypto.randomUUID()` is now accepted and normalized to uppercase;
20
+ a non-GUID string throws); `setTableCellBorders` `widthEmu` (ST_LineWidth);
21
+ `setTableColumnWidth` / `setTableRowHeight` / `addSlideTable` `w`/`h`
22
+ (ST_PositiveCoordinate); `setTableCellMargins` (ST_Coordinate32).
23
+ - Charts: bar/column `overlapPct` (ST_Overlap), `gapWidthPct` (ST_GapAmount),
24
+ and series `lineWidthEmu` (ST_LineWidth).
25
+ - Animations / transitions: `setShapeAnimation` `durationMs` and
26
+ `setSlideTransition` `advanceAfterMs` (xsd:unsignedInt); the transition
27
+ `effect` token is validated against the spec's effect set (an empty or unknown
28
+ string previously produced non-well-formed or schema-invalid XML).
29
+ - Connectors / strokes: `addSlideLine` and `setShapeStroke` `widthEmu`
30
+ (ST_LineWidth) and `addSlideLine` endpoint coordinates.
31
+ - Text boxes: `setShapeTextColumns` `count` (ST_TextColumnCount, 2..16) and
32
+ `gapEmu` (ST_PositiveCoordinate32); `setShapeTextMargins` insets
33
+ (ST_Coordinate32); `setShapeTextBodyRotationDeg` (guards the ST_Angle overflow).
34
+ - Fills: `setShapePatternFill` `preset` is validated against ST_PresetPatternVal
35
+ (and the `PatternPreset` type is now the exact token union, not `string`).
36
+ - Shape / image / chart geometry: `addSlideShape` / `addSlideTextBox` /
37
+ `addSlideImage` / `addSlideChart` and `setShapePosition` / `setShapeSize`
38
+ `x`/`y` (ST_Coordinate) and `w`/`h` (ST_PositiveCoordinate).
39
+
40
+ - eeb8659: Fix a batch of "generates but is schema-invalid / wrong" authoring bugs, add an
41
+ AI-agent authoring skill, and smooth several LLM-facing rough edges.
42
+
43
+ Correctness fixes (output is now schema-valid in these cases):
44
+
45
+ - Notes slides emitted a `<p:notesSlide>` root instead of the spec's `<p:notes>`,
46
+ failing schema validation.
47
+ - Combining a run's text `color` with `highlight` emitted them out of order.
48
+ - Combining stroke dash / arrowheads / join, or a paragraph's bullet with
49
+ `setParagraphSpacing`, or a table cell's fill with `setTableCellBorders`,
50
+ emitted child elements out of their schema-mandated order.
51
+ - Table cells containing leading/trailing spaces, tabs, or newlines emitted an
52
+ illegal `xml:space` attribute (and a newline now correctly splits a cell into
53
+ multiple lines).
54
+ - `setSlideTransition({ effect: 'none' })` emitted an invalid `<p:none/>`; per-effect
55
+ attributes (`direction`/`orientation`/`thruBlack`) are now only emitted on
56
+ effects that allow them, and `direction` is validated against the effect's own
57
+ value domain (e.g. `blinds` takes `horz`/`vert`, `push` takes `l`/`r`/`u`/`d`) —
58
+ a mismatched pair like `{ effect: 'blinds', direction: 'l' }` now throws instead
59
+ of emitting schema-invalid XML.
60
+ - Charts emitted `<c:marker>`, `<c:smooth>`, `<c:invertIfNegative>`, and
61
+ `<c:trendline>` on series kinds that don't permit them (e.g. a trendline on a
62
+ `pie`/`doughnut`/`radar` series, which `CT_PieSer`/`CT_RadarSer` reject), and
63
+ `valueAxis` `min`/`max` in the wrong order.
64
+ - `setShapeImageBrightness` / `setShapeImageContrast` emitted `<a:lumOff>` /
65
+ `<a:lumMod>`, which aren't valid `<a:blip>` children; both now write a single
66
+ schema-valid `<a:lum bright/contrast>`.
67
+ - `setShapeGradientFill` ignored its documented `path` / `focus` options, silently
68
+ downgrading radial/shape gradients to linear.
69
+ - `importSlide` could emit a duplicate `rId` when the source slide's layout
70
+ relationship wasn't `rId1`.
71
+ - `setShapeAnimation` wiped any pre-existing `<p:timing>` on the slide (losing a
72
+ template's authored animations); it now merges, so multiple shapes can animate.
73
+ - `compactPackage` / `readPackagePart` / `setMediaPartBytes` matched part names
74
+ case-sensitively, unlike the rest of the package layer — a referenced image
75
+ whose rel-target case differed could be wrongly deleted or missed.
76
+
77
+ Behavior change:
78
+
79
+ - `setShapeImageContrast` now takes a `[-1, 1]` offset (`0` = no change) instead
80
+ of the previous `[0, 2]` multiplier, matching the underlying `<a:lum contrast>`.
81
+ - Unstyled connectors (`addSlideLine` without an explicit stroke) previously
82
+ emitted no line style and rendered invisibly; they now carry a default
83
+ `<p:style>` (`lnRef`/`fillRef`/`effectRef`/`fontRef`) so the line is visible.
84
+
85
+ Ergonomics:
86
+
87
+ - Colors accept the CSS-style 3-digit hex shorthand (`#f0a` → `FF00AA`).
88
+ - New `setParagraphLineSpacing(shape, p, { kind, value })` (the writer counterpart
89
+ to the existing getter).
90
+ - `setTableCellBorders` accepts a partial border per side, so `{ color, widthEmu }`
91
+ type-checks without spelling out `dash` (the read type `getTableCellBorders`
92
+ returns stays strict — all fields populated).
93
+ - `addSlideShape` `textAnchor` is narrowed to the valid vertical anchors
94
+ (`'t' | 'ctr' | 'b'`).
95
+
96
+ Docs:
97
+
98
+ - New `skill/SKILL.md` — a guide for driving pptx-kit from an AI agent (canonical
99
+ calls, design rules, footguns, and a QA protocol), with a verified worked
100
+ example.
101
+
102
+ - eeb8659: Close a final batch of correctness defects a generative schema sweep surfaced,
103
+ where the writer emitted a `.pptx` PowerPoint marks corrupt:
104
+
105
+ - **XML-illegal control characters** in any text field (shape text, table cells,
106
+ notes, chart titles/categories/series, hyperlink tooltip/URL, section names,
107
+ comments) used to serialize raw, producing a non-well-formed part that
108
+ corrupts the whole package. They are now rejected at serialization with a
109
+ clear error; the XML-legal whitespace controls (tab / LF / CR) still pass
110
+ through. (XML 1.0 forbids the other C0 controls outright — they cannot even be
111
+ escaped as numeric references.)
112
+ - **Chart percentages** are now range-checked at the boundary: `gapWidthPct`
113
+ (ST_GapAmount, 0..500 — the previous limit of 65535 let 501..65535 through),
114
+ doughnut `holeSizePct` (ST_HoleSize, 1..90), and pie/doughnut
115
+ `firstSliceAngleDeg` (ST_FirstSliceAng, 0..360).
116
+ - **Shape effects**: `setShapeShadow` `blurEmu`/`offsetEmu` and `setShapeGlow`
117
+ `radiusEmu` are validated as ST_PositiveCoordinate (fractional rounds;
118
+ negative / non-finite / over-max throws) instead of emitting an invalid value.
119
+ - **Scheme-color round-trip**: the read-back getters return `scheme:<token>`, but
120
+ the setters rejected that string. `setShapeFill` / `setShapeStroke` /
121
+ `setSlideBackground` now accept the `scheme:` prefix, so `setX(getX(...))`
122
+ round-trips. (An unknown `scheme:` token still throws.)
123
+ - **`importSlide` / `mergePresentations`**: importing a slide that contains a
124
+ chart left a dangling `r:id` (the chart frame referenced a relationship the
125
+ imported slide no longer carried), producing a corrupt package. The orphaned
126
+ graphic frame is now dropped, matching the documented "charts are not imported
127
+ in v1" behavior.
128
+ - **`addSlideShape` presets**: the math-operator tokens were misspelled
129
+ (`minus`/`mult`/`div`/`equal`/`notEqual`) and not in `ST_ShapeType`, so the
130
+ shape silently vanished on open. They are now the spec names `mathMinus`,
131
+ `mathMultiply`, `mathDivide`, `mathEqual`, `mathNotEqual` (plus `mathPlus`).
132
+
133
+ ### Patch Changes
134
+
135
+ - e9eae5c: Fix `<a:tint>` / `<a:shade>` colour resolution to compute in linear-light RGB,
136
+ matching PowerPoint and LibreOffice. A 75% tint of black now resolves to a mid
137
+ grey (~#8B8B8B) instead of the too-dark #404040, so colours derived from theme
138
+ scheme transforms (subtitle placeholders, table banding, chart fills) render at
139
+ the right lightness.
140
+
141
+ ## 0.8.0
142
+
143
+ ### Minor Changes
144
+
145
+ - 7200690: Drop Node.js 22 support. The minimum supported version is now Node 24.16. The published runtime bundles are unchanged; this only raises the `engines` floor and the CI/test matrix to Node 24.
146
+
147
+ ### Patch Changes
148
+
149
+ - ffeaef0: Numbered lists now carry a bullet font and explicit start number
150
+
151
+ `setShapeBullets('number')` / `setParagraphBullet(..., 'number')` emitted only
152
+ `<a:buAutoNum>`, with no `<a:buFont>` — so the auto-number glyph fell through to
153
+ whatever font happened to apply, instead of the theme's major font that
154
+ PowerPoint and PptxGenJS use. Numbered lists now emit
155
+ `<a:buFont typeface="+mj-lt"/>` ahead of the number and write the default
156
+ `startAt="1"` explicitly, matching PowerPoint-authored output.
157
+
3
158
  ## 0.7.0
4
159
 
5
160
  ### Minor Changes
package/README.md CHANGED
@@ -3,10 +3,12 @@
3
3
  Generate and edit `.pptx` (PowerPoint / Office Open XML Presentation) files
4
4
  from TypeScript — in **Node.js or the browser**, from a single ESM bundle.
5
5
 
6
- > **Status: 1.0 public API stabilized.** Every capability in the table
7
- > below works end-to-end against real PPTX fixtures, with every emitted XML
8
- > part validated against the ECMA-376 schemas via `xmllint` in CI. Future
9
- > 1.x releases are SemVer-compatible.
6
+ > **Status: 0.x — pre-1.0, public API still evolving.** The capabilities in
7
+ > the table below are exercised against real PPTX fixtures, and emitted XML is
8
+ > checked against the ECMA-376 schemas with `xmllint` where it is available on
9
+ > the machine running the tests. Until the 1.0 release the public API is not
10
+ > frozen — breaking changes can land in a minor (`0.x`) release, so pin a
11
+ > version or an exact range.
10
12
 
11
13
  ## Why
12
14
 
@@ -31,10 +33,11 @@ one trade-off:
31
33
 
32
34
  ## Scope
33
35
 
34
- The work is split into four levels of completeness. The v1.0 release targets
35
- levels 1-3 in full and level 4 in part:
36
+ The work is split into four levels of completeness. The current `0.x` line
37
+ covers levels 1-3 in full and level 4 in part; the table tracks where each
38
+ capability stands today. Items marked "post-1.0" are not implemented yet:
36
39
 
37
- | Level | Capability | v1.0 |
40
+ | Level | Capability | 0.x |
38
41
  | ----- | ------------------------------------------------------------------- | ------------------------------- |
39
42
  | L1 | Read an existing PPTX, save it back without corruption | ✅ |
40
43
  | L2 | Template edit — text replacement, image swap, add slide from layout | ✅ |
@@ -97,6 +100,16 @@ if (title) setShapeText(title, 'Hello');
97
100
  const out = await savePresentation(pres);
98
101
  ```
99
102
 
103
+ ## Driving pptx-kit from an AI agent
104
+
105
+ [`skill/SKILL.md`](skill/SKILL.md) is a self-contained guide for an LLM agent
106
+ authoring presentations with this library: the canonical call for each
107
+ capability, the design rules that keep output from looking template-generated,
108
+ the handful of API footguns worth memorizing, and a QA loop to run before
109
+ declaring a deck done. Its [worked example](skill/examples/business-deck.md) is
110
+ exercised by the test suite, so the code there is known to produce a
111
+ schema-valid deck.
112
+
100
113
  CI enforces the tree-shake bound in `test/tree-shake.test.ts`.
101
114
 
102
115
  ## Usage
@@ -346,7 +359,7 @@ shown together.
346
359
  | Shape authoring | `addSlideTextBox`, `addSlideShape`, `addSlideLine`, `addSlideTable`, `addSlideImage`, `addSlideChart` |
347
360
  | Shape lookup | `findShapeByName`, `findShapesByName`, `findShapesByKind`, `findShapeInPresentation`, `getAllShapes`, `getSlideShapes` |
348
361
  | Shape text | `setShapeText`, `setShapeBullets`, `setShapeAlignment`, `setShapeTextFormat`, `setShapeHyperlink` / `getShapeHyperlink` |
349
- | Per-paragraph | `setParagraphAlignment` / `getParagraphAlignment`, `setParagraphLevel` / `getParagraphLevel`, `setParagraphBullet` / `getParagraphBullet` |
362
+ | Per-paragraph | `setParagraphAlignment` / `getParagraphAlignment`, `setParagraphLevel` / `getParagraphLevel`, `setParagraphBullet` / `getParagraphBullet`, `setParagraphSpacing` / `getParagraphSpacing`, `setParagraphLineSpacing` / `getParagraphLineSpacing` |
350
363
  | Per-run text | `setShapeRunText` / `getShapeRunText`, `setShapeRunFormat` / `getShapeRunFormat`, `getShapeParagraphCount`, `getShapeRunCount` |
351
364
  | Text frame | `setShapeTextAnchor` / `getShapeTextAnchor`, `setShapeTextMargins` / `getShapeTextMargins` |
352
365
  | Fill | `setShapeFill` / `getShapeFill`, `setShapeGradientFill`, `setShapePatternFill`, `setShapeImageFill`, `setShapeNoFill`, `clearShapeFill` |
@@ -365,12 +378,12 @@ shown together.
365
378
 
366
379
  ## Compatibility
367
380
 
368
- - **Node**: >= 20.
381
+ - **Node**: >= 24.16.
369
382
  - **Browsers**: current and current-1 of Chrome, Firefox, Safari, Edge.
370
383
  - **TypeScript**: >= 5.4 (for strict `satisfies` and `const` type parameters).
371
- - **Output**: PPTX files validated against ECMA-376 schemas, smoke-tested
372
- against PowerPoint (current), Keynote (current), Google Slides, and
373
- LibreOffice Impress.
384
+ - **Output**: PPTX files checked against the ECMA-376 schemas with `xmllint`
385
+ where it is available, and smoke-tested against PowerPoint (current),
386
+ Keynote (current), Google Slides, and LibreOffice Impress.
374
387
 
375
388
  ## Development
376
389