@shbernal/ts-pptx 3.7.0 → 4.0.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.
Files changed (136) hide show
  1. package/README.md +124 -262
  2. package/dist/autopage-odPz7zZO.js +536 -0
  3. package/dist/autopage-odPz7zZO.js.map +1 -0
  4. package/dist/binary-string-CKVAYI3M.js +24 -0
  5. package/dist/binary-string-CKVAYI3M.js.map +1 -0
  6. package/dist/body-insets-Dw_BeWD_.js +54 -0
  7. package/dist/body-insets-Dw_BeWD_.js.map +1 -0
  8. package/dist/browser.d.ts +29 -9
  9. package/dist/browser.d.ts.map +1 -1
  10. package/dist/browser.js +41 -14
  11. package/dist/browser.js.map +1 -1
  12. package/dist/clip-Bl01BPcN.d.ts +67 -0
  13. package/dist/clip-Bl01BPcN.d.ts.map +1 -0
  14. package/dist/diagnostics-D8ot4Ei7.d.ts +244 -0
  15. package/dist/diagnostics-D8ot4Ei7.d.ts.map +1 -0
  16. package/dist/embedded-fonts-DarT9aoa.d.ts +20 -0
  17. package/dist/embedded-fonts-DarT9aoa.d.ts.map +1 -0
  18. package/dist/entry-compose-DCnvBZz2.d.ts +1046 -0
  19. package/dist/entry-compose-DCnvBZz2.d.ts.map +1 -0
  20. package/dist/{enums-CvRYniUA.d.ts → enums-BUKTUB6V.d.ts} +21 -13
  21. package/dist/{enums-CvRYniUA.d.ts.map → enums-BUKTUB6V.d.ts.map} +1 -1
  22. package/dist/{errors-Bvln0H-7.js → errors-C4oENPcu.js} +92 -2
  23. package/dist/errors-C4oENPcu.js.map +1 -0
  24. package/dist/families.d.ts +260 -0
  25. package/dist/families.d.ts.map +1 -0
  26. package/dist/families.js +57 -0
  27. package/dist/families.js.map +1 -0
  28. package/dist/{fit-BKs0zxMI.js → fit-Cb7naFj6.js} +249 -167
  29. package/dist/fit-Cb7naFj6.js.map +1 -0
  30. package/dist/font-metrics-v5fn7s7e.d.ts +613 -0
  31. package/dist/font-metrics-v5fn7s7e.d.ts.map +1 -0
  32. package/dist/grid-DikTjFey.js +187 -0
  33. package/dist/grid-DikTjFey.js.map +1 -0
  34. package/dist/{html-dom-B0I0QSbU.js → html-dom-Iuog2wdK.js} +121 -91
  35. package/dist/html-dom-Iuog2wdK.js.map +1 -0
  36. package/dist/html.d.ts +6 -6
  37. package/dist/html.d.ts.map +1 -1
  38. package/dist/html.js +7 -6
  39. package/dist/html.js.map +1 -1
  40. package/dist/image-size-CvN2iCA4.js +1611 -0
  41. package/dist/image-size-CvN2iCA4.js.map +1 -0
  42. package/dist/index.d.ts +24 -10
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +31 -11
  45. package/dist/index.js.map +1 -1
  46. package/dist/inspect.d.ts +40 -31
  47. package/dist/inspect.d.ts.map +1 -1
  48. package/dist/inspect.js +40 -48
  49. package/dist/inspect.js.map +1 -1
  50. package/dist/math.d.ts +7 -5
  51. package/dist/math.d.ts.map +1 -1
  52. package/dist/math.js +16 -7
  53. package/dist/math.js.map +1 -1
  54. package/dist/measure.d.ts +12 -225
  55. package/dist/measure.d.ts.map +1 -1
  56. package/dist/measure.js +3 -3
  57. package/dist/node.d.ts +22 -8
  58. package/dist/node.d.ts.map +1 -1
  59. package/dist/node.js +27 -7
  60. package/dist/node.js.map +1 -1
  61. package/dist/notes-Dh12JAbn.js +3264 -0
  62. package/dist/notes-Dh12JAbn.js.map +1 -0
  63. package/dist/options-internal-WqgMf720.js +43 -0
  64. package/dist/options-internal-WqgMf720.js.map +1 -0
  65. package/dist/{package-CaOLXSNi.d.ts → package-J49Ck6S2.d.ts} +27 -12
  66. package/dist/package-J49Ck6S2.d.ts.map +1 -0
  67. package/dist/playbtn-CUqQdoDf.js +22 -0
  68. package/dist/playbtn-CUqQdoDf.js.map +1 -0
  69. package/dist/{slide-ZqAdVvHV.d.ts → pres-C6qgOFAa.d.ts} +1021 -1423
  70. package/dist/pres-C6qgOFAa.d.ts.map +1 -0
  71. package/dist/{presentation-DrJtj3-C.js → presentation-DGYlAWhl.js} +3208 -2727
  72. package/dist/presentation-DGYlAWhl.js.map +1 -0
  73. package/dist/{presentation-types-CDjScsev.d.ts → presentation-types-8jLQHI4M.d.ts} +1070 -683
  74. package/dist/presentation-types-8jLQHI4M.d.ts.map +1 -0
  75. package/dist/read.d.ts +9 -9
  76. package/dist/read.d.ts.map +1 -1
  77. package/dist/read.js +4 -4
  78. package/dist/script.d.ts +80 -66
  79. package/dist/script.d.ts.map +1 -1
  80. package/dist/script.js +2399 -1139
  81. package/dist/script.js.map +1 -1
  82. package/dist/{shapes-BemroU-z.js → shapes-re0KyQk_.js} +2807 -1609
  83. package/dist/shapes-re0KyQk_.js.map +1 -0
  84. package/dist/slide-Dx2ZeVZ6.d.ts +1256 -0
  85. package/dist/slide-Dx2ZeVZ6.d.ts.map +1 -0
  86. package/dist/slide-size-BalTjFuv.js +88 -0
  87. package/dist/slide-size-BalTjFuv.js.map +1 -0
  88. package/dist/{units-internal-Dg95w_YD.js → table-cell-margins-EVg0EwxT.js} +235 -273
  89. package/dist/table-cell-margins-EVg0EwxT.js.map +1 -0
  90. package/dist/table-dom-BTDP3lEP.js +21 -0
  91. package/dist/table-dom-BTDP3lEP.js.map +1 -0
  92. package/dist/text-anchor-CrYXAfUu.js +176 -0
  93. package/dist/text-anchor-CrYXAfUu.js.map +1 -0
  94. package/dist/text-sN64Otf_.js +3980 -0
  95. package/dist/text-sN64Otf_.js.map +1 -0
  96. package/dist/transition-speed-kUEWDWTx.js +14 -0
  97. package/dist/transition-speed-kUEWDWTx.js.map +1 -0
  98. package/dist/units-internal-XJlf-hOl.js +649 -0
  99. package/dist/units-internal-XJlf-hOl.js.map +1 -0
  100. package/dist/zip-C0leZZMj.d.ts +67 -0
  101. package/dist/zip-C0leZZMj.d.ts.map +1 -0
  102. package/dist/zip-CKd8ihcf.js +177 -0
  103. package/dist/zip-CKd8ihcf.js.map +1 -0
  104. package/dist/zip.d.ts +3 -68
  105. package/dist/zip.js +3 -163
  106. package/dist/zoom-DPUHh85d.js +8865 -0
  107. package/dist/zoom-DPUHh85d.js.map +1 -0
  108. package/package.json +24 -94
  109. package/skills/ts-pptx-upstream/SKILL.md +58 -57
  110. package/dist/autopage-DkjYZUFD.js +0 -423
  111. package/dist/autopage-DkjYZUFD.js.map +0 -1
  112. package/dist/diagnostics-DfBdDHre.d.ts +0 -829
  113. package/dist/diagnostics-DfBdDHre.d.ts.map +0 -1
  114. package/dist/errors-Bvln0H-7.js.map +0 -1
  115. package/dist/errors-PflMPWBn.d.ts +0 -182
  116. package/dist/errors-PflMPWBn.d.ts.map +0 -1
  117. package/dist/fit-BKs0zxMI.js.map +0 -1
  118. package/dist/html-dom-B0I0QSbU.js.map +0 -1
  119. package/dist/namespaces-BVnNu7sg.js +0 -666
  120. package/dist/namespaces-BVnNu7sg.js.map +0 -1
  121. package/dist/notes-CJFJaG6M.js +0 -1724
  122. package/dist/notes-CJFJaG6M.js.map +0 -1
  123. package/dist/package-CaOLXSNi.d.ts.map +0 -1
  124. package/dist/pres-BcBR3CSM.d.ts +0 -202
  125. package/dist/pres-BcBR3CSM.d.ts.map +0 -1
  126. package/dist/presentation-DrJtj3-C.js.map +0 -1
  127. package/dist/presentation-types-CDjScsev.d.ts.map +0 -1
  128. package/dist/shapes-BemroU-z.js.map +0 -1
  129. package/dist/slide-ZqAdVvHV.d.ts.map +0 -1
  130. package/dist/text-B8SLEaZx.js +0 -11327
  131. package/dist/text-B8SLEaZx.js.map +0 -1
  132. package/dist/units-1kRzYShk.js +0 -231
  133. package/dist/units-1kRzYShk.js.map +0 -1
  134. package/dist/units-internal-Dg95w_YD.js.map +0 -1
  135. package/dist/zip.d.ts.map +0 -1
  136. package/dist/zip.js.map +0 -1
