pptx-ts 3.7.0 → 4.0.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.
Files changed (136) hide show
  1. package/README.md +116 -269
  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-KnLOtEEu.js +3980 -0
  93. package/dist/text-KnLOtEEu.js.map +1 -0
  94. package/dist/text-anchor-CrYXAfUu.js +176 -0
  95. package/dist/text-anchor-CrYXAfUu.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-cX9sllpH.js +8865 -0
  107. package/dist/zoom-cX9sllpH.js.map +1 -0
  108. package/package.json +106 -19
  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
@@ -1,35 +1,12 @@
1
- import { lt as ColorMapToken, pt as ThemeColorSlot } from "./slide-ZqAdVvHV.js";
2
- import { t as CustomPropertyValue } from "./pres-BcBR3CSM.js";
3
- import { a as Part, i as Relationships, n as OpcPackage, o as Element, t as OpcInput } from "./package-CaOLXSNi.js";
4
- //#region src/embedded-fonts.d.ts
5
- /**
6
- * The four face slots of `CT_EmbeddedFontListEntry`, in schema child order
7
- * (`font` first, then these). Iterate in this order everywhere so the read- and
8
- * write-side emitters agree on element order.
9
- */
10
- declare const EMBEDDED_FONT_SLOTS: readonly ['regular', 'bold', 'italic', 'boldItalic'];
11
- type EmbeddedFontSlot = (typeof EMBEDDED_FONT_SLOTS)[number];
12
- /** One embeddable face: a slot plus the raw font bytes (absent in pure read-side merges). */
13
- interface EmbeddedFontFace {
14
- slot: EmbeddedFontSlot;
15
- bytes?: Uint8Array;
16
- }
17
- /** A typeface family with 1..4 embedded faces — one `p:embeddedFont` entry. */
18
- interface EmbeddedFont {
19
- /** `p:font/@typeface` — MUST match the family name used in run/`fontFace` typefaces or PowerPoint won't bind it. */
20
- typeface: string;
21
- panose?: string;
22
- pitchFamily?: number;
23
- charset?: number;
24
- faces: EmbeddedFontFace[];
25
- }
26
- //#endregion
1
+ import { Sn as ThemeColorSlot, sn as ColorMapToken, t as CustomPropertyValue } from "./pres-C6qgOFAa.js";
2
+ import { t as EmbeddedFont } from "./embedded-fonts-DarT9aoa.js";
3
+ import { a as Part, i as Relationships, n as OpcPackage, o as Element, t as OpcInput } from "./package-J49Ck6S2.js";
27
4
  //#region src/read/oxml/theme.d.ts
28
5
  /**
29
6
  * The colour-resolution context: the two maps that turn a DrawingML colour
30
7
  * reference into a literal hex — the effective colour map (token → `clrScheme`
31
8
  * slot, honouring any slide `clrMapOvr`) and the resolved colour scheme (slot →
32
- * 6-hex RGB). Shared by the read-model colour getters and {@link ThemeContext}.
9
+ * 6-hex RGB). Shared by the read-model colour getters and `ThemeContext`.
33
10
  */
