@office-kit/pptx 0.15.1 → 0.16.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/CHANGELOG.md +23 -1
- package/README.md +232 -51
- package/dist/{api-IjQrAsCE.js → api-Dt6q_IAv.js} +129 -17
- package/dist/api-Dt6q_IAv.js.map +1 -0
- package/dist/{index-B3Dj178Q.d.ts → index-mFv1-sf4.d.ts} +17 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +1 -1
- package/package.json +1 -1
- package/dist/api-IjQrAsCE.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,26 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @office-kit/pptx
|
|
2
|
+
|
|
3
|
+
## 0.16.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b8adc13: Duplicated slides now have independent charts, embedded workbooks and notes.
|
|
8
|
+
Editing a duplicate no longer changes the original's chart or notes. Unknown
|
|
9
|
+
owned dependency parts are copied too, including cyclic relationships. Layouts,
|
|
10
|
+
masters, themes and media remain shared. Invalid missing dependencies fail before
|
|
11
|
+
parts are added.
|
|
12
|
+
|
|
13
|
+
## 0.16.0
|
|
14
|
+
|
|
15
|
+
### Minor Changes
|
|
16
|
+
|
|
17
|
+
- 22f1f30: feat: author and read the complex-script typeface (`<a:cs>`), and align the blank deck's font scheme with Office's
|
|
18
|
+
|
|
19
|
+
- `TextFormat.fontComplexScript` sets and reads `<a:cs typeface="…"/>`, the third typeface slot next to `font` (`<a:latin>`) and `fontEastAsian` (`<a:ea>`). It works everywhere the other two already did: `setShapeRunFormat` / `setShapeTextFormat`, `setShapeParagraphs` and `setTableCellParagraphs` (runs and `endFormat`), and it comes back from `getShapeRunFormat`, `getShapeRunFormatEffective` (including `+mj-cs` / `+mn-cs` and the theme's complex-script fallback), `getShapeParagraphElements`, `getParagraphEndFormat` and `getTableCellParagraphs`.
|
|
20
|
+
- `ChartTextStyle.fontComplexScript` writes `<a:cs>` on a chart title / axis / data-label / legend style, and the chart reader returns it. `font` keeps filling the Latin and East Asian slots only, so a chart can name a complex-script face on the legend alone.
|
|
21
|
+
- The three slots stay independent: setting one never changes the other two. Rewriting a slot writes its `typeface` attribute alone, so a `pitchFamily` / `charset` the source file carried on that element is dropped — as was already the case for `<a:latin>` and `<a:ea>`.
|
|
22
|
+
- `createPresentation`'s blank deck now carries the standard per-script font list (`<a:font script="Thai" typeface="Cordia New"/>` and its 46 siblings) in both `majorFont` and `minorFont`, the same list Office's own default theme ships. It is what resolves a face for text in a script no run names one for. Every deck `createPresentation()` produces therefore has a larger `theme1.xml` than before — its bytes change — and text in a script with no explicit typeface now resolves through that list.
|
|
23
|
+
- Chart titles and axis titles no longer carry a `lang="en-US"` language tag on their run. The chart-level tag is still `ChartSpec.language` (`<c:lang>`).
|
|
2
24
|
|
|
3
25
|
## 0.15.1
|
|
4
26
|
|
package/README.md
CHANGED
|
@@ -1,72 +1,218 @@
|
|
|
1
1
|
# @office-kit/pptx
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@office-kit/pptx)
|
|
4
|
+
[](https://github.com/office-kit/pptx/actions/workflows/ci.yml)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
|
|
7
|
+
Read, edit, and write `.pptx` (PowerPoint / Office Open XML Presentation) files
|
|
8
|
+
from TypeScript, in **Node.js and the browser**, from a single ESM bundle.
|
|
9
|
+
|
|
10
|
+
**[Documentation](https://office-kit.github.io/pptx/)** ·
|
|
11
|
+
**[Playground](https://office-kit.github.io/pptx/playground)** (inspect a deck in your browser) ·
|
|
12
|
+
**[REPL](https://office-kit.github.io/pptx/repl)** (write code, watch the deck redraw)
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { loadPresentation, replaceTokensInPresentation, savePresentation } from '@office-kit/pptx';
|
|
16
|
+
|
|
17
|
+
// A designer makes template.pptx in PowerPoint. Your code fills it in.
|
|
18
|
+
const pres = await loadPresentation(templateBytes);
|
|
19
|
+
replaceTokensInPresentation(pres, { name: 'Alice', event: 'Re:Invent', date: '2026-12-01' });
|
|
20
|
+
const out: Uint8Array = await savePresentation(pres);
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
> **Status: 0.x, pre-1.0.** The capabilities in the [scope table](#scope) are
|
|
24
|
+
> exercised against real PPTX fixtures and validated in CI (see
|
|
25
|
+
> [How output is checked](#how-output-is-checked)). Until 1.0 the public API is
|
|
26
|
+
> not frozen: a breaking change can land in a minor (`0.x`) release, so pin a
|
|
11
27
|
> version or an exact range.
|
|
12
28
|
|
|
13
|
-
## Why
|
|
29
|
+
## Why this library
|
|
30
|
+
|
|
31
|
+
For declarative TSX authoring, use the companion
|
|
32
|
+
[`@office-kit/pptx-dsl`](packages/dsl) and
|
|
33
|
+
[`@office-kit/pptx-dev`](packages/dev) packages. They provide typed elements,
|
|
34
|
+
template editing, a local watch preview and PPTX export, with no React or Vue
|
|
35
|
+
runtime. The dev package initializes a project with VSCode tasks and a
|
|
36
|
+
`CLAUDE.md` authoring guide. Start with the
|
|
37
|
+
[step-by-step authoring guide](https://office-kit.github.io/pptx/docs/authoring):
|
|
38
|
+
the CLI and DSL are not yet published to npm, so it includes a verified
|
|
39
|
+
source-checkout installation.
|
|
40
|
+
|
|
41
|
+
- **It reads as well as it writes.** Open a deck made in PowerPoint, Keynote,
|
|
42
|
+
or Google Slides, change it, and save it. Every setter has a getter, and
|
|
43
|
+
there are deck-wide queries (find every hyperlink, every comment by an
|
|
44
|
+
author, every slide with an empty title).
|
|
45
|
+
- **Parts it does not model survive the round trip.** SmartArt, OLE objects,
|
|
46
|
+
video, modern threaded comments, and vendor extensions are carried through
|
|
47
|
+
untouched. The library never silently strips what it does not understand.
|
|
48
|
+
- **The output is valid, not "valid enough".** Microsoft's own
|
|
49
|
+
`OpenXmlValidator` gates every CI run. A file that opens in PowerPoint but
|
|
50
|
+
breaks Keynote is treated as a bug.
|
|
51
|
+
- **One ESM bundle for Node and the browser.** No `fs`, `Buffer`, or `zlib` on
|
|
52
|
+
the hot path, and one runtime dependency ([fflate](https://github.com/101arrowz/fflate), for ZIP).
|
|
53
|
+
- **You ship only what you import.** The API is 451 side-effect-free functions.
|
|
54
|
+
A `load → save` bundle is about 56 KB unminified; the entire API is about
|
|
55
|
+
142 KB. CI fails if either grows past its cap (`test/tree-shake.test.ts`).
|
|
56
|
+
- **Types follow the spec.** The model mirrors ECMA-376 Part 1 §19
|
|
57
|
+
(PresentationML). Positions are branded `Emu` numbers, so inches and points
|
|
58
|
+
cannot be mixed up by accident.
|
|
59
|
+
|
|
60
|
+
## How it differs from PptxGenJS
|
|
61
|
+
|
|
62
|
+
[PptxGenJS](https://github.com/gitbrent/PptxGenJS) is the established way to
|
|
63
|
+
generate a deck in JavaScript, and it is good at that job. The difference is
|
|
64
|
+
direction: **PptxGenJS writes new files; `@office-kit/pptx` reads, edits, and
|
|
65
|
+
writes.** If your deck starts from a template, or from a file a person made,
|
|
66
|
+
PptxGenJS cannot open it.
|
|
67
|
+
|
|
68
|
+
Compared against PptxGenJS 4.0.1:
|
|
69
|
+
|
|
70
|
+
| | `@office-kit/pptx` | PptxGenJS |
|
|
71
|
+
| --------------------------------- | -------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
|
|
72
|
+
| Open and edit an existing `.pptx` | ✅ Load, change, save; unknown parts are preserved | ❌ Creates new files only |
|
|
73
|
+
| Templates | Any `.pptx` a designer made in PowerPoint | Slide masters defined in code (`defineSlideMaster`) |
|
|
74
|
+
| Read back what is in a deck | ✅ Every setter has a getter, plus deck-wide queries | ❌ The API is write-only |
|
|
75
|
+
| API shape | Tree-shakeable functions (`addSlideChart(slide, …)`) | One class with methods (`slide.addChart(…)`) |
|
|
76
|
+
| Module formats | ESM only | ESM, CommonJS, and a script-tag bundle |
|
|
77
|
+
| Runtime dependencies | 1 (`fflate`) | 4 (`jszip`, `image-size`, `https`, `@types/node`) |
|
|
78
|
+
| Slide transitions | ✅ | ❌ |
|
|
79
|
+
| Animations | ✅ Four entrance / exit presets | ❌ |
|
|
80
|
+
| Comments | ✅ | ❌ (speaker notes only) |
|
|
81
|
+
| Chart types you can author | Bar, column, line, pie, doughnut, area; combos, secondary axis, trendlines, per-point labels | Those, plus scatter, bubble, radar, and 3D bar |
|
|
82
|
+
| Audio, video, YouTube embeds | ❌ Not yet (media already in a deck is preserved) | ✅ |
|
|
83
|
+
| HTML `<table>` to slides | ❌ | ✅ With automatic paging |
|
|
84
|
+
| Render a slide to an image | ✅ SVG and PNG, via [`@office-kit/pptx-preview`](packages/preview) | ❌ |
|
|
85
|
+
| How output is checked | Open XML SDK validator and ECMA-376 XSDs, in CI | Manual runs in PowerPoint and other apps before a release |
|
|
86
|
+
|
|
87
|
+
**Pick PptxGenJS** if you only ever generate new decks and need video,
|
|
88
|
+
scatter / bubble / radar charts, HTML-table import, CommonJS, or a
|
|
89
|
+
`<script>`-tag build.
|
|
90
|
+
|
|
91
|
+
**Pick `@office-kit/pptx`** if a template, an existing deck, or a validation
|
|
92
|
+
requirement is involved, or if you need to read a deck as well as write one.
|
|
93
|
+
|
|
94
|
+
The two also work together. Decks written by PptxGenJS are part of this
|
|
95
|
+
library's test fixtures (`test/pptxgenjs-compat.test.ts`), so you can generate
|
|
96
|
+
with PptxGenJS and post-process the result here.
|
|
97
|
+
|
|
98
|
+
### The same slide in both
|
|
14
99
|
|
|
15
|
-
|
|
16
|
-
|
|
100
|
+
```ts
|
|
101
|
+
// PptxGenJS
|
|
102
|
+
import pptxgen from 'pptxgenjs';
|
|
103
|
+
|
|
104
|
+
const pptx = new pptxgen();
|
|
105
|
+
const slide = pptx.addSlide();
|
|
106
|
+
slide.addText('Q3 Review', { x: 1, y: 0.5, w: 8, h: 1, fontSize: 28, bold: true });
|
|
107
|
+
slide.addChart(
|
|
108
|
+
pptx.ChartType.bar,
|
|
109
|
+
[{ name: 'Revenue', labels: ['Q1', 'Q2'], values: [120, 180] }],
|
|
110
|
+
{
|
|
111
|
+
x: 1,
|
|
112
|
+
y: 1.5,
|
|
113
|
+
w: 8,
|
|
114
|
+
h: 4,
|
|
115
|
+
barDir: 'col',
|
|
116
|
+
},
|
|
117
|
+
);
|
|
118
|
+
await pptx.writeFile({ fileName: 'out.pptx' });
|
|
119
|
+
```
|
|
17
120
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
121
|
+
```ts
|
|
122
|
+
// @office-kit/pptx
|
|
123
|
+
import {
|
|
124
|
+
addBlankSlide,
|
|
125
|
+
addSlideChart,
|
|
126
|
+
addSlideTextBox,
|
|
127
|
+
createPresentation,
|
|
128
|
+
inches,
|
|
129
|
+
setShapeTextFormat,
|
|
130
|
+
} from '@office-kit/pptx';
|
|
131
|
+
import { savePresentationToFile } from '@office-kit/pptx/node';
|
|
22
132
|
|
|
23
|
-
|
|
133
|
+
const pres = createPresentation();
|
|
134
|
+
const slide = addBlankSlide(pres);
|
|
135
|
+
const title = addSlideTextBox(slide, {
|
|
136
|
+
x: inches(1),
|
|
137
|
+
y: inches(0.5),
|
|
138
|
+
w: inches(8),
|
|
139
|
+
h: inches(1),
|
|
140
|
+
text: 'Q3 Review',
|
|
141
|
+
});
|
|
142
|
+
setShapeTextFormat(title, { size: 28, bold: true });
|
|
143
|
+
addSlideChart(slide, {
|
|
144
|
+
x: inches(1),
|
|
145
|
+
y: inches(1.5),
|
|
146
|
+
w: inches(8),
|
|
147
|
+
h: inches(4),
|
|
148
|
+
spec: {
|
|
149
|
+
kind: 'column',
|
|
150
|
+
categories: ['Q1', 'Q2'],
|
|
151
|
+
series: [{ name: 'Revenue', values: [120, 180] }],
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
await savePresentationToFile(pres, 'out.pptx');
|
|
155
|
+
```
|
|
24
156
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
-
|
|
157
|
+
Two differences show up straight away. Positions are explicit units
|
|
158
|
+
(`inches(1)`, `cm(2.5)`, `pt(12)`) rather than bare numbers, and everything is
|
|
159
|
+
a function that takes the thing it changes, which is what lets a bundler drop
|
|
160
|
+
the ones you do not call.
|
|
161
|
+
|
|
162
|
+
## How output is checked
|
|
163
|
+
|
|
164
|
+
- **Open XML SDK.** A CI job generates the sample decks and runs Microsoft's
|
|
165
|
+
`OpenXmlValidator` over them (`tools/ooxml-validate`). Any validation error
|
|
166
|
+
fails the build.
|
|
167
|
+
- **ECMA-376 XSDs.** Emitted XML is validated against the official schemas
|
|
168
|
+
with `xmllint` in the test suite (these tests skip on a machine without
|
|
169
|
+
`xmllint`).
|
|
170
|
+
- **Real files and a parity corpus.** Fixture tests round-trip decks written
|
|
171
|
+
by python-pptx and PptxGenJS, and `test/corpus` authors the same slide once
|
|
172
|
+
with PptxGenJS and once with this library, then diffs the two drawing trees.
|
|
173
|
+
The suite runs on Node 22, 24, and 26.
|
|
174
|
+
- **At runtime.** `validatePresentation(pres)` checks package invariants
|
|
175
|
+
(missing relationships, dangling slide ids, duplicate shape ids, layouts
|
|
176
|
+
without masters) in Node and the browser.
|
|
33
177
|
|
|
34
178
|
## Scope
|
|
35
179
|
|
|
36
|
-
The work is split into four levels
|
|
37
|
-
|
|
38
|
-
capability stands today. Items marked "post-1.0" are not implemented yet:
|
|
180
|
+
The work is split into four levels. The `0.x` line covers levels 1–3 and part
|
|
181
|
+
of level 4. Items marked "post-1.0" are not implemented yet:
|
|
39
182
|
|
|
40
183
|
| Level | Capability | 0.x |
|
|
41
184
|
| ----- | ------------------------------------------------------------------- | ------------------------------- |
|
|
42
185
|
| L1 | Read an existing PPTX, save it back without corruption | ✅ |
|
|
43
|
-
| L2 | Template edit
|
|
44
|
-
| L3 | Authoring
|
|
186
|
+
| L2 | Template edit: text replacement, image swap, add slide from layout | ✅ |
|
|
187
|
+
| L3 | Authoring: shapes, text, tables, fills, effects, transforms, groups | ✅ |
|
|
45
188
|
| L3 | Authoring on top of existing themes / masters / layouts | ✅ |
|
|
189
|
+
| L3 | Rebranding a deck: theme colors and theme fonts | ✅ |
|
|
46
190
|
| L3 | Constructing new themes / masters / layouts from scratch | ❌ post-1.0 |
|
|
47
|
-
| L3 | Charts
|
|
191
|
+
| L3 | Charts: bar, column, line, pie, doughnut, area, and combos | ✅ |
|
|
192
|
+
| L3 | Charts: scatter, radar, bubble | Read + preview only |
|
|
48
193
|
| L4 | Notes, comments, transitions | ✅ |
|
|
49
|
-
| L4 | Simple animations (entrance / exit
|
|
194
|
+
| L4 | Simple animations (entrance / exit presets) | ✅ |
|
|
195
|
+
| L4 | Audio / video authoring | ❌ post-1.0 (read pass-through) |
|
|
50
196
|
| L4 | SmartArt authoring | ❌ post-1.0 (read pass-through) |
|
|
51
197
|
| L4 | Complex animation timing trees | ❌ post-1.0 |
|
|
52
198
|
| L4 | OLE / ActiveX authoring | ❌ post-1.0 (read pass-through) |
|
|
53
199
|
| L4 | Document encryption (read + write) | ❌ post-1.0 |
|
|
54
200
|
|
|
55
|
-
Out-of-scope content is still **preserved on round-trip
|
|
56
|
-
|
|
201
|
+
Out-of-scope content is still **preserved on round-trip**. That is the L1
|
|
202
|
+
contract.
|
|
57
203
|
|
|
58
204
|
When NOT to use this:
|
|
59
205
|
|
|
60
206
|
- You need a **pixel-perfect** PPTX rendering (print, archival). The
|
|
61
207
|
companion [`@office-kit/pptx-preview`](packages/preview) package renders slides to
|
|
62
|
-
SVG in the browser and to PNG on the server
|
|
63
|
-
is measured per slide and gated in CI (`site/fidelity`)
|
|
208
|
+
SVG in the browser and to PNG on the server, and its closeness to LibreOffice
|
|
209
|
+
is measured per slide and gated in CI (`site/fidelity`). It is a
|
|
64
210
|
high-fidelity preview, not a spec-complete paint engine. For
|
|
65
211
|
pixel-authoritative output, use PowerPoint itself or LibreOffice headless.
|
|
66
|
-
- You
|
|
67
|
-
|
|
212
|
+
- You only generate new decks and need a feature in the PptxGenJS column
|
|
213
|
+
above. Use PptxGenJS.
|
|
68
214
|
- You want to convert PPTX to another format (Keynote, ODP). Out of scope
|
|
69
|
-
forever
|
|
215
|
+
forever; that is a renderer's job.
|
|
70
216
|
|
|
71
217
|
## Install
|
|
72
218
|
|
|
@@ -83,7 +229,8 @@ yarn add @office-kit/pptx
|
|
|
83
229
|
@office-kit/pptx exposes a single tree-shakeable free-function API. Every
|
|
84
230
|
capability is a named export — `loadPresentation`, `savePresentation`,
|
|
85
231
|
`addSlideTextBox`, `setShapeFill`, etc. Bundlers drop every entry you
|
|
86
|
-
don't import, so the minimal `load → save` bundle is
|
|
232
|
+
don't import, so the minimal `load → save` bundle is **about 56 KB**
|
|
233
|
+
unminified. CI enforces the bound in `test/tree-shake.test.ts`.
|
|
87
234
|
|
|
88
235
|
```ts
|
|
89
236
|
import {
|
|
@@ -110,8 +257,6 @@ declaring a deck done. Its [worked example](skill/examples/business-deck.md) is
|
|
|
110
257
|
exercised by the test suite, so the code there is known to produce a
|
|
111
258
|
schema-valid deck.
|
|
112
259
|
|
|
113
|
-
CI enforces the tree-shake bound in `test/tree-shake.test.ts`.
|
|
114
|
-
|
|
115
260
|
## Usage
|
|
116
261
|
|
|
117
262
|
### Edit a template
|
|
@@ -184,7 +329,7 @@ setShapeText(findSlidePlaceholder(slide, 'ctrTitle')!, 'Authored with @office-ki
|
|
|
184
329
|
const out: Uint8Array = await savePresentation(pres);
|
|
185
330
|
```
|
|
186
331
|
|
|
187
|
-
###
|
|
332
|
+
### Add slides to your own template
|
|
188
333
|
|
|
189
334
|
```ts
|
|
190
335
|
import {
|
|
@@ -201,7 +346,8 @@ import {
|
|
|
201
346
|
setShapeText,
|
|
202
347
|
} from '@office-kit/pptx';
|
|
203
348
|
|
|
204
|
-
|
|
349
|
+
// Layout names come from the template; list them with getSlideLayouts(pres).
|
|
350
|
+
const pres = await loadPresentation(await fetch('/template.pptx').then((r) => r.arrayBuffer()));
|
|
205
351
|
|
|
206
352
|
const titleLayout = findSlideLayout(pres, 'Title Slide')!;
|
|
207
353
|
const slide1 = addSlide(pres, { layout: titleLayout });
|
|
@@ -277,7 +423,7 @@ addSlideChart(slide!, {
|
|
|
277
423
|
w: inches(8),
|
|
278
424
|
h: inches(4.5),
|
|
279
425
|
spec: {
|
|
280
|
-
kind: 'column', // bar | column | line | pie | doughnut | area
|
|
426
|
+
kind: 'column', // bar | column | line | pie | doughnut | area (combine per series with `chartKind`)
|
|
281
427
|
categories: ['Q1', 'Q2', 'Q3', 'Q4'],
|
|
282
428
|
series: [
|
|
283
429
|
{ name: 'Revenue', values: [120, 180, 240, 300] },
|
|
@@ -378,28 +524,63 @@ shown together.
|
|
|
378
524
|
| Shape removal | `removeShape` |
|
|
379
525
|
| Tables | `getTableCell` / `getTableCells`, `setTableCellText` / `getTableCellText`, `setTableCellParagraphs` / `getTableCellParagraphs`, `setTableCellFill` / `clearTableCellFill`, `setTableCellAlignment`, `setTableCellTextFormat`, `insertTableRow` / `removeTableRow`, `insertTableColumn` / `removeTableColumn`, `mergeTableCells` / `getTableCellSpan` |
|
|
380
526
|
| Charts | `addSlideChart`, `getSlideCharts`, `setChartSpec` — kinds: `bar`, `column`, `line`, `pie`, `doughnut`, `area`; axis tick labels via `categoryAxisTickLabelPos` / `valueAxisTickLabelPos` / `secondaryValueAxis.tickLabelPos`; axis line / gridline widths via `valueAxisLineWidthEmu`, `valueAxisMajorGridlineWidthEmu` and their category / secondary-axis mirrors; series `lineColor` / `markerColor` / `markerLineColor`; `dataLabels.showLeaderLines` |
|
|
381
|
-
| Theme | `getPresentationTheme` — color scheme (`accent1`..`accent6`, `dark1`, `light1`, `hyperlink`, ...)
|
|
527
|
+
| Theme | `getPresentationTheme` / `setPresentationTheme` — color scheme (`accent1`..`accent6`, `dark1`, `light1`, `hyperlink`, ...); `getPresentationFonts` / `setPresentationFonts` — major / minor Latin, East Asian, and complex-script faces |
|
|
528
|
+
| Groups | `groupShapes`, `ungroupShapes`, `getGroupChildren`, `getGroupTransform` |
|
|
529
|
+
| Text autofit | `setShapeTextAutoFit` / `getShapeTextAutoFit`, `getShapeTextAutoFitParams` |
|
|
530
|
+
| Preset adjustments | `setShapeAdjustValues`; `getShapeCustomGeometry` (custom geometry is read-only) |
|
|
531
|
+
| Document properties | `getCoreProperties` / `setCoreProperties`, `touchModified`, `getThumbnail` / `setThumbnail` / `removeThumbnail` |
|
|
532
|
+
| Package inspection | `listPackageParts`, `readPackagePart`, `getMediaParts`, `getOrphanMediaPartNames`, `getPackageSize`, `compactPackage` |
|
|
382
533
|
| Validation | `validatePresentation(pres)` — invariant checks, returns `ValidationIssue[]` |
|
|
383
534
|
| Units | `inches(n)`, `cm(n)`, `mm(n)`, `pt(n)`, `emu(n)` — return branded `Emu` numbers |
|
|
384
535
|
|
|
385
|
-
Text formats (`TextFormat`, including a paragraph's `endFormat`) cover the Latin
|
|
536
|
+
Text formats (`TextFormat`, including a paragraph's `endFormat`) cover the Latin, East Asian and complex-script typefaces (`font`, `fontEastAsian`, `fontComplexScript` — `<a:latin>`, `<a:ea>`, `<a:cs>`). Each is authored and read on its own; setting one leaves the others as they were. Chart labels carry the Latin / East Asian pair and the complex-script slot on `ChartTextStyle`: `font` fills `<a:latin>` and `<a:ea>`, `fontComplexScript` fills `<a:cs>`, and neither implies the other. Rebuilding a typeface writes the `typeface` attribute only, so any `pitchFamily` / `charset` the source file carried on that element is dropped.
|
|
537
|
+
|
|
538
|
+
Runs that name no face fall back to the theme's font scheme, which is also where a per-script list (`<a:font script="Thai" typeface="Cordia New"/>` and 46 siblings) lives. `createPresentation`'s blank deck carries Office's own list in both `majorFont` and `minorFont`.
|
|
386
539
|
|
|
387
540
|
Authored XML text and attribute values must contain only XML 1.0 characters. Illegal C0 controls (except tab, LF, and CR), U+FFFE, U+FFFF, and unpaired UTF-16 surrogates throw an error identifying the code point. Remove these characters before authoring; valid supplementary characters such as emoji are preserved.
|
|
388
541
|
|
|
542
|
+
## Preview and text-overflow checks
|
|
543
|
+
|
|
544
|
+
[`@office-kit/pptx-preview`](packages/preview) is a companion package that
|
|
545
|
+
renders a slide to SVG (browser and Node) or to PNG (Node, via resvg, with no
|
|
546
|
+
headless Office). `auditTextLayout` reports text that overflows its box or
|
|
547
|
+
wraps unexpectedly, which is how an automated pipeline catches a broken slide
|
|
548
|
+
before a person sees it.
|
|
549
|
+
|
|
550
|
+
```ts
|
|
551
|
+
import { getSlides } from '@office-kit/pptx';
|
|
552
|
+
import { renderSlideToSvg } from '@office-kit/pptx-preview';
|
|
553
|
+
|
|
554
|
+
const svg = renderSlideToSvg(pres, getSlides(pres)[0]!);
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
## Office Kit
|
|
558
|
+
|
|
559
|
+
`@office-kit/pptx` is one of three libraries built on the same rules: the
|
|
560
|
+
ECMA-376 spec is the source of truth, output has to validate, and one ESM
|
|
561
|
+
build has to run everywhere.
|
|
562
|
+
|
|
563
|
+
| Package | Files |
|
|
564
|
+
| -------------------------------------------------------- | ------------------ |
|
|
565
|
+
| [`@office-kit/pptx`](https://github.com/office-kit/pptx) | PowerPoint `.pptx` |
|
|
566
|
+
| [`@office-kit/xlsx`](https://github.com/office-kit/xlsx) | Excel `.xlsx` |
|
|
567
|
+
| [`@office-kit/docx`](https://github.com/office-kit/docx) | Word `.docx` |
|
|
568
|
+
|
|
389
569
|
## Compatibility
|
|
390
570
|
|
|
391
|
-
- **Node**: >= 24.
|
|
571
|
+
- **Node**: >= 22.18 (CI runs 22, 24, and 26).
|
|
392
572
|
- **Browsers**: current and current-1 of Chrome, Firefox, Safari, Edge.
|
|
393
573
|
- **TypeScript**: >= 5.4 (for strict `satisfies` and `const` type parameters).
|
|
394
|
-
- **Output**:
|
|
395
|
-
|
|
396
|
-
Keynote (current), Google Slides, and LibreOffice
|
|
574
|
+
- **Output**: validated with the Open XML SDK and the ECMA-376 schemas (see
|
|
575
|
+
[How output is checked](#how-output-is-checked)), and smoke-tested against
|
|
576
|
+
PowerPoint (current), Keynote (current), Google Slides, and LibreOffice
|
|
577
|
+
Impress.
|
|
397
578
|
|
|
398
579
|
## Development
|
|
399
580
|
|
|
400
581
|
```sh
|
|
401
582
|
git clone --recurse-submodules git@github.com:office-kit/pptx.git
|
|
402
|
-
cd
|
|
583
|
+
cd pptx
|
|
403
584
|
pnpm install
|
|
404
585
|
pnpm test
|
|
405
586
|
```
|