reamkit 1.21.0 → 1.23.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 (90) hide show
  1. package/dist/esm/core/bytes.d.ts +22 -4
  2. package/dist/esm/core/bytes.js +73 -5
  3. package/dist/esm/core/converter/ream.d.ts +16 -0
  4. package/dist/esm/core/converter/ream.js +59 -9
  5. package/dist/esm/core/document-model/types.d.ts +78 -0
  6. package/dist/esm/core/drawingml/chart-geometry.js +11 -5
  7. package/dist/esm/core/drawingml/chart-parser.d.ts +2 -1
  8. package/dist/esm/core/drawingml/chart-parser.js +23 -1
  9. package/dist/esm/core/drawingml/colors.d.ts +30 -4
  10. package/dist/esm/core/drawingml/colors.js +45 -6
  11. package/dist/esm/core/drawingml/preset-geometry.js +236 -0
  12. package/dist/esm/core/drawingml/theme-parser.d.ts +38 -0
  13. package/dist/esm/core/drawingml/theme-parser.js +64 -1
  14. package/dist/esm/core/fonts/families.d.ts +10 -0
  15. package/dist/esm/core/fonts/families.js +44 -0
  16. package/dist/esm/core/fonts/index.d.ts +3 -2
  17. package/dist/esm/core/fonts/remote-fonts.d.ts +50 -0
  18. package/dist/esm/core/fonts/remote-fonts.js +114 -8
  19. package/dist/esm/core/fonts/scripts.d.ts +26 -0
  20. package/dist/esm/core/fonts/scripts.js +177 -0
  21. package/dist/esm/core/metafile/blit.d.ts +33 -0
  22. package/dist/esm/core/metafile/blit.js +67 -0
  23. package/dist/esm/core/metafile/dib.d.ts +61 -0
  24. package/dist/esm/core/metafile/dib.js +205 -0
  25. package/dist/esm/core/metafile/emf.js +139 -24
  26. package/dist/esm/core/metafile/picture.d.ts +12 -1
  27. package/dist/esm/core/metafile/symbol-fonts.d.ts +42 -0
  28. package/dist/esm/core/metafile/symbol-fonts.js +154 -0
  29. package/dist/esm/core/metafile/wmf.js +183 -10
  30. package/dist/esm/core/ole/escher-blip.d.ts +12 -0
  31. package/dist/esm/core/ole/escher-blip.js +88 -0
  32. package/dist/esm/{pdf-reader → core}/png-encode.js +1 -1
  33. package/dist/esm/core/vector.d.ts +5 -0
  34. package/dist/esm/excel/print-model.js +3 -1
  35. package/dist/esm/excel/sheet-shape-parser.js +1 -12
  36. package/dist/esm/excel/styles-parser.js +1 -1
  37. package/dist/esm/excel/xls/biff-reader.js +53 -18
  38. package/dist/esm/excel/xls/biff-styles.d.ts +5 -2
  39. package/dist/esm/excel/xls/biff-styles.js +9 -7
  40. package/dist/esm/excel/xls/escher.js +90 -24
  41. package/dist/esm/excel/xlsx-reader.d.ts +1 -1
  42. package/dist/esm/excel/xlsx-reader.js +3 -3
  43. package/dist/esm/layout/page-doc.d.ts +77 -0
  44. package/dist/esm/layout/page-doc.js +34 -18
  45. package/dist/esm/layout/styled-layout.d.ts +2 -2
  46. package/dist/esm/layout/styled-layout.js +467 -76
  47. package/dist/esm/pdf/shading.d.ts +19 -0
  48. package/dist/esm/pdf/shading.js +84 -11
  49. package/dist/esm/pdf/styled-page-emitter.js +647 -444
  50. package/dist/esm/pdf-reader/image-decode.js +1 -1
  51. package/dist/esm/pptx/embedded-fonts.d.ts +31 -0
  52. package/dist/esm/pptx/embedded-fonts.js +104 -0
  53. package/dist/esm/pptx/ole-preview.d.ts +10 -0
  54. package/dist/esm/pptx/ole-preview.js +52 -0
  55. package/dist/esm/pptx/placeholder-cascade.d.ts +136 -5
  56. package/dist/esm/pptx/placeholder-cascade.js +260 -27
  57. package/dist/esm/pptx/ppt/ppt-reader.js +120 -10
  58. package/dist/esm/pptx/ppt/ppt-text.d.ts +66 -1
  59. package/dist/esm/pptx/ppt/ppt-text.js +576 -137
  60. package/dist/esm/pptx/pptx-reader.d.ts +8 -0
  61. package/dist/esm/pptx/pptx-reader.js +271 -41
  62. package/dist/esm/pptx/preset-table-styles.d.ts +9 -0
  63. package/dist/esm/pptx/preset-table-styles.js +27 -0
  64. package/dist/esm/pptx/slide-parser.d.ts +78 -10
  65. package/dist/esm/pptx/slide-parser.js +396 -95
  66. package/dist/esm/pptx/sp-helpers.d.ts +2 -1
  67. package/dist/esm/pptx/sp-helpers.js +22 -6
  68. package/dist/esm/pptx/table-style.d.ts +64 -0
  69. package/dist/esm/pptx/table-style.js +203 -0
  70. package/dist/esm/svg/svg-writer.js +53 -5
  71. package/dist/esm/word/document-parser.d.ts +7 -1
  72. package/dist/esm/word/document-parser.js +6 -6
  73. package/dist/esm/word/docx-reader.js +8 -5
  74. package/dist/esm/word/docx-to-pdf.d.ts +8 -7
  75. package/dist/esm/word/docx-to-pdf.js +25 -7
  76. package/dist/esm/word/drawing-parser.d.ts +34 -0
  77. package/dist/esm/word/drawing-parser.js +173 -15
  78. package/dist/esm/word/numbering-parser.d.ts +2 -1
  79. package/dist/esm/word/numbering-parser.js +6 -6
  80. package/dist/esm/word/paragraph-properties.d.ts +2 -1
  81. package/dist/esm/word/paragraph-properties.js +2 -2
  82. package/dist/esm/word/run-properties.d.ts +5 -2
  83. package/dist/esm/word/run-properties.js +13 -8
  84. package/dist/esm/word/styles-parser.d.ts +2 -1
  85. package/dist/esm/word/styles-parser.js +12 -12
  86. package/dist/esm/word/table-parser.js +3 -3
  87. package/dist/esm/word/theme-fonts.d.ts +10 -0
  88. package/dist/esm/word/theme-fonts.js +28 -0
  89. package/package.json +1 -1
  90. /package/dist/esm/{pdf-reader → core}/png-encode.d.ts +0 -0