34
11
  interface ColorContext {
35
12
  clrMap: Map<string, string>;
@@ -59,7 +36,9 @@ interface ThemeContext extends ColorContext {
59
36
  /**
60
37
  * The theme's `a:fontScheme`, for resolving a `+mj-*`/`+mn-*` major/minor font
61
38
  * token (the placeholder-inherited typeface chain bottoms out in one) to a
62
- * literal face name via {@link resolveThemeFont}. `null`/absent leaves such a
39
+ * literal face name via `resolveThemeFont` in this module. (Named rather than linked: it is
40
+ * internal, so a reference link to it resolves to nothing in the published reference.)
41
+ * `null`/absent leaves such a
63
42
  * token unresolved.
64
43
  */
65
44
  fontScheme?: Element | null;
@@ -78,10 +57,29 @@ interface ThemeContext extends ColorContext {
78
57
  * `presentation.xml`), keyed by level — PowerPoint's lowest-priority text
79
58
  * fallback, applying to any run (placeholder or not) that resolves nothing
80
59
  * above it. Only ever set on a *slide* context (see `resolveSlideColorContext`);
81
- * absent on notes/master/layout contexts, so their chains are unaffected.
60
+ * absent on notes/master/layout contexts, so their chains are unaffected. A table
61
+ * cell's text is read against a copy that holds the slide master's `p:otherStyle`
62
+ * here instead, the tier PowerPoint resolves cell text through (`TableCell.textFrame`).
82
63
  * Read-only — never mutated.
83
64
  */
84
65
  defaultTextStyle?: Element | null;
66
+ /**
67
+ * Memo for the placeholder lookups `findPlaceholder` (`read/oxml/placeholder-inherit.ts`)
68
+ * performs against
69
+ * {@link layoutRoot} and {@link masterRoot}, keyed by tier, placeholder type and `idx`.
70
+ *
71
+ * The lookup is a full subtree scan, and reading one run's five inherited properties used
72
+ * to perform ten of them: each property walks the tier chain, and each tier walk scans a
73
+ * layout and a master. The answer depends only on the roots and the `(type, idx)` asked
74
+ * for, and the roots on a context never change — so it is computed once per context.
75
+ *
76
+ * The memo lives here rather than in a module-level cache keyed by the root element
77
+ * because that is what scopes it correctly: a context is built per `Slide`/`TemplatePart`
78
+ * proxy, so the memo lasts exactly as long as the captured roots it agrees with, and a
79
+ * caller who mutates the deck and reads again gets a fresh context along with a fresh
80
+ * everything else. Written by `placeholder-inherit.ts` and read by nothing else.
81
+ */
82
+ placeholderMemo?: Map<string, Element | null>;
85
83
  }
86
84
  //#endregion
87
85
  //#region src/read/oxml/color-transform.d.ts
@@ -150,6 +148,37 @@ interface ResolvedColor {
150
148
  * resolve). Shared by the solid-fill and gradient-stop colour reads.
151
149
  */
152
150
  declare function resolveColorElement(colorEl: Element | null, ctx: ColorContext): ResolvedColor | null;
151
+ /**
152
+ * A DrawingML colour as the file writes it and as it renders. Every read value type that carries a
153
+ * colour carries one of these: a gradient stop, a shadow or glow, a bullet, a cell border, a
154
+ * pattern's two colours, a picture's recolour, a solid background, and a chart series' fill and line.
155
+ *
156
+ * At most one of {@link srgb}, {@link scheme} and {@link preset} is set, naming the colour model the
157
+ * file used. A colour written as `a:sysClr` or `a:hslClr` sets none of the three and is reported
158
+ * through {@link resolved} alone. With no colour at all, every field is `null`.
159
+ */
160
+ interface ColorRef {
161
+ /** `a:srgbClr/@val`, a 6-hex literal, or `null`. */
162
+ srgb: string | null;
163
+ /** `a:schemeClr/@val`, a theme token such as `accent1`, or `null`. */
164
+ scheme: string | null;
165
+ /** `a:prstClr/@val`, a preset name such as `black`, or `null`; `presetColorHex` makes one literal. */
166
+ preset: string | null;
167
+ /**
168
+ * The colour resolved against the theme, with its transforms applied, or `null` when there is no
169
+ * colour, it cannot be made literal (an unmapped token, or `a:scrgbClr`), or it was read without a
170
+ * theme, as a chart part's colours are. Read `resolved.transforms` when re-authoring against a
171
+ * different theme: `effectiveHex` alone is one theme baked in, and an empty list means the file
172
+ * stated no transforms.
173
+ */
174
+ resolved: ResolvedColor | null;
175
+ }
176
+ /**
177
+ * Read a colour element into a {@link ColorRef}.
178
+ * @param colorEl - an `a:EG_ColorChoice` element, or `null` for no colour
179
+ * @param ctx - the theme to resolve against, or `null` to leave {@link ColorRef.resolved} unset
180
+ */
181
+ declare function readColorRef(colorEl: Element | null, ctx: ColorContext | null): ColorRef;
153
182
  /** A shape's resolved `p:style/a:fontRef` text tier: its colour and theme face. */
154
183
  interface StyleFontRef {
155
184
  /** The `a:fontRef` child colour (`a:schemeClr`/`a:srgbClr`/…) resolved through the theme, or `null` when it names none / cannot be made literal. */
@@ -163,48 +192,11 @@ interface StyleFontRef {
163
192
  interface GradientStop {
164
193
  /** Stop offset along the gradient, 0–1 (from `@pos`, thousandths of a percent), or `null` if unset. */
165
194
  position: number | null;
166
- /** Explicit RGB colour as 6-hex (`a:srgbClr/@val`), or `null` when the stop uses another colour model. */
167
- color: string | null;
168
- /** Theme colour token (`a:schemeClr/@val`, e.g. `accent1`), or `null` when the stop uses another colour model. */
169
- schemeColor: string | null;
170
- /**
171
- * Preset colour name (`a:prstClr/@val`, e.g. `black`/`cornflowerBlue` — the
172
- * ECMA-376 §20.1.10.47 table), or `null` when the stop uses another colour
173
- * model. The same raw/resolved split {@link import('./shapes/types.js').RecolorColor}
174
- * uses; {@link import('../oxml/preset-color.js').presetColorHex}, exported from
175
- * `ts-pptx/read`, makes one literal.
176
- *
177
- * These three raw fields name three of the five colour models the reader
178
- * resolves. A stop written as `a:sysClr` or `a:hslClr` leaves all three `null`
179
- * and is reported through {@link resolvedColor} alone, which is the only place
180
- * its colour appears; `a:scrgbClr`, which the reader deliberately does not
181
- * resolve, leaves {@link resolvedColor} `null` too.
182
- */
183
- presetColor: string | null;
184
- /**
185
- * The stop's colour as a full {@link ResolvedColor} — base `hex`, the raw
186
- * `transforms` list (`lumMod`/`shade`/…) in document order, and the
187
- * `effectiveHex`/`alpha` after applying them — exactly what a solid fill's
188
- * `resolvedFill` gives. `null` when the colour cannot be made literal (an
189
- * unmapped token, or a colour model we do not resolve).
190
- *
191
- * This is the field to read when re-authoring a stop against a *different*
192
- * theme: {@link effectiveHex} alone is one theme baked in, so carrying it
193
- * forward as a literal silently stops the stop tracking the theme it came from.
194
- * `transforms` is what says whether there was anything to track, and an empty
195
- * list here means the stop stated none — not that the reader could not see them.
196
- */
197
- resolvedColor: ResolvedColor | null;
198
- /**
199
- * The stop's colour resolved against the slide theme **with its colour
200
- * transforms applied** — the final rendered hex, i.e. exactly
201
- * `resolvedColor?.effectiveHex ?? null`, kept as a flat field because painting a
202
- * gradient is what most callers want. `null` when the colour cannot be made
203
- * literal (an unmapped token, or a colour model we do not resolve).
204
- */
205
- effectiveHex: string | null;
206
- /** The stop's opacity (0–1) when an `alpha*` transform set one, else `undefined`. Mirrors `resolvedColor.alpha`. */
207
- alpha?: number;
195
+ /**
196
+ * The stop's colour, as written and resolved against the slide theme. Its `resolved.effectiveHex` is
197
+ * the rendered colour and `resolved.alpha` the stop's opacity, when an `alpha*` transform set one.
198
+ */
199
+ colorRef: ColorRef;
208
200
  }
209
201
  /**
210
202
  * A gradient fill (`a:gradFill`), as read from a container — the stops plus the
@@ -260,7 +252,7 @@ interface PictureFillTile {
260
252
  * {@link srcRect}, the destination inset {@link fillRect}, and {@link tile}.
261
253
  *
262
254
  * Rect fields follow the read API's fraction convention (see
263
- * {@link import('./shapes.js').Picture.crop}): the raw attributes are
255
+ * {@link Picture.crop}): the raw attributes are
264
256
  * thousandths of a percent and are divided by 100000, so `0.1` is 10 % and a
265
257
  * negative value (a `fillRect` that bleeds past the edge) stays negative.
266
258
  */
@@ -285,6 +277,21 @@ interface PictureFill {
285
277
  rotWithShape: boolean | null;
286
278
  }
287
279
  //#endregion
280
+ //#region src/read/api/pattern-fill.d.ts
281
+ /**
282
+ * A pattern fill (`a:pattFill`) — a two-colour preset hatch. The write-side
283
+ * `fill: { type: 'pattern', pattern: { preset, fgColor, bgColor } }` emits the same element,
284
+ * so the {@link preset} name and both colours round-trip.
285
+ */
286
+ interface PatternFill {
287
+ /** Preset pattern name (`@prst`, e.g. `pct50`/`diagCross`/`ltUpDiag`), or `null` when unset. */
288
+ preset: string | null;
289
+ /** Foreground colour (`a:fgClr`); every field is `null` when the pattern states none. */
290
+ foreground: ColorRef;
291
+ /** Background colour (`a:bgClr`); every field is `null` when the pattern states none. */
292
+ background: ColorRef;
293
+ }
294
+ //#endregion
288
295
  //#region src/read/api/slide-background.d.ts
289
296
  /** Where a slide's effective background comes from in the slide → layout → master chain. */
290
297
  type BackgroundSource = 'slide' | 'layout' | 'master';
@@ -292,7 +299,7 @@ type BackgroundSource = 'slide' | 'layout' | 'master';
292
299
  * An explicit background fill, decoded from a `p:bgPr` (or from a `p:bgRef`'s
293
300
  * resolved `fmtScheme` entry). The source-less core of {@link SlideBackground}: the
294
301
  * top-level variants add {@link BackgroundSource}, and it is what a `themeRef`'s
295
- * {@link SlideBackground.resolvedFill} carries.
302
+ * `SlideBackground.resolvedFill` carries.
296
303
  *
297
304
  * The `image` variant keeps `relId`/`partName` at the top level — the fields
298
305
  * callers already read — and adds the full {@link PictureFill} (stretch/tile
@@ -300,7 +307,7 @@ type BackgroundSource = 'slide' | 'layout' | 'master';
300
307
  */
301
308
  type BackgroundFill = {
302
309
  type: 'solid';
303
- color: ResolvedColor | null;
310
+ colorRef: ColorRef;
304
311
  } | {
305
312
  type: 'gradient';
306
313
  gradient: GradientFill;
@@ -309,19 +316,16 @@ type BackgroundFill = {
309
316
  picture: PictureFill;
310
317
  relId: string | null;
311
318
  partName: string | null;
312
- } | {
319
+ } | ({
313
320
  type: 'pattern';
314
- preset: string | null;
315
- foreground: ResolvedColor | null;
316
- background: ResolvedColor | null;
317
- } | {
321
+ } & PatternFill) | {
318
322
  type: 'none';
319
323
  };
320
324
  /**
321
325
  * A slide's effective background (`p:cSld/p:bg`), as a discriminated union on
322
- * `type`. Every variant carries {@link BackgroundSource}. `solid`/`gradient`/`image`
323
- * are what the writer authors and round-trip faithfully; `pattern`/`themeRef` are
324
- * read-only (imported decks) and `none` is an explicit `a:noFill`. A `themeRef`
326
+ * `type`. Every variant carries {@link BackgroundSource}. `solid`/`gradient`/`pattern`/`image`
327
+ * are what the writer authors and round-trip faithfully; `themeRef` is read-only
328
+ * (imported decks) and `none` is an explicit `a:noFill`. A `themeRef`
325
329
  * keeps its raw `idx` for fidelity and also exposes `resolvedFill` — the concrete
326
330
  * fill that `idx` resolves to through the slide theme's `fmtScheme` (`null` when the
327
331
  * theme/entry cannot be resolved).
@@ -329,7 +333,7 @@ type BackgroundFill = {
329
333
  type SlideBackground = {
330
334
  type: 'solid';
331
335
  source: BackgroundSource;
332
- color: ResolvedColor | null;
336
+ colorRef: ColorRef;
333
337
  } | {
334
338
  type: 'gradient';
335
339
  source: BackgroundSource;
@@ -340,17 +344,14 @@ type SlideBackground = {
340
344
  picture: PictureFill;
341
345
  relId: string | null;
342
346
  partName: string | null;
343
- } | {
347
+ } | ({
344
348
  type: 'pattern';
345
349
  source: BackgroundSource;
346
- preset: string | null;
347
- foreground: ResolvedColor | null;
348
- background: ResolvedColor | null;
349
- } | {
350
+ } & PatternFill) | {
350
351
  type: 'themeRef';
351
352
  source: BackgroundSource;
352
353
  idx: number | null;
353
- color: ResolvedColor | null;
354
+ colorRef: ColorRef;
354
355
  resolvedFill: BackgroundFill | null;
355
356
  } | {
356
357
  type: 'none';
@@ -359,30 +360,15 @@ type SlideBackground = {
359
360
  //#endregion
360
361
  //#region src/read/api/shapes/oxml.d.ts
361
362
  /**
362
- * A shape's properties element (`p:spPr` / `p:grpSpPr`) paired with the schema
363
- * successors for ordered insertion of its `a:solidFill` and `a:ln` children.
364
- * `lnAfter` is `null` for kinds with no `a:ln` (group shapes).
365
- */
366
- interface ShapeProperties {
367
- props: Element;
368
- fillAfter: string[];
369
- lnAfter: string[] | null;
370
- }
371
- //#endregion
372
- //#region src/read/api/pattern-fill.d.ts
373
- /**
374
- * A pattern fill (`a:pattFill`) — a two-colour preset hatch. The write-side
375
- * `fill: { type: 'pattern', pattern: { preset, fgColor, bgColor } }` emits the same element,
376
- * so the {@link preset} name and both colours round-trip. Colours resolve against the theme
377
- * (a scheme token → literal hex) the same way a solid fill does.
363
+ * Where a shape kind's paint is written: its properties element (`p:spPr` / `p:grpSpPr`), created
364
+ * in document order on demand, and for each paint the schema successors that paint's element is
365
+ * inserted before, or `null` for a paint the kind cannot carry (a group's `p:grpSpPr` has no
366
+ * `a:ln`).
378
367
  */
379
- interface PatternFill {
380
- /** Preset pattern name (`@prst`, e.g. `pct50`/`diagCross`/`ltUpDiag`), or `null` when unset. */
381
- preset: string | null;
382
- /** Foreground colour (`a:fgClr`) resolved against the theme, or `null`. */
383
- foreground: ResolvedColor | null;
384
- /** Background colour (`a:bgClr`) resolved against the theme, or `null`. */
385
- background: ResolvedColor | null;
368
+ interface PaintSurface {
369
+ getOrAdd(): Element;
370
+ fill: readonly string[] | null;
371
+ line: readonly string[] | null;
386
372
  }
387
373
  //#endregion
388
374
  //#region src/read/api/shapes/types.d.ts
@@ -429,15 +415,14 @@ interface ConnectionSite {
429
415
  * A shape's outer drop shadow (`spPr/a:effectLst/a:outerShdw`), as read from a
430
416
  * shape and resolved against the slide theme. Distances are in points (the EMU
431
417
  * source ÷ 12700) and the direction in degrees (the `60000`ths source ÷ 60000),
432
- * matching the write-side {@link ShadowProps} convention so it round-trips.
418
+ * matching the write-side `ShadowProps` convention so it round-trips.
433
419
  */
434
420
  interface OuterShadow {
435
- /** Effective shadow colour as 6-hex (theme-resolved, transforms applied), or `null`. */
436
- color: string | null;
437
- /** Theme colour token when the shadow colour was a scheme colour (e.g. `accent1`), else `undefined`. */
438
- colorToken?: string;
439
- /** Shadow opacity 0–1 (from the colour's `a:alpha`), or `undefined` when fully opaque. */
440
- alpha?: number;
421
+ /**
422
+ * The shadow colour, as written and resolved against the slide theme. Its `resolved.alpha` is the
423
+ * shadow's opacity, absent when it is fully opaque.
424
+ */
425
+ colorRef: ColorRef;
441
426
  /** Blur radius in points (`@blurRad` ÷ 12700), or `undefined` when unset. */
442
427
  blurPt?: number;
443
428
  /** Offset distance in points (`@dist` ÷ 12700), or `undefined` when unset. */
@@ -453,12 +438,11 @@ interface OuterShadow {
453
438
  * direction in degrees, matching the write-side `shadow: { type: 'inner' }`.
454
439
  */
455
440
  interface InnerShadow {
456
- /** Effective shadow colour as 6-hex (theme-resolved, transforms applied), or `null`. */
457
- color: string | null;
458
- /** Theme colour token when the shadow colour was a scheme colour (e.g. `accent1`), else `undefined`. */
459
- colorToken?: string;
460
- /** Shadow opacity 0–1 (from the colour's `a:alpha`), or `undefined` when fully opaque. */
461
- alpha?: number;
441
+ /**
442
+ * The shadow colour, as written and resolved against the slide theme. Its `resolved.alpha` is the
443
+ * shadow's opacity, absent when it is fully opaque.
444
+ */
445
+ colorRef: ColorRef;
462
446
  /** Blur radius in points (`@blurRad` ÷ 12700), or `undefined` when unset. */
463
447
  blurPt?: number;
464
448
  /** Offset distance in points (`@dist` ÷ 12700), or `undefined` when unset. */
@@ -468,17 +452,15 @@ interface InnerShadow {
468
452
  }
469
453
  /**
470
454
  * A shape's glow effect (`spPr/a:effectLst/a:glow`) — a coloured halo — resolved
471
- * against the slide theme. The write-side text glow (`glow: { size, color,
472
- * opacity }`) emits the same element, so {@link radiusPt} (`@rad` ÷ 12700) and the
473
- * colour round-trip.
455
+ * against the slide theme. The write-side `glow` option is a text glow: it writes
456
+ * `a:glow` into each run's `a:rPr/a:effectLst`, which this does not read.
474
457
  */
475
458
  interface Glow {
476
- /** Effective glow colour as 6-hex (theme-resolved, transforms applied), or `null`. */
477
- color: string | null;
478
- /** Theme colour token when the glow colour was a scheme colour (e.g. `accent1`), else `undefined`. */
479
- colorToken?: string;
480
- /** Glow opacity 0–1 (from the colour's `a:alpha`), or `undefined` when fully opaque. */
481
- alpha?: number;
459
+ /**
460
+ * The glow colour, as written and resolved against the slide theme. Its `resolved.alpha` is the
461
+ * glow's opacity, absent when it is fully opaque.
462
+ */
463
+ colorRef: ColorRef;
482
464
  /** Glow radius in points (`@rad` ÷ 12700), or `undefined` when unset. */
483
465
  radiusPt?: number;
484
466
  }
@@ -597,6 +579,22 @@ interface AbsoluteFrame {
597
579
  /** Effective vertical flip after XOR-composing enclosing group flips. */
598
580
  flipV: boolean;
599
581
  }
582
+ /**
583
+ * Why {@link Shape.absoluteFrame} could not resolve a frame.
584
+ *
585
+ * - `no-own-transform` — the shape states no `a:xfrm` of its own, or an incomplete
586
+ * one: typically a placeholder inheriting its box from the layout. Nothing is
587
+ * wrong with the deck; the read model reports what the shape itself states.
588
+ * - `group-transform-missing` — an enclosing `p:grpSp` states no complete
589
+ * `a:off`/`a:ext` **and** `a:chOff`/`a:chExt` pair, so its child space is unknown.
590
+ * - `group-transform-degenerate` — an enclosing group's `a:chExt` is zero on an
591
+ * axis, so the child-space ratio the mapping divides by is undefined.
592
+ *
593
+ * A missing group transform outranks a degenerate one wherever the two meet in
594
+ * one chain: composing needs every group's mapping, so an ancestor that states
595
+ * none is reported even when a nearer group is the degenerate one.
596
+ */
597
+ type AbsoluteFrameFailure = 'no-own-transform' | 'group-transform-missing' | 'group-transform-degenerate';
600
598
  /**
601
599
  * A group shape's own child coordinate space (`p:grpSpPr/a:xfrm/a:chOff` and
602
600
  * `a:chExt`) in EMU — the space its children's `a:off`/`a:ext` are authored in.
@@ -618,32 +616,20 @@ interface ChildFrame {
618
616
  /** `a:chExt/@cy`. */
619
617
  extentY: number;
620
618
  }
621
- /**
622
- * A colour reference inside a picture recolour effect, split by colour model
623
- * (mirrors {@link GradientStop}). At most one field is non-`null`.
624
- */
625
- interface RecolorColor {
626
- /** Explicit RGB as 6-hex (`a:srgbClr/@val`), or `null`. */
627
- color: string | null;
628
- /** Theme colour token (`a:schemeClr/@val`, e.g. `accent1`), or `null`. */
629
- schemeColor: string | null;
630
- /** Preset colour name (`a:prstClr/@val`, e.g. `black`/`white` — the duotone icon-tint stops), or `null`. */
631
- presetColor: string | null;
632
- }
633
619
  /**
634
620
  * A picture's blip recolour effect (`p:blipFill/a:blip` recolour child), as read.
635
621
  * A small discriminated union over the effects a faithful reader needs to
636
- * reproduce a recoloured image. Colours use the same `color`/`schemeColor`/
637
- * `presetColor` split as {@link GradientStop}, so theme tokens can resolve through
638
- * {@link Slide.themeContext}. `threshold`/`amount` are 0–1 fractions.
622
+ * reproduce a recoloured image. Each colour is a {@link ColorRef}, resolved against the
623
+ * slide theme, so a duotone's `a:prstClr` and `a:sysClr` stops resolve as any other colour
624
+ * does. `threshold`/`amount` are 0–1 fractions.
639
625
  */
640
626
  type Recolor = {
641
627
  kind: 'duotone';
642
- stops: RecolorColor[];
628
+ stops: ColorRef[];
643
629
  } | {
644
630
  kind: 'clrChange';
645
- from: RecolorColor | null;
646
- to: RecolorColor | null;
631
+ from: ColorRef | null;
632
+ to: ColorRef | null;
647
633
  } | {
648
634
  kind: 'grayscale';
649
635
  } | {
@@ -654,29 +640,13 @@ type Recolor = {
654
640
  amount: number;
655
641
  };
656
642
  //#endregion
657
- //#region src/read/api/text.d.ts
658
- /**
659
- * What a {@link Run}'s text body needs to resolve an *inherited* run
660
- * colour/size/face/bold: which placeholder the text lives in (or `null` for a
661
- * non-placeholder shape, which still resolves its `p:style/a:fontRef` and the
662
- * presentation `p:defaultTextStyle`), the slide theme context (with the
663
- * layout/master roots) to resolve against, and the shape's resolved
664
- * `p:style/a:fontRef` text tier. The owning slide's text body `a:lstStyle` is added
665
- * per text frame. Absent only for text reached without a theme context (table cells).
666
- */
667
- interface PlaceholderTextContext {
668
- ph: PlaceholderRef | null;
669
- flatten: ThemeContext;
670
- /** The shape's resolved `p:style/a:fontRef` colour + face tier, or `null` when it has none. */
671
- fontRef?: StyleFontRef | null;
672
- }
643
+ //#region src/read/api/hyperlink.d.ts
673
644
  /**
674
- * A run's click hyperlink (`a:rPr/a:hlinkClick`): a link on a span of text. A URL
675
- * link carries an external {@link url}; a slide jump carries the internal
676
- * {@link targetPartName} (the linked slide's part) alongside its `hlinksldjump`
677
- * {@link action}. `tooltip` and `relId` are surfaced when present.
645
+ * A click hyperlink (`a:hlinkClick`), on a run or on a shape. A URL link carries an external
646
+ * {@link url}; a slide jump carries the internal {@link targetPartName} (the linked slide's part)
647
+ * alongside its `hlinksldjump` {@link action}. `tooltip` and `relId` are surfaced when present.
678
648
  */
679
- interface RunHyperlink {
649
+ interface Hyperlink {
680
650
  /** External URL target (its `@r:id` resolves to a `TargetMode="External"` rel), or `null` for an internal/action-only link. */
681
651
  url: string | null;
682
652
  /** Absolute partname of an internal target (e.g. the slide a jump points at), or `null`. */
@@ -688,6 +658,104 @@ interface RunHyperlink {
688
658
  /** The relationship id (`@r:id`) backing the link, or `null` when the link is action-only. */
689
659
  relId: string | null;
690
660
  }
661
+ //#endregion
662
+ //#region src/read/api/table-style-resolve.d.ts
663
+ /**
664
+ * The `a:tblPr` condition flags that gate which style parts apply to a table.
665
+ * `firstRow`/`bandRow` are the ones PowerPoint turns on by default; the rest are
666
+ * off unless the author enabled the corresponding "Header Column" / "Total Row" /
667
+ * "Banded Columns" toggle.
668
+ */
669
+ interface TableConditionFlags {
670
+ firstRow: boolean;
671
+ lastRow: boolean;
672
+ firstCol: boolean;
673
+ lastCol: boolean;
674
+ bandRow: boolean;
675
+ bandCol: boolean;
676
+ }
677
+ /** A table's resolved entry in `tableStyles.xml`: its GUID, display name, and raw element. */
678
+ interface ResolvedTableStyle {
679
+ /** The matched `@styleId` GUID (e.g. `{5C22544A-…}`). */
680
+ styleId: string;
681
+ /** The style's display name (`@styleName`, e.g. `Medium Style 2 - Accent 1`), or `null`. */
682
+ name: string | null;
683
+ /** Escape hatch: the underlying `a:tblStyle` element. After mutating it call {@link ResolvedTableStyle.markDirty}, or `save()` writes the original bytes. */
684
+ element_: Element;
685
+ /**
686
+ * Mark `tableStyles.xml` dirty so `save()` reserializes it. Call after mutating
687
+ * {@link ResolvedTableStyle.element_}. Note the part is deck-wide: an edit here
688
+ * reaches every table bound to this style.
689
+ */
690
+ markDirty(): void;
691
+ }
692
+ /**
693
+ * What a table style's text styles (`a:tcTxStyle`) give the text of one cell. Each property is
694
+ * taken from the highest-precedence part that states it, so a `firstRow` that makes the header
695
+ * bold and white still leaves the header's other properties to `wholeTbl`. Every field is `null`
696
+ * when no applicable part states it.
697
+ */
698
+ interface TableCellTextStyle {
699
+ /** The text colour: the style's own colour child, else its `a:fontRef` colour, resolved. */
700
+ color: ResolvedColor | null;
701
+ /** The face its `a:font/a:latin` names, or the theme font its `a:fontRef/@idx` names, resolved. */
702
+ face: string | null;
703
+ /** `@b`: `on` is `true` and `off` is `false`; `def`, the schema default, states nothing. */
704
+ bold: boolean | null;
705
+ /** `@i`, read the same way as {@link bold}. */
706
+ italic: boolean | null;
707
+ }
708
+ //#endregion
709
+ //#region src/read/api/text/run.d.ts
710
+ /**
711
+ * What a text body is read against, handed from a {@link TextFrame} to each paragraph and run: the
712
+ * part an edit marks dirty, the theme the `resolved*` getters resolve against, the relationships
713
+ * a hyperlink or a picture bullet resolves through, and the inheritance its runs fall back through.
714
+ */
715
+ interface TextContext {
716
+ /** The part the text lives in. */
717
+ part: Part;
718
+ /** The theme the text resolves against: the colour maps, `fontScheme`, and the layout and master roots. */
719
+ ctx: ThemeContext;
720
+ /**
721
+ * The owning part's relationships, or `null` for text read without them — a SmartArt drawing's
722
+ * cached text — whose run hyperlinks then report their raw `@r:id`, `@action` and `@tooltip`.
723
+ */
724
+ rels: Relationships | null;
725
+ /**
726
+ * What a run that sets no colour, size, face, bold or italic of its own inherits through, or
727
+ * `null` for text that inherits through nothing, such as a SmartArt point's.
728
+ */
729
+ inherit: TextInheritance | null;
730
+ }
731
+ /** The inheritance a shape's or a table cell's text resolves through below its own run properties. */
732
+ interface TextInheritance {
733
+ /**
734
+ * The placeholder the text lives in, or `null` for a non-placeholder shape, which still resolves
735
+ * its `p:style/a:fontRef` and the presentation's `p:defaultTextStyle`.
736
+ */
737
+ ph: PlaceholderRef | null;
738
+ /** The shape's resolved `p:style/a:fontRef` colour and face, or `null` when it has none. */
739
+ fontRef: StyleFontRef | null;
740
+ /**
741
+ * A table cell's text style: what the table style's `a:tcTxStyle` gives the cell's region, with
742
+ * the theme's `tx1` and minor font where it names no colour or face. Read after {@link fontRef}
743
+ * and before the list-style chain. Absent for text outside a table.
744
+ */
745
+ tableText?: TableCellTextStyle | null;
746
+ }
747
+ /**
748
+ * What the runs of one paragraph inherit, each property resolved at most once and only when a run
749
+ * that sets no value of its own asks. Every run in a paragraph shares its level and `a:pPr`, so
750
+ * they share one of these.
751
+ */
752
+ interface InheritedRunProps {
753
+ color(): ResolvedColor | null;
754
+ size(): number | null;
755
+ face(): string | null;
756
+ bold(): boolean | null;
757
+ italic(): boolean | null;
758
+ }
691
759
  /**
692
760
  * A paragraph's line spacing (`a:pPr/a:lnSpc`), in whichever of the two OOXML
693
761
  * forms the file uses: an exact point height (`a:spcPts`) or a percentage of the
@@ -716,16 +784,12 @@ interface BulletStyle {
716
784
  sizePct: number | null;
717
785
  /** `a:buSzPts/@val` as an absolute point size (the raw attribute is hundredths of a point), or `null`. The alternative to {@link sizePct}; at most one is set. */
718
786
  sizePt: number | null;
719
- /** Explicit RGB bullet colour as 6-hex (`a:buClr/a:srgbClr/@val`), or `null`. */
720
- color: string | null;
721
- /** Theme colour token when the bullet colour is a scheme colour (`a:buClr/a:schemeClr/@val`), or `null`. */
722
- schemeColor: string | null;
723
- /** The bullet colour resolved against the slide theme with its transforms applied, or `null` when unset or not resolvable to a literal. */
724
- resolvedColor: ResolvedColor | null;
787
+ /** The bullet's own colour (`a:buClr`); every field is `null` when the paragraph leaves it to be inherited. */
788
+ colorRef: ColorRef;
725
789
  }
726
790
  /**
727
791
  * A paragraph's bullet, as the structured counterpart of the `a:pPr` bullet
728
- * children. Discriminated on {@link kind}, which is one of the four mutually
792
+ * children. Discriminated on `kind`, which is one of the four mutually
729
793
  * exclusive choices the schema allows:
730
794
  *
731
795
  * - `'none'` — `a:buNone`, the bullet explicitly suppressed. Carries no style,
@@ -766,102 +830,31 @@ type BulletDetail = {
766
830
  declare class Run {
767
831
  #private;
768
832
  private readonly element;
769
- private readonly part;
770
- /** The owning slide's theme context (colour maps + `fontScheme`), for the `resolved*` getters; absent when the run was reached without one. */
771
- private readonly themeContext?;
772
833
  /**
773
- * Resolves the colour this run inherits from its placeholder/list-style chain
774
- * when it sets none of its own (item A). Built by the owning {@link Paragraph}
775
- * for placeholder text; absent for non-placeholder runs. Called lazily.
834
+ * What the run is read against; see {@link TextContext}. Its `inherit.fontRef` is the tier
835
+ * {@link resolvedColor} and {@link resolvedFontFace} consult just below the run's own `a:rPr`
836
+ * and above the placeholder and `p:defaultTextStyle` chain.
776
837
  */
777
- private readonly inheritedColor?;
838
+ private readonly context;
778
839
  /**
779
- * Resolves the point size this run inherits from the same chain when it sets no
780
- * own `@sz`. Built by the owning {@link Paragraph} for placeholder text; absent
781
- * for non-placeholder runs. Called lazily.
840
+ * What the run inherits when it sets no colour, size, face, bold or italic of its own, or `null`
841
+ * for text that inherits through nothing. Built by the owning {@link Paragraph} and shared by
842
+ * its runs; nothing in it is resolved until a run asks.
782
843
  */
783
- private readonly inheritedSize?;
784
- /**
785
- * Resolves the typeface this run inherits from the same chain (a `+mj-*`/`+mn-*`
786
- * theme token already resolved to a literal face) when it sets no own `a:latin`.
787
- * Built by the owning {@link Paragraph} for placeholder text; absent otherwise.
788
- * Called lazily.
789
- */
790
- private readonly inheritedFace?;
791
- /**
792
- * Resolves whether this run inherits bold from the same chain when it sets no
793
- * own `@b`. Built by the owning {@link Paragraph} for placeholder text; absent
794
- * for non-placeholder runs. Called lazily.
795
- */
796
- private readonly inheritedBold?;
797
- /**
798
- * Resolves whether this run inherits italic from the same chain when it sets no
799
- * own `@i`. Built by the owning {@link Paragraph} for placeholder text; absent
800
- * for non-placeholder runs. Called lazily.
801
- */
802
- private readonly inheritedItalic?;
803
- /**
804
- * The owning part's relationships, used to resolve a run hyperlink's `@r:id`
805
- * to its external URL or internal target partname. Absent when the run was
806
- * reached without them (e.g. table-cell or notes text), in which case
807
- * {@link hyperlink} still reports the raw `@r:id`/`@action`/`@tooltip`.
808
- */
809
- private readonly relationships?;
810
- /**
811
- * The owning shape's resolved `p:style/a:fontRef` colour + face tier — the
812
- * fallback consulted for {@link resolvedColor}/{@link resolvedFontFace} just
813
- * below the run's own `a:rPr` and above the placeholder/`p:defaultTextStyle`
814
- * chain. Absent when the shape has no `p:style/a:fontRef`.
815
- */
816
- private readonly fontRef?;
817
- constructor(element: Element, part: Part,
818
- /** The owning slide's theme context (colour maps + `fontScheme`), for the `resolved*` getters; absent when the run was reached without one. */
819
- themeContext?: ThemeContext | undefined,
820
- /**
821
- * Resolves the colour this run inherits from its placeholder/list-style chain
822
- * when it sets none of its own (item A). Built by the owning {@link Paragraph}
823
- * for placeholder text; absent for non-placeholder runs. Called lazily.
824
- */
825
- inheritedColor?: (() => ResolvedColor | null) | undefined,
826
- /**
827
- * Resolves the point size this run inherits from the same chain when it sets no
828
- * own `@sz`. Built by the owning {@link Paragraph} for placeholder text; absent
829
- * for non-placeholder runs. Called lazily.
830
- */
831
- inheritedSize?: (() => number | null) | undefined,
832
- /**
833
- * Resolves the typeface this run inherits from the same chain (a `+mj-*`/`+mn-*`
834
- * theme token already resolved to a literal face) when it sets no own `a:latin`.
835
- * Built by the owning {@link Paragraph} for placeholder text; absent otherwise.
836
- * Called lazily.
837
- */
838
- inheritedFace?: (() => string | null) | undefined,
839
- /**
840
- * Resolves whether this run inherits bold from the same chain when it sets no
841
- * own `@b`. Built by the owning {@link Paragraph} for placeholder text; absent
842
- * for non-placeholder runs. Called lazily.
843
- */
844
- inheritedBold?: (() => boolean | null) | undefined,
845
- /**
846
- * Resolves whether this run inherits italic from the same chain when it sets no
847
- * own `@i`. Built by the owning {@link Paragraph} for placeholder text; absent
848
- * for non-placeholder runs. Called lazily.
849
- */
850
- inheritedItalic?: (() => boolean | null) | undefined,
844
+ private readonly inherited;
845
+ constructor(element: Element,
851
846
  /**
852
- * The owning part's relationships, used to resolve a run hyperlink's `@r:id`
853
- * to its external URL or internal target partname. Absent when the run was
854
- * reached without them (e.g. table-cell or notes text), in which case
855
- * {@link hyperlink} still reports the raw `@r:id`/`@action`/`@tooltip`.
847
+ * What the run is read against; see {@link TextContext}. Its `inherit.fontRef` is the tier
848
+ * {@link resolvedColor} and {@link resolvedFontFace} consult just below the run's own `a:rPr`
849
+ * and above the placeholder and `p:defaultTextStyle` chain.
856
850
  */
857
- relationships?: Relationships | undefined,
851
+ context: TextContext,
858
852
  /**
859
- * The owning shape's resolved `p:style/a:fontRef` colour + face tier — the
860
- * fallback consulted for {@link resolvedColor}/{@link resolvedFontFace} just
861
- * below the run's own `a:rPr` and above the placeholder/`p:defaultTextStyle`
862
- * chain. Absent when the shape has no `p:style/a:fontRef`.
853
+ * What the run inherits when it sets no colour, size, face, bold or italic of its own, or `null`
854
+ * for text that inherits through nothing. Built by the owning {@link Paragraph} and shared by
855
+ * its runs; nothing in it is resolved until a run asks.
863
856
  */
864
- fontRef?: StyleFontRef | null | undefined);
857
+ inherited: InheritedRunProps | null);
865
858
  /** The run's text (`a:t`), verbatim — whitespace is not normalized. */
866
859
  get text(): string;
867
860
  set text(value: string);
@@ -876,6 +869,7 @@ declare class Run {
876
869
  set italic(value: boolean | null);
877
870
  /** Underline style token (`a:rPr/@u`, e.g. `sng`), or `null` when unset. */
878
871
  get underline(): string | null;
872
+ /** @throws {InvalidOptionError} when the token is not an `ST_TextUnderlineType` */
879
873
  set underline(value: string | null);
880
874
  /**
881
875
  * Strikethrough token (`a:rPr/@strike`: `noStrike` | `sngStrike` |
@@ -893,6 +887,9 @@ declare class Run {
893
887
  * in 1000ths of a percent): positive for superscript (the writer's default is
894
888
  * `30`), negative for subscript (`-40`), or `null` when unset. Reported as the
895
889
  * percentage (`@baseline` ÷ 1000).
890
+ *
891
+ * `@baseline` is `a:ST_Percentage`, a union that also admits `"62.5%"` — the only form the
892
+ * Strict profile has — so it is read through `parsePercentPoints` rather than as a bare number.
896
893
  */
897
894
  get baselinePct(): number | null;
898
895
  /**
@@ -903,21 +900,20 @@ declare class Run {
903
900
  get charSpacingPt(): number | null;
904
901
  /**
905
902
  * The run's highlight colour (`a:rPr/a:highlight`), resolved to a literal hex
906
- * through the owning slide's theme, or `null` when the run has no highlight
907
- * (or a token colour cannot be made literal without a theme context). The
908
- * writer authors highlights from a hex colour, so `effectiveHex` is that
909
- * colour; imported decks may carry a theme token, resolved here when possible.
903
+ * through the owning slide's theme, or `null` when the run has no highlight or
904
+ * its colour cannot be made literal. The writer authors highlights from a hex
905
+ * colour, so `effectiveHex` is that colour; imported decks may carry a theme token.
910
906
  */
911
907
  get highlight(): ResolvedColor | null;
912
908
  /**
913
909
  * The run's click hyperlink (`a:rPr/a:hlinkClick`), or `null` when the run
914
910
  * carries none. A URL link resolves its `@r:id` to the external target
915
- * ({@link RunHyperlink.url}); a slide jump resolves it to the linked slide's
916
- * partname ({@link RunHyperlink.targetPartName}). When the run was reached
917
- * without the owning part's relationships, only the raw `@r:id`/`@action`/
918
- * `@tooltip` are reported (the target stays `null`).
911
+ * ({@link Hyperlink.url}); a slide jump resolves it to the linked slide's
912
+ * partname ({@link Hyperlink.targetPartName}). When the run is read without
913
+ * its part's relationships (see {@link TextContext.rels}), only the raw
914
+ * `@r:id`/`@action`/`@tooltip` are reported (the target stays `null`).
919
915
  */
920
- get hyperlink(): RunHyperlink | null;
916
+ get hyperlink(): Hyperlink | null;
921
917
  /** Latin typeface name (`a:rPr/a:latin/@typeface`), or `null` when unset. */
922
918
  get fontName(): string | null;
923
919
  set fontName(value: string | null);
@@ -926,6 +922,7 @@ declare class Run {
926
922
  set color(value: string | null);
927
923
  /** Theme colour token when the fill is a scheme colour (`a:schemeClr/@val`, e.g. `accent2`), or `null`. */
928
924
  get schemeColor(): string | null;
925
+ /** @throws {InvalidOptionError} when the token is not an `ST_SchemeColorVal` */
929
926
  set schemeColor(value: string | null);
930
927
  /**
931
928
  * The colour this run effectively renders, resolved against the owning slide's
@@ -934,8 +931,11 @@ declare class Run {
934
931
  * `p:style/a:fontRef` colour, then — for a run inside a placeholder — the colour
935
932
  * it inherits from the placeholder/list-style chain (layout → master placeholder
936
933
  * `a:lstStyle` → master `p:txStyles`), then the presentation's
937
- * `p:defaultTextStyle`. `null` when the run sets no colour and inherits none, the
938
- * colour cannot be made literal, or the run was reached without a theme context.
934
+ * `p:defaultTextStyle`. `null` when the run sets no colour and inherits none, or the
935
+ * colour cannot be made literal.
936
+ * `null` too when the run's own fill is not a solid colour (`a:noFill`, a gradient):
937
+ * the run decides its own colour then, and the one it would otherwise inherit is not
938
+ * what it paints in, the rule `Shape.resolvedFill` and `TableCell.resolvedFill` follow.
939
939
  * The returned {@link ResolvedColor} carries `effectiveHex` — the base colour with
940
940
  * its child transforms (`lumMod`/`shade`/…) applied — for the final rendered colour.
941
941
  */
@@ -986,37 +986,27 @@ declare class Run {
986
986
  /** Mark the owning part dirty so `save()` reserializes it. Call after mutating {@link element_}. */
987
987
  markDirty(): void;
988
988
  }
989
+ //#endregion
990
+ //#region src/read/api/text/paragraph.d.ts
989
991
  /** One paragraph (`a:p`) of a text frame. */
990
992
  declare class Paragraph {
991
993
  #private;
992
994
  private readonly element;
993
- private readonly part;
994
- /** The owning slide's theme context (colour maps + `fontScheme`), threaded to each {@link Run} for the `resolved*` getters. */
995
- private readonly themeContext?;
996
- /**
997
- * Placeholder + slide-list-style context for resolving a placeholder-inherited
998
- * run colour/size/face; absent for non-placeholder text. The owning
999
- * {@link TextFrame} supplies the placeholder identity and the text body's
1000
- * `a:lstStyle`.
1001
- */
1002
- private readonly inherit?;
1003
- /** The owning part's relationships, threaded to each {@link Run} for hyperlink `@r:id` resolution; absent when reached without them. */
1004
- private readonly relationships?;
1005
- constructor(element: Element, part: Part,
1006
- /** The owning slide's theme context (colour maps + `fontScheme`), threaded to each {@link Run} for the `resolved*` getters. */
1007
- themeContext?: ThemeContext | undefined,
1008
- /**
1009
- * Placeholder + slide-list-style context for resolving a placeholder-inherited
1010
- * run colour/size/face; absent for non-placeholder text. The owning
1011
- * {@link TextFrame} supplies the placeholder identity and the text body's
1012
- * `a:lstStyle`.
1013
- */
1014
- inherit?: {
1015
- placeholder: PlaceholderTextContext;
1016
- slideLstStyle: Element | null;
1017
- } | undefined,
1018
- /** The owning part's relationships, threaded to each {@link Run} for hyperlink `@r:id` resolution; absent when reached without them. */
1019
- relationships?: Relationships | undefined);
995
+ /** What the paragraph is read against; see {@link TextContext}. */
996
+ private readonly context;
997
+ /**
998
+ * The owning text body's own `a:lstStyle`, the tier just below the paragraph in the chain its
999
+ * runs inherit through. Read only when {@link TextContext.inherit} is set.
1000
+ */
1001
+ private readonly slideLstStyle;
1002
+ constructor(element: Element,
1003
+ /** What the paragraph is read against; see {@link TextContext}. */
1004
+ context: TextContext,
1005
+ /**
1006
+ * The owning text body's own `a:lstStyle`, the tier just below the paragraph in the chain its
1007
+ * runs inherit through. Read only when {@link TextContext.inherit} is set.
1008
+ */
1009
+ slideLstStyle: Element | null);
1020
1010
  /** The runs (`a:r`) in document order. Fields (`a:fld`) and breaks are not runs; see `text`. */
1021
1011
  get runs(): Run[];
1022
1012
  /** Indent level (`a:pPr/@lvl`), 0 when unset. */
@@ -1075,6 +1065,8 @@ declare class Paragraph {
1075
1065
  markDirty(): void;
1076
1066
  }
1077
1067
  /** A shape's text frame (`p:txBody`): an ordered list of paragraphs. */
1068
+ //#endregion
1069
+ //#region src/read/api/text/frame.d.ts
1078
1070
  /**
1079
1071
  * A text frame's body properties (`a:bodyPr`), as read from a shape. Carries the
1080
1072
  * inset/anchor/vertical-text settings that govern where text sits inside its box
@@ -1108,28 +1100,17 @@ type AutofitMode = 'none' | 'normAutofit' | 'spAutoFit';
1108
1100
  declare class TextFrame {
1109
1101
  #private;
1110
1102
  private readonly txBody;
1111
- private readonly part;
1112
- /** The owning slide's theme context (colour maps + `fontScheme`), threaded to each {@link Paragraph}/{@link Run} for the `resolved*` getters. */
1113
- private readonly themeContext?;
1114
- /**
1115
- * The placeholder this text body lives in, when any — enables
1116
- * placeholder-inherited run colour/size/face resolution. Absent for ordinary
1117
- * text boxes and table cells.
1118
- */
1119
- private readonly placeholder?;
1120
- /** The owning part's relationships, threaded to each {@link Paragraph}/{@link Run} for hyperlink `@r:id` resolution; absent when reached without them. */
1121
- private readonly relationships?;
1122
- constructor(txBody: Element, part: Part,
1123
- /** The owning slide's theme context (colour maps + `fontScheme`), threaded to each {@link Paragraph}/{@link Run} for the `resolved*` getters. */
1124
- themeContext?: ThemeContext | undefined,
1125
- /**
1126
- * The placeholder this text body lives in, when any — enables
1127
- * placeholder-inherited run colour/size/face resolution. Absent for ordinary
1128
- * text boxes and table cells.
1129
- */
1130
- placeholder?: PlaceholderTextContext | undefined,
1131
- /** The owning part's relationships, threaded to each {@link Paragraph}/{@link Run} for hyperlink `@r:id` resolution; absent when reached without them. */
1132
- relationships?: Relationships | undefined);
1103
+ /**
1104
+ * What the frame is read against — its part, the theme, the part's relationships and the
1105
+ * inheritance its runs fall back through — handed on to each {@link Paragraph} and {@link Run}.
1106
+ */
1107
+ private readonly context;
1108
+ constructor(txBody: Element,
1109
+ /**
1110
+ * What the frame is read against — its part, the theme, the part's relationships and the
1111
+ * inheritance its runs fall back through — handed on to each {@link Paragraph} and {@link Run}.
1112
+ */
1113
+ context: TextContext);
1133
1114
  /** Paragraphs (`a:p`) in document order. */
1134
1115
  get paragraphs(): Paragraph[];
1135
1116
  /**
@@ -1186,7 +1167,7 @@ declare class TextFrame {
1186
1167
  }
1187
1168
  //#endregion
1188
1169
  //#region src/read/api/shapes/host.d.ts
1189
- /** The part-level surface a {@link import('./base.js').Shape} resolves against. */
1170
+ /** The part-level surface a {@link Shape} resolves against. */
1190
1171
  interface ShapeHost {
1191
1172
  /** The OPC part holding the shape tree (`p:sld` / `p:sldLayout` / `p:sldMaster`). */
1192
1173
  readonly part: Part;
@@ -1242,6 +1223,19 @@ declare abstract class Shape {
1242
1223
  get id(): number | null;
1243
1224
  /** Shape name (`p:cNvPr/@name`), or `''` if unnamed. */
1244
1225
  get name(): string;
1226
+ /**
1227
+ * The shape's own click hyperlink (`p:cNvPr/a:hlinkClick`), or `null` when it carries none.
1228
+ *
1229
+ * This is the link PowerPoint's Insert > Link puts on a whole shape, as opposed to the one a
1230
+ * {@link Run} carries on a span of text. It is the same element, read the same way, and it had
1231
+ * no reader at all -- so a linked shape read back as an ordinary one and a replica lost the
1232
+ * link with nothing to say so. `addShape`, `addText` and `addImage` all take `hyperlink`.
1233
+ *
1234
+ * A URL link resolves its `@r:id` to the external target; a slide jump resolves it to the
1235
+ * linked slide's partname and reports `ppaction://hlinksldjump` as its `action`. An
1236
+ * action-only link (a slide-show navigation button) has no `@r:id` and resolves to neither.
1237
+ */
1238
+ get hyperlink(): Hyperlink | null;
1245
1239
  /**
1246
1240
  * Whether the shape is explicitly hidden (`p:cNvPr/@hidden="1"`); `false` when
1247
1241
  * the attribute is unset. A hidden shape stays in the slide XML but is not
@@ -1345,21 +1339,39 @@ declare abstract class Shape {
1345
1339
  *
1346
1340
  * `null` when the shape (or any enclosing group) has no own transform, or a
1347
1341
  * group's `a:chExt` is degenerate (zero) — there is then no resolvable frame.
1342
+ * {@link absoluteFrameFailure} says which of those it was.
1348
1343
  *
1349
1344
  * A rotated shape's returned `left`/`top` remain PowerPoint's unrotated
1350
1345
  * placement box (the same box PowerPoint writes after Ungroup), with the
1351
1346
  * effective rotation exposed separately.
1352
1347
  */
1353
1348
  get absoluteFrame(): AbsoluteFrame | null;
1349
+ /**
1350
+ * Why {@link absoluteFrame} is `null`, or `null` when it resolved.
1351
+ *
1352
+ * `absoluteFrame` reports one `null` for three different situations, and only a
1353
+ * caller that wants to *report* the unresolvable shape needs them apart — an
1354
+ * inherited placeholder box is ordinary, a group with no usable `a:xfrm` is not.
1355
+ * The distinction is not recoverable from the `null`, and re-deriving it means
1356
+ * walking the same ancestry a second time, so it is named here instead. See
1357
+ * {@link AbsoluteFrameFailure} for what each value means.
1358
+ */
1359
+ get absoluteFrameFailure(): AbsoluteFrameFailure | null;
1354
1360
  /** The shape's properties element (`p:spPr` / `p:grpSpPr`), or `null` when absent. */
1355
1361
  protected properties(): Element | null;
1356
- /** Get-or-add the properties element in document order, with the successor
1357
- * arrays for inserting its fill / line children. Subclasses override this
1358
- * to point at `p:grpSpPr`, or to reject kinds with no properties element. */
1359
- protected getOrAddProperties(): ShapeProperties;
1360
- /** Whether a solid fill can be set on this shape kind. Pictures and graphic
1361
- * frames opt out (they carry their own image / table-cell fill model). */
1362
- protected get supportsFill(): boolean;
1362
+ /**
1363
+ * Where this kind's paint is written, and which paints it can carry: its properties element,
1364
+ * and for each paint the successors that paint's element goes before, or `null` for a paint
1365
+ * the kind cannot carry. `null` for a kind with no properties element at all.
1366
+ *
1367
+ * The one capability a kind declares about paint, checked in one place. Setting a fill (a
1368
+ * colour, a theme token, {@link noFill}) on a kind that cannot carry one throws
1369
+ * `shape/fill-unsupported`, and setting a line colour throws `shape/line-unsupported`.
1370
+ * Clearing never throws: a kind that cannot be *given* a paint may still hold one a deck wrote,
1371
+ * so clearing removes whatever of that paint the element has, and changes nothing when it has
1372
+ * none.
1373
+ */
1374
+ protected paintSurface(): PaintSurface | null;
1363
1375
  /** Explicit RGB fill colour as a 6-hex string (`spPr/a:solidFill/a:srgbClr/@val`), or `null`. */
1364
1376
  get fillColor(): string | null;
1365
1377
  set fillColor(value: string | null);
@@ -1436,6 +1448,19 @@ declare abstract class Shape {
1436
1448
  * this kind carries. A group has no geometry of its own and reads `null`.
1437
1449
  */
1438
1450
  get presetGeometry(): string | null;
1451
+ /**
1452
+ * Custom freeform geometry (`spPr/a:custGeom/a:pathLst`), or `null` when the
1453
+ * shape uses preset geometry / none. The faithful, multi-path counterpart of
1454
+ * {@link presetGeometry}: each `a:path` keeps its own path-unit viewport
1455
+ * (`w`/`h`) and ordered {@link GeometryCommand}s. Coordinates are raw path-unit
1456
+ * integers, not EMU — pair the path `w`/`h` with the shape's box size to map
1457
+ * them into slide space.
1458
+ *
1459
+ * Not an auto-shape-only property either: a picture clipped to a freeform (what
1460
+ * PowerPoint writes when Merge Shapes intersects a picture with a shape, and what
1461
+ * `addImage({ points })` writes) carries its clip here. A group reads `null`.
1462
+ */
1463
+ get customGeometry(): CustomGeometry | null;
1439
1464
  /**
1440
1465
  * Preset-geometry adjustment values (`spPr/a:prstGeom/a:avLst/a:gd`) as a
1441
1466
  * name → formula map, e.g. `{ adj: 'val 16667' }`. Empty when the shape has no
@@ -1489,8 +1514,8 @@ declare abstract class Shape {
1489
1514
  get innerShadow(): InnerShadow | null;
1490
1515
  /**
1491
1516
  * The shape's glow halo (`spPr/a:effectLst/a:glow`), resolved against the host's
1492
- * theme, or `null` when the shape has no glow. Same element the write-side text
1493
- * glow emits, so its {@link Glow.radiusPt} and colour round-trip.
1517
+ * theme, or `null` when the shape has no glow. The write-side `glow` option is a
1518
+ * text glow in run properties, so it does not read back here.
1494
1519
  */
1495
1520
  get glow(): Glow | null;
1496
1521
  /**
@@ -1544,8 +1569,11 @@ declare abstract class Shape {
1544
1569
  * Like {@link resolvedFill}, the result carries `effectiveHex` (the base colour
1545
1570
  * with its transforms applied) for the final rendered colour.
1546
1571
  *
1547
- * When the shape carries no explicit `spPr/a:ln`, this falls back to the line
1548
- * the shape inherits from its `p:style` `a:lnRef` (the theme style matrix).
1572
+ * When the shape's `spPr/a:ln` states no fill of its own, this falls back to the line
1573
+ * colour the shape inherits from its `p:style` `a:lnRef` (the theme style matrix). An
1574
+ * `a:ln` without a fill is not a replacement: PowerPoint layers it over the style line one
1575
+ * property at a time, and changing only an outline's weight writes `<a:ln w="76200"/>`
1576
+ * and paints the style colour (`test/read/fixtures/shape-line-style-override.pptx`).
1549
1577
  */
1550
1578
  get resolvedLine(): ResolvedColor | null;
1551
1579
  /** Whether this shape can hold text (only `p:sp` does in this read model). */
@@ -1570,6 +1598,10 @@ declare abstract class Shape {
1570
1598
  /**
1571
1599
  * Remove this shape from its parent (the host's shape tree, or an enclosing
1572
1600
  * group) and mark the owning host's part dirty. The proxy is dead afterwards.
1601
+ *
1602
+ * The build animations targeting the shape, or any shape inside a deleted group, go with it,
1603
+ * and a connector attached to one of them keeps its geometry with that end unbound. PowerPoint
1604
+ * refuses a deck whose animation names a shape that is not on the slide.
1573
1605
  */
1574
1606
  delete(): void;
1575
1607
  /** Escape hatch: the underlying shape element. After mutating it call {@link markDirty}, or `save()` writes the original bytes. */
@@ -1588,15 +1620,6 @@ declare class AutoShape extends Shape {
1588
1620
  * PowerPoint does. Use {@link Slide.placeholder} to find a placeholder by type.
1589
1621
  */
1590
1622
  get placeholder(): PlaceholderRef | null;
1591
- /**
1592
- * Custom freeform geometry (`spPr/a:custGeom/a:pathLst`), or `null` when the
1593
- * shape uses preset geometry / none. The faithful, multi-path counterpart of
1594
- * {@link presetGeometry}: each `a:path` keeps its own path-unit viewport
1595
- * (`w`/`h`) and ordered {@link GeometryCommand}s. Coordinates are raw path-unit
1596
- * integers, not EMU — pair the path `w`/`h` with the shape's box size to map
1597
- * them into slide space.
1598
- */
1599
- get customGeometry(): CustomGeometry | null;
1600
1623
  }
1601
1624
  //#endregion
1602
1625
  //#region src/read/api/shapes/picture.d.ts
@@ -1604,7 +1627,7 @@ declare class AutoShape extends Shape {
1604
1627
  declare class Picture extends Shape {
1605
1628
  #private;
1606
1629
  readonly shapeType: 'picture';
1607
- protected get supportsFill(): boolean;
1630
+ protected paintSurface(): PaintSurface | null;
1608
1631
  /** Relationship id of the embedded image (`p:blipFill/a:blip/@r:embed`), or `null`. */
1609
1632
  get imageRelId(): string | null;
1610
1633
  /**
@@ -1613,7 +1636,13 @@ declare class Picture extends Shape {
1613
1636
  * the id exists and targets an image; use {@link setImage} to add fresh bytes.
1614
1637
  */
1615
1638
  set imageRelId(value: string);
1616
- /** Absolute partname of the embedded image, resolved via the owning part's relationships, or `null`. */
1639
+ /**
1640
+ * Absolute partname of the embedded image, resolved via the owning part's relationships.
1641
+ *
1642
+ * `null` covers every way there is nothing to name: no `r:embed`, an id the part does not
1643
+ * declare, or a relationship whose target is external (a LINKED image). It used to throw on
1644
+ * the last two while the same blip reached through a picture fill returned `null`.
1645
+ */
1617
1646
  get imagePartName(): string | null;
1618
1647
  /**
1619
1648
  * Relationship id of the embedded **vector (SVG)** image, read from the
@@ -1624,7 +1653,7 @@ declare class Picture extends Shape {
1624
1653
  * so a reader that wants the real drawn art must consult both.
1625
1654
  */
1626
1655
  get svgRelId(): string | null;
1627
- /** Absolute partname of the embedded SVG image, resolved via the owning part's relationships, or `null`. */
1656
+ /** Absolute partname of the embedded SVG image, or `null`. Same rule as {@link imagePartName}. */
1628
1657
  get svgPartName(): string | null;
1629
1658
  /**
1630
1659
  * Which drawable media this picture carries:
@@ -1658,12 +1687,7 @@ declare class Picture extends Shape {
1658
1687
  * match the fraction convention used elsewhere in the read API (see
1659
1688
  * {@link recolor}).
1660
1689
  */
1661
- get crop(): {
1662
- left: number;
1663
- top: number;
1664
- right: number;
1665
- bottom: number;
1666
- } | null;
1690
+ get crop(): FillRect | null;
1667
1691
  /**
1668
1692
  * The picture's blip recolour effect (`p:blipFill/a:blip` recolour child), or
1669
1693
  * `null` when the blip carries none. Recognises the effects a faithful reader
@@ -1743,7 +1767,7 @@ interface ChartLegend {
1743
1767
  /** Whether the legend overlays the plot area (`c:overlay/@val`). */
1744
1768
  overlay: boolean | null;
1745
1769
  }
1746
- /** A chart's data-label settings (`c:dLbls`), read from the first plot group. */
1770
+ /** Data-label settings (`c:dLbls`), read from a plot group or from one series. */
1747
1771
  interface ChartDataLabels {
1748
1772
  /** Show the point value (`c:showVal`). */
1749
1773
  showValue: boolean | null;
@@ -1766,10 +1790,11 @@ interface ChartDataLabels {
1766
1790
  }
1767
1791
  /** A series' solid fill (`c:ser/c:spPr`). */
1768
1792
  interface ChartFill {
1769
- /** Literal fill colour (`a:srgbClr/@val`), or `null` for a scheme/no fill. */
1770
- color: string | null;
1771
- /** Raw scheme-colour token (`a:schemeClr/@val`), unresolved. */
1772
- schemeColor: string | null;
1793
+ /**
1794
+ * The fill's solid colour; every field is `null` for a non-solid fill. A chart part is read
1795
+ * without a theme, so `resolved` is always `null` and a scheme colour stays a token.
1796
+ */
1797
+ colorRef: ColorRef;
1773
1798
  /** Whether the fill is explicitly suppressed (`a:noFill`). */
1774
1799
  noFill: boolean;
1775
1800
  }
@@ -1779,10 +1804,8 @@ interface ChartLine {
1779
1804
  widthPt: number | null;
1780
1805
  /** Dash style (`a:prstDash/@val`), or `null` when solid/unset. */
1781
1806
  dash: string | null;
1782
- /** Literal stroke colour (`a:srgbClr/@val`), or `null`. */
1783
- color: string | null;
1784
- /** Raw scheme-colour token (`a:schemeClr/@val`), unresolved. */
1785
- schemeColor: string | null;
1807
+ /** The stroke's solid colour; unresolved, as {@link ChartFill.colorRef} is. */
1808
+ colorRef: ColorRef;
1786
1809
  /** Whether the line is explicitly suppressed (`a:noFill`). */
1787
1810
  noFill: boolean;
1788
1811
  }
@@ -1820,7 +1843,12 @@ declare class Chart {
1820
1843
  /**
1821
1844
  * The chart-level data-label settings, read from the first plot group's
1822
1845
  * aggregate `c:dLbls` (the group-wide block after the series). `null` when the
1823
- * plot group carries no data-label block (e.g. pie via a different builder).
1846
+ * plot group carries no data-label block.
1847
+ *
1848
+ * A pie keeps its labels on the series instead: PowerPoint writes the flags the
1849
+ * user set into `c:ser/c:dLbls` and leaves this block all off, and this library's
1850
+ * writer emits no group block for a pie at all. Read those through
1851
+ * {@link ChartSeries.dataLabels}.
1824
1852
  */
1825
1853
  get dataLabels(): ChartDataLabels | null;
1826
1854
  /** The data series (`c:ser`) across all chart groups, in document order. */
@@ -1830,6 +1858,8 @@ declare class Chart {
1830
1858
  * (`c:cat`), as written. Empty when the chart has no category axis.
1831
1859
  */
1832
1860
  get categories(): (string | null)[];
1861
+ /** Every category level of the first series, leaf first; see {@link ChartSeries.categoryLevels}. */
1862
+ get categoryLevels(): (string | null)[][];
1833
1863
  /** Escape hatch: the underlying `c:chartSpace` element. After mutating it call {@link markDirty}, or `save()` writes the original bytes. */
1834
1864
  get element_(): Element | null;
1835
1865
  /** Mark the chart part dirty so `save()` reserializes it. Call after mutating {@link element_}. */
@@ -1889,6 +1919,7 @@ declare class ChartAxis {
1889
1919
  }
1890
1920
  /** One data series (`c:ser`) of a chart. */
1891
1921
  declare class ChartSeries {
1922
+ #private;
1892
1923
  private readonly ser;
1893
1924
  /** The owning chart's OPC part, so {@link markDirty} can reach it from {@link element_}. */
1894
1925
  private readonly part;
@@ -1909,10 +1940,49 @@ declare class ChartSeries {
1909
1940
  get index(): number | null;
1910
1941
  /** Series name from the cached `c:tx`, or `null` when unnamed. */
1911
1942
  get name(): string | null;
1912
- /** Cached numeric values (`c:val`); non-numeric or missing points are `null`. */
1943
+ /**
1944
+ * Cached numeric values (`c:val`); non-numeric or missing points are `null`. Empty on a
1945
+ * scatter or bubble series, which caches its values as {@link yValues} instead.
1946
+ */
1913
1947
  get values(): (number | null)[];
1914
- /** Cached category labels for this series (`c:cat`), as written. */
1948
+ /**
1949
+ * Cached X values of a scatter or bubble series (`c:xVal`); missing points are `null`.
1950
+ * A series plotted against text X labels reads `null` at every point, a label that looks like a
1951
+ * number included: {@link xLabels} has the text. A series with no `c:xVal` reads `[]`, and
1952
+ * PowerPoint plots it at X = 1, 2, … n, as it does a series plotted against text.
1953
+ */
1954
+ get xValues(): (number | null)[];
1955
+ /**
1956
+ * The X labels of a series plotted against text (`c:xVal` holding a string cache rather than
1957
+ * numbers), as written, or `null` when its X values are numbers or absent.
1958
+ *
1959
+ * One text cell makes the whole X column a string cache, so the numbers in it arrive as text too.
1960
+ * PowerPoint then plots the points at X = 1, 2, … n in point order and uses none of the labels
1961
+ * as a coordinate, not even one that reads as a number.
1962
+ */
1963
+ get xLabels(): (string | null)[] | null;
1964
+ /** Cached Y values of a scatter or bubble series (`c:yVal`); non-numeric or missing points are `null`. */
1965
+ get yValues(): (number | null)[];
1966
+ /** Cached bubble sizes of a bubble series (`c:bubbleSize`); non-numeric or missing points are `null`. */
1967
+ get bubbleSizes(): (number | null)[];
1968
+ /**
1969
+ * Cached category labels for this series (`c:cat`), as written. On a multi-level axis this
1970
+ * is the leaf level, the labels next to the plot; {@link categoryLevels} has the rest.
1971
+ */
1915
1972
  get categories(): (string | null)[];
1973
+ /**
1974
+ * Every level of cached category labels (`c:cat`), leaf first: the order PowerPoint writes the
1975
+ * `c:multiLvlStrCache/c:lvl` children in, and the order `OptsChartData.labels` takes them.
1976
+ * Each level is as long as the leaf level. An outer level names a group once, at the group's
1977
+ * first category, so the other slots of that group are `null`. A single-level axis reads as
1978
+ * one level, and a series with no categories as none.
1979
+ */
1980
+ get categoryLevels(): (string | null)[][];
1981
+ /**
1982
+ * The data-label settings this series carries itself (`c:ser/c:dLbls`), or `null` when it has
1983
+ * none. This is where a pie's labels are: see {@link Chart.dataLabels}.
1984
+ */
1985
+ get dataLabels(): ChartDataLabels | null;
1916
1986
  /** Escape hatch: the underlying `c:ser` element. After mutating it call {@link markDirty}, or `save()` writes the original bytes. */
1917
1987
  get element_(): Element;
1918
1988
  /** Mark the owning chart part dirty so `save()` reserializes it. Call after mutating {@link element_}. */
@@ -2132,8 +2202,22 @@ interface DiagramDrawnShape {
2132
2202
  declare class DrawingIndex {
2133
2203
  #private;
2134
2204
  private readonly drawingPart;
2135
- private readonly themeContext?;
2136
- constructor(root: Element | null, drawingPart: Part | null, themeContext?: ThemeContext | undefined);
2205
+ private readonly themeContext;
2206
+ /**
2207
+ * The drawing part's own relationships, so a hyperlink in the cached text resolves to a url
2208
+ * rather than reporting a raw `@r:id`. It used to be read without them, so the same run
2209
+ * answered differently depending on which of the two paths reached it: through the point's
2210
+ * own `textFrame` it resolved, through `drawnShape.textFrame` it did not.
2211
+ */
2212
+ private readonly drawingRelationships;
2213
+ constructor(root: Element | null, drawingPart: Part | null, themeContext: ThemeContext,
2214
+ /**
2215
+ * The drawing part's own relationships, so a hyperlink in the cached text resolves to a url
2216
+ * rather than reporting a raw `@r:id`. It used to be read without them, so the same run
2217
+ * answered differently depending on which of the two paths reached it: through the point's
2218
+ * own `textFrame` it resolved, through `drawnShape.textFrame` it did not.
2219
+ */
2220
+ drawingRelationships: Relationships | null);
2137
2221
  /**
2138
2222
  * Resolve one authored point to the `pres` point that presents it and to the drawn
2139
2223
  * paragraph carrying its text.
@@ -2156,13 +2240,13 @@ declare class DiagramPoint {
2156
2240
  private readonly pt;
2157
2241
  /** The diagram data part, so a text edit marks the right part dirty. */
2158
2242
  private readonly part;
2159
- private readonly themeContext?;
2160
- private readonly relationships?;
2243
+ private readonly themeContext;
2244
+ private readonly relationships;
2161
2245
  /** The owning diagram's drawing index, built on first use; absent when reached without one. */
2162
2246
  private readonly drawing?;
2163
2247
  constructor(pt: Element,
2164
2248
  /** The diagram data part, so a text edit marks the right part dirty. */
2165
- part: Part, themeContext?: ThemeContext | undefined, relationships?: Relationships | undefined,
2249
+ part: Part, themeContext: ThemeContext, relationships: Relationships,
2166
2250
  /** The owning diagram's drawing index, built on first use; absent when reached without one. */
2167
2251
  drawing?: (() => DrawingIndex) | undefined);
2168
2252
  /** This point's id (`@modelId`), which connections reference. */
@@ -2277,14 +2361,14 @@ declare class Diagram {
2277
2361
  private readonly opc;
2278
2362
  /** Relationships of the part holding the frame — what `dgm:relIds` resolves against. */
2279
2363
  private readonly frameRelationships;
2280
- private readonly themeContext?;
2364
+ private readonly themeContext;
2281
2365
  constructor(
2282
2366
  /** The diagram's data part (`/ppt/diagrams/data{N}.xml`), whose root is `dgm:dataModel`. */
2283
2367
  part: Part,
2284
2368
  /** The frame's `dgm:relIds`, which names the other three parts by relationship id. */
2285
2369
  relIds: Element, opc: OpcPackage,
2286
2370
  /** Relationships of the part holding the frame — what `dgm:relIds` resolves against. */
2287
- frameRelationships: Relationships, themeContext?: ThemeContext | undefined);
2371
+ frameRelationships: Relationships, themeContext: ThemeContext);
2288
2372
  /** Partname of the diagram data part. */
2289
2373
  get partName(): string;
2290
2374
  /**
@@ -2292,7 +2376,7 @@ declare class Diagram {
2292
2376
  * points and the `doc` root included. Filter on {@link DiagramPoint.type} for the user's
2293
2377
  * nodes; {@link text} is the shortcut for the common case, {@link nodes} the structured one.
2294
2378
  *
2295
- * Built per access like every other read proxy (`docs/reference/pptx-read.md`, "Object
2379
+ * Built per access like every other read proxy (`docs/reference/read-object-model.md`, "Object
2296
2380
  * model"), so `points[0] !== points[0]` while both wrap the same `dgm:pt`. Key a `Map`
2297
2381
  * on {@link DiagramPoint.modelId}, not on the point.
2298
2382
  */
@@ -2369,38 +2453,7 @@ declare const EDGE_QNAMES: {
2369
2453
  /** Which border of a cell an edit addresses. */
2370
2454
  type TableCellEdge = keyof typeof EDGE_QNAMES;
2371
2455
  //#endregion
2372
- //#region src/read/api/table-style-resolve.d.ts
2373
- /**
2374
- * The `a:tblPr` condition flags that gate which style parts apply to a table.
2375
- * `firstRow`/`bandRow` are the ones PowerPoint turns on by default; the rest are
2376
- * off unless the author enabled the corresponding "Header Column" / "Total Row" /
2377
- * "Banded Columns" toggle.
2378
- */
2379
- interface TableConditionFlags {
2380
- firstRow: boolean;
2381
- lastRow: boolean;
2382
- firstCol: boolean;
2383
- lastCol: boolean;
2384
- bandRow: boolean;
2385
- bandCol: boolean;
2386
- }
2387
- /** A table's resolved entry in `tableStyles.xml`: its GUID, display name, and raw element. */
2388
- interface ResolvedTableStyle {
2389
- /** The matched `@styleId` GUID (e.g. `{5C22544A-…}`). */
2390
- styleId: string;
2391
- /** The style's display name (`@styleName`, e.g. `Medium Style 2 - Accent 1`), or `null`. */
2392
- name: string | null;
2393
- /** Escape hatch: the underlying `a:tblStyle` element. After mutating it call {@link ResolvedTableStyle.markDirty}, or `save()` writes the original bytes. */
2394
- element_: Element;
2395
- /**
2396
- * Mark `tableStyles.xml` dirty so `save()` reserializes it. Call after mutating
2397
- * {@link ResolvedTableStyle.element_}. Note the part is deck-wide: an edit here
2398
- * reaches every table bound to this style.
2399
- */
2400
- markDirty(): void;
2401
- }
2402
- //#endregion
2403
- //#region src/read/api/table.d.ts
2456
+ //#region src/read/api/table-cell.d.ts
2404
2457
  /**
2405
2458
  * One border as {@link TableCell.setBorder} takes it — the write-side mirror of
2406
2459
  * {@link CellBorder}, which is what reading one gives back.
@@ -2437,9 +2490,8 @@ interface TableCellStyleContext {
2437
2490
  /**
2438
2491
  * One edge border of a table cell (`a:tcPr/a:lnL|lnR|lnT|lnB|lnTlToBr|lnBlToTr`).
2439
2492
  * Mirrors the `a:ln`-style decode used for shape strokes: {@link widthPt} from
2440
- * `@w` (EMU → points), {@link dash} from `a:prstDash/@val`, and the stroke colour
2441
- * split into a resolved {@link color} (literal hex) and the raw {@link schemeColor}
2442
- * token — the cell-border counterpart of a shape's line accessors.
2493
+ * `@w` (EMU → points), {@link dash} from `a:prstDash/@val`, and the stroke colour as a
2494
+ * {@link ColorRef} — the cell-border counterpart of a shape's line accessors.
2443
2495
  */
2444
2496
  interface CellBorder {
2445
2497
  /** Border width in points (`@w` is EMU; 12700 EMU = 1pt), or `null` when unset. */
@@ -2447,28 +2499,12 @@ interface CellBorder {
2447
2499
  /** Dash style (`a:prstDash/@val`, e.g. `solid`/`sysDash`), or `null` when unset. */
2448
2500
  dash: string | null;
2449
2501
  /**
2450
- * The stroke colour as a full {@link ResolvedColor} — base `hex`, the raw
2451
- * `transforms` list (`lumMod`/`shade`/…) in document order, and the
2452
- * `effectiveHex`/`alpha` after applying them — the same object a shape's
2453
- * `resolvedLine` gives. `null` when the edge carries no solid fill, or the
2454
- * colour cannot be made literal.
2455
- *
2456
- * This is the field to read when re-authoring a border against a *different*
2457
- * theme: {@link color} alone is one theme baked in, so a `lumMod`-darkened
2458
- * accent carried forward as a literal hex silently stops tracking the theme it
2459
- * came from. `transforms` is what says whether there was anything to track, and
2460
- * an empty list here means the edge stated none — not that the reader could not
2461
- * see them.
2462
- */
2463
- resolvedColor: ResolvedColor | null;
2464
- /**
2465
- * The stroke colour resolved against the table theme to a literal hex — exactly
2466
- * `resolvedColor?.effectiveHex ?? null`, kept as a flat field because painting a
2467
- * rule is what most callers want. `null` when the edge has no resolvable colour.
2502
+ * The stroke's solid colour, as written and resolved against the slide theme; every field is
2503
+ * `null` when the edge carries no solid fill. `resolved.effectiveHex` is what a renderer paints,
2504
+ * and `resolved.transforms` is what to carry when re-authoring a border against a different
2505
+ * theme: a `lumMod`-darkened accent carried forward as a literal hex stops tracking its theme.
2468
2506
  */
2469
- color: string | null;
2470
- /** Raw `schemeClr` token of the stroke (`a:solidFill/a:schemeClr/@val`), or `null` for an srgb/absent colour. */
2471
- schemeColor: string | null;
2507
+ colorRef: ColorRef;
2472
2508
  /** `true` when the edge is an explicit no-border (`a:noFill`) — a deliberately suppressed side. */
2473
2509
  noFill: boolean;
2474
2510
  }
@@ -2509,216 +2545,43 @@ interface CellThreeD {
2509
2545
  dir: string | null;
2510
2546
  } | null;
2511
2547
  }
2512
- /** A table: a grid of rows and cells inside a graphic frame. */
2513
- declare class Table {
2514
- #private;
2515
- private readonly tbl;
2516
- private readonly part;
2517
- /** The owning slide's theme colour context, threaded to each cell's text for `Run.resolvedColor`. */
2518
- private readonly themeColors?;
2519
- /** The deck package, for resolving `a:tableStyleId` against `tableStyles.xml` (style-graph cell fills). */
2520
- private readonly opc?;
2521
- /** The owning slide's relationships, for resolving a cell picture fill's `r:embed` to a partname. */
2522
- private readonly rels?;
2523
- constructor(tbl: Element, part: Part,
2524
- /** The owning slide's theme colour context, threaded to each cell's text for `Run.resolvedColor`. */
2525
- themeColors?: ThemeContext | undefined,
2526
- /** The deck package, for resolving `a:tableStyleId` against `tableStyles.xml` (style-graph cell fills). */
2527
- opc?: OpcPackage | undefined,
2528
- /** The owning slide's relationships, for resolving a cell picture fill's `r:embed` to a partname. */
2529
- rels?: Relationships | undefined);
2530
- /** The table's rows (`a:tr`) in document (top-to-bottom) order. */
2531
- get rows(): TableRow[];
2532
- /**
2533
- * The table's style graph entry (`styleId`, `name`, raw `a:tblStyle`) resolved
2534
- * from the deck's `tableStyles.xml`, or `null` when the table names no
2535
- * `a:tableStyleId`, the deck has no `tableStyles.xml`, or the id is a built-in
2536
- * `[MS-OE376]` style the deck does not materialise. This is what supplies the
2537
- * banded-row / header shading a cell with no own fill inherits — read the
2538
- * resolved per-cell colour off {@link TableCell.resolvedFill}.
2539
- */
2540
- get resolvedStyle(): ResolvedTableStyle | null;
2541
- /** Number of rows (`a:tr`). */
2542
- get rowCount(): number;
2543
- /** Number of grid columns (`a:tblGrid/a:gridCol`). */
2544
- get columnCount(): number;
2545
- /** Column widths in EMU (`a:gridCol/@w`), one per grid column. */
2546
- get columnWidths(): (number | null)[];
2547
- /**
2548
- * The table's style GUID (`a:tblPr/a:tableStyleId` text), e.g.
2549
- * `{5940675A-B579-460E-94D1-54222C63F5DA}`, or `null` when the table carries no
2550
- * `a:tableStyleId`. This is the reference into `ppt/tableStyles.xml` (or a
2551
- * built-in `[MS-OE376]` style) that supplies the banded-row / header shading the
2552
- * `firstRow`/`bandRow` flags activate — without it a replica loses the whole
2553
- * table style, so it is the read counterpart of the writer's `tableStyle` option.
2554
- */
2555
- get styleId(): string | null;
2556
- /**
2557
- * The table's own background (`a:tblPr` fill) resolved against the slide's theme colour
2558
- * context to a literal hex, or `null` when the table carries no solid background.
2559
- *
2560
- * This is the table-level counterpart of {@link TableCell.resolvedFill}, and it is a
2561
- * genuinely different thing from a cell fill: a `a:tblPr` fill sits *behind* the grid, so
2562
- * a cell with no fill of its own shows it through. Reports `null` for a non-solid choice
2563
- * (`a:blipFill`/`a:gradFill`/`a:pattFill`/`a:noFill`) — read {@link pictureFill} for an
2564
- * image background — and `null` with no theme context.
2565
- */
2566
- get resolvedFill(): ResolvedColor | null;
2567
- /**
2568
- * The table's picture background (`a:tblPr/a:blipFill`), or `null` when the table is not
2569
- * image-backed. The table-level twin of {@link TableCell.pictureFill}, and needed for the
2570
- * same reason: {@link resolvedFill} decodes only solid colours, so without this an
2571
- * image-backed table is indistinguishable from an unfilled one.
2572
- */
2573
- get pictureFill(): PictureFill | null;
2574
- /**
2575
- * The table's gradient background (`a:tblPr/a:gradFill`), or `null` when it is not
2576
- * gradient-filled. Needed for the same reason {@link pictureFill} is:
2577
- * {@link resolvedFill} decodes only solid colours.
2578
- */
2579
- get gradientFill(): GradientFill | null;
2580
- /**
2581
- * The table's pattern (hatch) background (`a:tblPr/a:pattFill`), or `null` when it is not
2582
- * pattern-filled.
2583
- */
2584
- get patternFill(): PatternFill | null;
2585
- /**
2586
- * The raw `schemeClr` token of the table's own background
2587
- * (`a:tblPr/a:solidFill/a:schemeClr/@val`), or `null` for an absent or `srgbClr` fill.
2588
- * {@link resolvedFill} is the literal it resolves to; this is the unresolved reference,
2589
- * which is what a replica should carry so the copy still tracks its theme.
2590
- */
2591
- get fillSchemeColor(): string | null;
2592
- /** Whether the first row is styled as a header (`a:tblPr/@firstRow`). */
2593
- get firstRowHeader(): boolean;
2594
- /** Whether rows are banded (`a:tblPr/@bandRow`). */
2595
- get bandedRows(): boolean;
2596
- /**
2597
- * The cell at `(rowIndex, columnIndex)` (both zero-based), or `null` when out
2598
- * of range. Column index counts `a:tc` elements in the row, so a cell that
2599
- * spans columns (`gridSpan`) occupies a single index here.
2600
- */
2601
- cell(rowIndex: number, columnIndex: number): TableCell | null;
2602
- /**
2603
- * Insert a row, defaulting to the bottom of the table. Returns the new {@link TableRow}.
2604
- *
2605
- * The new row is auto-height (`a:tr/@h="0"`) and its cells are empty. Inserting *through*
2606
- * a vertical merge extends that merge rather than interrupting it: the span's origin
2607
- * grows by a row and the new cell joins as a continuation, because an origin claiming
2608
- * more rows than it has continuations is a table PowerPoint reports as corrupt.
2609
- * @param {number} [index] - where to insert, `0`..`rowCount`; appended when omitted
2610
- * @throws {InvalidOptionError} when `index` is outside that range
2611
- */
2612
- addRow(index?: number): TableRow;
2613
- /**
2614
- * Remove the row at `index`, with its content.
2615
- *
2616
- * A cell in the row that *continues* a vertical merge shortens that merge. A cell that
2617
- * *starts* one hands the region to its first continuation, which becomes the new origin —
2618
- * the merged region survives one row shorter, and only the removed row's own text is lost.
2619
- * @throws {InvalidOptionError} when `index` is out of range
2620
- */
2621
- removeRow(index: number): void;
2622
- /**
2623
- * Insert a column, defaulting to the right-hand end. Updates `a:tblGrid` **and** every
2624
- * row, which is the pair that has to stay in step.
2625
- *
2626
- * The mirror of {@link addRow}'s merge case: inserting inside a horizontal merge widens
2627
- * it instead of splitting it.
2628
- * @param {number} [index] - where to insert, `0`..`columnCount`; appended when omitted
2629
- * @param {number} [widthEmu] - the new column's width; defaults to 1 inch
2630
- * @throws {InvalidOptionError} when `index` is outside that range
2631
- */
2632
- addColumn(index?: number, widthEmu?: number): void;
2633
- /**
2634
- * Remove the column at `index`, from `a:tblGrid` and from every row.
2635
- *
2636
- * Inside a horizontal merge the region narrows by one and keeps its content: a covered
2637
- * cell is dropped rather than the origin. Elsewhere the column's cells go with it.
2638
- * @throws {InvalidOptionError} when `index` is out of range
2639
- */
2640
- removeColumn(index: number): void;
2641
- /**
2642
- * Merge the rectangle between two cell positions into one cell. The top-left cell keeps
2643
- * its content; the rest become covered cells and are emptied, since a covered cell is
2644
- * never rendered.
2645
- *
2646
- * A rectangle that cuts through an existing merge is **rejected**, not silently widened
2647
- * to fit — the caller asked for a specific region, and quietly producing a different one
2648
- * is how a layout ends up wrong with nothing to point at. Unmerge first.
2649
- * @throws {InvalidOptionError} when an index is out of range, the range covers one cell,
2650
- * or it partially overlaps an existing merge
2651
- */
2652
- mergeCells(row1: number, col1: number, row2: number, col2: number): void;
2653
- /**
2654
- * Split the merged cell whose **origin** is `(row, col)` back into individual cells.
2655
- * A no-op on a cell that is not merged; addressing a covered cell instead of the origin
2656
- * throws, and the message names the origin to use.
2657
- * @throws {InvalidOptionError} when an index is out of range or the cell is a covered cell
2658
- */
2659
- unmergeCell(row: number, col: number): void;
2660
- /** Escape hatch: the underlying `a:tbl` element. After mutating it call {@link markDirty}, or `save()` writes the original bytes. */
2661
- get element_(): Element;
2662
- /** Mark the owning part dirty so `save()` reserializes it. Call after mutating {@link element_}. */
2663
- markDirty(): void;
2664
- }
2665
- /** One table row (`a:tr`). */
2666
- declare class TableRow {
2667
- private readonly tr;
2668
- private readonly part;
2669
- /** The owning slide's theme colour context, threaded to each {@link TableCell}. */
2670
- private readonly themeColors?;
2671
- /** The table's style-resolution context, threaded to each cell for {@link TableCell.resolvedFill}. */
2672
- private readonly style?;
2673
- /** This row's zero-based index in the table, for style-graph banding/edge conditions. */
2674
- private readonly rowIndex;
2675
- /** The owning slide's relationships, threaded to each cell for {@link TableCell.pictureFill}. */
2676
- private readonly rels?;
2677
- constructor(tr: Element, part: Part,
2678
- /** The owning slide's theme colour context, threaded to each {@link TableCell}. */
2679
- themeColors?: ThemeContext | undefined,
2680
- /** The table's style-resolution context, threaded to each cell for {@link TableCell.resolvedFill}. */
2681
- style?: TableCellStyleContext | null | undefined,
2682
- /** This row's zero-based index in the table, for style-graph banding/edge conditions. */
2683
- rowIndex?: number,
2684
- /** The owning slide's relationships, threaded to each cell for {@link TableCell.pictureFill}. */
2685
- rels?: Relationships | undefined);
2686
- /** The row's cells (`a:tc`) in left-to-right order. */
2687
- get cells(): TableCell[];
2688
- /** Row height in EMU (`a:tr/@h`), or `null` if unset. */
2689
- get heightEmu(): number | null;
2690
- /** Escape hatch: the underlying `a:tr` element. After mutating it call {@link markDirty}, or `save()` writes the original bytes. */
2691
- get element_(): Element;
2692
- /** Mark the owning part dirty so `save()` reserializes it. Call after mutating {@link element_}. */
2693
- markDirty(): void;
2694
- }
2695
2548
  /** One table cell (`a:tc`). */
2696
2549
  declare class TableCell {
2697
2550
  #private;
2698
2551
  private readonly tc;
2699
2552
  private readonly part;
2700
2553
  /** The owning slide's theme colour context, threaded to the cell's text for `Run.resolvedColor`. */
2701
- private readonly themeColors?;
2702
- /** The table's style-resolution context, for the {@link resolvedFill} style-graph fallback. */
2703
- private readonly style?;
2554
+ private readonly themeContext;
2555
+ /** The table's style-resolution context, for the {@link resolvedFill} style-graph fallback; `null` when no style resolves. */
2556
+ private readonly style;
2704
2557
  /** This cell's zero-based row index in the table. */
2705
2558
  private readonly rowIndex;
2706
2559
  /** This cell's zero-based column index in its row. */
2707
2560
  private readonly colIndex;
2708
2561
  /** The owning slide's relationships, for resolving {@link pictureFill}'s `r:embed` to a partname. */
2709
- private readonly rels?;
2562
+ private readonly rels;
2710
2563
  constructor(tc: Element, part: Part,
2711
2564
  /** The owning slide's theme colour context, threaded to the cell's text for `Run.resolvedColor`. */
2712
- themeColors?: ThemeContext | undefined,
2713
- /** The table's style-resolution context, for the {@link resolvedFill} style-graph fallback. */
2714
- style?: TableCellStyleContext | null | undefined,
2565
+ themeContext: ThemeContext,
2566
+ /** The table's style-resolution context, for the {@link resolvedFill} style-graph fallback; `null` when no style resolves. */
2567
+ style: TableCellStyleContext | null,
2715
2568
  /** This cell's zero-based row index in the table. */
2716
- rowIndex?: number,
2569
+ rowIndex: number,
2717
2570
  /** This cell's zero-based column index in its row. */
2718
- colIndex?: number,
2571
+ colIndex: number,
2719
2572
  /** The owning slide's relationships, for resolving {@link pictureFill}'s `r:embed` to a partname. */
2720
- rels?: Relationships | undefined);
2721
- /** The cell's text frame (`a:txBody`); `null` only if the cell has none (non-conformant). */
2573
+ rels: Relationships);
2574
+ /**
2575
+ * The cell's text frame (`a:txBody`); `null` only if the cell has none (non-conformant).
2576
+ *
2577
+ * A run that sets nothing of its own resolves the way PowerPoint paints it
2578
+ * (`test/read/fixtures/table-text-inheritance.pptx`). Its colour, face, bold and italic come
2579
+ * first from the table style's text style for the cell's region, and a colour or face no part
2580
+ * states is the theme's `tx1` and minor font, with no table style at all as much as with one.
2581
+ * Below that, the chain a text box's runs walk bottoms out in the slide master's
2582
+ * `p:otherStyle` rather than in `p:defaultTextStyle`, which cell text never reads. So size comes
2583
+ * from `p:otherStyle`, and so do bold and italic where the table style says nothing.
2584
+ */
2722
2585
  get textFrame(): TextFrame | null;
2723
2586
  /** The cell's text, paragraphs joined by `\n`. */
2724
2587
  get text(): string;
@@ -2808,7 +2671,7 @@ declare class TableCell {
2808
2671
  /**
2809
2672
  * The cell's solid fill resolved against the table's theme colour context to a
2810
2673
  * literal hex — the table-cell counterpart of
2811
- * {@link import('./shapes.js').AutoShape.resolvedFill}. The cell's own
2674
+ * {@link AutoShape.resolvedFill}. The cell's own
2812
2675
  * `a:tcPr/a:solidFill` wins; when the cell defines none, this falls back to the
2813
2676
  * table **style** graph (the `firstRow`/banded/`wholeTbl` shading the
2814
2677
  * `a:tableStyleId` supplies — see {@link Table.resolvedStyle}), so a styled cell
@@ -2818,9 +2681,9 @@ declare class TableCell {
2818
2681
  * A cell that carries *some other* fill choice (`a:blipFill`/`a:gradFill`/
2819
2682
  * `a:pattFill`/`a:noFill`) overrides the style graph in PowerPoint, so this
2820
2683
  * reports `null` for one rather than falling through to the inherited shading —
2821
- * the same guard {@link import('./shapes.js').AutoShape.resolvedFill} applies to
2684
+ * the same guard {@link AutoShape.resolvedFill} applies to
2822
2685
  * the style matrix. Read {@link pictureFill} for an image-filled cell. Also
2823
- * `null` with no theme context, or when neither source yields a solid colour (an
2686
+ * `null` when neither source yields a solid colour (an
2824
2687
  * unmapped token, an explicit style `a:noFill`). The returned
2825
2688
  * {@link ResolvedColor} carries `effectiveHex` (the base colour with its
2826
2689
  * `lumMod`/`lumOff`/… transforms applied) — read that for the final colour.
@@ -2841,13 +2704,13 @@ declare class TableCell {
2841
2704
  /**
2842
2705
  * `true` when the cell sets an explicit no-fill (`a:tcPr/a:noFill`) — a deliberately
2843
2706
  * transparent cell showing the table background (or the slide) through. The cell-side
2844
- * counterpart of {@link import('./shapes.js').AutoShape.fillNoFill}, and what
2707
+ * counterpart of {@link AutoShape.fillNoFill}, and what
2845
2708
  * {@link noFill} writes.
2846
2709
  *
2847
2710
  * {@link hasOwnFill} is not this question: it is `true` for *any* `EG_FillProperties`
2848
2711
  * child, so on its own it cannot separate a suppressed fill from a gradient or an image
2849
- * one — and every colour accessor ({@link resolvedFill}, {@link fillColor},
2850
- * {@link fillSchemeColor}) reports `null` for a no-fill cell exactly as it does for a
2712
+ * one — and every colour accessor ({@link resolvedFill}, {@link fillSchemeColor})
2713
+ * reports `null` for a no-fill cell exactly as it does for a
2851
2714
  * cell that inherits its shading from the table style. Deriving it as "has a fill of its
2852
2715
  * own, and no accessor recognises it" instead of reading it has two failure modes: it
2853
2716
  * folds `a:grpFill` in with `a:noFill`, and its meaning changes silently the day a
@@ -2859,7 +2722,7 @@ declare class TableCell {
2859
2722
  /**
2860
2723
  * The cell's picture (image) fill (`a:tcPr/a:blipFill`), or `null` when the cell
2861
2724
  * is not image-filled. The cell counterpart of
2862
- * {@link import('./shapes.js').AutoShape.pictureFill}: {@link resolvedFill}
2725
+ * {@link AutoShape.pictureFill}: {@link resolvedFill}
2863
2726
  * decodes only solid colours, so without this an image-filled cell is
2864
2727
  * indistinguishable from an empty one. Carries the embedded image
2865
2728
  * ({@link PictureFill.relId}/{@link PictureFill.partName}) plus the stretch/tile
@@ -2974,6 +2837,214 @@ declare class TableCell {
2974
2837
  markDirty(): void;
2975
2838
  }
2976
2839
  //#endregion
2840
+ //#region src/read/api/table-row.d.ts
2841
+ /** One table row (`a:tr`). */
2842
+ declare class TableRow {
2843
+ private readonly tr;
2844
+ private readonly part;
2845
+ /** The owning slide's theme colour context, threaded to each {@link TableCell}. */
2846
+ private readonly themeContext;
2847
+ /** The table's style-resolution context, threaded to each cell for {@link TableCell.resolvedFill}; `null` when no style resolves. */
2848
+ private readonly style;
2849
+ /** This row's zero-based index in the table, for style-graph banding/edge conditions. */
2850
+ private readonly rowIndex;
2851
+ /** The owning slide's relationships, threaded to each cell for {@link TableCell.pictureFill}. */
2852
+ private readonly rels;
2853
+ constructor(tr: Element, part: Part,
2854
+ /** The owning slide's theme colour context, threaded to each {@link TableCell}. */
2855
+ themeContext: ThemeContext,
2856
+ /** The table's style-resolution context, threaded to each cell for {@link TableCell.resolvedFill}; `null` when no style resolves. */
2857
+ style: TableCellStyleContext | null,
2858
+ /** This row's zero-based index in the table, for style-graph banding/edge conditions. */
2859
+ rowIndex: number,
2860
+ /** The owning slide's relationships, threaded to each cell for {@link TableCell.pictureFill}. */
2861
+ rels: Relationships);
2862
+ /** The row's cells (`a:tc`) in left-to-right order. */
2863
+ get cells(): TableCell[];
2864
+ /** Row height in EMU (`a:tr/@h`), or `null` if unset. */
2865
+ get heightEmu(): number | null;
2866
+ /** Escape hatch: the underlying `a:tr` element. After mutating it call {@link markDirty}, or `save()` writes the original bytes. */
2867
+ get element_(): Element;
2868
+ /** Mark the owning part dirty so `save()` reserializes it. Call after mutating {@link element_}. */
2869
+ markDirty(): void;
2870
+ }
2871
+ //#endregion
2872
+ //#region src/read/api/table.d.ts
2873
+ /** A table: a grid of rows and cells inside a graphic frame. */
2874
+ declare class Table {
2875
+ #private;
2876
+ private readonly tbl;
2877
+ private readonly part;
2878
+ /** The owning slide's theme colour context, threaded to each cell's text for `Run.resolvedColor`. */
2879
+ private readonly themeContext;
2880
+ /** The deck package, for resolving `a:tableStyleId` against `tableStyles.xml` (style-graph cell fills). */
2881
+ private readonly opc;
2882
+ /** The owning slide's relationships, for resolving a cell picture fill's `r:embed` to a partname. */
2883
+ private readonly rels;
2884
+ constructor(tbl: Element, part: Part,
2885
+ /** The owning slide's theme colour context, threaded to each cell's text for `Run.resolvedColor`. */
2886
+ themeContext: ThemeContext,
2887
+ /** The deck package, for resolving `a:tableStyleId` against `tableStyles.xml` (style-graph cell fills). */
2888
+ opc: OpcPackage,
2889
+ /** The owning slide's relationships, for resolving a cell picture fill's `r:embed` to a partname. */
2890
+ rels: Relationships);
2891
+ /** The table's rows (`a:tr`) in document (top-to-bottom) order. */
2892
+ get rows(): TableRow[];
2893
+ /**
2894
+ * The table's style graph entry (`styleId`, `name`, raw `a:tblStyle`) resolved
2895
+ * from the deck's `tableStyles.xml`, or `null` when the table names no
2896
+ * `a:tableStyleId`, the deck has no `tableStyles.xml`, or the id is a built-in
2897
+ * `[MS-OE376]` style the deck does not materialise. This is what supplies the
2898
+ * banded-row / header shading a cell with no own fill inherits — read the
2899
+ * resolved per-cell colour off {@link TableCell.resolvedFill}.
2900
+ *
2901
+ * Resolved afresh on every read, not through the per-instance memo the cells share, so an
2902
+ * edit made through the returned `element_` shows in the next read's `name`. A caller reads
2903
+ * this once per table; the memo exists for the per-cell path that reads it hundreds of times.
2904
+ */
2905
+ get resolvedStyle(): ResolvedTableStyle | null;
2906
+ /** Number of rows (`a:tr`). */
2907
+ get rowCount(): number;
2908
+ /** Number of grid columns (`a:tblGrid/a:gridCol`). */
2909
+ get columnCount(): number;
2910
+ /** Column widths in EMU (`a:gridCol/@w`), one per grid column. */
2911
+ get columnWidths(): (number | null)[];
2912
+ /**
2913
+ * The table's style GUID (`a:tblPr/a:tableStyleId` text), e.g.
2914
+ * `{5940675A-B579-460E-94D1-54222C63F5DA}`, or `null` when the table carries no
2915
+ * `a:tableStyleId`. This is the reference into `ppt/tableStyles.xml` (or a
2916
+ * built-in `[MS-OE376]` style) that supplies the banded-row / header shading the
2917
+ * `firstRow`/`bandRow` flags activate — without it a replica loses the whole
2918
+ * table style, so it is the read counterpart of the writer's `tableStyle` option.
2919
+ */
2920
+ get styleId(): string | null;
2921
+ /**
2922
+ * The table's own background (`a:tblPr` fill) resolved against the slide's theme colour
2923
+ * context to a literal hex, or `null` when the table carries no solid background.
2924
+ *
2925
+ * This is the table-level counterpart of {@link TableCell.resolvedFill}, and it is a
2926
+ * genuinely different thing from a cell fill: a `a:tblPr` fill sits *behind* the grid, so
2927
+ * a cell with no fill of its own shows it through. Reports `null` for a non-solid choice
2928
+ * (`a:blipFill`/`a:gradFill`/`a:pattFill`/`a:noFill`) — read {@link pictureFill} for an
2929
+ * image background.
2930
+ */
2931
+ get resolvedFill(): ResolvedColor | null;
2932
+ /**
2933
+ * The table's picture background (`a:tblPr/a:blipFill`), or `null` when the table is not
2934
+ * image-backed. The table-level twin of {@link TableCell.pictureFill}, and needed for the
2935
+ * same reason: {@link resolvedFill} decodes only solid colours, so without this an
2936
+ * image-backed table is indistinguishable from an unfilled one.
2937
+ */
2938
+ get pictureFill(): PictureFill | null;
2939
+ /**
2940
+ * The table's gradient background (`a:tblPr/a:gradFill`), or `null` when it is not
2941
+ * gradient-filled. Needed for the same reason {@link pictureFill} is:
2942
+ * {@link resolvedFill} decodes only solid colours.
2943
+ */
2944
+ get gradientFill(): GradientFill | null;
2945
+ /**
2946
+ * The table's pattern (hatch) background (`a:tblPr/a:pattFill`), or `null` when it is not
2947
+ * pattern-filled.
2948
+ */
2949
+ get patternFill(): PatternFill | null;
2950
+ /**
2951
+ * The raw `schemeClr` token of the table's own background
2952
+ * (`a:tblPr/a:solidFill/a:schemeClr/@val`), or `null` for an absent or `srgbClr` fill.
2953
+ * {@link resolvedFill} is the literal it resolves to; this is the unresolved reference,
2954
+ * which is what a replica should carry so the copy still tracks its theme.
2955
+ */
2956
+ get fillSchemeColor(): string | null;
2957
+ /**
2958
+ * Whether the first row is styled as a header (`a:tblPr/@firstRow`), which `addTable` writes
2959
+ * from `hasHeader`.
2960
+ *
2961
+ * This and the five below are PowerPoint's Table Style Options, the six flags that decide which
2962
+ * regions of the table style paint. Two of them were readable and four were not, although
2963
+ * {@link resolvedStyle} has always read all six to resolve a cell: `addTable` writes every one,
2964
+ * so a table read back and re-authored lost its footer row, its banded columns and its first
2965
+ * and last column emphasis with nothing to say so.
2966
+ */
2967
+ get firstRowHeader(): boolean;
2968
+ /** Whether the last row is styled as a footer (`a:tblPr/@lastRow`), from `addTable`'s `hasFooter`. */
2969
+ get lastRowFooter(): boolean;
2970
+ /** Whether rows are banded (`a:tblPr/@bandRow`), from `addTable`'s `hasBandedRows`. */
2971
+ get bandedRows(): boolean;
2972
+ /** Whether columns are banded (`a:tblPr/@bandCol`), from `addTable`'s `hasBandedColumns`. */
2973
+ get bandedColumns(): boolean;
2974
+ /** Whether the first column is emphasised (`a:tblPr/@firstCol`), from `addTable`'s `hasFirstColumn`. */
2975
+ get firstColumnHeader(): boolean;
2976
+ /** Whether the last column is emphasised (`a:tblPr/@lastCol`), from `addTable`'s `hasLastColumn`. */
2977
+ get lastColumnFooter(): boolean;
2978
+ /**
2979
+ * The cell at `(rowIndex, columnIndex)` (both zero-based), or `null` when out
2980
+ * of range. Column index counts `a:tc` elements in the row, so a cell that
2981
+ * spans columns (`gridSpan`) occupies a single index here.
2982
+ */
2983
+ cell(rowIndex: number, columnIndex: number): TableCell | null;
2984
+ /**
2985
+ * Insert a row, defaulting to the bottom of the table. Returns the new {@link TableRow}.
2986
+ *
2987
+ * The new row is auto-height (`a:tr/@h="0"`) and its cells are empty. Inserting *through*
2988
+ * a vertical merge extends that merge rather than interrupting it: the span's origin
2989
+ * grows by a row and the new cell joins as a continuation, because an origin claiming
2990
+ * more rows than it has continuations is a table PowerPoint reports as corrupt.
2991
+ * @param {number} [index] - where to insert, `0`..`rowCount`; appended when omitted
2992
+ * @throws {InvalidOptionError} when `index` is outside that range
2993
+ */
2994
+ addRow(index?: number): TableRow;
2995
+ /**
2996
+ * Remove the row at `index`, with its content.
2997
+ *
2998
+ * A cell in the row that *continues* a vertical merge shortens that merge. A cell that
2999
+ * *starts* one hands the region to its first continuation, which becomes the new origin —
3000
+ * the merged region survives one row shorter, and only the removed row's own text is lost.
3001
+ * @throws {InvalidOptionError} when `index` is out of range
3002
+ */
3003
+ removeRow(index: number): void;
3004
+ /**
3005
+ * Insert a column, defaulting to the right-hand end. Updates `a:tblGrid` **and** every
3006
+ * row, which is the pair that has to stay in step.
3007
+ *
3008
+ * The mirror of {@link addRow}'s merge case: inserting inside a horizontal merge widens
3009
+ * it instead of splitting it.
3010
+ * @param {number} [index] - where to insert, `0`..`columnCount`; appended when omitted
3011
+ * @param {number} [widthEmu] - the new column's width; defaults to 1 inch
3012
+ * @throws {InvalidOptionError} when `index` is outside that range
3013
+ */
3014
+ addColumn(index?: number, widthEmu?: number): void;
3015
+ /**
3016
+ * Remove the column at `index`, from `a:tblGrid` and from every row.
3017
+ *
3018
+ * Inside a horizontal merge the region narrows by one and keeps its content: a covered
3019
+ * cell is dropped rather than the origin. Elsewhere the column's cells go with it.
3020
+ * @throws {InvalidOptionError} when `index` is out of range
3021
+ */
3022
+ removeColumn(index: number): void;
3023
+ /**
3024
+ * Merge the rectangle between two cell positions into one cell. The top-left cell keeps
3025
+ * its content; the rest become covered cells and are emptied, since a covered cell is
3026
+ * never rendered.
3027
+ *
3028
+ * A rectangle that cuts through an existing merge is **rejected**, not silently widened
3029
+ * to fit — the caller asked for a specific region, and quietly producing a different one
3030
+ * is how a layout ends up wrong with nothing to point at. Unmerge first.
3031
+ * @throws {InvalidOptionError} when an index is out of range, the range covers one cell,
3032
+ * or it partially overlaps an existing merge
3033
+ */
3034
+ mergeCells(row1: number, col1: number, row2: number, col2: number): void;
3035
+ /**
3036
+ * Split the merged cell whose **origin** is `(row, col)` back into individual cells.
3037
+ * A no-op on a cell that is not merged; addressing a covered cell instead of the origin
3038
+ * throws, and the message names the origin to use.
3039
+ * @throws {InvalidOptionError} when an index is out of range or the cell is a covered cell
3040
+ */
3041
+ unmergeCell(row: number, col: number): void;
3042
+ /** Escape hatch: the underlying `a:tbl` element. After mutating it call {@link markDirty}, or `save()` writes the original bytes. */
3043
+ get element_(): Element;
3044
+ /** Mark the owning part dirty so `save()` reserializes it. Call after mutating {@link element_}. */
3045
+ markDirty(): void;
3046
+ }
3047
+ //#endregion
2977
3048
  //#region src/read/api/shapes/graphic-frame.d.ts
2978
3049
  /** A graphic frame (`p:graphicFrame`) — host for tables, charts and SmartArt diagrams. */
2979
3050
  declare class GraphicFrame extends Shape {
@@ -2981,14 +3052,20 @@ declare class GraphicFrame extends Shape {
2981
3052
  readonly shapeType: 'graphicFrame';
2982
3053
  protected xfrm(): Element | null;
2983
3054
  protected getOrAddXfrm(): Element;
2984
- protected getOrAddProperties(): ShapeProperties;
3055
+ protected paintSurface(): PaintSurface | null;
2985
3056
  /** Whether this frame hosts a table (`a:graphicData/@uri` is the table URI). */
2986
3057
  get hasTable(): boolean;
2987
3058
  /** Whether this frame hosts a classic chart (`a:graphicData/@uri` is the chart URI). */
2988
3059
  get hasChart(): boolean;
2989
- /** Whether this frame hosts a chartEx chart (`a:graphicData/@uri` is the chartEx URI). */
3060
+ /**
3061
+ * Whether this frame hosts a chartEx chart. Its `a:graphicData/@uri` is the `cx` namespace,
3062
+ * which the reference child (`cx:chart`) is also in.
3063
+ */
2990
3064
  get hasChartEx(): boolean;
2991
- /** Whether this frame hosts a SmartArt diagram (`a:graphicData/@uri` is the diagram URI). */
3065
+ /**
3066
+ * Whether this frame hosts a SmartArt diagram. Its `a:graphicData/@uri` is the `dgm`
3067
+ * namespace, and the payload under it is a `dgm:relIds` reference rather than the drawing.
3068
+ */
2992
3069
  get hasDiagram(): boolean;
2993
3070
  /**
2994
3071
  * The `a:graphicData/@uri` verbatim — the namespace naming what this frame hosts, or
@@ -3032,7 +3109,7 @@ declare class GroupShape extends Shape {
3032
3109
  protected xfrm(): Element | null;
3033
3110
  protected getOrAddXfrm(): Element;
3034
3111
  protected properties(): Element | null;
3035
- protected getOrAddProperties(): ShapeProperties;
3112
+ protected paintSurface(): PaintSurface | null;
3036
3113
  /**
3037
3114
  * The group's own child coordinate space (`p:grpSpPr/a:xfrm/a:chOff` and
3038
3115
  * `a:chExt`) in EMU, or `null` when the group has no transform or either
@@ -3122,7 +3199,12 @@ declare class Theme {
3122
3199
  * define reads `null`. Use {@link color} to look one slot up.
3123
3200
  */
3124
3201
  get colorScheme(): Record<ThemeColorSlot, string | null>;
3125
- /** The 6-hex RGB of one colour-scheme slot, or `null` when the theme does not define it. */
3202
+ /**
3203
+ * The 6-hex RGB of one colour-scheme slot, or `null` when the theme does not define it.
3204
+ *
3205
+ * Parsed once per proxy: the whole `a:clrScheme` is read to answer for one slot, and a
3206
+ * caller asking for several -- which is the normal way to ask -- re-read it each time.
3207
+ */
3126
3208
  color(slot: ThemeColorSlot): string | null;
3127
3209
  /** The theme's `a:fontScheme` (major/minor font families), or `null` when the theme declares none. */
3128
3210
  get fontScheme(): ThemeFontScheme | null;
@@ -3146,27 +3228,38 @@ declare class Theme {
3146
3228
  * *draw* it.
3147
3229
  */
3148
3230
  declare class Placeholder {
3149
- #private;
3150
3231
  /** The placeholder's `p:sp`. `protected` so {@link NotesPlaceholder} can read it. */
3151
3232
  protected readonly sp: Element;
3152
3233
  /** The part the `p:sp` lives in — a master, a layout, or a notes slide. */
3153
- protected readonly part: Part;
3154
- /** The owning part's theme context, threaded to {@link textFrame}. */
3155
- protected readonly themeContext: ThemeContext;
3156
- /** The owning part's relationships, threaded to {@link textFrame} for hyperlink resolution. */
3157
- protected readonly relationships: Relationships;
3234
+ protected readonly host: ShapeHost;
3235
+ /**
3236
+ * The same `p:sp` as an {@link AutoShape}. Identity, geometry and the text frame are
3237
+ * forwarded to it rather than re-derived here.
3238
+ *
3239
+ * They used to be re-derived, and the two answers had drifted apart. `#cNvPr()` hard-coded
3240
+ * `p:nvSpPr` where `nonVisualCNvPr` finds any `p:nv*Pr`; the four geometry getters read the
3241
+ * `p:spPr/a:xfrm` chain through a helper no other caller used, against `Shape`'s own
3242
+ * `xfrm()` + `emuFrom`; and,
3243
+ * the one that showed, the text frame was built with **no** inheritance context, so
3244
+ * `Run.resolvedSizePt`, `resolvedFontFace`, `resolvedColor` and `resolvedBold` resolved
3245
+ * through `SlideMaster.shapes` and came back `null` through `SlideMaster.placeholders` —
3246
+ * two views of one element disagreeing about the same run.
3247
+ */
3248
+ protected readonly shape: AutoShape;
3158
3249
  constructor(
3159
3250
  /** The placeholder's `p:sp`. `protected` so {@link NotesPlaceholder} can read it. */
3160
3251
  sp: Element,
3161
3252
  /** The part the `p:sp` lives in — a master, a layout, or a notes slide. */
3162
- part: Part,
3163
- /** The owning part's theme context, threaded to {@link textFrame}. */
3164
- themeContext: ThemeContext,
3165
- /** The owning part's relationships, threaded to {@link textFrame} for hyperlink resolution. */
3166
- relationships: Relationships);
3253
+ host: ShapeHost);
3167
3254
  /** Placeholder type (`p:ph/@type`: `title` | `body` | `sldNum` | …), or `null` when absent (a body placeholder). */
3168
3255
  get type(): string | null;
3169
- /** Placeholder index (`p:ph/@idx`), or `null` when unset. */
3256
+ /**
3257
+ * Placeholder index (`p:ph/@idx`), or `null` when unset.
3258
+ *
3259
+ * Not forwarded to {@link AutoShape.placeholder}, whose `idx` defaults to `'0'` the way
3260
+ * PowerPoint resolves it. Here the absence is the contract: this view reports what the
3261
+ * part says.
3262
+ */
3170
3263
  get idx(): string | null;
3171
3264
  /** Shape name (`p:cNvPr/@name`), or `''` when unnamed. */
3172
3265
  get name(): string;
@@ -3182,8 +3275,9 @@ declare class Placeholder {
3182
3275
  get height(): number | null;
3183
3276
  /**
3184
3277
  * The placeholder's text as a navigable {@link TextFrame} (`p:txBody`), or `null`
3185
- * when it carries no text body. Threaded with the owning master/layout theme
3186
- * context so a run's own `schemeClr` resolves through `Run.resolvedColor`.
3278
+ * when it carries no text body. Threaded with the owning tier's theme context and
3279
+ * placeholder identity, so a run's `resolved*` getters walk the same inheritance chain
3280
+ * they walk through {@link SlideMaster.shapes}.
3187
3281
  */
3188
3282
  get textFrame(): TextFrame | null;
3189
3283
  /** Escape hatch: the underlying `p:sp` element. After mutating it call {@link markDirty}, or `save()` writes the original bytes. */
@@ -3359,23 +3453,39 @@ declare class NotesPlaceholder extends Placeholder {
3359
3453
  }
3360
3454
  /**
3361
3455
  * A slide's speaker-notes slide (`notesSlideN.xml`) as a modeled object — the deep
3362
- * companion to {@link import('./slide.js').Slide.notesText}. Exposes the notes
3456
+ * companion to {@link Slide.notesText}. Exposes the notes
3363
3457
  * shape tree as {@link NotesPlaceholder}s ({@link body}/{@link slideImage}/
3364
3458
  * {@link slideNumber}) plus the body {@link textFrame} the older getters flatten.
3365
3459
  *
3366
3460
  * The theme context (notesMaster → `theme2.xml`) is resolved once and shared across
3367
3461
  * every placeholder's text frame.
3368
3462
  */
3369
- declare class NotesSlide {
3463
+ declare class NotesSlide implements ShapeHost {
3370
3464
  #private;
3371
- private readonly opc;
3465
+ /** The package the notes slide belongs to, for reaching the notesMaster and its theme. */
3466
+ readonly opc: OpcPackage;
3372
3467
  /** The notes slide's OPC part (`/ppt/notesSlides/notesSlideN.xml`). */
3373
3468
  readonly part: Part;
3374
- constructor(opc: OpcPackage,
3469
+ constructor(
3470
+ /** The package the notes slide belongs to, for reaching the notesMaster and its theme. */
3471
+ opc: OpcPackage,
3375
3472
  /** The notes slide's OPC part (`/ppt/notesSlides/notesSlideN.xml`). */
3376
3473
  part: Part);
3377
3474
  /** Partname of the notes slide part. */
3378
3475
  get partName(): string;
3476
+ /** The notes part's own relationships — a notes hyperlink resolves through these. */
3477
+ get relationships(): Relationships;
3478
+ /**
3479
+ * The notes shape tree as full shapes, in document order.
3480
+ *
3481
+ * A notes slide holds nothing but its three placeholders, so {@link placeholders} is the
3482
+ * view to read. This one exists because a notes slide is a {@link ShapeHost} — which is
3483
+ * what lets a {@link NotesPlaceholder} be the same {@link AutoShape} view of its `p:sp`
3484
+ * that a master or layout placeholder is, rather than a second reading of one.
3485
+ */
3486
+ get shapes(): AnyShape[];
3487
+ /** The shape anywhere in the notes tree with the given drawing id, or `undefined`. */
3488
+ shapeByIdDeep(id: number): AnyShape | undefined;
3379
3489
  /**
3380
3490
  * The notes theme context, resolved through the notesMaster → `theme2.xml` chain
3381
3491
  * and cached. Backs {@link NotesPlaceholder.textFrame}'s `Run.resolvedColor`.
@@ -3519,16 +3629,40 @@ interface TransitionSoundInfo {
3519
3629
  /** Display name on `p:snd @name`, or `null`. */
3520
3630
  name: string | null;
3521
3631
  }
3522
- /** Transition fields accepted by the {@link Slide.transition} setter. `speed` defaults are derived from `durationMs`. */
3632
+ /**
3633
+ * Transition fields accepted by the {@link Slide.transition} setter. A {@link TransitionInfo} read
3634
+ * from the same slide is a valid input, so `slide.transition = { ...slide.transition, speed: 'slow' }`
3635
+ * changes the speed and keeps everything else, the sound included.
3636
+ */
3523
3637
  interface TransitionInput {
3524
3638
  type: string;
3525
3639
  /** Namespace prefix for the type element; defaults to `p` (base ECMA-376). */
3526
3640
  namespace?: string;
3641
+ /**
3642
+ * Coarse speed bucket (`spd`). When omitted it is derived from `durationMs` if one is given, and
3643
+ * otherwise not written. A stated `fast`, the schema default, is not written when the slide's
3644
+ * transition had no `spd` either, so a transition read back and assigned again keeps its markup.
3645
+ */
3527
3646
  speed?: TransitionSpeed;
3647
+ /** Exact duration in milliseconds (`p14:dur`), a finite number from 0; `null` or omitted writes none. */
3528
3648
  durationMs?: number | null;
3529
3649
  advanceOnClick?: boolean;
3650
+ /** Auto-advance delay in milliseconds (`advTm`), a finite number from 0; `null` or omitted writes none. */
3530
3651
  advanceAfterMs?: number | null;
3531
3652
  variant?: Record<string, string>;
3653
+ /**
3654
+ * The transition sound (`p:sndAc`), in three states.
3655
+ *
3656
+ * - **omitted** keeps the sound the slide's transition already has;
3657
+ * - **`null`** removes it;
3658
+ * - **a value** is accepted only when it is that same sound, as a spread of the getter passes it.
3659
+ *
3660
+ * A different sound throws `transition/sound-unsupported`: a start sound names an embedded audio
3661
+ * part, which this setter does not add, so writing one would point the slide at a relationship it
3662
+ * may not have. Add a sound when authoring the deck (`slide.transition = { sound }` on the write
3663
+ * side) instead.
3664
+ */
3665
+ sound?: TransitionSoundInfo | null;
3532
3666
  }
3533
3667
  //#endregion
3534
3668
  //#region src/read/api/slide.d.ts
@@ -3657,12 +3791,17 @@ declare class Slide implements ShapeHost {
3657
3791
  * (a `p14` Choice carrying `p14:dur` plus a base `mc:Fallback`); otherwise the
3658
3792
  * bare `<p:transition>` is written. The node is inserted at its schema slot —
3659
3793
  * after `p:clrMapOvr`, before `p:timing`/`p:extLst`. Marks the slide part dirty.
3794
+ *
3795
+ * The new transition is built from the current one before that is removed: it keeps the sound
3796
+ * unless `sound` says otherwise (see {@link TransitionInput.sound}), and a value that is refused
3797
+ * (a `durationMs` or `advanceAfterMs` that is not a number of milliseconds from 0, or a sound
3798
+ * that is not the slide's own) leaves the slide as it was.
3660
3799
  */
3661
3800
  set transition(value: TransitionInput | null);
3662
3801
  /**
3663
3802
  * Whether the slide carries build animations (`p:timing` with a `<p:bldP>` or a
3664
3803
  * `presetID`-bearing time node). The animation tree itself is preserved opaquely;
3665
- * see {@link animationSpids}.
3804
+ * see `animationSpids`.
3666
3805
  */
3667
3806
  get hasAnimations(): boolean;
3668
3807
  /**
@@ -3786,7 +3925,7 @@ declare class Slide implements ShapeHost {
3786
3925
  * position (EMU), timestamp, and its author resolved through the deck-wide
3787
3926
  * {@link Presentation.commentAuthors} registry (`@authorId` → name/initials). These
3788
3927
  * are the comments the writer authors via `slide.addComment(...)`; the 2018 modern
3789
- * comment parts (`p188:cm`) are a separate schema, preserved but not decoded.
3928
+ * comment parts (`p188:cm`) are a separate schema, read by {@link modernComments}.
3790
3929
  */
3791
3930
  get comments(): Comment[];
3792
3931
  /**
@@ -3817,15 +3956,15 @@ declare class Slide implements ShapeHost {
3817
3956
  * Colour tokens resolve against this slide's theme; an image background's
3818
3957
  * `r:embed` resolves to an absolute part name through the *owning* part's
3819
3958
  * relationships (the layout's rels for a layout-inherited image, etc.). Solid,
3820
- * gradient, and image backgrounds are the three the writer authors and so
3821
- * round-trip faithfully; `pattern`/`themeRef` are read-only for imported decks.
3959
+ * gradient, pattern and image backgrounds are the ones the writer authors and so
3960
+ * round-trip faithfully; `themeRef` is read-only for imported decks.
3822
3961
  */
3823
3962
  get background(): SlideBackground | null;
3824
3963
  /**
3825
3964
  * The slide's own slide-number placeholder (`p:sp` with `p:ph type="sldNum"`,
3826
3965
  * carrying an `<a:fld type="slidenum">`), or `null` when the slide shows no slide
3827
- * number of its own. This is the concrete shape the writer emits for
3828
- * `pptx.setSlideNumber(...)` on a slide's layout; its geometry and run formatting
3966
+ * number of its own. This is the concrete shape the writer emits for a slide given
3967
+ * `slide.slideNumber`, or added to a master defined with `slideNumber`; its geometry and run formatting
3829
3968
  * read off the returned {@link AutoShape} the same as any placeholder.
3830
3969
  *
3831
3970
  * Scoped to the slide's *own* shape tree — a slide number inherited purely from
@@ -3843,7 +3982,7 @@ declare class Slide implements ShapeHost {
3843
3982
  *
3844
3983
  * Drawing ids are unique within a slide, so the first match is the only match; the
3845
3984
  * pre-order walk just fixes a deterministic order. This backs the connector-binding
3846
- * resolution ({@link import('./shapes.js').Connector.startConnection}), which must
3985
+ * resolution ({@link Connector.startConnection}), which must
3847
3986
  * resolve a binding into a group that top-level {@link shapeById} cannot see.
3848
3987
  */
3849
3988
  shapeByIdDeep(id: number): AnyShape | undefined;
@@ -3899,9 +4038,13 @@ declare class Slide implements ShapeHost {
3899
4038
  */
3900
4039
  shapeTree(): Element | null;
3901
4040
  /**
3902
- * @internal The smallest drawing id (`p:cNvPr/@id`) not already used on this
3903
- * slide. Exposed so `Presentation.importShape` can give a lifted shape (and its
3904
- * group children) collision-free ids on the host.
4041
+ * @internal One past the highest drawing id (`p:cNvPr/@id`) in use on this slide. Exposed so
4042
+ * `Presentation.importShape` can give a lifted shape (and its group children) collision-free
4043
+ * ids on the host.
4044
+ *
4045
+ * It does NOT fill gaps, and it does not reserve what it hands out: calling it twice without
4046
+ * appending in between returns the same id both times. A caller allocating several ids at
4047
+ * once counts up from one call rather than calling repeatedly.
3905
4048
  */
3906
4049
  nextShapeId(): number;
3907
4050
  }
@@ -3939,6 +4082,32 @@ interface CoreProperties {
3939
4082
  /** `cp:lastPrinted`, raw W3CDTF string. */
3940
4083
  lastPrinted?: string;
3941
4084
  }
4085
+ /**
4086
+ * Decoded `docProps/app.xml` — the *extended* properties, which are the producer's own
4087
+ * account of the deck rather than the author's metadata. Every field is optional (present
4088
+ * only when the element is).
4089
+ *
4090
+ * Deliberately a subset. `<Slides>`, `<Words>`, `<Paragraphs>` and the rest are statistics
4091
+ * the producing application computed for the file it wrote; reporting them from a read model
4092
+ * that can hand back an edited deck would be reporting a number about a document that no
4093
+ * longer exists. The four here identify the producer and name the deck's parts, which stay
4094
+ * true, and `company` is the one this library's write API can set.
4095
+ */
4096
+ interface ExtendedProperties {
4097
+ /** `<Application>` — the producing application, e.g. `Microsoft Office PowerPoint`. */
4098
+ application?: string;
4099
+ /** `<AppVersion>` — that application's version, in its own `major.minor` spelling (`16.0000`). */
4100
+ appVersion?: string;
4101
+ /** `<Company>` (the write-side `pptx.company`). */
4102
+ company?: string;
4103
+ /**
4104
+ * `<TitlesOfParts>` — the flat `vt:lpstr` vector naming the deck's fonts, themes and slide
4105
+ * titles in one list. It is the vector as written, NOT split by section: `<HeadingPairs>`
4106
+ * holds the counts that partition it, and this library does not read them, so the caller
4107
+ * that wants the slide titles alone has to pair the two itself.
4108
+ */
4109
+ titlesOfParts?: string[];
4110
+ }
3942
4111
  /** One user-defined custom document property (`docProps/custom.xml`). */
3943
4112
  interface CustomProperty {
3944
4113
  /** The property's `@name`. */
@@ -3953,6 +4122,17 @@ interface CustomProperty {
3953
4122
  * elements decode to the empty string.
3954
4123
  */
3955
4124
  declare function readCoreProperties(opc: OpcPackage): CoreProperties;
4125
+ /**
4126
+ * Read the deck's extended document properties from `/docProps/app.xml`, resolved
4127
+ * via the package-root `extended-properties` relationship (fallback: the part's
4128
+ * content type). Missing part → `{}` (all fields undefined). Present-but-empty
4129
+ * elements decode to the empty string.
4130
+ *
4131
+ * Children are matched by **local name**: the extended-properties namespace is not in the
4132
+ * read model's qname registry, and its elements are unprefixed there, so this reads them the
4133
+ * way {@link readCustomProperties} reads a `<property>`'s `vt:` child.
4134
+ */
4135
+ declare function readExtendedProperties(opc: OpcPackage): ExtendedProperties;
3956
4136
  /**
3957
4137
  * Read the deck's user-defined custom properties from `/docProps/custom.xml`,
3958
4138
  * resolved via the package-root `custom-properties` relationship (fallback: the
@@ -3966,6 +4146,134 @@ declare function readCoreProperties(opc: OpcPackage): CoreProperties;
3966
4146
  */
3967
4147
  declare function readCustomProperties(opc: OpcPackage): CustomProperty[];
3968
4148
  //#endregion
4149
+ //#region src/read/api/ops/deck-target.d.ts
4150
+ /** The destination deck: just the package and its main part. `Presentation` satisfies it. */
4151
+ interface DeckTarget {
4152
+ readonly opc: OpcPackage;
4153
+ readonly presentationPart: Part;
4154
+ }
4155
+ //#endregion
4156
+ //#region src/read/api/ops/part-copy.d.ts
4157
+ /**
4158
+ * One import in progress: where parts are going, where they are coming from, and
4159
+ * what has already come across.
4160
+ *
4161
+ * `source` and `registry` are one fact, not two — a registry maps partnames *of
4162
+ * that package*, so pairing it with any other package silently returns partnames
4163
+ * for parts that were never copied. Holding them in a single value makes the
4164
+ * pairing a type invariant rather than a call-site convention; mint one with
4165
+ * `Presentation`'s factory, which reads through to the per-source registry that
4166
+ * outlives any one call (see {@link copyPart}'s idempotence).
4167
+ */
4168
+ interface ImportContext {
4169
+ /** The deck being copied into. */
4170
+ readonly dest: DeckTarget;
4171
+ /** The package being copied out of. */
4172
+ readonly source: OpcPackage;
4173
+ /** Source partname → the partname allocated for it in `dest`. */
4174
+ readonly registry: Map<string, string>;
4175
+ /**
4176
+ * The pages this call is materializing, and where each is headed: source slide
4177
+ * partname → the destination partname pre-allocated for it. A page named here
4178
+ * gets its own part even when the registry already holds a copy of it, which is
4179
+ * what lets one source page be imported more than once.
4180
+ *
4181
+ * Both import entry points set it — {@link Presentation.importSlides} for the
4182
+ * whole batch, {@link copySlidePart} for the single page of one
4183
+ * {@link Presentation.importSlide}. For the batch it carries a second meaning:
4184
+ * `slide → slide` relationships resolve only within the set, so an imported page
4185
+ * may link to another *selected* page (rewritten to its fresh partname) but must
4186
+ * not drag an unselected source page across as a dependency.
4187
+ *
4188
+ * One destination per source page is deliberate: a page is a link target as well
4189
+ * as an output, and a map to *many* destinations would make every jump link
4190
+ * ambiguous. A batch asked for the same page N times therefore runs the
4191
+ * traversal N times, each round naming that page's Nth reserved partname and the
4192
+ * other pages' first — see `importSlides` step 3.
4193
+ */
4194
+ readonly selection?: SelectionPlan;
4195
+ /**
4196
+ * Set when the traversal is planning rather than copying: every write goes to the
4197
+ * plan instead of `dest`, and `registry` is the plan's own copy of the real one.
4198
+ */
4199
+ readonly plan?: CopyPlan;
4200
+ }
4201
+ /** Which pages of one source package an import is materializing, and where each is headed. */
4202
+ interface SelectionPlan {
4203
+ /** Source slide partname → the destination partname reserved for it. */
4204
+ readonly destinations: ReadonlyMap<string, string>;
4205
+ }
4206
+ /**
4207
+ * What a copy writes through: the destination package, or a {@link CopyPlan} standing in for it.
4208
+ * `OpcPackage` satisfies it.
4209
+ */
4210
+ interface CopyTarget {
4211
+ reservePartNameLike(templatePartName: string): string;
4212
+ part(partName: string): unknown;
4213
+ addPart(partName: string, contentType: string, bytes: Uint8Array): unknown;
4214
+ relationshipsFor(partName: string): Pick<Relationships, 'add' | 'addWithId'>;
4215
+ }
4216
+ /** One part a {@link CopyPlan} would add. */
4217
+ interface PlannedPart {
4218
+ readonly partName: string;
4219
+ readonly contentType: string;
4220
+ }
4221
+ /** One relationship a {@link CopyPlan} would add; `id` is absent where the copy allocates one. */
4222
+ interface PlannedRel {
4223
+ readonly from: string;
4224
+ readonly id?: string;
4225
+ readonly type: string;
4226
+ readonly target: string;
4227
+ readonly targetMode?: 'Internal' | 'External';
4228
+ }
4229
+ /**
4230
+ * An import's copy, run without writing: the parts and relationships it would add, and every error
4231
+ * it would throw, found before anything in the destination moves.
4232
+ *
4233
+ * This is what lets a refused import leave the deck byte-identical. The copy changes the deck as it
4234
+ * goes — parts added, a master registered in `presentation.xml`, a layout linked into its master —
4235
+ * so a failure it met halfway would leave all of that behind. An import therefore runs the same
4236
+ * traversal twice: first with a plan in its context, which throws what the copy would and writes
4237
+ * nothing, then for real. The dry run used to be a separate walk of the source, transcribed from the
4238
+ * copy under a comment asking readers to keep the two in step, and it had drifted: it walked a
4239
+ * rebinding import's source layout chain, which the rebind never reads, and every source's notes
4240
+ * master in a batch, where the copy reads only the first one it installs.
4241
+ *
4242
+ * A plan stands in for the destination package as a {@link CopyTarget}. It hands out the partnames
4243
+ * the copy will be given, keeps its own copy of each source's registry so a part it planned is found
4244
+ * again as the copy would find it, and remembers the notes master it would install in a deck that has
4245
+ * none. Destination bookkeeping that adds no part — registering a master, linking a layout into it —
4246
+ * is not recorded.
4247
+ */
4248
+ declare class CopyPlan implements CopyTarget {
4249
+ #private;
4250
+ readonly api: string;
4251
+ readonly linkable?: ReadonlySet<string> | undefined;
4252
+ /** The parts the copy would add, in the order it would add them. */
4253
+ readonly parts: PlannedPart[];
4254
+ /** The relationships the copy would add to the parts it copies. */
4255
+ readonly rels: PlannedRel[];
4256
+ /** The notes master the copy would install in a deck that has none; later notes bind to it. */
4257
+ notesMaster: string | undefined;
4258
+ /**
4259
+ * @param dest the deck the import copies into
4260
+ * @param api the public method planning, which opens every error the plan throws
4261
+ * @param linkable the pages a jump link may land on when the traversal has no selection of its
4262
+ * own: the page a rebinding import builds itself
4263
+ */
4264
+ constructor(dest: DeckTarget, api: string, linkable?: ReadonlySet<string> | undefined);
4265
+ /** This plan's context for an import out of `ctx.source`, over the plan's copy of its registry. */
4266
+ contextFor(ctx: ImportContext): ImportContext;
4267
+ reservePartNameLike(templatePartName: string): string;
4268
+ part(partName: string): unknown;
4269
+ addPart(partName: string, contentType: string): void;
4270
+ relationshipsFor(from: string): Pick<Relationships, 'add' | 'addWithId'>;
4271
+ }
4272
+ //#endregion
4273
+ //#region src/read/api/ops/rescale.d.ts
4274
+ /** How an import's rescale maps the source canvas onto the destination's. */
4275
+ type RescaleMode = 'fit' | 'stretch';
4276
+ //#endregion
3969
4277
  //#region src/read/api/presentation.d.ts
3970
4278
  declare class Presentation {
3971
4279
  #private;
@@ -4020,7 +4328,8 @@ declare class Presentation {
4020
4328
  * The deck-wide **legacy** comment-author registry (`p:cmAuthorLst` in
4021
4329
  * `ppt/commentAuthors.xml`), `[]` when the deck has no comments. Each slide's
4022
4330
  * {@link Slide.comments} resolves its `@authorId` against this list. The 2018
4023
- * modern comment authors (`ppt/authors.xml`) are a separate part, not decoded here.
4331
+ * modern comment authors (`ppt/authors.xml`) are a separate part, read by
4332
+ * {@link modernCommentAuthors}.
4024
4333
  */
4025
4334
  get commentAuthors(): CommentAuthor[];
4026
4335
  /**
@@ -4048,6 +4357,17 @@ declare class Presentation {
4048
4357
  * (→ `creator`)/`revision` setters.
4049
4358
  */
4050
4359
  get coreProperties(): CoreProperties;
4360
+ /**
4361
+ * The deck's extended document properties (`docProps/app.xml`): the producing
4362
+ * application and its version, the company, and the flat `TitlesOfParts` vector.
4363
+ * `{}` when the deck carries no extended-properties part. The read counterpart of
4364
+ * the write-side `pptx.company` setter — the only one of the four this library
4365
+ * writes from a caller's value; the other three it states about itself.
4366
+ *
4367
+ * A deliberate subset of the part: see {@link ExtendedProperties} for why the
4368
+ * statistics (`Slides`, `Words`, `Paragraphs`, …) are not reported.
4369
+ */
4370
+ get appProperties(): ExtendedProperties;
4051
4371
  /**
4052
4372
  * The deck's user-defined custom document properties (`docProps/custom.xml`) as
4053
4373
  * `{ name, value }` pairs, each value typed from its `vt:` element (string,
@@ -4089,7 +4409,9 @@ declare class Presentation {
4089
4409
  * (its notes slide, slide-only media, charts/embeddings) that no remaining part
4090
4410
  * references is pruned too — recursively. Shared deck chrome (layout, master,
4091
4411
  * theme, …) is never pruned, so the deck stays renderable; removing every slide
4092
- * leaves a valid master/layout-only package (a template shell).
4412
+ * leaves a valid master/layout-only package (a template shell). The slide also
4413
+ * leaves every custom show and section it was in, which stay even when that
4414
+ * empties them, as PowerPoint leaves them.
4093
4415
  *
4094
4416
  * Untouched parts stay byte-identical, matching the package fidelity contract.
4095
4417
  * Throws when there is no slide at `index`.
@@ -4120,10 +4442,15 @@ declare class Presentation {
4120
4442
  * master/layout with its theme references left symbolic, so it re-brands to the
4121
4443
  * destination palette — see {@link ImportSlideOptions}.
4122
4444
  *
4123
- * v1 limitations: by default the source slide size must equal this
4124
- * presentation's — pass `{ rescale: 'fit' | 'stretch' }` to rescale the imported
4125
- * geometry onto this deck's canvas instead (geometry only, not fonts/line
4126
- * widths). Source notes are dropped unless you pass `{ importNotes: true }`.
4445
+ * By default the source slide size must equal this presentation's. Pass
4446
+ * `{ rescale: 'fit' | 'stretch' }` to rescale the imported geometry onto this
4447
+ * deck's canvas instead (geometry only, not fonts or line widths). Source notes
4448
+ * are dropped unless you pass `{ importNotes: true }`.
4449
+ *
4450
+ * A jump link on the page must land on a page an earlier import from the same source already
4451
+ * brought across, the rule {@link importSlides} applies to a batch: a link to any other page
4452
+ * throws `import/unresolved-slide-link`. Like that check, a missing or unparseable source part
4453
+ * is found before anything is copied, so a refused import leaves this deck unchanged.
4127
4454
  */
4128
4455
  importSlide(source: Presentation, index: number, options?: ImportSlideOptions): Slide;
4129
4456
  /**
@@ -4166,11 +4493,21 @@ declare class Presentation {
4166
4493
  * several requests gets its own copy of its notes each time, as of everything
4167
4494
  * else that page owns.
4168
4495
  *
4496
+ * `embedFonts` and `rescale` travel per request as well, and both are whole-deck
4497
+ * decisions wearing a per-page spelling, so the batch reconciles them before it
4498
+ * moves anything. A source deck's embedded fonts are carried once when *any* of
4499
+ * its requests asks for them (the list does not record which page uses which
4500
+ * face, so there is nothing finer to carry), and the font parts are part of the
4501
+ * up-front dry run like everything else. `rescale` must **agree** across every
4502
+ * request naming one source: a `'copy'` import rescales the imported layout and
4503
+ * master alongside the page, and those are shared, so a batch that rescaled one
4504
+ * page of a source and not another would leave the second bound to a rescaled
4505
+ * master. Disagreement is `import/rescale-conflict` rather than a silent pick.
4506
+ *
4169
4507
  * Scope: pages come across under `'copy'` theme semantics (their own layout →
4170
- * master → theme subgraph, shared parts deduped via the copy registry).
4171
- * Embedded fonts are not carried, and sizes must match, since there is no batch
4172
- * spelling for `embedFonts` or `rescale`. Use {@link importSlide} when you need
4173
- * either of those.
4508
+ * master → theme subgraph, shared parts deduped via the copy registry). There is
4509
+ * still no batch spelling for `theme`, `carryMasterGraphics` or `remapLiterals`;
4510
+ * use {@link importSlide} when you need one of those.
4174
4511
  */
4175
4512
  importSlides(requests: readonly ImportSlidesRequest[]): Slide[];
4176
4513
  /**
@@ -4200,8 +4537,9 @@ declare class Presentation {
4200
4537
  * `options.embedFonts` and table styles via `options.tableStyles`. By default a
4201
4538
  * grafted master is appended after the deck's existing masters; `options.primary`
4202
4539
  * moves the grafted masters to the front so the deck presents as their theme (see
4203
- * {@link ImportSlideMastersOptions}). The v1 limitation mirroring
4204
- * {@link importSlide} is that geometry is not rescaled.
4540
+ * {@link ImportSlideMastersOptions}). Geometry is never rescaled: unlike
4541
+ * {@link importSlide}, {@link importSlides} and {@link importShape}, this method
4542
+ * takes no `rescale` option.
4205
4543
  */
4206
4544
  importSlideMasters(source: Presentation, options?: ImportSlideMastersOptions): ImportedSlideMaster[];
4207
4545
  /**
@@ -4299,6 +4637,28 @@ declare class Presentation {
4299
4637
  * relationship. Returns the new {@link Shape}s in `shapeIndices` order.
4300
4638
  */
4301
4639
  importShapes(target: Slide, source: Slide, shapeIndices: number[], options?: ImportShapeOptions): AnyShape[];
4640
+ /**
4641
+ * @internal Wire a new slide part into `p:sldIdLst` at position `at`, as the private
4642
+ * method below does. Exposed for `presentation-imports.ts`; this one stays because
4643
+ * {@link cloneSlide} and {@link appendSlides} wire their slides in through it too.
4644
+ */
4645
+ insertSlidePart(newPart: Part, at?: number): Slide;
4646
+ /**
4647
+ * @internal The parts whose geometry a rescale has already rewritten, and in which mode.
4648
+ * Exposed for `presentation-imports.ts` as a live map the callee adds to — the memo is what
4649
+ * makes a layout or master shared across repeated imports from one source scale exactly
4650
+ * once, so like the copy registry it has to outlive the call that fills it.
4651
+ */
4652
+ get rescaledParts(): Map<string, RescaleMode>;
4653
+ /**
4654
+ * @internal Open an import out of `source`: this deck as the destination, paired with
4655
+ * the copy registry for that package (created on first use). The registry is held on
4656
+ * the class rather than in the context because it must outlive any one call — that is
4657
+ * what makes a second import from the same source reuse the layout, master, theme, and
4658
+ * media it already copied instead of duplicating them, and it is why the import bodies
4659
+ * in `presentation-imports.ts` call back here rather than carrying it with them.
4660
+ */
4661
+ importContext(source: OpcPackage): ImportContext;
4302
4662
  /** Re-emit the package; untouched parts stay byte-identical (see `OpcPackage.save`). */
4303
4663
  save(): Promise<Uint8Array>;
4304
4664
  }
@@ -4856,6 +5216,33 @@ interface ImportSlidesRequest {
4856
5216
  * has none, exactly as `importSlide` and `appendSlides` do.
4857
5217
  */
4858
5218
  importNotes?: boolean;
5219
+ /**
5220
+ * Carry this request's *source deck's* embedded fonts across, as
5221
+ * `importSlide`'s {@link ImportSlideOptions.embedFonts} does. Default false.
5222
+ *
5223
+ * Spelled per request for symmetry with the rest, but the carry itself is a
5224
+ * whole-deck operation: `p:embeddedFontLst` does not record which page uses
5225
+ * which face, so a source deck whose requests include even one `embedFonts`
5226
+ * carries **all** of its faces, once. Merging into this deck de-dupes by
5227
+ * typeface and face slot, so several sources embedding the same family
5228
+ * contribute it once.
5229
+ */
5230
+ embedFonts?: boolean;
5231
+ /**
5232
+ * Rescale this page's geometry onto this deck's canvas when the source deck's
5233
+ * slide size differs, as `importSlide`'s {@link ImportSlideOptions.rescale}
5234
+ * does (`'fit'`/`true` preserves aspect ratio and centres; `'stretch'` fills).
5235
+ * Default false, which keeps the batch's requirement that the sizes match.
5236
+ *
5237
+ * **Every request naming one source must give the same value.** A batch import
5238
+ * uses `'copy'` theme semantics, so a rescale rewrites the imported layout and
5239
+ * master shape trees as well as the page's, and those are shared between that
5240
+ * source's pages: rescaling one page and not another would leave the second
5241
+ * aligned against a master that had moved under it. A batch that disagrees is
5242
+ * refused with `import/rescale-conflict` before anything is copied. Different
5243
+ * sources are independent and may each choose.
5244
+ */
5245
+ rescale?: boolean | 'fit' | 'stretch';
4859
5246
  }
4860
5247
  /** Options for {@link Presentation.fromTemplate}. */
4861
5248
  interface FromTemplateOptions {
@@ -4868,5 +5255,5 @@ interface FromTemplateOptions {
4868
5255
  keepTemplateContentType?: boolean;
4869
5256
  }
4870
5257
  //#endregion
4871
- export { TableCell as $, ShapeType as $t, CommentSchema as A, AutofitMode as At, ThemeFontScheme as B, ChildFrame as Bt, TransitionInfo as C, ChartLine as Ct, readTagsForPart as D, AutoShape as Dt, Tag as E, Picture as Et, Placeholder as F, Paragraph as Ft, isGraphicFrame as G, Glow as Gt, GroupShape as H, CustomGeometry as Ht, SlideLayout as I, Run as It, GraphicFrame as J, LineEnds as Jt, isGroupShape as K, InnerShadow as Kt, SlideMaster as L, RunHyperlink as Lt, ModernCommentAuthor as M, BulletDetail as Mt, NotesPlaceholder as N, BulletStyle as Nt, Comment as O, Shape as Ot, NotesSlide as P, LineSpacing as Pt, Table as Q, Reflection as Qt, Theme as R, TextFrame as Rt, Slide as S, ChartLegend as St, TransitionSpeed as T, Connector as Tt, isAutoShape as U, CustomGeometryPath as Ut, AnyShape as V, ConnectionSite as Vt, isConnector as W, GeometryCommand as Wt, CellBorders as X, Recolor as Xt, CellBorder as Y, OuterShadow as Yt, CellThreeD as Z, RecolorColor as Zt, CustomProperty as _, AxisNumberFormat as _t, ExtractedSlides as a, FillRect as an, Diagram as at, AddPictureOptions as b, ChartDataLabels as bt, ImportSlideMastersOptions as c, GradientFill as cn, DiagramDrawnShape as ct, ImportedSlideMaster as d, resolveColorElement as dn, DiagramPointType as dt, SoftEdge as en, TableCellBorderEdit as et, LayoutHandle as f, ColorTransform as fn, ChartEx as ft, CoreProperties as g, EmbeddedFontSlot as gn, ChartExSeries as gt, Presentation as h, ColorContext as hn, ChartExLegend as ht, ExtractedSlide as i, SlideBackground as in, TableCellEdge as it, ModernComment as j, BodyProperties as jt, CommentAuthor as k, ShapeHost as kt, ImportSlideOptions as l, GradientStop as ln, DiagramNode as lt, SlideSource as m, applyColorTransforms as mn, ChartExDataLabels as mt, EmbeddedFontFaceInfo as n, BackgroundFill as nn, ResolvedTableStyle as nt, FromTemplateOptions as o, PictureFill as on, DiagramConnection as ot, SlideSize as p, EffectiveColor as pn, ChartExAxis as pt, isPicture as q, LineEnd as qt, EmbeddedFontInfo as r, BackgroundSource as rn, TableConditionFlags as rt, ImportShapeOptions as s, PictureFillTile as sn, DiagramConnectionType as st, AppendSlidesOptions as t, PatternFill as tn, TableRow as tt, ImportSlidesRequest as u, ResolvedColor as un, DiagramPoint as ut, readCoreProperties as v, Chart as vt, TransitionInput as w, ChartSeries as wt, AddTextBoxOptions as x, ChartFill as xt, readCustomProperties as y, ChartAxis as yt, ThemeFontFace as z, AbsoluteFrame as zt };
4872
- //# sourceMappingURL=presentation-types-CDjScsev.d.ts.map
5258
+ export { isGroupShape as $, ConnectionSite as $t, TransitionInput as A, EffectiveColor as An, Connector as At, NotesPlaceholder as B, BulletStyle as Bt, readCoreProperties as C, PlaceholderRef as Cn, Chart as Ct, AddTextBoxOptions as D, readColorRef as Dn, ChartLegend as Dt, AddPictureOptions as E, StyleFontRef as En, ChartFill as Et, Comment as F, AutofitMode as Ft, Theme as G, TextInheritance as Gt, Placeholder as H, LineSpacing as Ht, CommentAuthor as I, BodyProperties as It, AnyShape as J, TableConditionFlags as Jt, ThemeFontFace as K, ResolvedTableStyle as Kt, CommentSchema as L, TextFrame as Lt, TransitionSpeed as M, ColorContext as Mn, AutoShape as Mt, Tag as N, ThemeContext as Nn, Shape as Nt, Slide as O, resolveColorElement as On, ChartLine as Ot, readTagsForPart as P, ShapeHost as Pt, isGraphicFrame as Q, ChildFrame as Qt, ModernComment as R, Paragraph as Rt, ExtendedProperties as S, GeometrySource as Sn, AxisNumberFormat as St, readExtendedProperties as T, ResolvedFrame as Tn, ChartDataLabels as Tt, SlideLayout as U, Run as Ut, NotesSlide as V, InheritedRunProps as Vt, SlideMaster as W, TextContext as Wt, isAutoShape as X, AbsoluteFrame as Xt, GroupShape as Y, Hyperlink as Yt, isConnector as Z, AbsoluteFrameFailure as Zt, SlideSize as _, PictureFill as _n, ChartEx as _t, ExtractedChart as a, LineEnd as an, CellBorders as at, CoreProperties as b, GradientStop as bn, ChartExLegend as bt, ExtractedSlides as c, Recolor as cn, TableCellBorderEdit as ct, ImportSlideMastersOptions as d, SoftEdge as dn, DiagramConnection as dt, CustomGeometry as en, isPicture as et, ImportSlideOptions as f, BackgroundFill as fn, DiagramConnectionType as ft, OnlineMediaItem as g, FillRect as gn, DiagramPointType as gt, LayoutHandle as h, PatternFill as hn, DiagramPoint as ht, EmbeddedFontInfo as i, InnerShadow as in, CellBorder as it, TransitionSoundInfo as j, applyColorTransforms as jn, Picture as jt, TransitionInfo as k, ColorTransform as kn, ChartSeries as kt, FromTemplateOptions as l, Reflection as ln, TableCellEdge as lt, ImportedSlideMaster as m, SlideBackground as mn, DiagramNode as mt, AvMediaItem as n, GeometryCommand as nn, Table as nt, ExtractedNotes as o, LineEnds as on, CellThreeD as ot, ImportSlidesRequest as p, BackgroundSource as pn, DiagramDrawnShape as pt, ThemeFontScheme as q, TableCellTextStyle as qt, EmbeddedFontFaceInfo as r, Glow as rn, TableRow as rt, ExtractedSlide as s, OuterShadow as sn, TableCell as st, AppendSlidesOptions as t, CustomGeometryPath as tn, GraphicFrame as tt, ImportShapeOptions as u, ShapeType as un, Diagram as ut, SlideSource as v, PictureFillTile as vn, ChartExAxis as vt, readCustomProperties as w, ResolvedColor as wn, ChartAxis as wt, CustomProperty as x, ColorRef as xn, ChartExSeries as xt, Presentation as y, GradientFill as yn, ChartExDataLabels as yt, ModernCommentAuthor as z, BulletDetail as zt };
5259
+ //# sourceMappingURL=presentation-types-8jLQHI4M.d.ts.map