package/README.md CHANGED
@@ -1,80 +1,45 @@
1
1
  # ts-pptx
2
2
 
3
- [![npm](https://img.shields.io/npm/v/%40shbernal%2Fts-pptx)](https://www.npmjs.com/package/@shbernal/ts-pptx)
4
- [![weekly downloads](https://img.shields.io/npm/dw/%40shbernal%2Fts-pptx.svg?label=npm%20downloads&logo=npm)](https://www.npmjs.com/package/@shbernal/ts-pptx)
5
- [![total downloads](https://img.shields.io/npm/dt/%40shbernal%2Fts-pptx.svg?label=npm%20total%20downloads&logo=npm)](https://www.npmjs.com/package/@shbernal/ts-pptx)
3
+ > **`@shbernal/ts-pptx` is an alias.** It is the same package as
4
+ > [`pptx-ts`](https://www.npmjs.com/package/pptx-ts), published from the
5
+ > same commit at the same version with the same contents. Install one or the other,
6
+ > never both: two copies of this library in one dependency tree are two module
7
+ > registries, and state such as the diagnostic handler is per-copy.
8
+ > `pptx-ts` is the canonical name, and the issue tracker, the changelog and
9
+ > every example below use it.
10
+
11
+ [![npm](https://img.shields.io/npm/v/pptx-ts)](https://www.npmjs.com/package/pptx-ts)
12
+ [![weekly downloads](https://img.shields.io/npm/dw/pptx-ts.svg?label=npm%20downloads&logo=npm)](https://www.npmjs.com/package/pptx-ts)
13
+ [![total downloads](https://img.shields.io/npm/dt/pptx-ts.svg?label=npm%20total%20downloads&logo=npm)](https://www.npmjs.com/package/pptx-ts)
6
14
  [![CI](https://github.com/shbernal/ts-pptx/actions/workflows/ci.yml/badge.svg)](https://github.com/shbernal/ts-pptx/actions/workflows/ci.yml)
7
15
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
8
16
 
9
- ts-pptx generates PowerPoint `.pptx` files from TypeScript and modern
10
- JavaScript. This project targets ESM package consumers, typed application code,
11
- reproducible package verification, and agent-assisted OOXML development.
17
+ **Write a program, get a PowerPoint file.**
12
18
 
13
- > **Lineage.** ts-pptx descends from [gitbrent/PptxGenJS](https://github.com/gitbrent/PptxGenJS)
14
- > (MIT), detached at its v6.0.0 (June 2025) and developed independently since. It
15
- > does not track, merge from, or mirror the original project, and pursues its own
16
- > Node-first direction (see _Project Target_). The original work remains under its
17
- > MIT license: see _License_ below.
19
+ A `.pptx` is a zip full of XML. ts-pptx writes that zip for you, so you describe
20
+ slides in TypeScript and a `.pptx` comes out the other end. PowerPoint never runs, no
21
+ Office licence is involved, and nothing has to be installed on the machine doing the
22
+ writing. The file opens cleanly in desktop PowerPoint, and Keynote, LibreOffice Impress
23
+ and Google Slides import it on a best-effort basis.
18
24
 
19
- ## Project Target
20
-
21
- - Generate standards-based PowerPoint `.pptx` packages without requiring
22
- PowerPoint at runtime.
23
- - Support TypeScript-first workflows with checked declarations and modern
24
- bundler resolution.
25
- - Ship a small, explicit ESM package boundary for Node.js, Vite, React,
26
- Angular, Electron, and similar modern toolchains.
27
- - Keep OOXML changes grounded in fixtures, schema validation, and PowerPoint
28
- compatibility evidence.
29
- - Make the repository practical for human and agent-driven maintenance.
25
+ Reach for it when a deck has to be built from data that changes: a monthly report,
26
+ one deck per customer, a hundred decks per night, or a download button on a page that
27
+ hands the user a deck built from what they are looking at.
30
28
 
31
29
  ## Install
32
30
 
33
31
  ```bash
34
- pnpm add @shbernal/ts-pptx
35
- ```
36
-
37
- ```bash
38
- npm install @shbernal/ts-pptx
39
- ```
40
-
41
- ```bash
42
- yarn add @shbernal/ts-pptx
43
- ```
44
-
45
- The unscoped name [`pptx-ts`](https://www.npmjs.com/package/pptx-ts) is an alias
46
- for the same package: same contents, same version, published from the same
47
- commit by the same workflow. Take it if a scoped name is awkward somewhere in
48
- your toolchain. Install one or the other and never both, because two copies of
49
- this library in one dependency tree are two module registries and state such as
50
- the diagnostic handler is per-copy. The scoped name is canonical: the issue
51
- tracker, the changelog and every example in these docs use it.
52
-
53
- ### Installing an unreleased commit
54
-
55
- Any commit is installable directly from GitHub, without waiting for a release:
56
-
57
- ```bash
58
- npm install github:shbernal/ts-pptx#<commit-sha>
32
+ pnpm add pptx-ts
59
33
  ```
60
34
 
61
- `master` (`github:shbernal/ts-pptx`) works too, but pin the sha: a branch spec
62
- re-resolves to whatever is at the head of it when the lockfile is next written.
63
-
64
- `dist/` is not committed, so this builds the package on install: your package
65
- manager clones the repo, installs this package's `devDependencies`, and runs its
66
- `prepare` script. That makes the install slow (a couple of minutes) and heavier
67
- than a registry install, and it needs a working Node toolchain. It is meant for
68
- trying a fix before it ships, not for production dependencies.
69
-
70
- Note that `pres.version` reports the version in `package.json` at that commit, so
71
- several different commits report the same number. The sha in your `package.json`
72
- is what identifies the build.
35
+ `@shbernal/ts-pptx` is the same package under its first name, so install one or the other.
36
+ [Installation](docs/getting-started/installation.md) covers npm, CommonJS and the optional
37
+ math dependencies.
73
38
 
74
- ## Quick Start
39
+ ## Quick start
75
40
 
76
41
  ```ts
77
- import TsPptx from "@shbernal/ts-pptx"
42
+ import TsPptx from "pptx-ts"
78
43
 
79
44
  const pptx = new TsPptx()
80
45
  const slide = pptx.addSlide()
@@ -91,218 +56,115 @@ slide.addText("Hello from ts-pptx", {
91
56
  await pptx.writeFile({ fileName: "example.pptx" })
92
57
  ```
93
58
 
94
- ## What It Can Generate
95
-
96
- - Slides, layouts, masters, sections, notes, and metadata.
97
- - Text, tables, shapes, images, SVGs, charts, and media.
98
- - Browser-downloadable, streamed, buffered, Blob, base64, or file outputs,
99
- depending on the runtime.
100
- - OOXML that is intended to open cleanly in Microsoft PowerPoint and other
101
- `.pptx` consumers such as Keynote, LibreOffice Impress, and Google Slides
102
- import.
103
-
104
- ## Scope And Contributions
105
-
106
- This project is **Node-first**: it generates and is tested without a browser or any
107
- office application. Two areas are out of *active* maintenance scope, not because
108
- they lack merit, but because there is no in-house use case driving them, so the
109
- maintainer generally will not pick up bugs or feature requests there:
110
-
111
- - **Live-DOM / browser-layout features**, anything whose answer comes from a
112
- *rendered* page: real `offsetWidth` after layout, the resolved cascade, fonts as
113
- the browser actually chose them. (Converting an HTML `<table>` is *not* in this
114
- category: see [HTML tables → slides](#html-tables--slides) below. Only real
115
- measurement needs a browser.)
116
- - **Third-party office-suite interop quirks** that appear only after a file is
117
- round-tripped through another application (for example, copy/paste inside WPS
118
- Office, then opening in PowerPoint) when the generated package is itself valid
119
- OOXML. The supported bar is that output opens cleanly in Microsoft PowerPoint.
120
-
121
- **Contributions in these areas are welcome**: issues and pull requests are
122
- encouraged even though the maintainer is not actively developing them. See
123
- [`docs/project-target.md`](docs/project-target.md) for the full scope statement
124
- and suggested testing approaches.
125
-
126
- ## Hit A Bug? There Is A Skill For That
127
-
128
- Most code that uses this library is written by an agent, and an agent that hits a
129
- library defect will usually route around it silently, so the defect is never
130
- reported and never fixed. `ts-pptx-upstream` is a skill that turns that moment into
131
- a filed issue with a minimal reproduction, which is what becomes a permanent
132
- regression test here. It ships inside the package, so it is already on disk:
133
-
134
- ```bash
135
- # Name the skill and the runtimes, and take the defaults: this is the form that
136
- # completes unattended, which is how an agent will be running it.
137
- npx skills add ./node_modules/@shbernal/ts-pptx -s '*' -a claude-code -a codex -a universal -y
138
-
139
- npx skills add shbernal/ts-pptx # same flags, straight from the repo instead of node_modules
140
- ```
141
-
142
- Drop the flags for an interactive prompt if you are at a terminal yourself. Do not reach
143
- for `--all` to avoid the prompt: it installs into every runtime the CLI knows about,
144
- around seventy of them, and leaves an `agent/` directory at your repository root for
145
- runtimes nobody there uses. Name the ones you have.
146
-
147
- Two things about living with the installed copy. It is a copy, so **a version bump does
148
- not update it**: re-run the command above, or `npx skills update ts-pptx-upstream`, in
149
- the same commit as the bump. And if you track it, track `skills-lock.json` and ignore the
150
- copy: `skills experimental_install` restores the file from that lock but creates none of
151
- the runtime links, so it is a record, not a restore command.
152
-
153
- It covers triage (is this ours, your deck's, or out of scope?), reducing a failure to
154
- a script that builds its own deck, and (because presentations carry client names and
155
- unreleased numbers) never uploading one to a public tracker. Once the reproduction
156
- stands on its own it files without interrupting you, and tells you the issue number
157
- afterwards. It also covers the far end of the cycle, which is the half that usually
158
- rots: when a release lands, finding every workaround it retires and deleting them.
159
-
160
- You do not need it to report something: <https://github.com/shbernal/ts-pptx/issues>
161
- is open, and errors the library knows are its own fault print that link themselves.
162
- See [errors](docs/errors.md#which-failures-are-worth-reporting) for which failures are
163
- worth a report.
164
-
165
- ## Runtime And Package Support
166
-
167
- The package is ESM-only.
168
-
169
- Supported package surface:
170
-
171
- - `import TsPptx, { ShapeType } from "@shbernal/ts-pptx"` (enums, shared types, and
172
- layout helpers ship from the main entry)
173
- - `import { inspectPptx } from "@shbernal/ts-pptx/inspect"`
174
- - `import { measureText } from "@shbernal/ts-pptx/measure"`
175
- - `import { Presentation } from "@shbernal/ts-pptx/read"`
176
- - `import { latexToOmml } from "@shbernal/ts-pptx/math"`
177
- - `import { tableToSlides } from "@shbernal/ts-pptx/html"`
178
- - `import TsPptx from "@shbernal/ts-pptx/node"`
179
- - `import TsPptx from "@shbernal/ts-pptx/browser"`:
180
- the bare specifier resolves to one of these two by export condition, so Node
181
- and bundled browser apps get the right build without naming it. A runtime that
182
- sets neither (Deno, Bun, edge workers) gets a runtime-agnostic build that
183
- authors and exports bytes normally but has no `writeFile` destination; see
184
- [Runtime And Package Support](docs/runtime-and-package-support.md#which-build-the-bare-import-gives-you).
185
- - generated runtime and declaration artifacts under `dist/`
186
- - Node.js `>=24`
187
- - modern bundlers and module-aware app frameworks
188
-
189
- Deliberately not supported:
190
-
191
- - No CommonJS: no `require("@shbernal/ts-pptx")`, no CJS export condition, and no
192
- `.cjs` artifact. Modern Node.js may provide `require()` interop for ESM, but it
193
- is not a maintained API.
194
- - No IIFE/global browser bundle: no classic-script global, no `dist/*.bundle.js`,
195
- and no `dist/*.min.js`.
196
-
197
- Use the package exports rather than direct `dist/` artifact paths.
198
-
199
- See [runtime and package support](docs/runtime-and-package-support.md) for the
200
- complete support contract.
201
-
202
- ## HTML Tables → Slides
203
-
204
- `@shbernal/ts-pptx/html` reproduces an existing HTML `<table>` as a PowerPoint
205
- table, auto-paging across as many slides as its rows need. It works in the
206
- browser and under Node with any DOM implementation, from one artifact.
207
-
208
- ```ts
209
- import { TsPptx } from '@shbernal/ts-pptx'
210
- import { tableToSlides } from '@shbernal/ts-pptx/html'
211
- import { Window } from 'happy-dom'
212
-
213
- const win = new Window()
214
- win.document.body.innerHTML = '<table id="report">…</table>'
215
-
216
- const pptx = new TsPptx()
217
- tableToSlides(pptx, win.document.getElementById('report'))
218
- await pptx.writeFile({ fileName: 'report.pptx' })
219
- ```
220
-
221
- Pass the element itself and no global DOM is consulted at all. To pass a string
222
- id instead, say which document it belongs to:
223
-
224
- ```ts
225
- tableToSlides(pptx, 'report', { document: win.document })
226
- ```
227
-
228
- In a browser, `options.document` defaults to the global `document`, so
229
- `tableToSlides(pptx, 'report')` is enough. The equivalent method form,
230
- `pptx.tableToSlides('report', options)`, remains on the browser build and
231
- delegates to the same implementation.
232
-
233
- **Column widths need a layout engine.** In a browser the columns are sized from
234
- each cell's rendered `offsetWidth`, reproducing the table's real proportions.
235
- Nothing outside a browser lays a table out, so `offsetWidth` is `0` there and
236
- the conversion falls back in two steps: it uses the computed CSS `width`s when the
237
- stylesheet states them for every column in one unit (all `px` or all `%`), and
238
- an equal split when it does not.
239
-
240
- The first step is a *fallback*, not a graceful loss of precision: `offsetWidth` is
241
- the border box and computed `width` the content box, so padding alone can put the
242
- two bases in different proportions. The same table can therefore come out with
243
- different column widths in a browser and outside one.
244
-
245
- To pin widths regardless of runtime, annotate the `<thead>` header cells, which
246
- win outright on every path:
247
-
248
- ```html
249
- <thead>
250
- <tr>
251
- <th data-pptx-width="2.5">Name</th>
252
- <th data-pptx-min-width="1">Qty</th>
253
- </tr>
254
- </thead>
255
- ```
256
-
257
- Everything else behaves the same wherever it runs: cell text (with `<br>` kept
258
- as a line break), `colspan`/`rowspan`, computed colors, weight, alignment,
259
- padding and borders, and auto-paging.
59
+ That is the whole shape of it. Make a presentation, add a slide, put things on the
60
+ slide, write the file. Positions are in inches by default, so `x: 1, y: 1` is an inch
61
+ in from the top-left corner of a 10 by 5.625 inch slide.
62
+ [Your first deck](docs/getting-started/first-deck.md) builds a bigger one from data, with a
63
+ table, a chart and speaker notes.
64
+
65
+ ## What you can put on a slide
66
+
67
+ Text and rich paragraphs. Tables, including ones that spill onto as many slides as
68
+ they need. Shapes and connectors between them. Pictures, SVGs, video and audio.
69
+ Charts, with a real embedded workbook behind them, so double-clicking a chart in
70
+ PowerPoint opens its data the way it does for a chart a human made. Speaker notes,
71
+ sections, slide masters and layouts, gradients, an image clipped to a shape, a
72
+ spreadsheet embedded as an object, a 3D model, and LaTeX maths.
73
+
74
+ Two features worth knowing about by name:
75
+
76
+ - **[An HTML table becomes slides](docs/html-tables.md).** Point `tableToSlides` at a
77
+ `<table>` you already have and it comes out as a PowerPoint table, paged across
78
+ slides. Works in a browser and under Node.
79
+ - **[Text that has to fit](docs/text-fit.md).** ts-pptx can measure the text
80
+ against the real font and shrink or grow the box before it writes the file, instead
81
+ of leaving you to guess at font sizes.
82
+
83
+ ## Reading decks, not only writing them
84
+
85
+ Writing is half of it. ts-pptx also opens a `.pptx` you already have, which is
86
+ unusual: the library it descends from generates decks and does not read them.
87
+
88
+ - **[Look inside one](docs/reference/pptx-inspection.md)** and get slide count, size,
89
+ parts, media and fonts, without loading the whole thing into a model.
90
+ - **[Edit one](docs/reading/read-and-edit.md)**. Open a deck, change the text on slide
91
+ four, save it back. Parts you did not touch come out byte for byte as they went in.
92
+ - **[Turn one into code](docs/reference/pptx-to-script.md)**. Point it at a deck and
93
+ get TypeScript that rebuilds it. Anything it could not express is reported to you
94
+ rather than dropped in silence. It is the fastest way to learn the API: build a
95
+ slide by hand in PowerPoint, then read the script for it.
96
+
97
+ ## Where it runs
98
+
99
+ | Runtime | Load it with | `writeFile` |
100
+ | --- | --- | --- |
101
+ | Node.js 24 or later | `import`, or `require()` with the class on `.default` | writes to disk |
102
+ | A browser app built with a bundler | `import` | downloads the file |
103
+ | A browser page with no build step | `import TsPptx from "https://esm.sh/pptx-ts/browser"` in a module script | downloads the file |
104
+ | Deno, Bun, edge workers | `import` | throws; use `toBytes()` |
105
+
106
+ [Where it runs](docs/getting-started/runtime.md) lists every entry point and how each runtime
107
+ loads the one ESM build.
108
+
109
+ <!-- comparison:start -->
110
+ <!-- GENERATED REGION. Do not edit by hand.
111
+ Regenerate with `pnpm run comparison:render`.
112
+ Source: `scripts/comparison/snapshot.json`, written by `scripts/comparison/measure.mjs`. -->
113
+
114
+ ## How this compares with PptxGenJS
115
+
116
+ ts-pptx is an independent derivative of
117
+ [PptxGenJS](https://github.com/gitbrent/PptxGenJS), detached at its v4.0.1. Both were
118
+ measured on 2026-09-21 by building the same 22 deck intents with each library and reading
119
+ the bytes that came out.
120
+
121
+ - **Construct coverage:** ts-pptx emitted 21 of 22, pptxgenjs 10 of 22. Nothing in the
122
+ corpus is emitted by pptxgenjs and not by ts-pptx.
123
+ - **Schema validity:** of the decks each library built, 21 of 21 ts-pptx decks and 0 of 10
124
+ pptxgenjs decks validate with no error against the Open XML SDK.
125
+ - **Adoption:** pptxgenjs is downloaded 10,539,687 times a month, against 1,780 for
126
+ ts-pptx. If a large installed base matters to you more than the differences above, use
127
+ pptxgenjs.
128
+ - **Activity:** last commit on the default branch, 2026-09-15 for ts-pptx and 2025-06-26
129
+ for pptxgenjs. Last npm publish, 2026-08-29 and 2025-06-26.
130
+
131
+ Where the two libraries part company is on the [comparison page](docs/comparison.md), and
132
+ [how it was measured](docs/comparison-method.md) has every full table. Every intent as
133
+ each library expresses it, including the calls that differ, is on [porting from
134
+ PptxGenJS](docs/comparison-syntax.md).
135
+
136
+ <!-- comparison:end -->
260
137
 
261
138
  ## Documentation
262
139
 
263
- The full documentation site is published at
264
- **<https://shbernal.github.io/ts-pptx/>**, including the generated API reference.
265
-
266
- - [Documentation index](docs/README.md)
267
- - [Project target](docs/project-target.md)
268
- - [Runtime and package support](docs/runtime-and-package-support.md)
269
- - [Development guide](docs/development.md)
270
- - [Testing guide](docs/testing.md)
271
- - [Agent development guide](docs/agent-development.md)
272
- - [OOXML agent context](docs/ooxml-agent-context.md)
273
- - [Evidence and fixtures](docs/evidence-and-fixtures.md)
274
-
275
- ## Repository Development
140
+ The documentation site, with the generated API reference, is at
141
+ **<https://shbernal.github.io/ts-pptx/>**. The [demos page](https://shbernal.github.io/ts-pptx/demos)
142
+ builds a quarterly review deck in your browser and previews the slides.
276
143
 
277
- This repository uses `pnpm` and requires Node.js `>=24`.
144
+ - Start with the [Introduction](docs/getting-started/introduction.md),
145
+ [Your first deck](docs/getting-started/first-deck.md) and
146
+ [Core concepts](docs/getting-started/concepts.md)
147
+ - [Tables](docs/tables.md), [connectors](docs/connectors.md), [groups](docs/groups.md) and
148
+ [HTML tables to slides](docs/html-tables.md)
149
+ - [Smaller bundles](docs/bundle-size.md) for a browser program that composes only what it uses
150
+ - [Errors and warnings](docs/errors-and-warnings.md) and
151
+ [troubleshooting](docs/troubleshooting.md)
278
152
 
279
- ```bash
280
- pnpm install
281
- pnpm run verify
282
- ```
153
+ ## Something wrong, or missing?
283
154
 
284
- OOXML serialization changes should also add or update a schema fixture in
285
- `test/schema-cases.js`. The schema suite validates through `ooxml-validate`, which
286
- fetches and caches its oracle binary on first use, so there is nothing to install.
155
+ Open an issue: <https://github.com/shbernal/ts-pptx/issues>. Errors the library knows
156
+ are its own fault print that link themselves.
287
157
 
288
- Package-boundary changes should run:
158
+ If an agent writes most of your code, install the `ts-pptx-upstream` skill that ships inside
159
+ the package. It turns a library defect the agent hits into a filed issue with a small
160
+ reproduction, instead of a silent workaround:
289
161
 
290
162
  ```bash
291
- pnpm run check:package
163
+ npx skills add ./node_modules/pptx-ts -s '*' -a claude-code -a codex -a universal -y
292
164
  ```
293
165
 
294
- ## Demos
295
-
296
- - `demos/showcases` builds the two flagship decks from one command.
297
- - `demos/node` exercises Node.js ESM generation and stream output.
298
- - The [demos page](https://shbernal.github.io/ts-pptx/demos) builds the quarterly review in
299
- your browser and previews the slides: nothing to clone.
300
-
301
- ## Relationship To Upstream
302
-
303
- ts-pptx builds on the original work of Brent Ely and the gitbrent/PptxGenJS
304
- contributors. The modernized package target is intentionally narrower than the
305
- original in order to simplify the runtime contract and keep maintenance focused.
166
+ Name the runtimes you use. [CONTRIBUTING.md](CONTRIBUTING.md) covers what the skill does
167
+ with a report and how to refresh it after a version bump.
306
168
 
307
169
  ## License
308
170