@@ -17,6 +17,14 @@ export declare function readPptx(bytes: Uint8Array): ReadResult<FlowDoc>;
17
17
  * Parse an OOXML part's bytes into preserve-order {@link PoNode} roots with the
18
18
  * module's shared, presentation-tuned {@link XMLParser} (attributes kept, values
19
19
  * not coerced, whitespace preserved). Shared with the slide-style resolvers.
20
+ *
21
+ * ISO/IEC 29500-3 §10.2 — `mc:AlternateContent` is resolved first, to the
22
+ * `mc:Fallback` a reader takes when it implements none of the namespaces the
23
+ * choices require. A deck writes the same shape twice this way, and reading the
24
+ * CHOICE means reading markup written for someone else: tdf143222's whole slide
25
+ * is an embedded worksheet whose preview picture lives in the fallback alone,
26
+ * and the choice — written for VML — carries no picture at all, so the slide
27
+ * came out blank. 82 of the corpus's decks carry such a block.
20
28
  */
21
29
  export declare function parseXml(data: Uint8Array): Array<PoNode>;
22
30
  /**
@@ -4,20 +4,25 @@ import { FEATURES } from "../core/ir/features.js";
4
4
  import { EMPTY_STYLE_SHEET, resolveBodyStyles } from "../core/style-cascade/resolver.js";
5
5
  import "../core/style-cascade/index.js";
6
6
  import { poAttr, poChildren, poFindDescendant, poIntAttr, poIs } from "../core/po-helpers.js";
7
- import { bytesIncludePartName } from "../core/bytes.js";
8
- import { DEFAULT_THEME_PALETTE, defaultColorResolver, makeColorResolver } from "../core/drawingml/colors.js";
7
+ import { packageHasPart } from "../core/bytes.js";
8
+ import { DEFAULT_SCHEME_ALIAS, DEFAULT_THEME_PALETTE, defaultColorResolver, makeColorResolver } from "../core/drawingml/colors.js";
9
9
  import { parseChart, withChartColorStyle } from "../core/drawingml/chart-parser.js";
10
- import { parseTheme } from "../core/drawingml/theme-parser.js";
10
+ import { parseTheme, parseThemeBgFillStyles, parseThemeFillStyles, parseThemeFonts, parseThemeLineWidths } from "../core/drawingml/theme-parser.js";
11
11
  import { OpcPackage } from "../core/opc/package.js";
12
12
  import "../core/opc/index.js";
13
- import { buildPlaceholderCascade } from "./placeholder-cascade.js";
14
- import { backdropElement, parseBackgroundFill, parseSlideShapes } from "./slide-parser.js";
13
+ import { loadPptxEmbeddedFonts } from "./embedded-fonts.js";
14
+ import { presetTableStyle } from "./preset-table-styles.js";
15
+ import { resolveAlternateContent } from "../core/opc/alternate-content.js";
16
+ import { buildPlaceholderCascade, parseLevelStyles } from "./placeholder-cascade.js";
17
+ import { normalizeSpid, parseVmlImageRels } from "./ole-preview.js";
18
+ import { asBackdrop, backdropElement, parseBackgroundFill, parseSlideShapes } from "./slide-parser.js";
15
19
  import { XMLParser } from "fast-xml-parser";
16
20
  //#region src/pptx/pptx-reader.ts
17
21
  var EMU_PER_PT = 12700;
18
22
  var DEFAULT_CX = 9144e3;
19
23
  var DEFAULT_CY = 6858e3;
20
24
  var decoder = new TextDecoder();
25
+ var encoder = new TextEncoder();
21
26
  var parser = new XMLParser({
22
27
  htmlEntities: true,
23
28
  ignoreAttributes: false,
@@ -47,15 +52,20 @@ function readPptx(bytes) {
47
52
  const losses = [];
48
53
  const pkg = OpcPackage.open(bytes);
49
54
  const presPath = pkg.getMainDocumentPath();
55
+ const tableStyles = makeTableStyleResolver(pkg, presPath);
50
56
  const presData = pkg.getPart(presPath);
51
57
  const resources = new ResourceStore();
52
58
  const charts = /* @__PURE__ */ new Map();
53
59
  let cx = DEFAULT_CX;
54
60
  let cy = DEFAULT_CY;
61
+ let defaultTextStyle;
62
+ let embeddedFonts = /* @__PURE__ */ new Map();
55
63
  const slideParts = [];
56
64
  if (presData) {
57
65
  const pres = parser.parse(decoder.decode(presData)).find((n) => poIs(n, "p:presentation"));
66
+ embeddedFonts = loadPptxEmbeddedFonts(pkg, presPath, pres, (loss) => losses.push(loss));
58
67
  const kids = pres ? poChildren(pres) : [];
68
+ defaultTextStyle = kids.find((c) => poIs(c, "p:defaultTextStyle"));
59
69
  const sldSz = kids.find((c) => poIs(c, "p:sldSz"));
60
70
  cx = (sldSz ? poIntAttr(sldSz, "cx") : void 0) || DEFAULT_CX;
61
71
  cy = (sldSz ? poIntAttr(sldSz, "cy") : void 0) || DEFAULT_CY;
@@ -103,20 +113,38 @@ function readPptx(bytes) {
103
113
  });
104
114
  const part = slideParts[i];
