@office-kit/pptx 0.15.0 → 0.16.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 +18 -0
- package/README.md +221 -49
- package/dist/{api-DN51TPPz.js → api-DQEn2Bo4.js} +47 -17
- package/dist/api-DQEn2Bo4.js.map +1 -0
- package/dist/{index-B3Dj178Q.d.ts → index-BHQiXp61.d.ts} +14 -1
- 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-DN51TPPz.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# pptx-kit
|
|
2
2
|
|
|
3
|
+
## 0.16.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 22f1f30: feat: author and read the complex-script typeface (`<a:cs>`), and align the blank deck's font scheme with Office's
|
|
8
|
+
|
|
9
|
+
- `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`.
|
|
10
|
+
- `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.
|
|
11
|
+
- 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>`.
|
|
12
|
+
- `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.
|
|
13
|
+
- 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>`).
|
|
14
|
+
|
|
15
|
+
## 0.15.1
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- d6036a5: Reject U+FFFE, U+FFFF, and unpaired surrogates in authored XML text and attributes, preventing malformed PPTX parts and silent replacement with U+FFFD. Valid supplementary characters, including emoji, remain unchanged.
|
|
20
|
+
|
|
3
21
|
## 0.15.0
|
|
4
22
|
|
|
5
23
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,72 +1,208 @@
|
|
|
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
|
+
- **It reads as well as it writes.** Open a deck made in PowerPoint, Keynote,
|
|
32
|
+
or Google Slides, change it, and save it. Every setter has a getter, and
|
|
33
|
+
there are deck-wide queries (find every hyperlink, every comment by an
|
|
34
|
+
author, every slide with an empty title).
|
|
35
|
+
- **Parts it does not model survive the round trip.** SmartArt, OLE objects,
|
|
36
|
+
video, modern threaded comments, and vendor extensions are carried through
|
|
37
|
+
untouched. The library never silently strips what it does not understand.
|
|
38
|
+
- **The output is valid, not "valid enough".** Microsoft's own
|
|
39
|
+
`OpenXmlValidator` gates every CI run. A file that opens in PowerPoint but
|
|
40
|
+
breaks Keynote is treated as a bug.
|
|
41
|
+
- **One ESM bundle for Node and the browser.** No `fs`, `Buffer`, or `zlib` on
|
|
42
|
+
the hot path, and one runtime dependency ([fflate](https://github.com/101arrowz/fflate), for ZIP).
|
|
43
|
+
- **You ship only what you import.** The API is 451 side-effect-free functions.
|
|
44
|
+
A `load → save` bundle is about 56 KB unminified; the entire API is about
|
|
45
|
+
142 KB. CI fails if either grows past its cap (`test/tree-shake.test.ts`).
|
|
46
|
+
- **Types follow the spec.** The model mirrors ECMA-376 Part 1 §19
|
|
47
|
+
(PresentationML). Positions are branded `Emu` numbers, so inches and points
|
|
48
|
+
cannot be mixed up by accident.
|
|
49
|
+
|
|
50
|
+
## How it differs from PptxGenJS
|
|
51
|
+
|
|
52
|
+
[PptxGenJS](https://github.com/gitbrent/PptxGenJS) is the established way to
|
|
53
|
+
generate a deck in JavaScript, and it is good at that job. The difference is
|
|
54
|
+
direction: **PptxGenJS writes new files; `@office-kit/pptx` reads, edits, and
|
|
55
|
+
writes.** If your deck starts from a template, or from a file a person made,
|
|
56
|
+
PptxGenJS cannot open it.
|
|
57
|
+
|
|
58
|
+
Compared against PptxGenJS 4.0.1:
|
|
59
|
+
|
|
60
|
+
| | `@office-kit/pptx` | PptxGenJS |
|
|
61
|
+
| --------------------------------- | -------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
|
|
62
|
+
| Open and edit an existing `.pptx` | ✅ Load, change, save; unknown parts are preserved | ❌ Creates new files only |
|
|
63
|
+
| Templates | Any `.pptx` a designer made in PowerPoint | Slide masters defined in code (`defineSlideMaster`) |
|
|
64
|
+
| Read back what is in a deck | ✅ Every setter has a getter, plus deck-wide queries | ❌ The API is write-only |
|
|
65
|
+
| API shape | Tree-shakeable functions (`addSlideChart(slide, …)`) | One class with methods (`slide.addChart(…)`) |
|
|
66
|
+
| Module formats | ESM only | ESM, CommonJS, and a script-tag bundle |
|
|
67
|
+
| Runtime dependencies | 1 (`fflate`) | 4 (`jszip`, `image-size`, `https`, `@types/node`) |
|
|
68
|
+
| Slide transitions | ✅ | ❌ |
|
|
69
|
+
| Animations | ✅ Four entrance / exit presets | ❌ |
|
|
70
|
+
| Comments | ✅ | ❌ (speaker notes only) |
|
|
71
|
+
| 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 |
|
|
72
|
+
| Audio, video, YouTube embeds | ❌ Not yet (media already in a deck is preserved) | ✅ |
|
|
73
|
+
| HTML `<table>` to slides | ❌ | ✅ With automatic paging |
|
|
74
|
+
| Render a slide to an image | ✅ SVG and PNG, via [`@office-kit/pptx-preview`](packages/preview) | ❌ |
|
|
75
|
+
| How output is checked | Open XML SDK validator and ECMA-376 XSDs, in CI | Manual runs in PowerPoint and other apps before a release |
|
|
76
|
+
|
|
77
|
+
**Pick PptxGenJS** if you only ever generate new decks and need video,
|
|
78
|
+
scatter / bubble / radar charts, HTML-table import, CommonJS, or a
|
|
79
|
+
`<script>`-tag build.
|
|
80
|
+
|
|
81
|
+
**Pick `@office-kit/pptx`** if a template, an existing deck, or a validation
|
|
82
|
+
requirement is involved, or if you need to read a deck as well as write one.
|
|
83
|
+
|
|
84
|
+
The two also work together. Decks written by PptxGenJS are part of this
|
|
85
|
+
library's test fixtures (`test/pptxgenjs-compat.test.ts`), so you can generate
|
|
86
|
+
with PptxGenJS and post-process the result here.
|
|
87
|
+
|
|
88
|
+
### The same slide in both
|
|
14
89
|
|
|
15
|
-
|
|
16
|
-
|
|
90
|
+
```ts
|
|
91
|
+
// PptxGenJS
|
|
92
|
+
import pptxgen from 'pptxgenjs';
|
|
93
|
+
|
|
94
|
+
const pptx = new pptxgen();
|
|
95
|
+
const slide = pptx.addSlide();
|
|
96
|
+
slide.addText('Q3 Review', { x: 1, y: 0.5, w: 8, h: 1, fontSize: 28, bold: true });
|
|
97
|
+
slide.addChart(
|
|
98
|
+
pptx.ChartType.bar,
|
|
99
|
+
[{ name: 'Revenue', labels: ['Q1', 'Q2'], values: [120, 180] }],
|
|
100
|
+
{
|
|
101
|
+
x: 1,
|
|
102
|
+
y: 1.5,
|
|
103
|
+
w: 8,
|
|
104
|
+
h: 4,
|
|
105
|
+
barDir: 'col',
|
|
106
|
+
},
|
|
107
|
+
);
|
|
108
|
+
await pptx.writeFile({ fileName: 'out.pptx' });
|
|
109
|
+
```
|
|
17
110
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
111
|
+
```ts
|
|
112
|
+
// @office-kit/pptx
|
|
113
|
+
import {
|
|
114
|
+
addBlankSlide,
|
|
115
|
+
addSlideChart,
|
|
116
|
+
addSlideTextBox,
|
|
117
|
+
createPresentation,
|
|
118
|
+
inches,
|
|
119
|
+
setShapeTextFormat,
|
|
120
|
+
} from '@office-kit/pptx';
|
|
121
|
+
import { savePresentationToFile } from '@office-kit/pptx/node';
|
|
22
122
|
|
|
23
|
-
|
|
123
|
+
const pres = createPresentation();
|
|
124
|
+
const slide = addBlankSlide(pres);
|
|
125
|
+
const title = addSlideTextBox(slide, {
|
|
126
|
+
x: inches(1),
|
|
127
|
+
y: inches(0.5),
|
|
128
|
+
w: inches(8),
|
|
129
|
+
h: inches(1),
|
|
130
|
+
text: 'Q3 Review',
|
|
131
|
+
});
|
|
132
|
+
setShapeTextFormat(title, { size: 28, bold: true });
|
|
133
|
+
addSlideChart(slide, {
|
|
134
|
+
x: inches(1),
|
|
135
|
+
y: inches(1.5),
|
|
136
|
+
w: inches(8),
|
|
137
|
+
h: inches(4),
|
|
138
|
+
spec: {
|
|
139
|
+
kind: 'column',
|
|
140
|
+
categories: ['Q1', 'Q2'],
|
|
141
|
+
series: [{ name: 'Revenue', values: [120, 180] }],
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
await savePresentationToFile(pres, 'out.pptx');
|
|
145
|
+
```
|
|
24
146
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
-
|
|
147
|
+
Two differences show up straight away. Positions are explicit units
|
|
148
|
+
(`inches(1)`, `cm(2.5)`, `pt(12)`) rather than bare numbers, and everything is
|
|
149
|
+
a function that takes the thing it changes, which is what lets a bundler drop
|
|
150
|
+
the ones you do not call.
|
|
151
|
+
|
|
152
|
+
## How output is checked
|
|
153
|
+
|
|
154
|
+
- **Open XML SDK.** A CI job generates the sample decks and runs Microsoft's
|
|
155
|
+
`OpenXmlValidator` over them (`tools/ooxml-validate`). Any validation error
|
|
156
|
+
fails the build.
|
|
157
|
+
- **ECMA-376 XSDs.** Emitted XML is validated against the official schemas
|
|
158
|
+
with `xmllint` in the test suite (these tests skip on a machine without
|
|
159
|
+
`xmllint`).
|
|
160
|
+
- **Real files and a parity corpus.** Fixture tests round-trip decks written
|
|
161
|
+
by python-pptx and PptxGenJS, and `test/corpus` authors the same slide once
|
|
162
|
+
with PptxGenJS and once with this library, then diffs the two drawing trees.
|
|
163
|
+
The suite runs on Node 22, 24, and 26.
|
|
164
|
+
- **At runtime.** `validatePresentation(pres)` checks package invariants
|
|
165
|
+
(missing relationships, dangling slide ids, duplicate shape ids, layouts
|
|
166
|
+
without masters) in Node and the browser.
|
|
33
167
|
|
|
34
168
|
## Scope
|
|
35
169
|
|
|
36
|
-
The work is split into four levels
|
|
37
|
-
|
|
38
|
-
capability stands today. Items marked "post-1.0" are not implemented yet:
|
|
170
|
+
The work is split into four levels. The `0.x` line covers levels 1–3 and part
|
|
171
|
+
of level 4. Items marked "post-1.0" are not implemented yet:
|
|
39
172
|
|
|
40
173
|
| Level | Capability | 0.x |
|
|
41
174
|
| ----- | ------------------------------------------------------------------- | ------------------------------- |
|
|
42
175
|
| L1 | Read an existing PPTX, save it back without corruption | ✅ |
|
|
43
|
-
| L2 | Template edit
|
|
44
|
-
| L3 | Authoring
|
|
176
|
+
| L2 | Template edit: text replacement, image swap, add slide from layout | ✅ |
|
|
177
|
+
| L3 | Authoring: shapes, text, tables, fills, effects, transforms, groups | ✅ |
|
|
45
178
|
| L3 | Authoring on top of existing themes / masters / layouts | ✅ |
|
|
179
|
+
| L3 | Rebranding a deck: theme colors and theme fonts | ✅ |
|
|
46
180
|
| L3 | Constructing new themes / masters / layouts from scratch | ❌ post-1.0 |
|
|
47
|
-
| L3 | Charts
|
|
181
|
+
| L3 | Charts: bar, column, line, pie, doughnut, area, and combos | ✅ |
|
|
182
|
+
| L3 | Charts: scatter, radar, bubble | Read + preview only |
|
|
48
183
|
| L4 | Notes, comments, transitions | ✅ |
|
|
49
|
-
| L4 | Simple animations (entrance / exit
|
|
184
|
+
| L4 | Simple animations (entrance / exit presets) | ✅ |
|
|
185
|
+
| L4 | Audio / video authoring | ❌ post-1.0 (read pass-through) |
|
|
50
186
|
| L4 | SmartArt authoring | ❌ post-1.0 (read pass-through) |
|
|
51
187
|
| L4 | Complex animation timing trees | ❌ post-1.0 |
|
|
52
188
|
| L4 | OLE / ActiveX authoring | ❌ post-1.0 (read pass-through) |
|
|
53
189
|
| L4 | Document encryption (read + write) | ❌ post-1.0 |
|
|
54
190
|
|
|
55
|
-
Out-of-scope content is still **preserved on round-trip
|
|
56
|
-
|
|
191
|
+
Out-of-scope content is still **preserved on round-trip**. That is the L1
|
|
192
|
+
contract.
|
|
57
193
|
|
|
58
194
|
When NOT to use this:
|
|
59
195
|
|
|
60
196
|
- You need a **pixel-perfect** PPTX rendering (print, archival). The
|
|
61
197
|
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`)
|
|
198
|
+
SVG in the browser and to PNG on the server, and its closeness to LibreOffice
|
|
199
|
+
is measured per slide and gated in CI (`site/fidelity`). It is a
|
|
64
200
|
high-fidelity preview, not a spec-complete paint engine. For
|
|
65
201
|
pixel-authoritative output, use PowerPoint itself or LibreOffice headless.
|
|
66
|
-
- You
|
|
67
|
-
|
|
202
|
+
- You only generate new decks and need a feature in the PptxGenJS column
|
|
203
|
+
above. Use PptxGenJS.
|
|
68
204
|
- You want to convert PPTX to another format (Keynote, ODP). Out of scope
|
|
69
|
-
forever
|
|
205
|
+
forever; that is a renderer's job.
|
|
70
206
|
|
|
71
207
|
## Install
|
|
72
208
|
|
|
@@ -83,7 +219,8 @@ yarn add @office-kit/pptx
|
|
|
83
219
|
@office-kit/pptx exposes a single tree-shakeable free-function API. Every
|
|
84
220
|
capability is a named export — `loadPresentation`, `savePresentation`,
|
|
85
221
|
`addSlideTextBox`, `setShapeFill`, etc. Bundlers drop every entry you
|
|
86
|
-
don't import, so the minimal `load → save` bundle is
|
|
222
|
+
don't import, so the minimal `load → save` bundle is **about 56 KB**
|
|
223
|
+
unminified. CI enforces the bound in `test/tree-shake.test.ts`.
|
|
87
224
|
|
|
88
225
|
```ts
|
|
89
226
|
import {
|
|
@@ -110,8 +247,6 @@ declaring a deck done. Its [worked example](skill/examples/business-deck.md) is
|
|
|
110
247
|
exercised by the test suite, so the code there is known to produce a
|
|
111
248
|
schema-valid deck.
|
|
112
249
|
|
|
113
|
-
CI enforces the tree-shake bound in `test/tree-shake.test.ts`.
|
|
114
|
-
|
|
115
250
|
## Usage
|
|
116
251
|
|
|
117
252
|
### Edit a template
|
|
@@ -277,7 +412,7 @@ addSlideChart(slide!, {
|
|
|
277
412
|
w: inches(8),
|
|
278
413
|
h: inches(4.5),
|
|
279
414
|
spec: {
|
|
280
|
-
kind: 'column', // bar | column | line | pie | doughnut | area
|
|
415
|
+
kind: 'column', // bar | column | line | pie | doughnut | area (combine per series with `chartKind`)
|
|
281
416
|
categories: ['Q1', 'Q2', 'Q3', 'Q4'],
|
|
282
417
|
series: [
|
|
283
418
|
{ name: 'Revenue', values: [120, 180, 240, 300] },
|
|
@@ -378,26 +513,63 @@ shown together.
|
|
|
378
513
|
| Shape removal | `removeShape` |
|
|
379
514
|
| Tables | `getTableCell` / `getTableCells`, `setTableCellText` / `getTableCellText`, `setTableCellParagraphs` / `getTableCellParagraphs`, `setTableCellFill` / `clearTableCellFill`, `setTableCellAlignment`, `setTableCellTextFormat`, `insertTableRow` / `removeTableRow`, `insertTableColumn` / `removeTableColumn`, `mergeTableCells` / `getTableCellSpan` |
|
|
380
515
|
| 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`, ...)
|
|
516
|
+
| Theme | `getPresentationTheme` / `setPresentationTheme` — color scheme (`accent1`..`accent6`, `dark1`, `light1`, `hyperlink`, ...); `getPresentationFonts` / `setPresentationFonts` — major / minor Latin, East Asian, and complex-script faces |
|
|
517
|
+
| Groups | `groupShapes`, `ungroupShapes`, `getGroupChildren`, `getGroupTransform` |
|
|
518
|
+
| Text autofit | `setShapeTextAutoFit` / `getShapeTextAutoFit`, `getShapeTextAutoFitParams` |
|
|
519
|
+
| Preset adjustments | `setShapeAdjustValues`; `getShapeCustomGeometry` (custom geometry is read-only) |
|
|
520
|
+
| Document properties | `getCoreProperties` / `setCoreProperties`, `touchModified`, `getThumbnail` / `setThumbnail` / `removeThumbnail` |
|
|
521
|
+
| Package inspection | `listPackageParts`, `readPackagePart`, `getMediaParts`, `getOrphanMediaPartNames`, `getPackageSize`, `compactPackage` |
|
|
382
522
|
| Validation | `validatePresentation(pres)` — invariant checks, returns `ValidationIssue[]` |
|
|
383
523
|
| Units | `inches(n)`, `cm(n)`, `mm(n)`, `pt(n)`, `emu(n)` — return branded `Emu` numbers |
|
|
384
524
|
|
|
385
|
-
Text formats (`TextFormat`, including a paragraph's `endFormat`) cover the Latin
|
|
525
|
+
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.
|
|
526
|
+
|
|
527
|
+
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`.
|
|
528
|
+
|
|
529
|
+
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.
|
|
530
|
+
|
|
531
|
+
## Preview and text-overflow checks
|
|
532
|
+
|
|
533
|
+
[`@office-kit/pptx-preview`](packages/preview) is a companion package that
|
|
534
|
+
renders a slide to SVG (browser and Node) or to PNG (Node, via resvg, with no
|
|
535
|
+
headless Office). `auditTextLayout` reports text that overflows its box or
|
|
536
|
+
wraps unexpectedly, which is how an automated pipeline catches a broken slide
|
|
537
|
+
before a person sees it.
|
|
538
|
+
|
|
539
|
+
```ts
|
|
540
|
+
import { getSlides } from '@office-kit/pptx';
|
|
541
|
+
import { renderSlideToSvg } from '@office-kit/pptx-preview';
|
|
542
|
+
|
|
543
|
+
const svg = renderSlideToSvg(pres, getSlides(pres)[0]!);
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
## Office Kit
|
|
547
|
+
|
|
548
|
+
`@office-kit/pptx` is one of three libraries built on the same rules: the
|
|
549
|
+
ECMA-376 spec is the source of truth, output has to validate, and one ESM
|
|
550
|
+
build has to run everywhere.
|
|
551
|
+
|
|
552
|
+
| Package | Files |
|
|
553
|
+
| -------------------------------------------------------- | ------------------ |
|
|
554
|
+
| [`@office-kit/pptx`](https://github.com/office-kit/pptx) | PowerPoint `.pptx` |
|
|
555
|
+
| [`@office-kit/xlsx`](https://github.com/office-kit/xlsx) | Excel `.xlsx` |
|
|
556
|
+
| [`@office-kit/docx`](https://github.com/office-kit/docx) | Word `.docx` |
|
|
386
557
|
|
|
387
558
|
## Compatibility
|
|
388
559
|
|
|
389
|
-
- **Node**: >= 24.
|
|
560
|
+
- **Node**: >= 22.18 (CI runs 22, 24, and 26).
|
|
390
561
|
- **Browsers**: current and current-1 of Chrome, Firefox, Safari, Edge.
|
|
391
562
|
- **TypeScript**: >= 5.4 (for strict `satisfies` and `const` type parameters).
|
|
392
|
-
- **Output**:
|
|
393
|
-
|
|
394
|
-
Keynote (current), Google Slides, and LibreOffice
|
|
563
|
+
- **Output**: validated with the Open XML SDK and the ECMA-376 schemas (see
|
|
564
|
+
[How output is checked](#how-output-is-checked)), and smoke-tested against
|
|
565
|
+
PowerPoint (current), Keynote (current), Google Slides, and LibreOffice
|
|
566
|
+
Impress.
|
|
395
567
|
|
|
396
568
|
## Development
|
|
397
569
|
|
|
398
570
|
```sh
|
|
399
571
|
git clone --recurse-submodules git@github.com:office-kit/pptx.git
|
|
400
|
-
cd
|
|
572
|
+
cd pptx
|
|
401
573
|
pnpm install
|
|
402
574
|
pnpm test
|
|
403
575
|
```
|