ooxml-core 1.19.2 → 1.20.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 (75) hide show
  1. package/README.md +12 -1
  2. package/dist/{PptxHandler-2V4PQL6O.mjs → PptxHandler-FYD7IYXT.mjs} +2 -2
  3. package/dist/PptxHandler-SITN3K3F.mjs +4 -0
  4. package/dist/{PptxHandler-6TNIQ7S5.cjs → PptxHandler-TEKISCJO.cjs} +3 -3
  5. package/dist/{PresentationBuilder-HQ6C7L4V.mjs → PresentationBuilder-EYI6Z2JP.mjs} +2 -2
  6. package/dist/{PresentationBuilder-G7MPEGXJ.mjs → PresentationBuilder-IMB4DVRN.mjs} +2 -2
  7. package/dist/{PresentationBuilder-RM52LCVN.cjs → PresentationBuilder-NCKASKXU.cjs} +5 -5
  8. package/dist/automation/index.cjs +257 -30
  9. package/dist/automation/index.mjs +256 -31
  10. package/dist/automation/xlsx-read.d.ts +56 -0
  11. package/dist/automation/xlsx-read.d.ts.map +1 -0
  12. package/dist/automation/xlsx.d.ts +105 -4
  13. package/dist/automation/xlsx.d.ts.map +1 -1
  14. package/dist/{chunk-M6GDBVQ7.mjs → chunk-GQYQQ3GA.mjs} +1 -1
  15. package/dist/{chunk-SLNQNVQM.mjs → chunk-LEV2SVMK.mjs} +1 -1
  16. package/dist/{chunk-JUABSM7C.mjs → chunk-LVM3IZJ2.mjs} +1 -1
  17. package/dist/{chunk-TJPUAUWL.mjs → chunk-MN27HKHM.mjs} +8 -194
  18. package/dist/{chunk-4FTUAD2B.mjs → chunk-MNXKRXFB.mjs} +715 -200
  19. package/dist/{chunk-R5FIHHGB.cjs → chunk-NXKATFM5.cjs} +1598 -1204
  20. package/dist/{chunk-ZJ2OKIJN.mjs → chunk-WXY5EDGT.mjs} +592 -198
  21. package/dist/index.cjs +25 -0
  22. package/dist/index.mjs +25 -0
  23. package/dist/pptx/automation/index.cjs +887 -453
  24. package/dist/pptx/automation/index.d.ts +2 -2
  25. package/dist/pptx/automation/index.mjs +5 -5
  26. package/dist/pptx/chunks/{index-Bqm-jFG-.d.ts → index-CgFX0T7b.d.ts} +7573 -7508
  27. package/dist/pptx/chunks/index-CgFX0T7b.d.ts.map +1 -0
  28. package/dist/pptx/chunks/{index-B9x557hr.d.ts → index-qwVYoFn6.d.ts} +2 -2
  29. package/dist/pptx/chunks/{index-B9x557hr.d.ts.map → index-qwVYoFn6.d.ts.map} +1 -1
  30. package/dist/pptx/cli/index.cjs +654 -221
  31. package/dist/pptx/cli/index.mjs +4 -4
  32. package/dist/pptx/converter/index.d.ts +1 -1
  33. package/dist/pptx/converter/index.mjs +2 -2
  34. package/dist/pptx/editor/render/find-replace.cjs +14 -14
  35. package/dist/pptx/editor/render/find-replace.d.ts +1 -1
  36. package/dist/pptx/editor/render/find-replace.mjs +1 -1
  37. package/dist/pptx/editor/render/slide-operations.cjs +8 -8
  38. package/dist/pptx/editor/render/slide-operations.mjs +2 -2
  39. package/dist/pptx/index.cjs +991 -619
  40. package/dist/pptx/index.d.ts +3 -3
  41. package/dist/pptx/index.mjs +5 -5
  42. package/dist/visio/index.cjs +61 -7
  43. package/dist/visio/index.mjs +61 -7
  44. package/dist/visio/ui/contract.d.ts +2 -1
  45. package/dist/visio/ui/contract.d.ts.map +1 -1
  46. package/dist/visio/ui/index.cjs +62 -7
  47. package/dist/visio/ui/index.mjs +62 -7
  48. package/dist/xlsx/edit/dimensions.d.ts.map +1 -1
  49. package/dist/xlsx/edit/history-rows.d.ts +7 -0
  50. package/dist/xlsx/edit/history-rows.d.ts.map +1 -0
  51. package/dist/xlsx/edit/history.d.ts +11 -1
  52. package/dist/xlsx/edit/history.d.ts.map +1 -1
  53. package/dist/xlsx/edit/outline.d.ts.map +1 -1
  54. package/dist/xlsx/edit/row-autofit.d.ts.map +1 -1
  55. package/dist/xlsx/index.cjs +90 -16
  56. package/dist/xlsx/index.mjs +90 -16
  57. package/dist/xlsx/load/index.cjs +61 -7
  58. package/dist/xlsx/load/index.mjs +61 -7
  59. package/dist/xlsx/numfmt/format.d.ts +8 -0
  60. package/dist/xlsx/numfmt/format.d.ts.map +1 -1
  61. package/dist/xlsx/read/sheet-data-source.d.ts.map +1 -1
  62. package/dist/xlsx/ui/index.cjs +138 -16
  63. package/dist/xlsx/ui/index.d.ts +1 -0
  64. package/dist/xlsx/ui/index.d.ts.map +1 -1
  65. package/dist/xlsx/ui/index.mjs +138 -17
  66. package/dist/xlsx/ui/selection-format.d.ts +13 -0
  67. package/dist/xlsx/ui/selection-format.d.ts.map +1 -0
  68. package/dist/xml/index.cjs +25 -0
  69. package/dist/xml/index.mjs +25 -0
  70. package/dist/xml/lite.d.ts.map +1 -1
  71. package/package.json +1 -1
  72. package/dist/PptxHandler-HSPKEP5E.mjs +0 -4
  73. package/dist/pptx/chunks/index-Bqm-jFG-.d.ts.map +0 -1
  74. /package/dist/{chunk-NYTR4UZ5.cjs → chunk-3IENHIFD.cjs} +0 -0
  75. /package/dist/{chunk-XTSHZGSM.mjs → chunk-CC5UNZOO.mjs} +0 -0