105
115
  if (part) {
106
- const styles = slideStylesFor(pkg, part.path, stylesByLayout);
116
+ const slideTree = parseXml(part.data);
117
+ const styles = slideStylesFor(pkg, part.path, stylesByLayout, resources, charts, (loss) => losses.push(loss.where ? loss : {
118
+ ...loss,
119
+ where: `slide ${i + 1}`
120
+ }), defaultTextStyle, {
121
+ widthPt: pageW,
122
+ heightPt: pageH
123
+ }, overrideAlias(slideTree, "p:sld"));
107
124
  const ctx = {
108
125
  ...styles.cascade ? { cascade: styles.cascade } : {},
109
126
  colors: styles.colors,
127
+ ...styles.background ? { backgroundFill: styles.background } : {},
128
+ slideSize: {
129
+ widthPt: pageW,
130
+ heightPt: pageH
131
+ },
132
+ ...styles.themeFonts ? { themeFonts: styles.themeFonts } : {},
133
+ ...styles.themeFills ? { themeFills: styles.themeFills } : {},
134
+ ...styles.themeLineWidths ? { themeLineWidths: styles.themeLineWidths } : {},
110
135
  resolveImage: makeSlideImageResolver(pkg, part.path, resources),
111
- resolveChart: makeSlideChartResolver(pkg, part.path, charts, styles.colors),
136
+ resolveChart: makeSlideChartResolver(pkg, part.path, charts, styles.colors, resources),
112
137
  resolveHyperlink: makeHyperlinkResolver(pkg, part.path),
113
138
  resolveDiagram: makeSlideDiagramResolver(pkg, part.path),
139
+ resolveOlePreview: makeOlePreviewResolver(pkg, part.path, resources),
140
+ resolveTableStyle: tableStyles,
114
141
  onLoss: (loss) => losses.push(loss.where ? loss : {
115
142
  ...loss,
116
143
  where: `slide ${i + 1}`
117
144
  })
118
145
  };
119
- body.push(...parseSlide(part.data, ctx, styles.background, pageW, pageH));
146
+ const inherited = showMasterShapes(slideTree, "p:sld") ? styles.inheritedShapes ?? [] : [];
147
+ body.push(...parseSlide(slideTree, ctx, styles.background, pageW, pageH, inherited));
120
148
  }
121
149
  }
122
150
  const section = {
@@ -141,7 +169,8 @@ function readPptx(bytes) {
141
169
  section,
142
170
  styles: EMPTY_STYLE_SHEET,
143
171
  resources,
144
- ...charts.size > 0 ? { charts } : {}
172
+ ...charts.size > 0 ? { charts } : {},
173
+ ...embeddedFonts.size > 0 ? { embeddedFonts } : {}
145
174
  },
146
175
  losses
147
176
  };
@@ -150,27 +179,41 @@ function readPptx(bytes) {
150
179
  * Parse an OOXML part's bytes into preserve-order {@link PoNode} roots with the
151
180
  * module's shared, presentation-tuned {@link XMLParser} (attributes kept, values
152
181
  * not coerced, whitespace preserved). Shared with the slide-style resolvers.
182
+ *
183
+ * ISO/IEC 29500-3 §10.2 — `mc:AlternateContent` is resolved first, to the
184
+ * `mc:Fallback` a reader takes when it implements none of the namespaces the
185
+ * choices require. A deck writes the same shape twice this way, and reading the
186
+ * CHOICE means reading markup written for someone else: tdf143222's whole slide
187
+ * is an embedded worksheet whose preview picture lives in the fallback alone,
188
+ * and the choice — written for VML — carries no picture at all, so the slide
189
+ * came out blank. 82 of the corpus's decks carry such a block.
153
190
  */
154
191
  function parseXml(data) {
155
- return parser.parse(decoder.decode(data));
192
+ return parser.parse(resolveAlternateContent(decoder.decode(data)));
156
193
  }
