reamkit 1.21.0 → 1.22.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 (37) 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/document-model/types.d.ts +60 -0
  4. package/dist/esm/core/drawingml/chart-parser.d.ts +2 -1
  5. package/dist/esm/core/drawingml/chart-parser.js +23 -1
  6. package/dist/esm/core/drawingml/colors.d.ts +27 -3
  7. package/dist/esm/core/drawingml/colors.js +30 -6
  8. package/dist/esm/core/drawingml/preset-geometry.js +236 -0
  9. package/dist/esm/core/metafile/emf.js +2 -1
  10. package/dist/esm/core/metafile/symbol-fonts.d.ts +42 -0
  11. package/dist/esm/core/metafile/symbol-fonts.js +154 -0
  12. package/dist/esm/core/metafile/wmf.js +35 -2
  13. package/dist/esm/core/vector.d.ts +5 -0
  14. package/dist/esm/excel/sheet-shape-parser.js +1 -12
  15. package/dist/esm/excel/xlsx-reader.d.ts +1 -1
  16. package/dist/esm/excel/xlsx-reader.js +3 -3
  17. package/dist/esm/layout/page-doc.d.ts +38 -0
  18. package/dist/esm/layout/page-doc.js +34 -18
  19. package/dist/esm/layout/styled-layout.js +174 -49
  20. package/dist/esm/pdf/shading.d.ts +19 -0
  21. package/dist/esm/pdf/shading.js +84 -11
  22. package/dist/esm/pdf/styled-page-emitter.js +614 -444
  23. package/dist/esm/pptx/ole-preview.d.ts +10 -0
  24. package/dist/esm/pptx/ole-preview.js +52 -0
  25. package/dist/esm/pptx/placeholder-cascade.d.ts +69 -5
  26. package/dist/esm/pptx/placeholder-cascade.js +162 -25
  27. package/dist/esm/pptx/pptx-reader.js +247 -39
  28. package/dist/esm/pptx/slide-parser.d.ts +72 -10
  29. package/dist/esm/pptx/slide-parser.js +310 -82
  30. package/dist/esm/pptx/sp-helpers.js +19 -4
  31. package/dist/esm/pptx/table-style.d.ts +56 -0
  32. package/dist/esm/pptx/table-style.js +161 -0
  33. package/dist/esm/svg/svg-writer.js +53 -5
  34. package/dist/esm/word/docx-reader.js +2 -2
  35. package/dist/esm/word/drawing-parser.d.ts +34 -0
  36. package/dist/esm/word/drawing-parser.js +159 -13
  37. package/package.json +1 -1
@@ -1,11 +1,14 @@
1
1
  import { emuToPt, pt } from "../core/ir/units.js";
2
2
  import { FEATURES } from "../core/ir/features.js";
3
3
  import { poAttr, poChildren, poFindDescendant, poIntAttr, poIs, poTag, poText } from "../core/po-helpers.js";
4
- import { defaultColorResolver, resolveColorNode } from "../core/drawingml/colors.js";
4
+ import { defaultColorResolver, placeholderColors, resolveColorNode } from "../core/drawingml/colors.js";
5
5
  import { boxFromXfrm, parsePh, parseXfrmBox, rPrToRunProps } from "./sp-helpers.js";
6
- import { parseCustGeom, parseFill, parseLine, parsePrstGeom, parseShadow, parseXfrm } from "../word/drawing-parser.js";
6
+ import { parseBullet } from "./placeholder-cascade.js";
7
+ import { colorChangeOf, parseCustGeom, parseFill, parseLine, parsePrstGeom, parseShadow, parseXfrm, statesFill, styleRefFill, styleRefFontColor, styleRefLine } from "../word/drawing-parser.js";
8
+ import { cellStyle, lineBorder, tableStyleFlags, tableStyleId, withCellStyle, withoutFill } from "./table-style.js";
7
9
  //#region src/pptx/slide-parser.ts
8
10
  var CHART_URI = "http://schemas.openxmlformats.org/drawingml/2006/chart";
11
+ var OLE_URI = "http://schemas.openxmlformats.org/presentationml/2006/ole";
9
12
  var TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table";
10
13
  var DIAGRAM_URI = "http://schemas.openxmlformats.org/drawingml/2006/diagram";