@@ -53297,13 +53297,14 @@ var init_SlideBuilder = __esm({
53297
53297
  "pptx/core/builders/sdk/SlideBuilder.ts"() {
53298
53298
  init_ElementFactory();
53299
53299
  SlideBuilder = class {
53300
- slide;
53301
53300
  /**
53302
53301
  * @param slideNumber - 1-based slide number.
53303
53302
  * @param layoutPath - Optional layout archive path.
53304
53303
  * @param layoutName - Optional layout display name.
53304
+ * @param handler - Loaded deck context for placeholder geometry and text styles.
53305
53305
  */
53306
- constructor(slideNumber, layoutPath, layoutName) {
53306
+ constructor(slideNumber, layoutPath, layoutName, handler) {
53307
+ this.handler = handler;
53307
53308
  this.slide = {
53308
53309
  id: `slide${slideNumber}`,
53309
53310
  rId: `rId${slideNumber + 1}`,
@@ -53313,11 +53314,52 @@ var init_SlideBuilder = __esm({
53313
53314
  layoutName: layoutName ?? "Title Slide"
53314
53315
  };
53315
53316
  }
53317
+ handler;
53318
+ slide;
53316
53319
  /** Add a text box to the slide. */
53317
53320
  addText(text2, options) {
53318
53321
  this.slide.elements.push(createTextElement(text2, options));
53319
53322
  return this;
53320
53323
  }
53324
+ /**
53325
+ * Fill a layout placeholder, inheriting its frame and text styles.
53326
+ *
53327
+ * Unlike addText, this writes a real p:ph binding, not a free text box.
53328
+ * Use idx to select repeated slots (for example, Two Content's 1 and 2).
53329
+ * Explicit frame fields override the layout; all other fields inherit.
53330
+ * A standalone builder requires the fourth constructor argument (a loaded
53331
+ * handler), even with an explicit frame, so text styles resolve consistently.
53332
+ * Missing slots without a complete frame throw instead of creating a text box.
53333
+ * Master frames requiring compatible-role fallback are materialized locally
53334
+ * for new content only, keeping existing-deck loading unchanged.
53335
+ *
53336
+ * @example
53337
+ * ```ts
53338
+ * createSlide('Title Slide')
53339
+ * .addPlaceholder('ctrTitle', 'Quarterly review')
53340
+ * .addPlaceholder('subTitle', 'October 2026');
53341
+ * createSlide('Two Content').addPlaceholder('body', 'Right column', { idx: 2 });
53342
+ * ```
53343
+ */
53344
+ addPlaceholder(type, text2, options = {}) {
53345
+ const input = createTextElement(text2);
53346
+ const context = `Slide ${this.slide.slideNumber} (${this.slide.id}), placeholder ${type} idx=${options.idx ?? "auto"}, layout ${this.slide.layoutName} (${this.slide.layoutPath})`;
53347
+ try {
53348
+ if (!this.handler) {
53349
+ throw new Error(
53350
+ "addPlaceholder requires a loaded handler as the fourth SlideBuilder constructor argument"
53351
+ );
53352
+ }
53353
+ this.slide.elements.push(
53354
+ this.handler.createPlaceholderElement(this.slide.layoutPath, input, type, options)
53355
+ );
53356
+ } catch (error) {
53357
+ throw new Error(`${context}: ${error instanceof Error ? error.message : String(error)}`, {
53358
+ cause: error
53359
+ });
53360
+ }
53361
+ return this;
53362
+ }
53321
53363
  /** Add a shape to the slide. */
53322
53364
  addShape(shapeType, options) {
53323
53365
  this.slide.elements.push(createShapeElement(shapeType, options));
@@ -53557,6 +53599,34 @@ var init_SlideBuilder = __esm({
53557
53599
  };
53558
53600
  }
53559
53601
  });
53602
+
53603
+ // pptx/core/builders/sdk/layout-operations.ts
53604
+ function pxToEmu(px2) {
53605
+ return Math.round(px2 * EMU_PER_PIXEL2);
53606
+ }
53607
+ function placeholderSpXml(ph, shapeId) {
53608
+ const name = ph.name ?? `${ph.type.charAt(0).toUpperCase() + ph.type.slice(1)} Placeholder ${shapeId - 1}`;
53609
+ const x = pxToEmu(ph.x);
53610
+ const y = pxToEmu(ph.y);
53611
+ const cx = pxToEmu(ph.width);
53612
+ const cy = pxToEmu(ph.height);
53613
+ const idxAttr = ph.idx !== void 0 ? ` idx="${Math.max(0, Math.round(ph.idx))}"` : "";
53614
+ return ` <p:sp>
53615
+ <p:nvSpPr>
53616
+ <p:cNvPr id="${shapeId}" name="${escAttr(name)}"/>
53617
+ <p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr>
53618
+ <p:nvPr><p:ph type="${escAttr(ph.type)}"${idxAttr}/></p:nvPr>
53619
+ </p:nvSpPr>
53620
+ <p:spPr>
53621
+ <a:xfrm><a:off x="${x}" y="${y}"/><a:ext cx="${cx}" cy="${cy}"/></a:xfrm>
53622
+ </p:spPr>
53623
+ <p:txBody>
53624
+ <a:bodyPr/>
53625
+ <a:lstStyle/>
53626
+ <a:p><a:endParaRPr lang="en-US"/></a:p>
53627
+ </p:txBody>
53628
+ </p:sp>`;
53629
+ }
53560
53630
  function normalizeSrgbHex(color2) {
53561
53631
  if (!color2) {
53562
53632
  return void 0;
@@ -53570,10 +53640,111 @@ function normalizeSrgbHex(color2) {
53570
53640
  }
53571
53641
  return void 0;
53572
53642
  }
53643
+ function generateLayoutXml(definition) {
53644
+ const layoutType = definition.type ?? "obj";
53645
+ const placeholders = definition.placeholders ?? [];
53646
+ const phShapes = placeholders.map((ph, i2) => placeholderSpXml(ph, i2 + 2)).join("\n");
53647
+ let bgXml = "";
53648
+ const hex3 = normalizeSrgbHex(definition.backgroundColor);
53649
+ if (hex3) {
53650
+ bgXml = ` <p:bg><p:bgPr><a:solidFill><a:srgbClr val="${hex3}"/></a:solidFill><a:effectLst/></p:bgPr></p:bg>
53651
+ `;
53652
+ }
53653
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
53654
+ <p:sldLayout xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
53655
+ xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
53656
+ xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"
53657
+ type="${escAttr(layoutType)}" preserve="1">
53658
+ <p:cSld name="${escAttr(definition.name)}">
53659
+ ${bgXml} <p:spTree>
53660
+ <p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr>
53661
+ <p:grpSpPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/><a:chOff x="0" y="0"/><a:chExt cx="0" cy="0"/></a:xfrm></p:grpSpPr>
53662
+ ${phShapes}
53663
+ </p:spTree>
53664
+ </p:cSld>
53665
+ <p:clrMapOvr><a:masterClrMapping/></p:clrMapOvr>
53666
+ </p:sldLayout>`;
53667
+ }
53668
+ var EMU_PER_PIXEL2;
53669
+ var init_layout_operations = __esm({
53670
+ "pptx/core/builders/sdk/layout-operations.ts"() {
53671
+ init_xml_utils();
53672
+ EMU_PER_PIXEL2 = 9525;
53673
+ }
53674
+ });
53675
+
53676
+ // pptx/core/builders/sdk/standard-layout-placeholders.ts
53677
+ function standardLayoutPlaceholders(type, width, height) {
53678
+ if (type === "blank") return [];
53679
+ const box = (type2, idx, x, y, w, h2) => ({
53680
+ type: type2,
53681
+ idx,
53682
+ x: x * width,
53683
+ y: y * height,
53684
+ width: w * width,
53685
+ height: h2 * height
53686
+ });
53687
+ const title = box("title", 0, 0.05, 0.04, 0.9, 0.15);
53688
+ const content2 = box("obj", 1, 0.05, 0.23, 0.9, 0.64);
53689
+ let slots;
53690
+ switch (type) {
53691
+ case "title":
53692
+ slots = [
53693
+ box("ctrTitle", 0, 0.08, 0.24, 0.84, 0.22),
53694
+ box("subTitle", 1, 0.12, 0.49, 0.76, 0.2)
53695
+ ];
53696
+ break;
53697
+ case "secHead":
53698
+ slots = [box("title", 0, 0.05, 0.37, 0.9, 0.2), box("body", 1, 0.05, 0.6, 0.9, 0.23)];
53699
+ break;
53700
+ case "twoObj":
53701
+ case "twoTxTwoObj":
53702
+ slots = [title, box("obj", 1, 0.05, 0.27, 0.43, 0.6), box("obj", 2, 0.52, 0.27, 0.43, 0.6)];
53703
+ if (type === "twoTxTwoObj")
53704
+ slots.push(box("body", 3, 0.05, 0.2, 0.43, 0.07), box("body", 4, 0.52, 0.2, 0.43, 0.07));
53705
+ break;
53706
+ case "titleOnly":
53707
+ slots = [title];
53708
+ break;
53709
+ case "objTx":
53710
+ case "picTx":
53711
+ slots = [
53712
+ title,
53713
+ box(type === "picTx" ? "pic" : "obj", 1, 0.36, 0.23, 0.59, 0.64),
53714
+ box("body", 2, 0.05, 0.23, 0.27, 0.64)
53715
+ ];
53716
+ break;
53717
+ default:
53718
+ slots = [title, content2];
53719
+ }
53720
+ return [
53721
+ ...slots,
53722
+ box("dt", 10, 0.05, 0.92, 0.25, 0.04),
53723
+ box("ftr", 11, 0.33, 0.92, 0.34, 0.04),
53724
+ box("sldNum", 12, 0.75, 0.92, 0.2, 0.04)
53725
+ ];
53726
+ }
53727
+ var init_standard_layout_placeholders = __esm({
53728
+ "pptx/core/builders/sdk/standard-layout-placeholders.ts"() {
53729
+ }
53730
+ });
53731
+ function normalizeSrgbHex2(color2) {
53732
+ if (!color2) {
53733
+ return void 0;
53734
+ }
53735
+ const raw = color2.trim().replace(/^#/, "").toUpperCase();
53736
+ if (/^[0-9A-F]{6}$/.test(raw)) {
53737
+ return raw;
53738
+ }
53739
+ if (/^[0-9A-F]{3}$/.test(raw)) {
53740
+ return raw.replace(/./g, (ch) => ch + ch);
53741
+ }
53742
+ return void 0;
53743
+ }
53573
53744
  function resolveThemeColors(overrides) {
53574
53745
  const resolved = {};
53575
53746
  for (const [key2, fallback] of Object.entries(DEFAULT_COLORS2)) {
53576
- resolved[key2] = normalizeSrgbHex(overrides?.[key2]) ?? normalizeSrgbHex(fallback) ?? "000000";
53747
+ resolved[key2] = normalizeSrgbHex2(overrides?.[key2]) ?? normalizeSrgbHex2(fallback) ?? "000000";
53577
53748
  }
53578
53749
  return resolved;
53579
53750
  }
@@ -53713,21 +53884,6 @@ ${layoutRels}
53713
53884
  <Relationship Id="rId${layoutCount + 1}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="../theme/theme1.xml"/>
53714
53885
  </Relationships>`;
53715
53886
  }
53716
- function slideLayoutXml(name, layoutType) {
53717
- return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
53718
- <p:sldLayout xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
53719
- xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
53720
- xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"
53721
- type="${escAttr(layoutType)}" preserve="1">
53722
- <p:cSld name="${escAttr(name)}">
53723
- <p:spTree>
53724
- <p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr>
53725
- <p:grpSpPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/><a:chOff x="0" y="0"/><a:chExt cx="0" cy="0"/></a:xfrm></p:grpSpPr>
53726
- </p:spTree>
53727
- </p:cSld>
53728
- <p:clrMapOvr><a:masterClrMapping/></p:clrMapOvr>
53729
- </p:sldLayout>`;
53730
- }
53731
53887
  function slideLayoutRelsXml() {
53732
53888
  return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
53733
53889
  <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
@@ -53876,7 +54032,14 @@ async function buildBlankPresentationArchive(options) {
53876
54032
  zip.file("ppt/slideMasters/_rels/slideMaster1.xml.rels", slideMasterRelsXml(layoutCount));
53877
54033
  for (let i2 = 0; i2 < layoutCount; i2++) {
53878
54034
  const layout = STANDARD_LAYOUTS[i2];
53879
- zip.file(`ppt/slideLayouts/slideLayout${i2 + 1}.xml`, slideLayoutXml(layout.name, layout.type));
54035
+ zip.file(
54036
+ `ppt/slideLayouts/slideLayout${i2 + 1}.xml`,
54037
+ generateLayoutXml({
54038
+ name: layout.name,
54039
+ type: layout.type,
54040
+ placeholders: standardLayoutPlaceholders(layout.type, width / 9525, height / 9525)
54041
+ })
54042
+ );
53880
54043
  zip.file(`ppt/slideLayouts/_rels/slideLayout${i2 + 1}.xml.rels`, slideLayoutRelsXml());
53881
54044
  }
53882
54045
  for (let i2 = 0; i2 < initialSlideCount; i2++) {
@@ -53897,6 +54060,8 @@ var init_PresentationBuilder = __esm({
53897
54060
  init_xml_utils();
53898
54061
  init_PptxHandler();
53899
54062
  init_SlideBuilder();
54063
+ init_layout_operations();
54064
+ init_standard_layout_placeholders();
53900
54065
  DEFAULT_WIDTH = 12192e3;
53901
54066
  DEFAULT_HEIGHT = 6858e3;
53902
54067
  DEFAULT_COLORS2 = {
@@ -53954,7 +54119,7 @@ var init_PresentationBuilder = __esm({
53954
54119
  const layoutIdx = STANDARD_LAYOUTS.findIndex((l) => l.name === layoutName) + 1 || 7;
53955
54120
  const layoutPath = `ppt/slideLayouts/slideLayout${layoutIdx}.xml`;
53956
54121
  const resolvedName = layoutName ?? STANDARD_LAYOUTS[layoutIdx - 1]?.name ?? "Blank";
53957
- return new SlideBuilder(slideNum, layoutPath, resolvedName);
54122
+ return new SlideBuilder(slideNum, layoutPath, resolvedName, handler);
53958
54123
  };
53959
54124
  return { handler, data, createSlide };
53960
54125
  }
@@ -56358,6 +56523,165 @@ var init_inherited_shape_transform = __esm({
56358
56523
  }
56359
56524
  });
56360
56525
 
56526
+ // pptx/core/utils/placeholder-xml.ts
56527
+ function findNonVisualProps(rawXml) {
56528
+ for (const container2 of ["p:nvSpPr", "p:nvPicPr", "p:nvGraphicFramePr"]) {
56529
+ const parent = rawXml[container2];
56530
+ const nvPr = parent?.["p:nvPr"];
56531
+ if (nvPr) {
56532
+ return nvPr;
56533
+ }
56534
+ }
56535
+ return void 0;
56536
+ }
56537
+ function retargetPlaceholder(rawXml, target) {
56538
+ const nvPr = findNonVisualProps(rawXml);
56539
+ if (!nvPr) {
56540
+ return;
56541
+ }
56542
+ const ph = nvPr["p:ph"] ?? {};
56543
+ nvPr["p:ph"] = ph;
56544
+ if (target.type) {
56545
+ ph["@_type"] = target.type;
56546
+ } else {
56547
+ delete ph["@_type"];
56548
+ }
56549
+ if (target.idx !== void 0) {
56550
+ ph["@_idx"] = target.idx;
56551
+ } else {
56552
+ delete ph["@_idx"];
56553
+ }
56554
+ }
56555
+ function setRawXmlTransform(rawXml, xEmu, yEmu, cxEmu, cyEmu) {
56556
+ const spPr = rawXml["p:spPr"];
56557
+ if (!spPr) {
56558
+ return;
56559
+ }
56560
+ const xfrm = spPr["a:xfrm"] ?? {};
56561
+ spPr["a:xfrm"] = xfrm;
56562
+ const off = xfrm["a:off"] ?? {};
56563
+ xfrm["a:off"] = off;
56564
+ off["@_x"] = String(xEmu);
56565
+ off["@_y"] = String(yEmu);
56566
+ const ext = xfrm["a:ext"] ?? {};
56567
+ xfrm["a:ext"] = ext;
56568
+ ext["@_cx"] = String(cxEmu);
56569
+ ext["@_cy"] = String(cyEmu);
56570
+ }
56571
+ function createEmptyPlaceholderElement(target, xEmu, yEmu, cxEmu, cyEmu, uniqueId) {
56572
+ if (cxEmu <= 0 || cyEmu <= 0) {
56573
+ return null;
56574
+ }
56575
+ const phNode = {};
56576
+ if (target.type) {
56577
+ phNode["@_type"] = target.type;
56578
+ }
56579
+ if (target.idx !== void 0) {
56580
+ phNode["@_idx"] = target.idx;
56581
+ }
56582
+ const rawXml = {
56583
+ "p:nvSpPr": {
56584
+ "p:cNvPr": {
56585
+ "@_id": uniqueId,
56586
+ "@_name": `Placeholder ${target.type || "content"}`
56587
+ },
56588
+ "p:cNvSpPr": {
56589
+ "a:spLocks": { "@_noGrp": "1" }
56590
+ },
56591
+ "p:nvPr": {
56592
+ "p:ph": phNode
56593
+ }
56594
+ },
56595
+ "p:spPr": {
56596
+ "a:xfrm": {
56597
+ "a:off": { "@_x": String(xEmu), "@_y": String(yEmu) },
56598
+ "a:ext": { "@_cx": String(cxEmu), "@_cy": String(cyEmu) }
56599
+ }
56600
+ },
56601
+ "p:txBody": {
56602
+ "a:bodyPr": {},
56603
+ "a:lstStyle": {},
56604
+ "a:p": { "a:endParaRPr": { "@_lang": "en-US" } }
56605
+ }
56606
+ };
56607
+ return {
56608
+ type: "text",
56609
+ id: `ph-${target.type || "content"}-${target.idx ?? "0"}-${uniqueId}`,
56610
+ x: Math.round(xEmu / EMU_PER_PX),
56611
+ y: Math.round(yEmu / EMU_PER_PX),
56612
+ width: Math.round(cxEmu / EMU_PER_PX),
56613
+ height: Math.round(cyEmu / EMU_PER_PX),
56614
+ text: "",
56615
+ rawXml
56616
+ };
56617
+ }
56618
+ var init_placeholder_xml = __esm({
56619
+ "pptx/core/utils/placeholder-xml.ts"() {
56620
+ init_constants2();
56621
+ }
56622
+ });
56623
+
56624
+ // pptx/core/core/runtime/save-geometry-validation.ts
56625
+ function omitsInheritedFrame(element) {
56626
+ if (!["text", "shape", "picture", "media"].includes(element.type) || !element.rawXml)
56627
+ return false;
56628
+ if (!xmlHasChild(findNonVisualProps(element.rawXml), "p:ph")) return false;
56629
+ if (xmlHasChild(xmlChild(element.rawXml, "p:spPr"), "a:xfrm") || xmlHasChild(element.rawXml, "p:xfrm"))
56630
+ return false;
56631
+ const baseline = element.inheritedTransform;
56632
+ if (!baseline) return FRAME_FIELDS.every((key2) => element[key2] === void 0);
56633
+ return FRAME_FIELDS.every(
56634
+ (key2) => Number.isFinite(baseline[key2]) && (element[key2] === void 0 || element[key2] === baseline[key2])
56635
+ ) && ["rotation", "skewX", "skewY", "flipHorizontal", "flipVertical"].every(
56636
+ (key2) => (element[key2] ?? 0) === (baseline[key2] ?? 0)
56637
+ );
56638
+ }
56639
+ function validateElementGeometry(element, context, emuPerPx = 9525) {
56640
+ const inherited = omitsInheritedFrame(element);
56641
+ const record2 = element;
56642
+ const fields = [...inherited ? [] : FRAME_FIELDS, ...OPTIONAL_FIELDS];
56643
+ for (const field of fields) {
56644
+ const value = record2[field];
56645
+ if (OPTIONAL_FIELDS.includes(field) && value === void 0) continue;
56646
+ if (typeof value !== "number" || !Number.isFinite(value) || !Number.isFinite(value * emuPerPx)) {
56647
+ throw new Error(
56648
+ `${context}: element '${element.id}' (${element.name ?? "unnamed"}, type=${element.type}) has invalid ${field}=${String(value)}; expected a finite number`
56649
+ );
56650
+ }
56651
+ }
56652
+ if (element.type === "group") {
56653
+ for (const child31 of element.children) validateElementGeometry(child31, context, emuPerPx);
56654
+ }
56655
+ }
56656
+ function validateSlideGeometry(slides) {
56657
+ for (const slide of slides) {
56658
+ for (const element of slide.elements) {
56659
+ validateElementGeometry(element, `Slide ${slide.slideNumber} (${slide.id})`);
56660
+ }
56661
+ }
56662
+ }
56663
+ var FRAME_FIELDS, OPTIONAL_FIELDS;
56664
+ var init_save_geometry_validation = __esm({
56665
+ "pptx/core/core/runtime/save-geometry-validation.ts"() {
56666
+ init_placeholder_xml();
56667
+ init_xml_access();
56668
+ FRAME_FIELDS = ["x", "y", "width", "height"];
56669
+ OPTIONAL_FIELDS = [
56670
+ "xEmu",
56671
+ "yEmu",
56672
+ "widthEmu",
56673
+ "heightEmu",
56674
+ "rotation",
56675
+ "skewX",
56676
+ "skewY",
56677
+ "chOffXEmu",
56678
+ "chOffYEmu",
56679
+ "chExtWidthEmu",
56680
+ "chExtHeightEmu"
56681
+ ];
56682
+ }
56683
+ });
56684
+
56361
56685
  // pptx/core/core/builders/PptxElementTransformUpdater.ts
56362
56686
  var PptxElementTransformUpdater;
56363
56687
  var init_PptxElementTransformUpdater = __esm({
@@ -56367,6 +56691,7 @@ var init_PptxElementTransformUpdater = __esm({
56367
56691
  init_xml_access();
56368
56692
  init_group_tight_rewrap();
56369
56693
  init_inherited_shape_transform();
56694
+ init_save_geometry_validation();
56370
56695
  PptxElementTransformUpdater = class {
56371
56696
  applyTransform(shape, element, emuPerPx, enclosingGroupChildSpace) {
56372
56697
  const transform7 = shape["p:spPr"]?.["a:xfrm"] || shape["p:xfrm"] || // A group's child geometry uses a different frame from the load-time baseline.
@@ -56374,6 +56699,7 @@ var init_PptxElementTransformUpdater = __esm({
56374
56699
  if (!transform7) {
56375
56700
  return;
56376
56701
  }
56702
+ validateElementGeometry(element, "Transform writer", emuPerPx);
56377
56703
  if (!transform7["a:off"]) {
56378
56704
  transform7["a:off"] = {};
56379
56705
  }
@@ -59408,7 +59734,7 @@ function parseBorderSide(side) {
59408
59734
  }
59409
59735
  const widthEmu = parseInt(String(ln["@_w"] || "0"), 10);
59410
59736
  if (widthEmu > 0) {
59411
- border.width = Math.max(1, Math.round(widthEmu / EMU_PER_PIXEL2));
59737
+ border.width = Math.max(1, Math.round(widthEmu / EMU_PER_PIXEL3));
59412
59738
  has2 = true;
59413
59739
  }
59414
59740
  const prstDash = ln["a:prstDash"];
@@ -59465,12 +59791,12 @@ function parseTableStyleSectionCell3D(tcStyle) {
59465
59791
  if (bevel2) {
59466
59792
  const bevelWidth = parseInt(String(bevel2["@_w"] || "0"), 10);
59467
59793
  if (bevelWidth > 0) {
59468
- cell3D.bevelWidth = Math.round(bevelWidth / EMU_PER_PIXEL2);
59794
+ cell3D.bevelWidth = Math.round(bevelWidth / EMU_PER_PIXEL3);
59469
59795
  hasStyle = true;
59470
59796
  }
59471
59797
  const bevelHeight = parseInt(String(bevel2["@_h"] || "0"), 10);
59472
59798
  if (bevelHeight > 0) {
59473
- cell3D.bevelHeight = Math.round(bevelHeight / EMU_PER_PIXEL2);
59799
+ cell3D.bevelHeight = Math.round(bevelHeight / EMU_PER_PIXEL3);
59474
59800
  hasStyle = true;
59475
59801
  }
59476
59802
  const bevelPreset = String(bevel2["@_prst"] || "").trim();
@@ -59494,11 +59820,11 @@ function parseTableStyleSectionCell3D(tcStyle) {
59494
59820
  }
59495
59821
  return hasStyle ? cell3D : void 0;
59496
59822
  }
59497
- var EMU_PER_PIXEL2, BORDER_SIDES;
59823
+ var EMU_PER_PIXEL3, BORDER_SIDES;
59498
59824
  var init_table_style_border_parse = __esm({
59499
59825
  "pptx/core/core/runtime/table-style-border-parse.ts"() {
59500
59826
  init_color_primitives();
59501
- EMU_PER_PIXEL2 = 9525;
59827
+ EMU_PER_PIXEL3 = 9525;
59502
59828
  BORDER_SIDES = [
59503
59829
  "left",
59504
59830
  "right",
@@ -88551,6 +88877,80 @@ var init_factories = __esm({
88551
88877
  }
88552
88878
  });
88553
88879
 
88880
+ // pptx/core/utils/placeholder-remap.ts
88881
+ function placeholderContentRole(type) {
88882
+ const declared = (type ?? "").trim().toLowerCase() || "body";
88883
+ if (TITLE_ROLE.has(declared)) {
88884
+ return "title";
88885
+ }
88886
+ if (CONTENT_ROLE.has(declared)) {
88887
+ return "content";
88888
+ }
88889
+ return declared;
88890
+ }
88891
+ function preferredPlaceholderTypes(element) {
88892
+ switch (element.type) {
88893
+ case "image":
88894
+ case "picture":
88895
+ return ["pic", "obj", "body"];
88896
+ case "chart":
88897
+ return ["chart", "obj", "body"];
88898
+ case "table":
88899
+ return ["tbl", "obj", "body"];
88900
+ case "media":
88901
+ case "model3d":
88902
+ return ["media", "pic", "obj", "body"];
88903
+ case "smartArt":
88904
+ return ["dgm", "obj", "body"];
88905
+ case "text":
88906
+ return ["body", "subtitle", "obj"];
88907
+ default:
88908
+ return ["obj", "body"];
88909
+ }
88910
+ }
88911
+ function scorePlaceholderMatch(element, source, target) {
88912
+ if (placeholderContentRole(source.type) !== placeholderContentRole(target.type)) {
88913
+ return -1;
88914
+ }
88915
+ const sourceType = normalizeType(source.type);
88916
+ const targetType = normalizeType(target.type);
88917
+ let score = 1;
88918
+ if (source.idx !== void 0 && source.idx === target.idx) {
88919
+ score += 100;
88920
+ }
88921
+ if (sourceType === targetType) {
88922
+ score += 50;
88923
+ }
88924
+ const preferred = preferredPlaceholderTypes(element).indexOf(targetType);
88925
+ if (preferred >= 0) {
88926
+ score += 30 - preferred * 5;
88927
+ }
88928
+ if (targetType === "obj") {
88929
+ score += 10;
88930
+ }
88931
+ return score;
88932
+ }
88933
+ function normalizeType(type) {
88934
+ return (type ?? "").trim().toLowerCase() || "body";
88935
+ }
88936
+ var TITLE_ROLE, CONTENT_ROLE;
88937
+ var init_placeholder_remap = __esm({
88938
+ "pptx/core/utils/placeholder-remap.ts"() {
88939
+ TITLE_ROLE = /* @__PURE__ */ new Set(["title", "ctrtitle"]);
88940
+ CONTENT_ROLE = /* @__PURE__ */ new Set([
88941
+ "body",
88942
+ "obj",
88943
+ "subtitle",
88944
+ "pic",
88945
+ "chart",
88946
+ "tbl",
88947
+ "media",
88948
+ "clipart",
88949
+ "dgm"
88950
+ ]);
88951
+ }
88952
+ });
88953
+
88554
88954
  // pptx/core/core/runtime/master-save-helpers.ts
88555
88955
  function applyHeaderFooterFlagsToNode(root, flags) {
88556
88956
  if (!flags || Object.keys(flags).length === 0) {
@@ -108061,178 +108461,6 @@ var init_chart_user_shapes_serializer = __esm({
108061
108461
  }
108062
108462
  });
108063
108463
 
108064
- // pptx/core/utils/placeholder-remap.ts
108065
- function placeholderContentRole(type) {
108066
- const declared = (type ?? "").trim().toLowerCase() || "body";
108067
- if (TITLE_ROLE.has(declared)) {
108068
- return "title";
108069
- }
108070
- if (CONTENT_ROLE.has(declared)) {
108071
- return "content";
108072
- }
108073
- return declared;
108074
- }
108075
- function preferredPlaceholderTypes(element) {
108076
- switch (element.type) {
108077
- case "image":
108078
- case "picture":
108079
- return ["pic", "obj", "body"];
108080
- case "chart":
108081
- return ["chart", "obj", "body"];
108082
- case "table":
108083
- return ["tbl", "obj", "body"];
108084
- case "media":
108085
- case "model3d":
108086
- return ["media", "pic", "obj", "body"];
108087
- case "smartArt":
108088
- return ["dgm", "obj", "body"];
108089
- case "text":
108090
- return ["body", "subtitle", "obj"];
108091
- default:
108092
- return ["obj", "body"];
108093
- }
108094
- }
108095
- function scorePlaceholderMatch(element, source, target) {
108096
- if (placeholderContentRole(source.type) !== placeholderContentRole(target.type)) {
108097
- return -1;
108098
- }
108099
- const sourceType = normalizeType(source.type);
108100
- const targetType = normalizeType(target.type);
108101
- let score = 1;
108102
- if (source.idx !== void 0 && source.idx === target.idx) {
108103
- score += 100;
108104
- }
108105
- if (sourceType === targetType) {
108106
- score += 50;
108107
- }
108108
- const preferred = preferredPlaceholderTypes(element).indexOf(targetType);
108109
- if (preferred >= 0) {
108110
- score += 30 - preferred * 5;
108111
- }
108112
- if (targetType === "obj") {
108113
- score += 10;
108114
- }
108115
- return score;
108116
- }
108117
- function normalizeType(type) {
108118
- return (type ?? "").trim().toLowerCase() || "body";
108119
- }
108120
- var TITLE_ROLE, CONTENT_ROLE;
108121
- var init_placeholder_remap = __esm({
108122
- "pptx/core/utils/placeholder-remap.ts"() {
108123
- TITLE_ROLE = /* @__PURE__ */ new Set(["title", "ctrtitle"]);
108124
- CONTENT_ROLE = /* @__PURE__ */ new Set([
108125
- "body",
108126
- "obj",
108127
- "subtitle",
108128
- "pic",
108129
- "chart",
108130
- "tbl",
108131
- "media",
108132
- "clipart",
108133
- "dgm"
108134
- ]);
108135
- }
108136
- });
108137
-
108138
- // pptx/core/utils/placeholder-xml.ts
108139
- function findNonVisualProps(rawXml) {
108140
- for (const container2 of ["p:nvSpPr", "p:nvPicPr", "p:nvGraphicFramePr"]) {
108141
- const parent = rawXml[container2];
108142
- const nvPr = parent?.["p:nvPr"];
108143
- if (nvPr) {
108144
- return nvPr;
108145
- }
108146
- }
108147
- return void 0;
108148
- }
108149
- function retargetPlaceholder(rawXml, target) {
108150
- const nvPr = findNonVisualProps(rawXml);
108151
- if (!nvPr) {
108152
- return;
108153
- }
108154
- const ph = nvPr["p:ph"] ?? {};
108155
- nvPr["p:ph"] = ph;
108156
- if (target.type) {
108157
- ph["@_type"] = target.type;
108158
- } else {
108159
- delete ph["@_type"];
108160
- }
108161
- if (target.idx !== void 0) {
108162
- ph["@_idx"] = target.idx;
108163
- } else {
108164
- delete ph["@_idx"];
108165
- }
108166
- }
108167
- function setRawXmlTransform(rawXml, xEmu, yEmu, cxEmu, cyEmu) {
108168
- const spPr = rawXml["p:spPr"];
108169
- if (!spPr) {
108170
- return;
108171
- }
108172
- const xfrm = spPr["a:xfrm"] ?? {};
108173
- spPr["a:xfrm"] = xfrm;
108174
- const off = xfrm["a:off"] ?? {};
108175
- xfrm["a:off"] = off;
108176
- off["@_x"] = String(xEmu);
108177
- off["@_y"] = String(yEmu);
108178
- const ext = xfrm["a:ext"] ?? {};
108179
- xfrm["a:ext"] = ext;
108180
- ext["@_cx"] = String(cxEmu);
108181
- ext["@_cy"] = String(cyEmu);
108182
- }
108183
- function createEmptyPlaceholderElement(target, xEmu, yEmu, cxEmu, cyEmu, uniqueId) {
108184
- if (cxEmu <= 0 || cyEmu <= 0) {
108185
- return null;
108186
- }
108187
- const phNode = {};
108188
- if (target.type) {
108189
- phNode["@_type"] = target.type;
108190
- }
108191
- if (target.idx !== void 0) {
108192
- phNode["@_idx"] = target.idx;
108193
- }
108194
- const rawXml = {
108195
- "p:nvSpPr": {
108196
- "p:cNvPr": {
108197
- "@_id": uniqueId,
108198
- "@_name": `Placeholder ${target.type || "content"}`
108199
- },
108200
- "p:cNvSpPr": {
108201
- "a:spLocks": { "@_noGrp": "1" }
108202
- },
108203
- "p:nvPr": {
108204
- "p:ph": phNode
108205
- }
108206
- },
108207
- "p:spPr": {
108208
- "a:xfrm": {
108209
- "a:off": { "@_x": String(xEmu), "@_y": String(yEmu) },
108210
- "a:ext": { "@_cx": String(cxEmu), "@_cy": String(cyEmu) }
108211
- }
108212
- },
108213
- "p:txBody": {
108214
- "a:bodyPr": {},
108215
- "a:lstStyle": {},
108216
- "a:p": { "a:endParaRPr": { "@_lang": "en-US" } }
108217
- }
108218
- };
108219
- return {
108220
- type: "text",
108221
- id: `ph-${target.type || "content"}-${target.idx ?? "0"}-${uniqueId}`,
108222
- x: Math.round(xEmu / EMU_PER_PX),
108223
- y: Math.round(yEmu / EMU_PER_PX),
108224
- width: Math.round(cxEmu / EMU_PER_PX),
108225
- height: Math.round(cyEmu / EMU_PER_PX),
108226
- text: "",
108227
- rawXml
108228
- };
108229
- }
108230
- var init_placeholder_xml = __esm({
108231
- "pptx/core/utils/placeholder-xml.ts"() {
108232
- init_constants2();
108233
- }
108234
- });
108235
-
108236
108464
  // pptx/core/utils/text-fill-blip.ts
108237
108465
  function resolveTextFillBlip(blipFill, lookupTarget, resolveArchivePath, allowExternal) {
108238
108466
  const blip = blipFill["a:blip"];
@@ -126656,8 +126884,8 @@ function mergeBorderSideXml(border, existingSide) {
126656
126884
  const ln = ensureChild2(existing, "a:ln");
126657
126885
  if (border.width !== void 0) {
126658
126886
  const currentEmu = parseInt(String(ln["@_w"] || "0"), 10);
126659
- if (currentEmu <= 0 || Math.max(1, Math.round(currentEmu / EMU_PER_PIXEL3)) !== border.width) {
126660
- ln["@_w"] = String(Math.round(border.width * EMU_PER_PIXEL3));
126887
+ if (currentEmu <= 0 || Math.max(1, Math.round(currentEmu / EMU_PER_PIXEL4)) !== border.width) {
126888
+ ln["@_w"] = String(Math.round(border.width * EMU_PER_PIXEL4));
126661
126889
  }
126662
126890
  }
126663
126891
  if (border.dash) {
@@ -126713,10 +126941,10 @@ function writeTableStyleSectionCell3D(section, cell3D) {
126713
126941
  if (cell3D.bevelWidth !== void 0 || cell3D.bevelHeight !== void 0 || cell3D.bevelPreset !== void 0) {
126714
126942
  const bevel2 = {};
126715
126943
  if (cell3D.bevelWidth !== void 0) {
126716
- bevel2["@_w"] = String(Math.round(cell3D.bevelWidth * EMU_PER_PIXEL3));
126944
+ bevel2["@_w"] = String(Math.round(cell3D.bevelWidth * EMU_PER_PIXEL4));
126717
126945
  }
126718
126946
  if (cell3D.bevelHeight !== void 0) {
126719
- bevel2["@_h"] = String(Math.round(cell3D.bevelHeight * EMU_PER_PIXEL3));
126947
+ bevel2["@_h"] = String(Math.round(cell3D.bevelHeight * EMU_PER_PIXEL4));
126720
126948
  }
126721
126949
  if (cell3D.bevelPreset) {
126722
126950
  bevel2["@_prst"] = cell3D.bevelPreset;
@@ -126735,12 +126963,12 @@ function writeTableStyleSectionCell3D(section, cell3D) {
126735
126963
  }
126736
126964
  tcStyle["a:cell3D"] = node;
126737
126965
  }
126738
- var EMU_PER_PIXEL3, BORDER_SIDE_ORDER, LN_CHILD_ORDER, LN_FILL_KEYS;
126966
+ var EMU_PER_PIXEL4, BORDER_SIDE_ORDER, LN_CHILD_ORDER, LN_FILL_KEYS;
126739
126967
  var init_table_style_border_write = __esm({
126740
126968
  "pptx/core/core/runtime/table-style-border-write.ts"() {
126741
126969
  init_xml_reorder();
126742
126970
  init_table_style_xml_helpers();
126743
- EMU_PER_PIXEL3 = 9525;
126971
+ EMU_PER_PIXEL4 = 9525;
126744
126972
  BORDER_SIDE_ORDER = [
126745
126973
  "a:left",
126746
126974
  "a:right",
@@ -127678,6 +127906,7 @@ var init_PptxHandlerRuntimeSavePipeline = __esm({
127678
127906
  init_header_footer_parts();
127679
127907
  init_pptx_print_properties();
127680
127908
  init_PptxHandlerRuntimeSaveStructuralIds();
127909
+ init_save_geometry_validation();
127681
127910
  PptxHandlerRuntime54 = class _PptxHandlerRuntime extends PptxHandlerRuntime53 {
127682
127911
  /**
127683
127912
  * Resolve the effective conformance class for this save operation.
@@ -127692,6 +127921,19 @@ var init_PptxHandlerRuntimeSavePipeline = __esm({
127692
127921
  return this.isStrictOoxml ? "strict" : "transitional";
127693
127922
  }
127694
127923
  async save(slides, options) {
127924
+ validateSlideGeometry(slides);
127925
+ const templates = [
127926
+ ...options?.slideMasters ?? [],
127927
+ ...options?.slideLayouts ?? [],
127928
+ ...options?.slideMasters?.flatMap((master) => master.layouts ?? []) ?? [],
127929
+ ...options?.notesMaster ? [options.notesMaster] : [],
127930
+ ...options?.handoutMaster ? [options.handoutMaster] : []
127931
+ ];
127932
+ for (const template of templates) {
127933
+ for (const element of template.elements ?? []) {
127934
+ validateElementGeometry(element, `Template (${template.path})`);
127935
+ }
127936
+ }
127695
127937
  if (options?.outputFormat === "ppt") {
127696
127938
  return this.saveAsLegacyPpt(
127697
127939
  slides,
@@ -128659,8 +128901,7 @@ var init_PptxHandlerRuntimePlaceholderLookup = __esm({
128659
128901
  return this.scanPlaceholderBuckets(spTree, (info) => info?.type === type);
128660
128902
  }
128661
128903
  /** The layout and master counterparts of a placeholder, unmerged. */
128662
- findPlaceholderContexts(slidePath, expected) {
128663
- const layoutPath = this.resolveLayoutPathForSlide(slidePath);
128904
+ findPlaceholderContexts(slidePath, expected, layoutPath = this.resolveLayoutPathForSlide(slidePath)) {
128664
128905
  if (!layoutPath) {
128665
128906
  return {};
128666
128907
  }
@@ -128672,10 +128913,11 @@ var init_PptxHandlerRuntimePlaceholderLookup = __esm({
128672
128913
  const master = this.findPlaceholderInShapeTree(masterSpTree, expected) ?? this.findSingletonPlaceholderInShapeTree(masterSpTree, expected);
128673
128914
  return { layout, master };
128674
128915
  }
128675
- findPlaceholderContext(slidePath, expected) {
128916
+ findPlaceholderContext(slidePath, expected, layoutPath) {
128676
128917
  const { layout: layoutContext, master: masterContext } = this.findPlaceholderContexts(
128677
128918
  slidePath,
128678
- expected
128919
+ expected,
128920
+ layoutPath
128679
128921
  );
128680
128922
  if (!layoutContext) {
128681
128923
  return masterContext;
@@ -128701,8 +128943,8 @@ var init_PptxHandlerRuntimePlaceholderLookup = __esm({
128701
128943
  * a master `p:sp`), so the layout keeps winning exactly as it does when
128702
128944
  * both are shapes.
128703
128945
  */
128704
- findPlaceholderNode(slidePath, expected) {
128705
- const { layout, master } = this.findPlaceholderContexts(slidePath, expected);
128946
+ findPlaceholderNode(slidePath, expected, layoutPath) {
128947
+ const { layout, master } = this.findPlaceholderContexts(slidePath, expected, layoutPath);
128706
128948
  const firstNode2 = (context) => context?.shape ?? context?.picture ?? context?.graphicFrame;
128707
128949
  const layoutNode = firstNode2(layout);
128708
128950
  const masterNode = firstNode2(master);
@@ -128743,8 +128985,7 @@ var init_PptxHandlerRuntimePlaceholderLookup = __esm({
128743
128985
  * reference. Checks the layout cache first, then the master cache, and
128744
128986
  * merges them so that layout values take priority over master values.
128745
128987
  */
128746
- lookupPlaceholderDefaults(slidePath, phInfo) {
128747
- const layoutPath = this.resolveLayoutPathForSlide(slidePath);
128988
+ lookupPlaceholderDefaults(slidePath, phInfo, layoutPath = this.resolveLayoutPathForSlide(slidePath)) {
128748
128989
  if (!layoutPath) {
128749
128990
  return void 0;
128750
128991
  }
@@ -130923,14 +131164,14 @@ var init_PptxHandlerRuntimeShapeParsing = __esm({
130923
131164
  init_element_paragraph_geometry();
130924
131165
  init_PptxHandlerRuntimeShapeParagraphContentParsing();
130925
131166
  PptxHandlerRuntime67 = class _PptxHandlerRuntime extends PptxHandlerRuntime66 {
130926
- parseShape(shape, id, slidePath) {
131167
+ parseShape(shape, id, slidePath, layoutPath) {
130927
131168
  try {
130928
131169
  const spPr = shape["p:spPr"];
130929
131170
  const slideRelationshipMap = slidePath ? this.slideRelsMap.get(slidePath) : void 0;
130930
131171
  const placeholderInfo = this.extractPlaceholderInfo(
130931
131172
  shape?.["p:nvSpPr"]?.["p:nvPr"]
130932
131173
  );
130933
- const inheritedPlaceholder = slidePath && placeholderInfo ? this.findPlaceholderContext(slidePath, placeholderInfo) : void 0;
131174
+ const inheritedPlaceholder = (slidePath || layoutPath) && placeholderInfo ? this.findPlaceholderContext(slidePath ?? "", placeholderInfo, layoutPath) : void 0;
130934
131175
  const inheritedSpPr = inheritedPlaceholder?.shape?.["p:spPr"] || inheritedPlaceholder?.picture?.["p:spPr"];
130935
131176
  const effectiveSpPr = spPr ? {
130936
131177
  ...spPr,
@@ -131056,7 +131297,7 @@ var init_PptxHandlerRuntimeShapeParsing = __esm({
131056
131297
  );
131057
131298
  const linkedTxbxId = bodyPropResult.linkedTxbxId;
131058
131299
  const linkedTxbxSeq = bodyPropResult.linkedTxbxSeq;
131059
- const phDefaults = slidePath && placeholderInfo ? this.lookupPlaceholderDefaults(slidePath, placeholderInfo) : void 0;
131300
+ const phDefaults = (slidePath || layoutPath) && placeholderInfo ? this.lookupPlaceholderDefaults(slidePath ?? "", placeholderInfo, layoutPath) : void 0;
131060
131301
  if (phDefaults) {
131061
131302
  this.applyPlaceholderBodyDefaults(textStyle, phDefaults);
131062
131303
  }
@@ -140419,14 +140660,199 @@ var init_PptxHandlerRuntimeBackgroundStyles = __esm({
140419
140660
  };
140420
140661
  }
140421
140662
  });
140663
+
140664
+ // pptx/core/core/runtime/sdk-placeholder.ts
140665
+ function selectTextPlaceholder(input, type, options, slots) {
140666
+ if (!TEXT_PLACEHOLDER_TYPES.has(type.toLowerCase())) {
140667
+ throw new Error(`Unsupported text placeholder type: ${type}`);
140668
+ }
140669
+ if (options.idx !== void 0 && (!Number.isInteger(options.idx) || options.idx < 0 || options.idx > 4294967295)) {
140670
+ throw new Error("Placeholder idx must be an unsigned 32-bit integer");
140671
+ }
140672
+ const source = {
140673
+ type: type.toLowerCase(),
140674
+ ...options.idx !== void 0 ? { idx: String(options.idx) } : {}
140675
+ };
140676
+ let best;
140677
+ let bestScore = 0;
140678
+ for (const slot of slots) {
140679
+ if (!TEXT_PLACEHOLDER_TYPES.has(slot.phInfo.type ?? "obj")) continue;
140680
+ if (source.idx !== void 0 && source.idx !== (slot.phInfo.idx ?? "0")) continue;
140681
+ const score = scorePlaceholderMatch(input, source, slot.phInfo);
140682
+ if (score > bestScore) {
140683
+ best = slot;
140684
+ bestScore = score;
140685
+ }
140686
+ }
140687
+ return best ? { type: canonicalPlaceholderType(best.phInfo.type ?? "obj"), idx: best.phInfo.idx } : { type: canonicalPlaceholderType(source.type), idx: source.idx };
140688
+ }
140689
+ function withoutFallbackLanguage(properties) {
140690
+ const { "@_lang": language, ...rest } = properties;
140691
+ if (language !== "en-US") return properties;
140692
+ const keys = Object.keys(rest);
140693
+ return keys.length === 0 || keys.length === 1 && rest["@_dirty"] === "0" ? void 0 : rest;
140694
+ }
140695
+ function stripFallbackLanguage(node, key2) {
140696
+ const properties = node[key2];
140697
+ if (!properties || typeof properties !== "object") return node;
140698
+ const next = withoutFallbackLanguage(properties);
140699
+ if (next === properties) return node;
140700
+ const result = {};
140701
+ for (const [name, value] of Object.entries(node)) {
140702
+ if (name !== key2) result[name] = value;
140703
+ else if (next) result[name] = next;
140704
+ }
140705
+ return result;
140706
+ }
140707
+ function withoutFallbackLanguages(paragraphs) {
140708
+ return paragraphs.map((paragraph) => {
140709
+ const next = { ...stripFallbackLanguage(paragraph, "a:endParaRPr") };
140710
+ for (const child31 of ["a:r", "a:br", "a:fld"]) {
140711
+ const nodes = next[child31];
140712
+ if (nodes === void 0) continue;
140713
+ next[child31] = Array.isArray(nodes) ? nodes.map((node) => stripFallbackLanguage(node, "a:rPr")) : stripFallbackLanguage(nodes, "a:rPr");
140714
+ }
140715
+ return next;
140716
+ });
140717
+ }
140718
+ function placeholderShape2(identity, paragraphs) {
140719
+ paragraphs = withoutFallbackLanguages(paragraphs);
140720
+ return {
140721
+ "p:nvSpPr": {
140722
+ "p:cNvPr": { "@_id": "2", "@_name": `Placeholder ${identity.type}` },
140723
+ "p:cNvSpPr": { "a:spLocks": { "@_noGrp": "1" } },
140724
+ "p:nvPr": {
140725
+ "p:ph": {
140726
+ "@_type": identity.type,
140727
+ ...identity.idx !== void 0 ? { "@_idx": identity.idx } : {}
140728
+ }
140729
+ }
140730
+ },
140731
+ "p:spPr": {},
140732
+ "p:txBody": { "a:bodyPr": {}, "a:lstStyle": {}, "a:p": paragraphs }
140733
+ };
140734
+ }
140735
+ function applyPlaceholderFrame(shape, inherited, options, emuPerPx, materializeFrame = false) {
140736
+ for (const key2 of ["x", "y", "width", "height"]) {
140737
+ if (options[key2] !== void 0 && !Number.isFinite(options[key2])) {
140738
+ throw new Error(`Invalid placeholder frame for ${key2}: expected a finite number`);
140739
+ }
140740
+ }
140741
+ const off = xmlPath(inherited, "p:spPr", "a:xfrm", "a:off");
140742
+ const ext = xmlPath(inherited, "p:spPr", "a:xfrm", "a:ext");
140743
+ const frame2 = {
140744
+ x: options.x ?? (off?.["@_x"] !== void 0 ? Number(off["@_x"]) / emuPerPx : void 0),
140745
+ y: options.y ?? (off?.["@_y"] !== void 0 ? Number(off["@_y"]) / emuPerPx : void 0),
140746
+ width: options.width ?? (ext?.["@_cx"] !== void 0 ? Number(ext["@_cx"]) / emuPerPx : void 0),
140747
+ height: options.height ?? (ext?.["@_cy"] !== void 0 ? Number(ext["@_cy"]) / emuPerPx : void 0)
140748
+ };
140749
+ for (const [key2, value] of Object.entries(frame2)) {
140750
+ if (!Number.isFinite(value)) {
140751
+ throw new Error(
140752
+ `No matching placeholder frame for ${key2}; supply a complete explicit frame or choose a layout containing this slot`
140753
+ );
140754
+ }
140755
+ }
140756
+ if (materializeFrame || ["x", "y", "width", "height"].some((key2) => options[key2] !== void 0)) {
140757
+ setRawXmlTransform(
140758
+ shape,
140759
+ ...["x", "y", "width", "height"].map(
140760
+ (key2) => Math.round(frame2[key2] * emuPerPx)
140761
+ )
140762
+ );
140763
+ }
140764
+ }
140765
+ var TEXT_PLACEHOLDER_TYPES;
140766
+ var init_sdk_placeholder = __esm({
140767
+ "pptx/core/core/runtime/sdk-placeholder.ts"() {
140768
+ init_placeholder_remap();
140769
+ init_placeholder_xml();
140770
+ init_placeholder_validation();
140771
+ init_xml_access();
140772
+ TEXT_PLACEHOLDER_TYPES = /* @__PURE__ */ new Set([
140773
+ "title",
140774
+ "ctrtitle",
140775
+ "subtitle",
140776
+ "body",
140777
+ "obj",
140778
+ "dt",
140779
+ "ftr",
140780
+ "hdr",
140781
+ "sldnum"
140782
+ ]);
140783
+ }
140784
+ });
140785
+
140786
+ // pptx/core/core/runtime/PptxHandlerRuntimeSdkPlaceholders.ts
140422
140787
  var PptxHandlerRuntime103;
140788
+ var init_PptxHandlerRuntimeSdkPlaceholders = __esm({
140789
+ "pptx/core/core/runtime/PptxHandlerRuntimeSdkPlaceholders.ts"() {
140790
+ init_placeholder_remap();
140791
+ init_xml_access();
140792
+ init_PptxHandlerRuntimeBackgroundStyles();
140793
+ init_sdk_placeholder();
140794
+ PptxHandlerRuntime103 = class _PptxHandlerRuntime extends PptxHandlerRuntime102 {
140795
+ createPlaceholderElement(layoutPath, input, type, options) {
140796
+ if (input.type !== "text") throw new Error("Placeholder input must be text");
140797
+ const layout = this.layoutXmlMap.get(layoutPath);
140798
+ if (!layout) throw new Error(`Unknown layout: ${layoutPath}`);
140799
+ const identity = selectTextPlaceholder(
140800
+ input,
140801
+ type,
140802
+ options,
140803
+ this.extractLayoutPlaceholders(layout, layoutPath)
140804
+ );
140805
+ const shape = placeholderShape2(
140806
+ identity,
140807
+ this.createParagraphsFromTextContent(input.text, void 0, input.textSegments)
140808
+ );
140809
+ const inherited = this.findPlaceholderNode(
140810
+ "",
140811
+ { type: identity.type.toLowerCase(), idx: identity.idx },
140812
+ layoutPath
140813
+ );
140814
+ const fallback = this.sdkMasterFrame(layoutPath, identity.type, identity.idx, inherited);
140815
+ applyPlaceholderFrame(
140816
+ shape,
140817
+ fallback ?? inherited,
140818
+ options,
140819
+ _PptxHandlerRuntime.EMU_PER_PX,
140820
+ fallback !== void 0
140821
+ );
140822
+ const element = this.parseShape(shape, input.id, void 0, layoutPath);
140823
+ if (!element) throw new Error("Unable to resolve placeholder content");
140824
+ if ((element.type === "text" || element.type === "shape") && !element.textStyle && element.textSegments?.[0]?.style) {
140825
+ element.textStyle = { ...element.textSegments[0].style };
140826
+ }
140827
+ return element;
140828
+ }
140829
+ sdkMasterFrame(layoutPath, type, idx, inherited) {
140830
+ if (!inherited) return void 0;
140831
+ if (xmlPath(inherited, "p:spPr", "a:xfrm", "a:off") && xmlPath(inherited, "p:spPr", "a:xfrm", "a:ext"))
140832
+ return void 0;
140833
+ const masterPath = this.resolveMasterPathForLayout(layoutPath);
140834
+ const tree = masterPath ? xmlPath(this.masterXmlMap.get(masterPath), "p:sldMaster", "p:cSld", "p:spTree") : void 0;
140835
+ const role = placeholderContentRole(type.toLowerCase());
140836
+ const candidates = this.ensureArray(tree?.["p:sp"]).filter((shape) => {
140837
+ const info = this.extractPlaceholderInfo(xmlPath(shape, "p:nvSpPr", "p:nvPr"));
140838
+ return info && placeholderContentRole(info.type) === role;
140839
+ });
140840
+ const master = candidates.find(
140841
+ (shape) => this.extractPlaceholderInfo(xmlPath(shape, "p:nvSpPr", "p:nvPr"))?.idx === idx
140842
+ ) ?? candidates[0];
140843
+ return master ? this.mergeXmlObjects(master, inherited) : void 0;
140844
+ }
140845
+ };
140846
+ }
140847
+ });
140848
+ var PptxHandlerRuntime104;
140423
140849
  var init_PptxHandlerRuntimeImplementation = __esm({
140424
140850
  "pptx/core/core/runtime/PptxHandlerRuntimeImplementation.ts"() {
140425
140851
  init_PptxElementXmlBuilder();
140426
140852
  init_builders();
140427
140853
  init_factories();
140428
- init_PptxHandlerRuntimeBackgroundStyles();
140429
- PptxHandlerRuntime103 = class _PptxHandlerRuntime extends PptxHandlerRuntime102 {
140854
+ init_PptxHandlerRuntimeSdkPlaceholders();
140855
+ PptxHandlerRuntime104 = class _PptxHandlerRuntime extends PptxHandlerRuntime103 {
140430
140856
  constructor(dependencyFactory = new PptxRuntimeDependencyFactory()) {
140431
140857
  super();
140432
140858
  this.dependencyFactory = dependencyFactory;
@@ -140566,11 +140992,11 @@ var init_PptxHandlerRuntimeImplementation = __esm({
140566
140992
  });
140567
140993
 
140568
140994
  // pptx/core/core/PptxHandlerRuntime.ts
140569
- var PptxHandlerRuntime104;
140995
+ var PptxHandlerRuntime105;
140570
140996
  var init_PptxHandlerRuntime = __esm({
140571
140997
  "pptx/core/core/PptxHandlerRuntime.ts"() {
140572
140998
  init_PptxHandlerRuntimeImplementation();
140573
- PptxHandlerRuntime104 = class extends PptxHandlerRuntime103 {
140999
+ PptxHandlerRuntime105 = class extends PptxHandlerRuntime104 {
140574
141000
  };
140575
141001
  }
140576
141002
  });
@@ -140580,7 +141006,7 @@ var createDefaultPptxHandlerRuntime;
140580
141006
  var init_PptxHandlerRuntimeFactory = __esm({
140581
141007
  "pptx/core/core/PptxHandlerRuntimeFactory.ts"() {
140582
141008
  init_PptxHandlerRuntime();
140583
- createDefaultPptxHandlerRuntime = () => new PptxHandlerRuntime104();
141009
+ createDefaultPptxHandlerRuntime = () => new PptxHandlerRuntime105();
140584
141010
  }
140585
141011
  });
140586
141012
 
@@ -143164,7 +143590,7 @@ function slideMasterXml2(deck, ctx) {
143164
143590
  </p:txStyles>
143165
143591
  </p:sldMaster>`;
143166
143592
  }
143167
- function slideLayoutXml2() {
143593
+ function slideLayoutXml() {
143168
143594
  return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
143169
143595
  <p:sldLayout ${XMLNS2} type="blank" preserve="1">
143170
143596
  <p:cSld name="Blank">
@@ -143484,7 +143910,7 @@ async function buildPptxPackage(deck) {
143484
143910
  ${masterRels.join("\n")}
143485
143911
  </Relationships>`
143486
143912
  );
143487
- zip.file("ppt/slideLayouts/slideLayout1.xml", slideLayoutXml2());
143913
+ zip.file("ppt/slideLayouts/slideLayout1.xml", slideLayoutXml());
143488
143914
  zip.file(
143489
143915
  "ppt/slideLayouts/_rels/slideLayout1.xml.rels",
143490
143916
  `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
@@ -143701,6 +144127,13 @@ var init_PptxHandlerCore = __esm({
143701
144127
  getLayoutOptions() {
143702
144128
  return this.runtime.getLayoutOptions();
143703
144129
  }
144130
+ /** Resolve a text placeholder in this loaded deck, preserving layout inheritance. */
144131
+ createPlaceholderElement(layoutPath, input, type, options = {}) {
144132
+ if (!this.runtime.createPlaceholderElement) {
144133
+ throw new Error("This runtime does not support creating layout placeholders");
144134
+ }
144135
+ return this.runtime.createPlaceholderElement(layoutPath, input, type, options);
144136
+ }
143704
144137
  /**
143705
144138
  * Build the artwork thumbnails backing the New Slide / Layout galleries.
143706
144139
  *