157
- function parseSlide(data, ctx, inheritedBg, pageW, pageH) {
158
- const sld = parseXml(data).find((n) => poIs(n, "p:sld"));
194
+ function parseSlide(tree, ctx, inheritedBg, pageW, pageH, inheritedShapes = []) {
195
+ const sld = tree.find((n) => poIs(n, "p:sld"));
159
196
  const cSld = sld ? poChildren(sld).find((c) => poIs(c, "p:cSld")) : void 0;
160
197
  const colors = ctx.colors ?? defaultColorResolver;
161
198
  const bgNode = cSld ? poChildren(cSld).find((c) => poIs(c, "p:bg")) : void 0;
162
- const bg = (bgNode ? parseBackgroundFill(bgNode, colors) : void 0) ?? inheritedBg;
199
+ const own = bgNode ? parseBackgroundFill(bgNode, colors, ctx.resolveImage, ctx.themeFills) : void 0;
200
+ const bg = own ?? inheritedBg;
163
201
  const spTree = cSld ? poChildren(cSld).find((c) => poIs(c, "p:spTree")) : void 0;
202
+ const shapeCtx = own ? {
203
+ ...ctx,
204
+ backgroundFill: own
205
+ } : ctx;
164
206
  const out = [];
165
207
  if (bg) out.push(backdropElement(bg, pageW, pageH));
166
- if (spTree) out.push(...parseSlideShapes(spTree, ctx));
208
+ out.push(...inheritedShapes.map(asBackdrop));
209
+ if (spTree) out.push(...parseSlideShapes(spTree, shapeCtx));
167
210
  return out;
168
211
  }
169
- function partBackground(tree, root, colors) {
212
+ function partBackground(tree, root, colors, resolveImage, themeFills) {
170
213
  const sld = tree.find((n) => poIs(n, root));
171
214
  const cSld = sld ? poChildren(sld).find((c) => poIs(c, "p:cSld")) : void 0;
172
215
  const bg = cSld ? poChildren(cSld).find((c) => poIs(c, "p:bg")) : void 0;
173
- return bg ? parseBackgroundFill(bg, colors) : void 0;
216
+ return bg ? parseBackgroundFill(bg, colors, resolveImage, themeFills) : void 0;
174
217
  }
175
218
  function makeSlideImageResolver(pkg, slidePath, resources) {
176
219
  const cache = /* @__PURE__ */ new Map();
@@ -183,19 +226,81 @@ function makeSlideImageResolver(pkg, slidePath, resources) {
183
226
  return id;
184
227
  };
185
228
  }
229
+ /**
230
+ * The preview picture resolver for one slide's embedded objects: a `p:oleObj`
231
+ * `@spid` → the media the slide's legacy VML drawing hangs off that shape.
232
+ *
233
+ * Two relationship hops, and neither is the slide's own: the slide names the
234
+ * VML part, and the VML part names the picture. The whole part is read once,
235
+ * lazily — most slides have no embedded object at all.
236
+ */
237
+ function makeOlePreviewResolver(pkg, slidePath, resources) {
238
+ let byShape;
239
+ let vmlPath;
240
+ const cache = /* @__PURE__ */ new Map();
241
+ return (spid) => {
242
+ const key = normalizeSpid(spid);
243
+ if (cache.has(key)) return cache.get(key);
244
+ if (byShape === void 0) {
245
+ const rel = pkg.getPartRelationships(slidePath).find((r) => r.type.endsWith("/vmlDrawing") || r.type.endsWith("/legacyDrawing"));
246
+ const part = rel ? pkg.resolveRelatedPart(slidePath, rel) : void 0;
247
+ byShape = part ? parseVmlImageRels(part.data) : /* @__PURE__ */ new Map();
248
+ vmlPath = part?.path;
249
+ }
250
+ const relId = byShape.get(key);
251
+ const imgRel = relId !== void 0 && vmlPath !== void 0 ? pkg.getPartRelationships(vmlPath).find((r) => r.id === relId) : void 0;
252
+ const media = imgRel && vmlPath !== void 0 ? pkg.resolveRelatedPart(vmlPath, imgRel) : void 0;
253
+ const id = media ? resources.put(media.data) : void 0;
254
+ cache.set(key, id);
255
+ return id;
256
+ };
257
+ }
258
+ /**
259
+ * §20.1.4.2.24 — the deck's table styles, by the GUID a table names.
260
+ *
261
+ * The list's own `@def` is NOT a fallback: it is the style PowerPoint applies
262
+ * when a table is INSERTED, and the table then records that GUID itself. A
263
+ * table that names none wears none — table-with-no-theme's two rows are bare
264
+ * text in a plain frame, not the blue banding `@def` points at.
265
+ *
266
+ * A GUID the part does not hold may still be one of the GALLERY's own, which
267
+ * every deck names and none ships (see `preset-table-styles`).
268
+ *
269
+ * The part is read once, on the first table in the deck.
270
+ */
271
+ function makeTableStyleResolver(pkg, presPath) {
272
+ let byId;
273
+ return (styleId) => {
274
+ if (byId === void 0) {
275
+ byId = /* @__PURE__ */ new Map();
276
+ const rel = pkg.getPartRelationships(presPath).find((r) => r.type.endsWith("/tableStyles"));
277
+ const part = rel ? pkg.resolveRelatedPart(presPath, rel) : void 0;
278
+ for (const root of part ? parseXml(part.data) : []) {
279
+ const list = poIs(root, "a:tblStyleLst") ? root : poFindDescendant(root, "a:tblStyleLst");
280
+ if (!list) continue;
281
+ for (const style of poChildren(list)) {
282
+ const id = poIs(style, "a:tblStyle") ? poAttr(style, "styleId") : void 0;
283
+ if (id !== void 0) byId.set(id, style);
284
+ }
285
+ }
286
+ }
287
+ if (styleId === void 0) return void 0;
288
+ return byId.get(styleId) ?? presetTableStyle(styleId, (xml) => parseXml(encoder.encode(xml)));
289
+ };
290
+ }
186
291
  function makeHyperlinkResolver(pkg, slidePath) {
187
292
  return (relId) => {
188
293
  const rel = pkg.getPartRelationships(slidePath).find((r) => r.id === relId);
189
294
  return rel && rel.targetMode === "External" ? rel.target : void 0;
190
295
  };
191
296
  }
192
- function makeSlideChartResolver(pkg, slidePath, charts, colors) {
297
+ function makeSlideChartResolver(pkg, slidePath, charts, colors, resources) {
193
298
  const cache = /* @__PURE__ */ new Map();
194
299
  return (relId) => {
195
300
  if (cache.has(relId)) return cache.get(relId);
196
301
  const rel = pkg.getPartRelationships(slidePath).find((r) => r.id === relId);
197
302
  const resolved = rel ? pkg.resolveRelatedPart(slidePath, rel) : void 0;
198
- const chart = resolved ? parseChart(resolved.data, colors) : null;
303
+ const chart = resolved ? parseChart(resolved.data, colors, makeSlideImageResolver(pkg, resolved.path, resources)) : null;
199
304
  let key;
200
305
  if (chart && resolved) {
201
306
  key = `${slidePath}!${relId}`;
@@ -212,49 +317,174 @@ function makeSlideDiagramResolver(pkg, slidePath) {
212
317
  let spTree;
213
318
  const dataRel = pkg.getPartRelationships(slidePath).find((r) => r.id === relId);
214
319
  const data = dataRel ? pkg.resolveRelatedPart(slidePath, dataRel) : void 0;
215
- if (data) {
216
- const drawRel = pkg.getPartRelationships(data.path).find((r) => r.type.endsWith("/diagramDrawing"));
217
- const draw = drawRel ? pkg.resolveRelatedPart(data.path, drawRel) : void 0;
218
- if (draw) for (const root of parseXml(draw.data)) {
219
- const found = poFindDescendant(root, "dsp:spTree");
220
- if (found) {
221
- spTree = found;
222
- break;
223
- }
320
+ const draw = data ? drawingPart(pkg, slidePath, data) : void 0;
321
+ if (draw) for (const root of parseXml(draw.data)) {
322
+ const found = poFindDescendant(root, "dsp:spTree");
323
+ if (found) {
324
+ spTree = found;
325
+ break;
224
326
  }
225
327
  }
226
328
  cache.set(relId, spTree);
227
329
  return spTree;
228
330
  };
229
331
  }
230
- function slideStylesFor(pkg, slidePath, cache) {
332
+ /**
333
+ * The pre-rendered drawing a diagram's data part points at.
334
+ *
335
+ * PowerPoint names it from INSIDE the data: `<dsp:dataModelExt relId>` in the
336
+ * data's extension list, and that id is a relationship of the SLIDE, not of the
337
+ * data part. Looked for on the data part alone — where some producers do put it
338
+ * — two corpus decks with a `drawing1.xml` sitting right there reported having
339
+ * no drawing at all and rendered nothing (smartart-missing-bullet,
340
+ * tdf145528_SmartArt_Matrix).
341
+ *
342
+ * @param pkg The package.
343
+ * @param slidePath The slide the diagram is on.
344
+ * @param data The resolved `dgm:relIds@r:dm` data part.
345
+ * @returns The drawing part, or undefined when the deck ships none.
346
+ */
347
+ function drawingPart(pkg, slidePath, data) {
348
+ const extRelId = parseXml(data.data).map((root) => poFindDescendant(root, "dsp:dataModelExt")).map((ext) => ext ? poAttr(ext, "relId") : void 0).find((id) => id !== void 0);
349
+ const bySlide = extRelId !== void 0 ? pkg.getPartRelationships(slidePath).find((r) => r.id === extRelId) : void 0;
350
+ if (bySlide) {
351
+ const part = pkg.resolveRelatedPart(slidePath, bySlide);
352
+ if (part) return part;
353
+ }
354
+ const own = pkg.getPartRelationships(data.path).find((r) => r.type.endsWith("/diagramDrawing"));
355
+ if (own) return pkg.resolveRelatedPart(data.path, own);
356
+ const onSlide = pkg.getPartRelationships(slidePath).filter((r) => r.type.endsWith("/diagramDrawing"));
357
+ return onSlide.length === 1 && onSlide[0] ? pkg.resolveRelatedPart(slidePath, onSlide[0]) : void 0;
358
+ }
359
+ function slideStylesFor(pkg, slidePath, cache, resources, charts, onLoss, deckDefaultTextStyle, slideSize, slideAlias) {
231
360
  const layoutRel = pkg.getPartRelationships(slidePath).find((r) => r.type.endsWith("/slideLayout"));
232
361
  const layout = layoutRel ? pkg.resolveRelatedPart(slidePath, layoutRel) : void 0;
233
362
  if (!layout) return { colors: defaultColorResolver };
234
- const cached = cache.get(layout.path);
363
+ const key = slideAlias ? `${layout.path}|${aliasKey(slideAlias)}` : layout.path;
364
+ const cached = cache.get(key);
235
365
  if (cached) return cached;
236
366
  const masterRel = pkg.getPartRelationships(layout.path).find((r) => r.type.endsWith("/slideMaster"));
237
367
  const master = masterRel ? pkg.resolveRelatedPart(layout.path, masterRel) : void 0;
238
- const colors = master ? deckColorResolver(pkg, master.path) : defaultColorResolver;
239
368
  const layoutTree = parseXml(layout.data);
240
369
  const masterTree = master ? parseXml(master.data) : void 0;
241
- const cascade = buildPlaceholderCascade(layoutTree, masterTree, colors);
242
- const background = partBackground(layoutTree, "p:sldLayout", colors) ?? (masterTree ? partBackground(masterTree, "p:sldMaster", colors) : void 0);
370
+ const inheritedAlias = overrideAlias(layoutTree, "p:sldLayout") ?? (masterTree ? masterAlias(masterTree) : void 0);
371
+ const alias = slideAlias ?? inheritedAlias;
372
+ const theme = master ? themePart(pkg, master.path) : void 0;
373
+ const colors = master ? deckColorResolver(theme?.data, alias) : defaultColorResolver;
374
+ const inheritedColors = slideAlias === void 0 || !master ? colors : deckColorResolver(theme?.data, inheritedAlias);
375
+ const themeFills = theme ? {
376
+ fills: parseThemeFillStyles(theme.data),
377
+ backgrounds: parseThemeBgFillStyles(theme.data),
378
+ resolveImage: makeSlideImageResolver(pkg, theme.path, resources)
379
+ } : void 0;
380
+ const themeLineWidths = theme ? parseThemeLineWidths(theme.data) : void 0;
381
+ const themeFonts = theme ? parseThemeFonts(theme.data) : void 0;
382
+ const cascade = buildPlaceholderCascade(layoutTree, masterTree, colors, parseLevelStyles(deckDefaultTextStyle, colors, themeFonts), themeFonts);
383
+ const background = partBackground(layoutTree, "p:sldLayout", inheritedColors, makeSlideImageResolver(pkg, layout.path, resources), themeFills) ?? (masterTree && master ? partBackground(masterTree, "p:sldMaster", inheritedColors, makeSlideImageResolver(pkg, master.path, resources), themeFills) : void 0);
384
+ const deps = {
385
+ colors: inheritedColors,
386
+ resources,
387
+ charts,
388
+ onLoss,
389
+ slideSize,
390
+ ...themeFills ? { themeFills } : {},
391
+ ...themeLineWidths && themeLineWidths.length > 0 ? { themeLineWidths } : {},
392
+ ...background ? { background } : {}
393
+ };
394
+ const inheritedShapes = [];
395
+ if (masterTree && master && showMasterShapes(layoutTree, "p:sldLayout")) inheritedShapes.push(...partShapes(pkg, master.path, masterTree, "p:sldMaster", deps));
396
+ inheritedShapes.push(...partShapes(pkg, layout.path, layoutTree, "p:sldLayout", deps));
243
397
  const styles = {
244
398
  cascade,
245
399
  colors,
246
- ...background ? { background } : {}
400
+ ...themeFonts ? { themeFonts } : {},
401
+ ...themeFills ? { themeFills } : {},
402
+ ...themeLineWidths && themeLineWidths.length > 0 ? { themeLineWidths } : {},
403
+ ...background ? { background } : {},
404
+ ...inheritedShapes.length > 0 ? { inheritedShapes } : {}
247
405
  };
248
- cache.set(layout.path, styles);
406
+ cache.set(key, styles);
249
407
  return styles;
250
408
  }
251
- function deckColorResolver(pkg, masterPath) {
252
- const themeRel = pkg.getPartRelationships(masterPath).find((r) => r.type.endsWith("/theme"));
253
- const theme = themeRel ? pkg.resolveRelatedPart(masterPath, themeRel) : void 0;
254
- if (!theme) return defaultColorResolver;
409
+ /**
410
+ * A master's or layout's own drawn shapes — everything in its `p:spTree` that
411
+ * is not a placeholder, read with resolvers bound to THAT part: a logo's image
412
+ * relationship, a chart's, a hyperlink's are all scoped to the part that names
413
+ * them.
414
+ */
415
+ function partShapes(pkg, path, tree, root, deps) {
416
+ const part = tree.find((n) => poIs(n, root));
417
+ const cSld = part ? poChildren(part).find((c) => poIs(c, "p:cSld")) : void 0;
418
+ const spTree = cSld ? poChildren(cSld).find((c) => poIs(c, "p:spTree")) : void 0;
419
+ if (!spTree) return [];
420
+ return parseSlideShapes(spTree, {
421
+ colors: deps.colors,
422
+ ...deps.themeFills ? { themeFills: deps.themeFills } : {},
423
+ ...deps.themeLineWidths ? { themeLineWidths: deps.themeLineWidths } : {},
424
+ ...deps.background ? { backgroundFill: deps.background } : {},
425
+ slideSize: deps.slideSize,
426
+ resolveImage: makeSlideImageResolver(pkg, path, deps.resources),
427
+ resolveChart: makeSlideChartResolver(pkg, path, deps.charts, deps.colors, deps.resources),
428
+ resolveHyperlink: makeHyperlinkResolver(pkg, path),
429
+ resolveDiagram: makeSlideDiagramResolver(pkg, path),
430
+ onLoss: deps.onLoss
431
+ }, void 0, true);
432
+ }
433
+ /**
434
+ * §19.3.1.38/§19.3.1.39 `@showMasterSp` — whether this part draws the shapes it
435
+ * inherits. Absent, it does.
436
+ */
437
+ function showMasterShapes(tree, root) {
438
+ const part = tree.find((n) => poIs(n, root));
439
+ return part === void 0 || poAttr(part, "showMasterSp") !== "0";
440
+ }
441
+ /** The master's `p:clrMap` (§19.3.1.6) as a scheme-alias table. */
442
+ function masterAlias(masterTree) {
443
+ const master = masterTree.find((n) => poIs(n, "p:sldMaster"));
444
+ const map = master ? poChildren(master).find((c) => poIs(c, "p:clrMap")) : void 0;
445
+ return map ? aliasFromAttrs(map) : void 0;
446
+ }
447
+ /**
448
+ * A layout's or slide's `p:clrMapOvr` (§19.3.1.7) as a scheme-alias table, or
449
+ * `undefined` when it holds `a:masterClrMapping` — which says "the master's",
450
+ * i.e. nothing of its own.
451
+ */
452
+ function overrideAlias(tree, root) {
453
+ const part = tree.find((n) => poIs(n, root));
454
+ const ovr = part ? poChildren(part).find((c) => poIs(c, "p:clrMapOvr")) : void 0;
455
+ const own = ovr ? poChildren(ovr).find((c) => poIs(c, "a:overrideClrMapping")) : void 0;
456
+ return own ? aliasFromAttrs(own) : void 0;
457
+ }
458
+ function aliasFromAttrs(node) {
459
+ const alias = {};
460
+ for (const name of [
461
+ "bg1",
462
+ "tx1",
463
+ "bg2",
464
+ "tx2"
465
+ ]) {
466
+ const slot = poAttr(node, name);
467
+ if (slot !== void 0) alias[name] = slot;
468
+ }
469
+ return alias;
470
+ }
471
+ /** A stable key for an alias table, so the per-layout cache can include it. */
472
+ function aliasKey(alias) {
473
+ return Object.entries(alias).sort(([a], [b]) => a < b ? -1 : 1).map(([k, v]) => `${k}=${v}`).join(",");
474
+ }
475
+ function deckColorResolver(theme, alias) {
255
476
  const palette = new Map(DEFAULT_THEME_PALETTE);
256
- for (const [slot, hex] of parseTheme(theme.data)) palette.set(slot, hex);
257
- return makeColorResolver(palette);
477
+ if (theme) for (const [slot, hex] of parseTheme(theme)) palette.set(slot, hex);
478
+ if (!theme && !alias) return defaultColorResolver;
479
+ return makeColorResolver(palette, {
480
+ ...DEFAULT_SCHEME_ALIAS,
481
+ ...alias
482
+ });
483
+ }
484
+ /** The master's theme part, if it has one — its path names its own pictures. */
485
+ function themePart(pkg, masterPath) {
486
+ const rel = pkg.getPartRelationships(masterPath).find((r) => r.type.endsWith("/theme"));
487
+ return rel ? pkg.resolveRelatedPart(masterPath, rel) : void 0;
258
488
  }
259
489
  /**
260
490
  * The {@link DocumentReader} for PresentationML (`.pptx`): sniffs the OPC ZIP for
@@ -271,7 +501,7 @@ var pptxReader = {
271
501
  FEATURES.charts,
272
502
  FEATURES.tables
273
503
  ]),
274
- sniff: (bytes) => bytes[0] === 80 && bytes[1] === 75 && bytesIncludePartName(bytes, "ppt/presentation.xml"),
504
+ sniff: (bytes) => bytes[0] === 80 && bytes[1] === 75 && packageHasPart(bytes, "ppt/presentation.xml"),
275
505
  read: (bytes) => readPptx(bytes)
276
506
  };
277
507
  //#endregion
@@ -0,0 +1,9 @@
1
+ import { PoNode } from '../core/po-helpers.js';
2
+ /**
3
+ * The built-in table style a GUID names, or `undefined` when it is not one this
4
+ * reader holds.
5
+ *
6
+ * @param styleId The `a:tableStyleId` a table states.
7
+ * @param parse The module's XML reader, injected so this file needs none.
8
+ */
9
+ export declare function presetTableStyle(styleId: string, parse: (xml: string) => ReadonlyArray<PoNode>): PoNode | undefined;
@@ -0,0 +1,27 @@
1
+ import { poAttr, poIs } from "../core/po-helpers.js";
2
+ //#region src/pptx/preset-table-styles.ts
3
+ /** The gallery styles this reader knows, by the GUID a table names. */
4
+ var PRESETS = new Map([
5
+ ["{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}", "<a:tblStyle styleId=\"{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}\" styleName=\"Medium Style 2 - Accent 1\"><a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:prstClr val=\"black\"/></a:fontRef><a:schemeClr val=\"dk1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:left><a:right><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:right><a:top><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:top><a:bottom><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:bottom><a:insideH><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:insideH><a:insideV><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:insideV></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"accent1\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:wholeTbl><a:band1H><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"accent1\"><a:tint val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1H><a:band2H><a:tcStyle><a:tcBdr/></a:tcStyle></a:band2H><a:band1V><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"accent1\"><a:tint val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1V><a:band2V><a:tcStyle><a:tcBdr/></a:tcStyle></a:band2V><a:lastCol><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:prstClr val=\"black\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"accent1\"/></a:solidFill></a:fill></a:tcStyle></a:lastCol><a:firstCol><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:prstClr val=\"black\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"accent1\"/></a:solidFill></a:fill></a:tcStyle></a:firstCol><a:lastRow><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:prstClr val=\"black\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:top><a:ln w=\"38100\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:top></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"accent1\"/></a:solidFill></a:fill></a:tcStyle></a:lastRow><a:firstRow><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:prstClr val=\"black\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:bottom><a:ln w=\"38100\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:bottom></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"accent1\"/></a:solidFill></a:fill></a:tcStyle></a:firstRow></a:tblStyle>"],
6
+ ["{073A0DAA-6AF3-43AB-8588-CEC1D06C72B9}", "<a:tblStyle styleId=\"{073A0DAA-6AF3-43AB-8588-CEC1D06C72B9}\" styleName=\"Medium Style 2\"><a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:prstClr val=\"black\"/></a:fontRef><a:schemeClr val=\"dk1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:left><a:right><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:right><a:top><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:top><a:bottom><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:bottom><a:insideH><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:insideH><a:insideV><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:insideV></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"20000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:wholeTbl><a:band1H><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1H><a:band2H><a:tcStyle><a:tcBdr/></a:tcStyle></a:band2H><a:band1V><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"dk1\"><a:tint val=\"40000\"/></a:schemeClr></a:solidFill></a:fill></a:tcStyle></a:band1V><a:band2V><a:tcStyle><a:tcBdr/></a:tcStyle></a:band2V><a:lastCol><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:prstClr val=\"black\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:fill></a:tcStyle></a:lastCol><a:firstCol><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:prstClr val=\"black\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr/><a:fill><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:fill></a:tcStyle></a:firstCol><a:lastRow><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:prstClr val=\"black\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:top><a:ln w=\"38100\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:top></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:fill></a:tcStyle></a:lastRow><a:firstRow><a:tcTxStyle b=\"on\"><a:fontRef idx=\"minor\"><a:prstClr val=\"black\"/></a:fontRef><a:schemeClr val=\"lt1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:bottom><a:ln w=\"38100\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"lt1\"/></a:solidFill></a:ln></a:bottom></a:tcBdr><a:fill><a:solidFill><a:schemeClr val=\"dk1\"/></a:solidFill></a:fill></a:tcStyle></a:firstRow></a:tblStyle>"],
7
+ ["{5940675A-B579-460E-94D1-54222C63F5DA}", "<a:tblStyle styleId=\"{5940675A-B579-460E-94D1-54222C63F5DA}\" styleName=\"No Style, Table Grid\"><a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"tx1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"tx1\"/></a:solidFill></a:ln></a:left><a:right><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"tx1\"/></a:solidFill></a:ln></a:right><a:top><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"tx1\"/></a:solidFill></a:ln></a:top><a:bottom><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"tx1\"/></a:solidFill></a:ln></a:bottom><a:insideH><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"tx1\"/></a:solidFill></a:ln></a:insideH><a:insideV><a:ln w=\"12700\" cmpd=\"sng\"><a:solidFill><a:schemeClr val=\"tx1\"/></a:solidFill></a:ln></a:insideV></a:tcBdr><a:fill><a:noFill/></a:fill></a:tcStyle></a:wholeTbl></a:tblStyle>"],
8
+ ["{2D5ABB26-0587-4C30-8999-92F81FD0307C}", "<a:tblStyle styleId=\"{2D5ABB26-0587-4C30-8999-92F81FD0307C}\" styleName=\"No Style, No Grid\"><a:wholeTbl><a:tcTxStyle><a:fontRef idx=\"minor\"><a:scrgbClr r=\"0\" g=\"0\" b=\"0\"/></a:fontRef><a:schemeClr val=\"tx1\"/></a:tcTxStyle><a:tcStyle><a:tcBdr><a:left><a:ln><a:noFill/></a:ln></a:left><a:right><a:ln><a:noFill/></a:ln></a:right><a:top><a:ln><a:noFill/></a:ln></a:top><a:bottom><a:ln><a:noFill/></a:ln></a:bottom><a:insideH><a:ln><a:noFill/></a:ln></a:insideH><a:insideV><a:ln><a:noFill/></a:ln></a:insideV></a:tcBdr><a:fill><a:noFill/></a:fill></a:tcStyle></a:wholeTbl></a:tblStyle>"]
9
+ ]);
10
+ var parsed = /* @__PURE__ */ new Map();
11
+ /**
12
+ * The built-in table style a GUID names, or `undefined` when it is not one this
13
+ * reader holds.
14
+ *
15
+ * @param styleId The `a:tableStyleId` a table states.
16
+ * @param parse The module's XML reader, injected so this file needs none.
17
+ */
18
+ function presetTableStyle(styleId, parse) {
19
+ const seen = parsed.get(styleId);
20
+ if (seen !== void 0 || parsed.has(styleId)) return seen;
21
+ const xml = PRESETS.get(styleId);
22
+ const style = xml ? parse(xml).find((n) => poIs(n, "a:tblStyle") && poAttr(n, "styleId") === styleId) : void 0;
23
+ parsed.set(styleId, style);
24
+ return style;
25
+ }
26
+ //#endregion
27
+ export { presetTableStyle };
@@ -1,5 +1,6 @@
1
1
  import { BodyElement, FloatAnchor, ShapeBlock, ShapeFill, ShapeGeometry, ShapeTextBody } from '../core/document-model/index.js';
2
2
  import { ColorResolver } from '../core/drawingml/colors.js';
3
+ import { ThemeFonts } from '../core/drawingml/theme-parser.js';
3
4
  import { Loss, Pt, ResourceId } from '../core/ir/index.js';
4
5
  import { PoNode } from '../core/po-helpers.js';
5
6
  import { PlaceholderCascade } from './placeholder-cascade.js';
@@ -15,6 +16,35 @@ export interface SlideContext {
15
16
  readonly cascade?: PlaceholderCascade;
16
17
  /** A slide-scoped blip relationship id (`a:blip @r:embed`) → a stored resource (PX3a). */
17
18
  readonly resolveImage?: (relId: string) => ResourceId | undefined;
19
+ /** The deck theme's fill style lists, for a `p:bgRef` on this slide. */
20
+ readonly themeFills?: ThemeFillStyles;
21
+ /**
22
+ * §20.1.4.1.16 — the two typefaces the deck's theme names. A run states its
23
+ * own by TOKEN (`+mn-lt`) more often than by name.
24
+ */
25
+ readonly themeFonts?: ThemeFonts;
26
+ /** §20.1.4.1.21 `a:lnStyleLst` — the widths an `a:lnRef` indexes, in points. */
27
+ readonly themeLineWidths?: ReadonlyArray<number>;
28
+ /**
29
+ * §19.3.1.43 — the slide's own background fill, which a shape marked
30
+ * `useBgFill` is painted with.
31
+ */
32
+ readonly backgroundFill?: ShapeFill;
33
+ /** The slide's size, which says WHERE that background lies under a shape. */
34
+ readonly slideSize?: {
35
+ readonly widthPt: Pt;
36
+ readonly heightPt: Pt;
37
+ };
38
+ /**
39
+ * §19.3.2.4 — the picture an embedded object shows, by the `@spid` of its
40
+ * shape in the slide's legacy VML drawing.
41
+ */
42
+ readonly resolveOlePreview?: (spid: string) => ResourceId | undefined;
43
+ /**
44
+ * §20.1.4.2.24 — the `a:tblStyle` a table names by GUID, from the deck's
45
+ * `tableStyles.xml`. A table that names none wears none.
46
+ */
47
+ readonly resolveTableStyle?: (styleId: string | undefined) => PoNode | undefined;
18
48
  /** A chart relationship id (`c:chart @r:id`) → its document-unique key (PX4a). */
19
49
  readonly resolveChart?: (relId: string) => string | undefined;
20
50
  /**
@@ -50,7 +80,7 @@ type GroupTransform = (box: ShapeBoxEmu) => ShapeBoxEmu;
50
80
  * @param transform Maps child-space boxes to the slide (identity at the top level).
51
81
  * @returns The container's shapes as positioned {@link BodyElement}s.
52
82
  */
53
- export declare function parseSlideShapes(container: PoNode, ctx?: SlideContext, transform?: GroupTransform): Array<BodyElement>;
83
+ export declare function parseSlideShapes(container: PoNode, ctx?: SlideContext, transform?: GroupTransform, skipPlaceholders?: boolean): Array<BodyElement>;
54
84
  /**
55
85
  * The diagram's child shapes live in the spTree's own coordinate space
56
86
  * (`dsp:grpSpPr/a:xfrm` `chOff`/`chExt`); map that onto a target box (the frame on
@@ -106,13 +136,43 @@ export declare function parseDiagramNodes(spTree: PoNode, transform: GroupTransf
106
136
  */
107
137
  export declare function parseDiagramDrawing(spTree: PoNode, transform: GroupTransform, makeFloat: (box: ShapeBoxEmu) => FloatAnchor, colors: ColorResolver, resolveLink: LinkResolver): Array<ShapeBlock>;
108
138
  /**
109
- * `p:bg` → the background fill, or `undefined` when none/unsupported. `p:bgPr`
110
- * carries the fill directly (`a:solidFill`/`a:gradFill` — the same children
111
- * `parseFill` reads; a picture background is not yet supported); `p:bgRef` (a
112
- * theme fill-style index) is approximated by its colour child as a solid fill.
139
+ * The theme fill styles a `p:bgRef` indexes into (§19.3.1.2), as the raw nodes
140
+ * the fill readers take.
141
+ */
142
+ export interface ThemeFillStyles {
143
+ /** `a:fillStyleLst` — what an index of 1…999 names. */
144
+ readonly fills: ReadonlyArray<PoNode>;
145
+ /** `a:bgFillStyleLst` — what an index past 1000 names, 1001 being the first. */
146
+ readonly backgrounds: ReadonlyArray<PoNode>;
147
+ /**
148
+ * A picture named inside a style belongs to the THEME part: the Office
149
+ * "Berlin" background is a photograph the theme carries and its `r:embed`
150
+ * means nothing in the master's relationships (corpus: tdf123684, where it
151
+ * resolved to a different image entirely).
152
+ */
153
+ readonly resolveImage?: (relId: string) => ResourceId | undefined;
154
+ }
155
+ /**
156
+ * `p:bg` → the background fill, or `undefined` when it declares none.
157
+ *
158
+ * Two spellings. `p:bgPr` carries the fill itself — solid, gradient, or a
159
+ * PICTURE, which needs the owning part's image resolver since the blip's
160
+ * relationship is scoped to the part the background is written in. `p:bgRef`
161
+ * (§19.3.1.2) carries no fill at all: an index into the theme's style lists and
162
+ * the colour to put wherever that style says `phClr`. Read as its colour alone
163
+ * — which is all this did — a deck whose theme opens with a black-to-grey
164
+ * gradient came out flat, and one whose first background slot is a picture came
165
+ * out a single colour.
166
+ *
113
167
  * Used for the slide's own background and the inherited layout/master one (PX5b).
168
+ *
169
+ * @param bg The `p:bg` node.
170
+ * @param colors The deck's colour resolver.
171
+ * @param resolveImage Resolver for a picture background's relationship, scoped
172
+ * to the part this `p:bg` is written in.
173
+ * @param theme The theme's fill style lists, for a `p:bgRef`.
114
174
  */
115
- export declare function parseBackgroundFill(bg: PoNode, colors: ColorResolver): ShapeFill | undefined;
175
+ export declare function parseBackgroundFill(bg: PoNode, colors: ColorResolver, resolveImage?: (relId: string) => ResourceId | undefined, theme?: ThemeFillStyles): ShapeFill | undefined;
116
176
  /**
117
177
  * A full-slide backdrop element for a background fill: a rectangle covering the
118
178
  * page, anchored behind the content (PX5b).
@@ -123,10 +183,18 @@ export declare function parseBackgroundFill(bg: PoNode, colors: ColorResolver):
123
183
  */
124
184
  export declare function backdropElement(fill: ShapeFill, widthPt: Pt, heightPt: Pt): BodyElement;
125
185
  /**
126
- * `p:spPr` geometry: `a:prstGeom` (preset) or `a:custGeom` (custom path), default
127
- * rect. Exported for sheet shapes (E-SHEET W2), whose `xdr:spPr` carries the same
128
- * `a:` children.
186
+ * The same element, painted BEHIND the slide's own content.
187
+ *
188
+ * §19.3.1 — a slide's shape tree is drawn over its layout's, and that over the
189
+ * master's; nothing a deck states once can bury what a slide puts on it. Our
190
+ * page paints by KIND (every image, then every shape), so without this a
191
+ * layout's white card landed on top of the photograph the slide is made of —
192
+ * themes.pptx's fifth slide is one picture and it vanished under the card.
193
+ *
194
+ * @param el The inherited element.
195
+ * @returns The element with its float sunk to the backdrop layer.
129
196
  */
197
+ export declare function asBackdrop(el: BodyElement): BodyElement;
130
198
  export declare function parseGeometry(spPr: PoNode | undefined): ShapeGeometry;
131
199
  /**
132
200
  * `p:txBody` → {@link ShapeTextBody}. `a:bodyPr` carries the insets and the
@@ -141,5 +209,5 @@ export declare function parseGeometry(spPr: PoNode | undefined): ShapeGeometry;
141
209
  * @param resolveLink A run hyperlink resolver, or `undefined`.
142
210
  * @returns The text body, or `undefined` when it holds no paragraphs.
143
211
  */
144
- export declare function parseTxBody(txBody: PoNode, ph: PlaceholderRef | undefined, cascade: PlaceholderCascade | undefined, colors: ColorResolver, resolveLink: LinkResolver): ShapeTextBody | undefined;
212
+ export declare function parseTxBody(txBody: PoNode, ph: PlaceholderRef | undefined, cascade: PlaceholderCascade | undefined, colors: ColorResolver, resolveLink: LinkResolver, styleColor?: string, themeFonts?: ThemeFonts): ShapeTextBody | undefined;
145
213
  export {};