11
14
  var ALGN_TO_ALIGNMENT = {
@@ -32,24 +35,37 @@ var IDENTITY_TRANSFORM = (box) => box;
32
35
  * @param transform Maps child-space boxes to the slide (identity at the top level).
33
36
  * @returns The container's shapes as positioned {@link BodyElement}s.
34
37
  */
35
- function parseSlideShapes(container, ctx = {}, transform = IDENTITY_TRANSFORM) {
38
+ function parseSlideShapes(container, ctx = {}, transform = IDENTITY_TRANSFORM, skipPlaceholders = false) {
36
39
  const out = [];
37
- for (const child of poChildren(container)) if (poIs(child, "p:sp")) {
38
- const shape = parseSp(child, ctx, transform);
39
- if (shape) out.push({
40
- kind: "shape",
41
- shape
42
- });
43
- } else if (poIs(child, "p:pic")) {
44
- const image = parsePic(child, ctx, transform);
45
- if (image) out.push({
46
- kind: "image",
47
- image
48
- });
49
- } else if (poIs(child, "p:graphicFrame")) out.push(...parseGraphicFrame(child, ctx, transform));
50
- else if (poIs(child, "p:grpSp")) out.push(...parseSlideShapes(child, ctx, composeGroupTransform(child, transform)));
40
+ for (const child of poChildren(container)) {
41
+ if (skipPlaceholders && isPlaceholder(child)) continue;
42
+ if (poIs(child, "p:sp")) {
43
+ const shape = parseSp(child, ctx, transform);
44
+ if (shape) out.push({
45
+ kind: "shape",
46
+ shape
47
+ });
48
+ } else if (poIs(child, "p:pic")) {
49
+ const image = parsePic(child, ctx, transform);
50
+ if (image) out.push({
51
+ kind: "image",
52
+ image
53
+ });
54
+ } else if (poIs(child, "p:graphicFrame")) out.push(...parseGraphicFrame(child, ctx, transform));
55
+ else if (poIs(child, "p:grpSp")) out.push(...parseSlideShapes(child, ctx, composeGroupTransform(child, transform), skipPlaceholders));
56
+ }
51
57
  return out;
52
58
  }
59
+ /**
60
+ * Whether a shape is a placeholder — `p:ph` in its OWN non-visual properties.
61
+ * Read as "anywhere below", a group holding one would take the whole group
62
+ * with it.
63
+ */
64
+ function isPlaceholder(shape) {
65
+ const nv = poChildren(shape).find((c) => poTag(c)?.startsWith("p:nv") === true);
66
+ const nvPr = nv ? poChildren(nv).find((c) => poIs(c, "p:nvPr")) : void 0;
67
+ return nvPr !== void 0 && poChildren(nvPr).some((c) => poIs(c, "p:ph"));
68
+ }
53
69
  function composeGroupTransform(grpSp, parent) {
54
70
  const grpSpPr = poChildren(grpSp).find((c) => poIs(c, "p:grpSpPr"));
55
71
  const xfrm = grpSpPr ? poChildren(grpSpPr).find((c) => poIs(c, "a:xfrm")) : void 0;
@@ -97,20 +113,41 @@ function parseSp(sp, ctx, transform) {
97
113
  if (!own && ph && ctx.cascade) own = ctx.cascade.geometryFor(ph);
98
114
  if (!own) return void 0;
99
115
  const box = transform(own);
116
+ const style = poChildren(sp).find((c) => poIs(c, "p:style"));
100
117
  const txBody = poChildren(sp).find((c) => poIs(c, "p:txBody"));
101
- const text = txBody ? parseTxBody(txBody, ph, ctx.cascade, colors, ctx.resolveHyperlink) : void 0;
102
- const geometry = parseGeometry(spPr);
103
- const fill = spPr ? parseFill(spPr, colors) : { kind: "none" };
104
- const line = spPr ? parseLine(spPr, colors) : void 0;
118
+ const styleColor = style ? styleRefFontColor(style, colors) : void 0;
119
+ const text = txBody ? parseTxBody(txBody, ph, ctx.cascade, colors, ctx.resolveHyperlink, styleColor) : void 0;
120
+ const proto = ph && ctx.cascade ? ctx.cascade.shapePropsFor(ph) : void 0;
121
+ const geometry = parseGeometry(spPr && statesGeometry(spPr) ? spPr : proto ?? spPr);
122
+ const useBgFill = poAttr(sp, "useBgFill") === "1";
123
+ const fillFrom = statesFill(spPr) ? spPr : proto ?? spPr;
124
+ const fill = useBgFill ? backgroundThrough(ctx.backgroundFill, box, ctx.slideSize) : fillFrom ? parseFill(fillFrom, colors, ctx.resolveImage) : { kind: "none" };
125
+ const lineFrom = spPr && poChildren(spPr).some((c) => poIs(c, "a:ln")) ? spPr : proto ?? spPr;
126
+ let line = lineFrom ? parseLine(lineFrom, colors) : void 0;
127
+ const themeStyles = ctx.themeFills ? {
128
+ fills: ctx.themeFills.fills,
129
+ bgFills: ctx.themeFills.backgrounds
130
+ } : void 0;
131
+ const styled = style && fill.kind === "none" && !statesFill(fillFrom) ? styleRefFill(style, colors, themeStyles) : fill;
132
+ if (style) {
133
+ const fromStyle = styleRefLine(style, colors, ctx.themeLineWidths);
134
+ if (fromStyle) line = line ? {
135
+ ...fromStyle,
136
+ ...Object.fromEntries(Object.entries(line).filter(([, v]) => v !== void 0))
137
+ } : fromStyle;
138
+ }
105
139
  const visibleLine = line !== void 0 && line.fill !== "none";
106
- if (!text && fill.kind === "none" && !visibleLine) return void 0;
140
+ if (!text && styled.kind === "none" && !visibleLine) return void 0;
141
+ const xfrm = spPr ? poChildren(spPr).find((c) => poIs(c, "a:xfrm")) : void 0;
142
+ const spin = xfrm ? parseXfrm(xfrm) : void 0;
107
143
  return {
108
144
  float: floatAt(box),
109
145
  width: emuToPt(box.cx),
110
146
  height: emuToPt(box.cy),
111
147
  geometry,
112
- fill,
148
+ fill: styled,
113
149
  ...line ? { line } : {},
150
+ ...spin && Object.keys(spin).length > 0 ? { transform: spin } : {},
114
151
  ...text ? { text } : {},
115
152
  paragraphProperties: {}
116
153
  };
@@ -139,10 +176,50 @@ function parseGraphicFrame(gf, ctx, transform) {
139
176
  }
140
177
  if (uri === TABLE_URI) {
141
178
  const tbl = poFindDescendant(gf, "a:tbl");
142
- return tbl ? [{
179
+ if (!tbl) return [];
180
+ const table = parseTable(tbl, ctx.colors ?? defaultColorResolver, ctx.resolveTableStyle);
181
+ return [{
143
182
  kind: "table",
144
- table: parseTable(tbl, ctx.colors ?? defaultColorResolver)
145
- }] : [];
183
+ table: {
184
+ ...table,
185
+ properties: {
186
+ ...table.properties,
187
+ float: floatAt(box)
188
+ }
189
+ }
190
+ }];
191
+ }
192
+ if (uri === OLE_URI) {
193
+ const oleObj = poFindDescendant(gf, "p:oleObj");
194
+ if (!oleObj) return [];
195
+ const pic = poChildren(oleObj).find((c) => poIs(c, "p:pic"));
196
+ if (pic) {
197
+ const image = parsePic(pic, ctx, transform);
198
+ return image ? [{
199
+ kind: "image",
200
+ image
201
+ }] : [];
202
+ }
203
+ const spid = poAttr(oleObj, "spid");
204
+ const resource = spid !== void 0 ? ctx.resolveOlePreview?.(spid) : void 0;
205
+ if (resource === void 0) {
206
+ ctx.onLoss?.({
207
+ severity: "dropped",
208
+ feature: FEATURES.images,
209
+ detail: "embedded object with no preview picture — the object is not drawn"
210
+ });
211
+ return [];
212
+ }
213
+ return [{
214
+ kind: "image",
215
+ image: {
216
+ float: floatAt(box),
217
+ resource,
218
+ width: emuToPt(box.cx),
219
+ height: emuToPt(box.cy),
220
+ paragraphProperties: {}
221
+ }
222
+ }];
146
223
  }
147
224
  if (uri === DIAGRAM_URI) {
148
225
  const relIds = poFindDescendant(gf, "dgm:relIds");
@@ -152,7 +229,9 @@ function parseGraphicFrame(gf, ctx, transform) {
152
229
  if (dmRelId !== void 0) ctx.onLoss?.(noDiagramOverrideLoss());
153
230
  return [];
154
231
  }
155
- return parseDiagramDrawing(spTree, diagramTransform(spTree, box), floatAt, ctx.colors ?? defaultColorResolver, ctx.resolveHyperlink).map((shape) => ({
232
+ const drawn = parseDiagramDrawing(spTree, diagramTransform(spTree, box), floatAt, ctx.colors ?? defaultColorResolver, ctx.resolveHyperlink);
233
+ if (drawn.length === 0) ctx.onLoss?.(noDiagramOverrideLoss());
234
+ return drawn.map((shape) => ({
156
235
  kind: "shape",
157
236
  shape
158
237
  }));
@@ -229,9 +308,9 @@ function parseDiagramNodes(spTree, transform, colors, resolveLink, resolveImage)
229
308
  const box = transform(own);
230
309
  const txBody = poChildren(sp).find((c) => poIs(c, "dsp:txBody"));
231
310
  const parsed = txBody ? parseTxBody(txBody, void 0, void 0, colors, resolveLink) : void 0;
232
- const text = parsed ? withDiagramFontColor(parsed, sp, colors) : void 0;
233
311
  const geometry = parseGeometry(spPr);
234
312
  const fill = spPr ? parseFill(spPr, colors, resolveImage) : { kind: "none" };
313
+ const text = parsed ? withDiagramFontColor(parsed, sp, colors, fill) : void 0;
235
314
  const line = spPr ? parseLine(spPr, colors) : void 0;
236
315
  const shadow = spPr ? parseShadow(spPr, colors) : void 0;
237
316
  const visibleLine = line !== void 0 && line.fill !== "none";
@@ -287,12 +366,13 @@ function parseDiagramDrawing(spTree, transform, makeFloat, colors, resolveLink)
287
366
  float: makeFloat(box)
288
367
  }));
289
368
  }
290
- function withDiagramFontColor(text, sp, colors) {
369
+ function withDiagramFontColor(text, sp, colors, fill) {
291
370
  const style = poChildren(sp).find((c) => poIs(c, "dsp:style"));
292
371
  const ref = style ? poChildren(style).find((c) => poIs(c, "a:fontRef")) : void 0;
293
372
  const child = ref ? poChildren(ref).find((c) => poTag(c) !== void 0) : void 0;
294
373
  const colorHex = child ? resolveColorNode(child, colors) : void 0;
295
374
  if (colorHex === void 0) return text;
375
+ if (fill.kind === "solid" && fill.colorHex === colorHex) return text;
296
376
  return {
297
377
  ...text,
298
378
  content: text.content.map((block) => block.kind === "paragraph" ? {
@@ -311,26 +391,45 @@ function withDiagramFontColor(text, sp, colors) {
311
391
  };
312
392
  }
313
393
  /**
314
- * `p:bg` → the background fill, or `undefined` when none/unsupported. `p:bgPr`
315
- * carries the fill directly (`a:solidFill`/`a:gradFill` — the same children
316
- * `parseFill` reads; a picture background is not yet supported); `p:bgRef` (a
317
- * theme fill-style index) is approximated by its colour child as a solid fill.
394
+ * `p:bg` → the background fill, or `undefined` when it declares none.
395
+ *
396
+ * Two spellings. `p:bgPr` carries the fill itself — solid, gradient, or a
397
+ * PICTURE, which needs the owning part's image resolver since the blip's
398
+ * relationship is scoped to the part the background is written in. `p:bgRef`
399
+ * (§19.3.1.2) carries no fill at all: an index into the theme's style lists and
400
+ * the colour to put wherever that style says `phClr`. Read as its colour alone
401
+ * — which is all this did — a deck whose theme opens with a black-to-grey
402
+ * gradient came out flat, and one whose first background slot is a picture came
403
+ * out a single colour.
404
+ *
318
405
  * Used for the slide's own background and the inherited layout/master one (PX5b).
406
+ *
407
+ * @param bg The `p:bg` node.
408
+ * @param colors The deck's colour resolver.
409
+ * @param resolveImage Resolver for a picture background's relationship, scoped
410
+ * to the part this `p:bg` is written in.
411
+ * @param theme The theme's fill style lists, for a `p:bgRef`.
319
412
  */
320
- function parseBackgroundFill(bg, colors) {
413
+ function parseBackgroundFill(bg, colors, resolveImage, theme) {
321
414
  const bgPr = poChildren(bg).find((c) => poIs(c, "p:bgPr"));
322
415
  if (bgPr) {
323
- const fill = parseFill(bgPr, colors);
416
+ const fill = parseFill(bgPr, colors, resolveImage);
324
417
  return fill.kind !== "none" ? fill : void 0;
325
418
  }
326
419
  const bgRef = poChildren(bg).find((c) => poIs(c, "p:bgRef"));
327
- if (bgRef) for (const c of poChildren(bgRef)) {
328
- const hex = resolveColorNode(c, colors);
329
- if (hex) return {
330
- kind: "solid",
331
- colorHex: hex
332
- };
420
+ if (!bgRef) return void 0;
421
+ const child = poChildren(bgRef).find((c) => poTag(c) !== void 0);
422
+ const hex = child ? resolveColorNode(child, colors) : void 0;
423
+ const idx = poIntAttr(bgRef, "idx");
424
+ const slot = idx === void 0 ? void 0 : idx > 1e3 ? theme?.backgrounds[idx - 1001] : theme?.fills[idx - 1];
425
+ if (slot) {
426
+ const themed = parseFill({ "a:spPr": [slot] }, hex === void 0 ? colors : placeholderColors(colors, hex), theme?.resolveImage ?? resolveImage);
427
+ if (themed.kind !== "none") return themed;
333
428
  }
429
+ return hex === void 0 ? void 0 : {
430
+ kind: "solid",
431
+ colorHex: hex
432
+ };
334
433
  }
335
434
  /**
336
435
  * A full-slide backdrop element for a background fill: a rectangle covering the
@@ -364,11 +463,73 @@ function backdropElement(fill, widthPt, heightPt) {
364
463
  }
365
464
  };
366
465
  }
466
+ function backgroundThrough(bg, box, slide) {
467
+ if (!bg) return { kind: "none" };
468
+ if (bg.kind !== "picture" || !slide || box.cx <= 0 || box.cy <= 0) return bg;
469
+ const [x, y] = [emuToPt(box.x), emuToPt(box.y)];
470
+ const [w, h] = [emuToPt(box.cx), emuToPt(box.cy)];
471
+ return {
472
+ ...bg,
473
+ imageFillRect: {
474
+ left: -x / w,
475
+ top: -y / h,
476
+ right: -(slide.widthPt - x - w) / w,
477
+ bottom: -(slide.heightPt - y - h) / h
478
+ }
479
+ };
480
+ }
481
+ /**
482
+ * The same element, painted BEHIND the slide's own content.
483
+ *
484
+ * §19.3.1 — a slide's shape tree is drawn over its layout's, and that over the
485
+ * master's; nothing a deck states once can bury what a slide puts on it. Our
486
+ * page paints by KIND (every image, then every shape), so without this a
487
+ * layout's white card landed on top of the photograph the slide is made of —
488
+ * themes.pptx's fifth slide is one picture and it vanished under the card.
489
+ *
490
+ * @param el The inherited element.
491
+ * @returns The element with its float sunk to the backdrop layer.
492
+ */
493
+ function asBackdrop(el) {
494
+ const sink = (item) => item.float ? {
495
+ ...item,
496
+ float: {
497
+ ...item.float,
498
+ behind: true
499
+ }
500
+ } : item;
501
+ switch (el.kind) {
502
+ case "shape": return {
503
+ ...el,
504
+ shape: sink(el.shape)
505
+ };
506
+ case "image": return {
507
+ ...el,
508
+ image: sink(el.image)
509
+ };
510
+ case "table": return {
511
+ ...el,
512
+ table: {
513
+ ...el.table,
514
+ properties: sink(el.table.properties)
515
+ }
516
+ };
517
+ case "chart": return {
518
+ ...el,
519
+ chart: sink(el.chart)
520
+ };
521
+ default: return el;
522
+ }
523
+ }
367
524
  /**
368
525
  * `p:spPr` geometry: `a:prstGeom` (preset) or `a:custGeom` (custom path), default
369
526
  * rect. Exported for sheet shapes (E-SHEET W2), whose `xdr:spPr` carries the same
370
527
  * `a:` children.
371
528
  */
529
+ /** Whether an `spPr` states a geometry of its own, rather than inheriting one. */
530
+ function statesGeometry(spPr) {
531
+ return poChildren(spPr).some((c) => poIs(c, "a:prstGeom") || poIs(c, "a:custGeom"));
532
+ }
372
533
  function parseGeometry(spPr) {
373
534
  if (!spPr) return RECT_GEOMETRY;
374
535
  const prst = poChildren(spPr).find((c) => poIs(c, "a:prstGeom"));
@@ -385,10 +546,16 @@ function parsePic(pic, ctx, transform) {
385
546
  const blip = blipFill ? poChildren(blipFill).find((c) => poIs(c, "a:blip")) : void 0;
386
547
  const relId = blip ? poAttr(blip, "embed") : void 0;
387
548
  const resource = relId !== void 0 ? ctx.resolveImage?.(relId) : void 0;
549
+ const colorChange = blip ? colorChangeOf(blip, ctx.colors ?? defaultColorResolver) : void 0;
550
+ const fixed = blip ? poChildren(blip).find((c) => poIs(c, "a:alphaModFix")) : void 0;
551
+ const amt = fixed ? poIntAttr(fixed, "amt") : void 0;
552
+ const alpha = amt === void 0 ? void 0 : Math.min(1, Math.max(0, amt / 1e5));
388
553
  const altText = picAltText(pic);
389
554
  return {
390
555
  float: floatAt(box),
391
556
  ...resource !== void 0 ? { resource } : {},
557
+ ...colorChange ? { colorChange } : {},
558
+ ...alpha !== void 0 && alpha < 1 ? { alpha } : {},
392
559
  width: emuToPt(box.cx),
393
560
  height: emuToPt(box.cy),
394
561
  paragraphProperties: {},
@@ -402,14 +569,14 @@ function picAltText(pic) {
402
569
  const title = cNvPr ? poAttr(cNvPr, "title") : void 0;
403
570
  return (descr ?? title)?.trim() || void 0;
404
571
  }
405
- function txBodyParagraphs(txBody, ph, cascade, colors, resolveLink) {
572
+ function txBodyParagraphs(txBody, ph, cascade, colors, resolveLink, styleColor) {
406
573
  const content = [];
407
574
  const counters = [];
408
575
  for (const child of poChildren(txBody)) {
409
576
  if (!poIs(child, "a:p")) continue;
410
577
  content.push({
411
578
  kind: "paragraph",
412
- paragraph: parseSlideParagraph(child, ph, cascade, colors, resolveLink, counters)
579
+ paragraph: parseSlideParagraph(child, ph, cascade, colors, resolveLink, counters, styleColor)
413
580
  });
414
581
  }
415
582
  return content;
@@ -427,8 +594,8 @@ function txBodyParagraphs(txBody, ph, cascade, colors, resolveLink) {
427
594
  * @param resolveLink A run hyperlink resolver, or `undefined`.
428
595
  * @returns The text body, or `undefined` when it holds no paragraphs.
429
596
  */
430
- function parseTxBody(txBody, ph, cascade, colors, resolveLink) {
431
- const content = txBodyParagraphs(txBody, ph, cascade, colors, resolveLink);
597
+ function parseTxBody(txBody, ph, cascade, colors, resolveLink, styleColor) {
598
+ const content = txBodyParagraphs(txBody, ph, cascade, colors, resolveLink, styleColor);
432
599
  if (content.length === 0) return void 0;
433
600
  const bodyPr = poChildren(txBody).find((c) => poIs(c, "a:bodyPr"));
434
601
  const lIns = bodyPr ? poIntAttr(bodyPr, "lIns") : void 0;
@@ -436,7 +603,7 @@ function parseTxBody(txBody, ph, cascade, colors, resolveLink) {
436
603
  const rIns = bodyPr ? poIntAttr(bodyPr, "rIns") : void 0;
437
604
  const bIns = bodyPr ? poIntAttr(bodyPr, "bIns") : void 0;
438
605
  const a = bodyPr ? poAttr(bodyPr, "anchor") : void 0;
439
- const anchor = a === "ctr" ? "ctr" : a === "b" ? "b" : a === "t" ? "t" : void 0;
606
+ const anchor = a === "ctr" || a === "b" || a === "t" ? a : ph && cascade ? cascade.anchorFor(ph) : void 0;
440
607
  return {
441
608
  content,
442
609
  ...lIns !== void 0 ? { insetLeft: emuToPt(lIns) } : {},
@@ -446,23 +613,38 @@ function parseTxBody(txBody, ph, cascade, colors, resolveLink) {
446
613
  ...anchor ? { anchor } : {}
447
614
  };
448
615
  }
449
- function parseSlideParagraph(aP, ph, cascade, colors, resolveLink, counters) {
616
+ function parseSlideParagraph(aP, ph, cascade, colors, resolveLink, counters, styleColor) {
450
617
  const pPr = poChildren(aP).find((c) => poIs(c, "a:pPr"));
451
618
  const level = (pPr ? poIntAttr(pPr, "lvl") : void 0) ?? 0;
452
- const defaults = ph && cascade ? cascade.defaultsFor(ph, level) : {};
619
+ const defaults = {
620
+ ...cascade ? cascade.defaultsFor(ph, level) : {},
621
+ ...styleColor !== void 0 ? { colorHex: styleColor } : {}
622
+ };
623
+ const inherited = cascade ? cascade.paragraphDefaultsFor(ph, level) : {};
453
624
  const algn = pPr ? poAttr(pPr, "algn") : void 0;
454
625
  const alignment = algn !== void 0 ? ALGN_TO_ALIGNMENT[algn] : void 0;
455
626
  const runs = [];
456
- const marker = bulletMarker(pPr, level, counters);
457
- if (marker !== void 0) runs.push({
458
- text: marker,
459
- properties: defaults,
460
- listMarker: true
461
- });
462
627
  for (const child of poChildren(aP)) if (poIs(child, "a:r") || poIs(child, "a:fld")) {
463
628
  const run = parseSlideRun(child, defaults, colors, resolveLink);
464
629
  if (run) runs.push(run);
465
630
  }
631
+ const marL = pPr ? poIntAttr(pPr, "marL") : void 0;
632
+ const indent = pPr ? poIntAttr(pPr, "indent") : void 0;
633
+ const indentLeft = marL !== void 0 ? emuToPt(marL) : level > 0 ? emuToPt(level * 457200) : void 0;
634
+ const hanging = (indent !== void 0 ? emuToPt(indent) : inherited.indentFirstLine ?? 0) < 0;
635
+ const bullet = {
636
+ ...cascade?.bulletFor(ph, level),
637
+ ...parseBullet(pPr, colors)
638
+ };
639
+ const marker = bulletMarker(bullet, level, counters);
640
+ if (marker !== void 0) {
641
+ const base = runs[0]?.properties ?? defaults;
642
+ runs.unshift({
643
+ text: marker + (hanging ? " " : " "),
644
+ properties: bulletProps(base, bullet),
645
+ listMarker: true
646
+ });
647
+ }
466
648
  if (runs.length === 0) {
467
649
  const endRPr = poChildren(aP).find((c) => poIs(c, "a:endParaRPr"));
468
650
  const sz = endRPr ? poIntAttr(endRPr, "sz") : void 0;
@@ -474,11 +656,9 @@ function parseSlideParagraph(aP, ph, cascade, colors, resolveLink, counters) {
474
656
  }
475
657
  });
476
658
  }
477
- const marL = pPr ? poIntAttr(pPr, "marL") : void 0;
478
- const indent = pPr ? poIntAttr(pPr, "indent") : void 0;
479
- const indentLeft = marL !== void 0 ? emuToPt(marL) : level > 0 ? emuToPt(level * 457200) : void 0;
480
659
  return {
481
660
  properties: {
661
+ ...inherited,
482
662
  ...alignment ? { alignment } : {},
483
663
  ...indentLeft !== void 0 ? { indentLeft } : {},
484
664
  ...indent !== void 0 ? { indentFirstLine: emuToPt(indent) } : {}
@@ -486,20 +666,22 @@ function parseSlideParagraph(aP, ph, cascade, colors, resolveLink, counters) {
486
666
  runs
487
667
  };
488
668
  }
489
- function bulletMarker(pPr, level, counters) {
490
- if (!pPr) return void 0;
491
- if (poChildren(pPr).some((c) => poIs(c, "a:buNone"))) return void 0;
492
- const buChar = poChildren(pPr).find((c) => poIs(c, "a:buChar"));
493
- if (buChar) return `${poAttr(buChar, "char") ?? "•"} `;
494
- const buAuto = poChildren(pPr).find((c) => poIs(c, "a:buAutoNum"));
495
- if (!buAuto) return void 0;
496
- const type = poAttr(buAuto, "type") ?? "arabicPeriod";
497
- const startAt = poIntAttr(buAuto, "startAt") ?? 1;
669
+ function bulletProps(base, bullet) {
670
+ const sizePt = bullet.sizePts ?? (bullet.sizePct !== void 0 && base.fontSizePt !== void 0 ? base.fontSizePt * bullet.sizePct : void 0);
671
+ return {
672
+ ...base,
673
+ ...sizePt !== void 0 ? { fontSizePt: pt(sizePt) } : {},
674
+ ...bullet.colorHex !== void 0 ? { colorHex: bullet.colorHex } : {}
675
+ };
676
+ }
677
+ function bulletMarker(bullet, level, counters) {
678
+ if (!bullet || bullet.kind === "none" || bullet.kind === void 0) return void 0;
679
+ if (bullet.kind === "char") return bullet.char ?? "•";
498
680
  const prev = counters[level];
499
- const n = (prev === void 0 ? startAt - 1 : prev) + 1;
681
+ const n = (prev === void 0 ? (bullet.startAt ?? 1) - 1 : prev) + 1;
500
682
  counters[level] = n;
501
683
  counters.length = level + 1;
502
- return `${n}${autoNumSuffix(type)} `;
684
+ return `${n}${autoNumSuffix(bullet.type ?? "arabicPeriod")}`;
503
685
  }
504
686
  function autoNumSuffix(type) {
505
687
  if (type.endsWith("ParenR") || type.endsWith("ParenBoth")) return ")";
@@ -523,31 +705,57 @@ function parseSlideRun(node, defaults, colors, resolveLink) {
523
705
  ...href ? { href } : {}
524
706
  };
525
707
  }
526
- function parseTable(tbl, colors) {
708
+ function parseTable(tbl, colors, resolveTableStyle) {
527
709
  const grid = [];
528
710
  const tblGrid = poChildren(tbl).find((c) => poIs(c, "a:tblGrid"));
529
711
  if (tblGrid) {
530
712
  for (const col of poChildren(tblGrid)) if (poIs(col, "a:gridCol")) grid.push(emuToPt(poIntAttr(col, "w") ?? 0));
531
713
  }
532
714
  const rows = [];
533
- for (const tr of poChildren(tbl)) if (poIs(tr, "a:tr")) rows.push(parseTableRow(tr, colors));
534
- return {
715
+ const sources = [];
716
+ for (const tr of poChildren(tbl)) {
717
+ if (!poIs(tr, "a:tr")) continue;
718
+ const cells = rowCells(tr);
719
+ sources.push(cells);
720
+ rows.push(parseTableRow(tr, cells, colors));
721
+ }
722
+ const tblPr = poChildren(tbl).find((c) => poIs(c, "a:tblPr"));
723
+ const style = resolveTableStyle?.(tableStyleId(tblPr));
724
+ if (!style) return {
535
725
  properties: {},
536
726
  grid,
537
727
  rows
538
728
  };
729
+ const flags = tableStyleFlags(tblPr);
730
+ return {
731
+ properties: {},
732
+ grid,
733
+ rows: rows.map((row, r) => ({
734
+ ...row,
735
+ cells: row.cells.map((cell, c) => {
736
+ const part = cellStyle(style, flags, {
737
+ row: r,
738
+ rowCount: rows.length,
739
+ col: c,
740
+ colCount: grid.length
741
+ }, colors);
742
+ const tc = sources[r]?.[c];
743
+ return withCellStyle(cell, tc && cellSaysNoFill(tc) ? withoutFill(part) : part);
744
+ })
745
+ }))
746
+ };
539
747
  }
540
- function parseTableRow(tr, colors) {
748
+ function rowCells(tr) {
749
+ return poChildren(tr).filter((tc) => poIs(tc, "a:tc") && poAttr(tc, "hMerge") !== "1");
750
+ }
751
+ function parseTableRow(tr, cells, colors) {
541
752
  const h = poIntAttr(tr, "h");
542
- const cells = [];
543
- for (const tc of poChildren(tr)) {
544
- if (!poIs(tc, "a:tc")) continue;
545
- if (poAttr(tc, "hMerge") === "1") continue;
546
- cells.push(parseTableCell(tc, colors));
547
- }
548
753
  return {
549
- properties: { ...h !== void 0 ? { height: emuToPt(h) } : {} },
550
- cells
754
+ properties: { ...h !== void 0 ? {
755
+ height: emuToPt(h),
756
+ heightRule: "atLeast"
757
+ } : {} },
758
+ cells: cells.map((tc) => parseTableCell(tc, colors))
551
759
  };
552
760
  }
553
761
  function parseTableCell(tc, colors) {
@@ -558,15 +766,35 @@ function parseTableCell(tc, colors) {
558
766
  const merge = rowSpan !== void 0 && rowSpan > 1 ? "start" : poAttr(tc, "vMerge") === "1" ? "middle" : void 0;
559
767
  const tcPr = poChildren(tc).find((c) => poIs(c, "a:tcPr"));
560
768
  const shadingHex = tcPr ? cellFillHex(tcPr, colors) : void 0;
769
+ const borders = tcPr ? cellOwnBorders(tcPr, colors) : void 0;
561
770
  return {
562
771
  properties: {
563
772
  ...gridSpan !== void 0 && gridSpan > 1 ? { colSpan: gridSpan } : {},
564
773
  ...merge ? { merge } : {},
565
- ...shadingHex ? { shading: { colorHex: shadingHex } } : {}
774
+ ...shadingHex ? { shading: { colorHex: shadingHex } } : {},
775
+ ...borders ? { borders } : {}
566
776
  },
567
777
  content
568
778
  };
569
779
  }
780
+ var CELL_LINES = [
781
+ ["a:lnL", "left"],
782
+ ["a:lnR", "right"],
783
+ ["a:lnT", "top"],
784
+ ["a:lnB", "bottom"]
785
+ ];
786
+ function cellOwnBorders(tcPr, colors) {
787
+ const out = {};
788
+ for (const [tag, side] of CELL_LINES) {
789
+ const ln = poChildren(tcPr).find((c) => poIs(c, tag));
790
+ if (ln) out[side] = lineBorder(ln, colors);
791
+ }
792
+ return Object.keys(out).length > 0 ? out : void 0;
793
+ }
794
+ function cellSaysNoFill(tc) {
795
+ const tcPr = poChildren(tc).find((c) => poIs(c, "a:tcPr"));
796
+ return tcPr !== void 0 && poChildren(tcPr).some((c) => poIs(c, "a:noFill"));
797
+ }
570
798
  function cellFillHex(tcPr, colors) {
571
799
  const solidFill = poChildren(tcPr).find((c) => poIs(c, "a:solidFill"));
572
800
  if (!solidFill) return void 0;
@@ -576,4 +804,4 @@ function cellFillHex(tcPr, colors) {
576
804
  }
577
805
  }
578
806
  //#endregion
579
- export { backdropElement, diagramTransform, noDiagramOverrideLoss, parseBackgroundFill, parseDiagramNodes, parseGeometry, parseSlideShapes, parseTxBody };
807
+ export { asBackdrop, backdropElement, diagramTransform, noDiagramOverrideLoss, parseBackgroundFill, parseDiagramNodes, parseGeometry, parseSlideShapes, parseTxBody };
@@ -61,14 +61,29 @@ function rPrToRunProps(rPr, colors) {
61
61
  const colorHex = solidFillColor(rPr, colors);
62
62
  const latin = poChildren(rPr).find((c) => poIs(c, "a:latin"));
63
63
  const typeface = latin ? poAttr(latin, "typeface")?.trim() : void 0;
64
+ const flag = (name) => {
65
+ const v = poAttr(rPr, name);
66
+ return v === void 0 ? void 0 : isTrue(v);
67
+ };
68
+ const [b, i] = [flag("b"), flag("i")];
64
69
  return {
65
- ...isTrue(poAttr(rPr, "b")) ? { bold: true } : {},
66
- ...isTrue(poAttr(rPr, "i")) ? { italic: true } : {},
67
- ...u !== void 0 && u !== "none" ? { underline: "single" } : {},
70
+ ...b !== void 0 ? { bold: b } : {},
71
+ ...i !== void 0 ? { italic: i } : {},
72
+ ...u !== void 0 ? { underline: u === "none" ? "none" : "single" } : {},
68
73
  ...sz !== void 0 ? { fontSizePt: pt(sz / 100) } : {},
69
74
  ...colorHex ? { colorHex } : {},
70
- ...typeface ? { fontFamily: { ascii: typeface } } : {}
75
+ ...typeface ? { fontFamily: { ascii: typeface } } : {},
76
+ ...capsOf(poAttr(rPr, "cap"))
77
+ };
78
+ }
79
+ function capsOf(cap) {
80
+ if (cap === "all") return { caps: true };
81
+ if (cap === "small") return { smallCaps: true };
82
+ if (cap === "none") return {
83
+ caps: false,
84
+ smallCaps: false
71
85
  };
86
+ return {};
72
87
  }
73
88
  function solidFillColor(rPr, colors) {
74
89
  const solidFill = poChildren(rPr).find((c) => poIs(c, "a:solidFill"));