docgen-utils 1.0.14 → 1.0.16

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.
package/dist/bundle.js CHANGED
@@ -46780,7 +46780,7 @@ var docgen = (() => {
46780
46780
  const trimmed = current.trim().replace(/^['"]|['"]$/g, "");
46781
46781
  if (trimmed)
46782
46782
  fonts.push(trimmed);
46783
- const genericFonts = /* @__PURE__ */ new Set([
46783
+ const cssGenericFamilies = /* @__PURE__ */ new Set([
46784
46784
  "sans-serif",
46785
46785
  "serif",
46786
46786
  "monospace",
@@ -46788,27 +46788,81 @@ var docgen = (() => {
46788
46788
  "fantasy",
46789
46789
  "system-ui",
46790
46790
  "-apple-system",
46791
- "BlinkMacSystemFont",
46792
- "Segoe UI",
46793
- "Roboto",
46794
- "Helvetica Neue",
46791
+ "BlinkMacSystemFont"
46792
+ ]);
46793
+ const systemFonts = /* @__PURE__ */ new Set([
46795
46794
  "Arial",
46796
46795
  "Helvetica",
46797
- "Ubuntu",
46798
- "Cantarell",
46799
- "Fira Sans",
46800
- "Droid Sans",
46801
- "Noto Sans",
46802
- "sans-serif",
46803
- "Oxygen",
46804
- "Open Sans"
46796
+ "Helvetica Neue",
46797
+ "Segoe UI",
46798
+ "Times New Roman",
46799
+ "Georgia",
46800
+ "Courier New"
46801
+ ]);
46802
+ const webFontMap = /* @__PURE__ */ new Map([
46803
+ // Sans-serif Google Fonts → Arial
46804
+ ["Inter", "Arial"],
46805
+ ["Roboto", "Arial"],
46806
+ ["Open Sans", "Arial"],
46807
+ ["Lato", "Arial"],
46808
+ ["Montserrat", "Arial"],
46809
+ ["Poppins", "Arial"],
46810
+ ["Nunito", "Arial"],
46811
+ ["Raleway", "Arial"],
46812
+ ["Ubuntu", "Arial"],
46813
+ ["Cantarell", "Arial"],
46814
+ ["Fira Sans", "Arial"],
46815
+ ["Droid Sans", "Arial"],
46816
+ ["Noto Sans", "Arial"],
46817
+ ["Oxygen", "Arial"],
46818
+ ["Source Sans Pro", "Arial"],
46819
+ ["Source Sans 3", "Arial"],
46820
+ ["Work Sans", "Arial"],
46821
+ ["DM Sans", "Arial"],
46822
+ ["IBM Plex Sans", "Arial"],
46823
+ ["Mulish", "Arial"],
46824
+ ["Quicksand", "Arial"],
46825
+ ["Manrope", "Arial"],
46826
+ ["Outfit", "Arial"],
46827
+ ["Plus Jakarta Sans", "Arial"],
46828
+ ["Figtree", "Arial"],
46829
+ ["Geist", "Arial"],
46830
+ // Serif Google Fonts → Times New Roman
46831
+ ["Playfair Display", "Times New Roman"],
46832
+ ["Merriweather", "Times New Roman"],
46833
+ ["Lora", "Times New Roman"],
46834
+ ["PT Serif", "Times New Roman"],
46835
+ ["Noto Serif", "Times New Roman"],
46836
+ ["Source Serif Pro", "Times New Roman"],
46837
+ ["Source Serif 4", "Times New Roman"],
46838
+ ["Libre Baskerville", "Times New Roman"],
46839
+ ["Crimson Text", "Times New Roman"],
46840
+ ["EB Garamond", "Times New Roman"],
46841
+ ["Cormorant Garamond", "Times New Roman"],
46842
+ ["DM Serif Display", "Times New Roman"],
46843
+ // Display/heading fonts (mostly sans-serif) → Arial
46844
+ ["Oswald", "Arial"],
46845
+ ["Abril Fatface", "Times New Roman"],
46846
+ ["Bebas Neue", "Arial"]
46805
46847
  ]);
46848
+ let webFontFallback;
46806
46849
  for (const font of fonts) {
46807
- if (!genericFonts.has(font) && !font.startsWith("-")) {
46808
- return font;
46850
+ if (cssGenericFamilies.has(font) || font.startsWith("-")) {
46851
+ continue;
46809
46852
  }
46853
+ if (systemFonts.has(font)) {
46854
+ continue;
46855
+ }
46856
+ const mapped = webFontMap.get(font);
46857
+ if (mapped) {
46858
+ if (!webFontFallback) {
46859
+ webFontFallback = mapped;
46860
+ }
46861
+ continue;
46862
+ }
46863
+ return font;
46810
46864
  }
46811
- return fonts[0];
46865
+ return webFontFallback;
46812
46866
  }
46813
46867
  function extractHexColor(value) {
46814
46868
  const namedColors = {
@@ -52293,31 +52347,44 @@ var docgen = (() => {
52293
52347
  // packages/docs/create-document.js
52294
52348
  function replaceChartPlaceholders(elements, chartImages) {
52295
52349
  let chartIndex = 0;
52296
- return elements.map((element) => {
52297
- if (element.type === "chart-placeholder" && element.chartId) {
52298
- const imageData = chartImages.get(element.chartId);
52299
- if (imageData) {
52300
- return {
52301
- type: "chart-image",
52302
- title: element.title,
52303
- imageData
52304
- };
52350
+ function replaceInElements(els) {
52351
+ return els.map((element) => {
52352
+ if (element.type === "chart-placeholder" && element.chartId) {
52353
+ const imageData = chartImages.get(element.chartId);
52354
+ if (imageData) {
52355
+ return {
52356
+ type: "chart-image",
52357
+ title: element.title,
52358
+ imageData
52359
+ };
52360
+ }
52305
52361
  }
52306
- }
52307
- if (element.type === "svg-chart") {
52308
- const key2 = `svg-chart-${chartIndex}`;
52309
- const imageData = chartImages.get(key2);
52310
- chartIndex++;
52311
- if (imageData) {
52362
+ if (element.type === "svg-chart") {
52363
+ const key2 = `svg-chart-${chartIndex}`;
52364
+ const imageData = chartImages.get(key2);
52365
+ chartIndex++;
52366
+ if (imageData) {
52367
+ return {
52368
+ type: "chart-image",
52369
+ title: element.title,
52370
+ imageData
52371
+ };
52372
+ }
52373
+ }
52374
+ if (element.type === "blockquote" && element.content) {
52375
+ return { ...element, content: replaceInElements(element.content) };
52376
+ }
52377
+ if (element.type === "two-column-layout") {
52312
52378
  return {
52313
- type: "chart-image",
52314
- title: element.title,
52315
- imageData
52379
+ ...element,
52380
+ sidebar: { ...element.sidebar, content: replaceInElements(element.sidebar.content) },
52381
+ main: { ...element.main, content: replaceInElements(element.main.content) }
52316
52382
  };
52317
52383
  }
52318
- }
52319
- return element;
52320
- });
52384
+ return element;
52385
+ });
52386
+ }
52387
+ return replaceInElements(elements);
52321
52388
  }
52322
52389
  function createDocxDocument(html, options = {}) {
52323
52390
  const { title, author, description, chartImages, imageMap, pageless, pageHeightTwips, elements: preElements } = options;
@@ -52559,18 +52626,29 @@ var docgen = (() => {
52559
52626
  }
52560
52627
  async function renderSvgChartsFromElements(elements) {
52561
52628
  const chartImages = /* @__PURE__ */ new Map();
52562
- let svgIndex = 0;
52563
- for (const element of elements) {
52564
- if (element.type === "svg-chart") {
52565
- try {
52566
- const imageData = await renderSvgToPng(element.svgContent, element.width, element.height, element.backgroundColor);
52567
- if (imageData) {
52568
- chartImages.set(`svg-chart-${svgIndex}`, imageData);
52569
- }
52570
- } catch (err) {
52571
- console.warn(`Failed to render SVG chart ${svgIndex}:`, err);
52629
+ const svgChartElements = [];
52630
+ function collectSvgCharts(els) {
52631
+ for (const el of els) {
52632
+ if (el.type === "svg-chart") {
52633
+ svgChartElements.push(el);
52634
+ } else if (el.type === "blockquote" && el.content) {
52635
+ collectSvgCharts(el.content);
52636
+ } else if (el.type === "two-column-layout") {
52637
+ collectSvgCharts(el.sidebar.content);
52638
+ collectSvgCharts(el.main.content);
52639
+ }
52640
+ }
52641
+ }
52642
+ collectSvgCharts(elements);
52643
+ for (let svgIndex = 0; svgIndex < svgChartElements.length; svgIndex++) {
52644
+ const element = svgChartElements[svgIndex];
52645
+ try {
52646
+ const imageData = await renderSvgToPng(element.svgContent, element.width, element.height, element.backgroundColor);
52647
+ if (imageData) {
52648
+ chartImages.set(`svg-chart-${svgIndex}`, imageData);
52572
52649
  }
52573
- svgIndex++;
52650
+ } catch (err) {
52651
+ console.warn(`Failed to render SVG chart ${svgIndex}:`, err);
52574
52652
  }
52575
52653
  }
52576
52654
  return chartImages;
@@ -67847,28 +67925,62 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
67847
67925
  const a = Math.round(alpha100k / 1e5 * 100) / 100;
67848
67926
  return `rgba(${r},${g},${b},${a})`;
67849
67927
  }
67928
+ function applyTint(hex, tintVal) {
67929
+ const factor = tintVal / 1e5;
67930
+ const r = parseInt(hex.slice(1, 3), 16);
67931
+ const g = parseInt(hex.slice(3, 5), 16);
67932
+ const b = parseInt(hex.slice(5, 7), 16);
67933
+ const nr = Math.round(r + (255 - r) * (1 - factor));
67934
+ const ng = Math.round(g + (255 - g) * (1 - factor));
67935
+ const nb = Math.round(b + (255 - b) * (1 - factor));
67936
+ return `#${nr.toString(16).padStart(2, "0")}${ng.toString(16).padStart(2, "0")}${nb.toString(16).padStart(2, "0")}`;
67937
+ }
67938
+ function applyShade(hex, shadeVal) {
67939
+ const factor = shadeVal / 1e5;
67940
+ const r = Math.round(parseInt(hex.slice(1, 3), 16) * factor);
67941
+ const g = Math.round(parseInt(hex.slice(3, 5), 16) * factor);
67942
+ const b = Math.round(parseInt(hex.slice(5, 7), 16) * factor);
67943
+ return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
67944
+ }
67945
+ function applyColorModifiers(colorEl, hex) {
67946
+ let color = hex;
67947
+ let alphaVal;
67948
+ const tintEl = findChild2(colorEl, "tint");
67949
+ if (tintEl) {
67950
+ const val = parseInt(tintEl.getAttribute("val") ?? "100000", 10);
67951
+ color = applyTint(color, val);
67952
+ }
67953
+ const shadeEl = findChild2(colorEl, "shade");
67954
+ if (shadeEl) {
67955
+ const val = parseInt(shadeEl.getAttribute("val") ?? "100000", 10);
67956
+ color = applyShade(color, val);
67957
+ }
67958
+ const alphaEl = findChild2(colorEl, "alpha");
67959
+ if (alphaEl) {
67960
+ alphaVal = parseInt(alphaEl.getAttribute("val") ?? "100000", 10);
67961
+ }
67962
+ return { color, alpha: alphaVal };
67963
+ }
67850
67964
  function resolveColor2(parent, themeColors) {
67851
67965
  const srgbClr = findChild2(parent, "srgbClr");
67852
67966
  if (srgbClr) {
67853
67967
  const hex = "#" + (srgbClr.getAttribute("val") ?? "000000");
67854
- const alphaEl = findChild2(srgbClr, "alpha");
67855
- if (alphaEl) {
67856
- const alphaVal = parseInt(alphaEl.getAttribute("val") ?? "100000", 10);
67857
- return hexToRgba(hex, alphaVal);
67968
+ const { color, alpha } = applyColorModifiers(srgbClr, hex);
67969
+ if (alpha !== void 0 && alpha < 1e5) {
67970
+ return hexToRgba(color, alpha);
67858
67971
  }
67859
- return hex;
67972
+ return color;
67860
67973
  }
67861
67974
  const schemeClr = findChild2(parent, "schemeClr");
67862
67975
  if (schemeClr) {
67863
67976
  const val = schemeClr.getAttribute("val");
67864
67977
  if (val && themeColors.has(val)) {
67865
67978
  const hex = themeColors.get(val);
67866
- const alphaEl = findChild2(schemeClr, "alpha");
67867
- if (alphaEl) {
67868
- const alphaVal = parseInt(alphaEl.getAttribute("val") ?? "100000", 10);
67869
- return hexToRgba(hex, alphaVal);
67979
+ const { color, alpha } = applyColorModifiers(schemeClr, hex);
67980
+ if (alpha !== void 0 && alpha < 1e5) {
67981
+ return hexToRgba(color, alpha);
67870
67982
  }
67871
- return hex;
67983
+ return color;
67872
67984
  }
67873
67985
  }
67874
67986
  return void 0;
@@ -67919,6 +68031,158 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
67919
68031
  return resolveColor2(solidFill, themeColors);
67920
68032
  return extractGradientFill(spPr, themeColors);
67921
68033
  }
68034
+ function resolveBgRef(bgRef, bgFillStyles, themeColors) {
68035
+ const idx = parseInt(bgRef.getAttribute("idx") ?? "0", 10);
68036
+ if (idx < 1001 || bgFillStyles.length === 0)
68037
+ return void 0;
68038
+ const styleIdx = idx - 1001;
68039
+ if (styleIdx >= bgFillStyles.length)
68040
+ return void 0;
68041
+ const fillStyle = bgFillStyles[styleIdx];
68042
+ const phColor = resolveColor2(bgRef, themeColors);
68043
+ if (fillStyle.localName === "solidFill") {
68044
+ const phClr = findChild2(fillStyle, "schemeClr");
68045
+ if (phClr?.getAttribute("val") === "phClr" && phColor) {
68046
+ return phColor;
68047
+ }
68048
+ return resolveColor2(fillStyle, themeColors) ?? phColor;
68049
+ }
68050
+ if (fillStyle.localName === "gradFill") {
68051
+ return extractGradientFill(
68052
+ // Wrap in a parent element for extractGradientFill
68053
+ { children: [fillStyle] },
68054
+ themeColors
68055
+ );
68056
+ }
68057
+ return phColor;
68058
+ }
68059
+ function extractBgFill(bgEl, bgFillStyles, themeColors) {
68060
+ const bgPr = findChild2(bgEl, "bgPr");
68061
+ if (bgPr) {
68062
+ return extractFill(bgPr, themeColors);
68063
+ }
68064
+ const bgRef = findChild2(bgEl, "bgRef");
68065
+ if (bgRef) {
68066
+ return resolveBgRef(bgRef, bgFillStyles, themeColors);
68067
+ }
68068
+ return void 0;
68069
+ }
68070
+ function extractCustGeomClipPath(custGeom) {
68071
+ const pathLst = findChild2(custGeom, "pathLst");
68072
+ if (!pathLst)
68073
+ return void 0;
68074
+ const pathEl = findChild2(pathLst, "path");
68075
+ if (!pathEl)
68076
+ return void 0;
68077
+ const pathW = parseInt(pathEl.getAttribute("w") ?? "0", 10);
68078
+ const pathH = parseInt(pathEl.getAttribute("h") ?? "0", 10);
68079
+ if (pathW <= 0 || pathH <= 0)
68080
+ return void 0;
68081
+ const points = [];
68082
+ for (let i = 0; i < pathEl.children.length; i++) {
68083
+ const cmd = pathEl.children[i];
68084
+ const localName = cmd.localName;
68085
+ if (localName === "moveTo" || localName === "lnTo") {
68086
+ const pt = findChild2(cmd, "pt");
68087
+ if (pt) {
68088
+ const x = parseInt(pt.getAttribute("x") ?? "0", 10);
68089
+ const y = parseInt(pt.getAttribute("y") ?? "0", 10);
68090
+ points.push({ x, y });
68091
+ }
68092
+ } else if (localName === "close") {
68093
+ } else {
68094
+ return void 0;
68095
+ }
68096
+ }
68097
+ if (points.length < 3)
68098
+ return void 0;
68099
+ const polygonPoints = points.map((p) => {
68100
+ const xPct = Math.round(p.x / pathW * 1e4) / 100;
68101
+ const yPct = Math.round(p.y / pathH * 1e4) / 100;
68102
+ return `${xPct}% ${yPct}%`;
68103
+ }).join(", ");
68104
+ return `polygon(${polygonPoints})`;
68105
+ }
68106
+ function parseDecorativeShapes(spTree, scale, themeColors, imageMap, themeFonts) {
68107
+ const elements = [];
68108
+ for (let i = 0; i < spTree.children.length; i++) {
68109
+ const child = spTree.children[i];
68110
+ if (child.localName === "sp") {
68111
+ const nvSpPr = findChild2(child, "nvSpPr");
68112
+ if (nvSpPr) {
68113
+ const phEl = findChild2(findChild2(nvSpPr, "nvPr") ?? nvSpPr, "ph");
68114
+ if (phEl)
68115
+ continue;
68116
+ }
68117
+ const spPr = findChild2(child, "spPr");
68118
+ if (spPr) {
68119
+ const custGeom = findChild2(spPr, "custGeom");
68120
+ if (custGeom) {
68121
+ const clipPath = extractCustGeomClipPath(custGeom);
68122
+ if (!clipPath)
68123
+ continue;
68124
+ const shape2 = parseShape(child, scale, themeColors, themeFonts);
68125
+ if (shape2) {
68126
+ shape2.clipPath = clipPath;
68127
+ elements.push({ kind: "shape", data: shape2 });
68128
+ }
68129
+ continue;
68130
+ }
68131
+ }
68132
+ const shape = parseShape(child, scale, themeColors, themeFonts);
68133
+ if (shape)
68134
+ elements.push({ kind: "shape", data: shape });
68135
+ } else if (child.localName === "pic") {
68136
+ const img = parsePicture(child, scale, imageMap);
68137
+ if (img)
68138
+ elements.push({ kind: "image", data: img });
68139
+ } else if (child.localName === "grpSp") {
68140
+ const grpElements = parseGroupShape(child, scale, themeColors, imageMap, themeFonts);
68141
+ elements.push(...grpElements);
68142
+ }
68143
+ }
68144
+ return elements;
68145
+ }
68146
+ function parseGroupShape(grpSp, scale, themeColors, imageMap, themeFonts) {
68147
+ const elements = [];
68148
+ for (let i = 0; i < grpSp.children.length; i++) {
68149
+ const child = grpSp.children[i];
68150
+ if (child.localName === "sp") {
68151
+ const nvSpPr = findChild2(child, "nvSpPr");
68152
+ if (nvSpPr) {
68153
+ const phEl = findChild2(findChild2(nvSpPr, "nvPr") ?? nvSpPr, "ph");
68154
+ if (phEl)
68155
+ continue;
68156
+ }
68157
+ const spPr = findChild2(child, "spPr");
68158
+ if (spPr) {
68159
+ const custGeom = findChild2(spPr, "custGeom");
68160
+ if (custGeom) {
68161
+ const clipPath = extractCustGeomClipPath(custGeom);
68162
+ if (!clipPath)
68163
+ continue;
68164
+ const shape2 = parseShape(child, scale, themeColors, themeFonts);
68165
+ if (shape2) {
68166
+ shape2.clipPath = clipPath;
68167
+ elements.push({ kind: "shape", data: shape2 });
68168
+ }
68169
+ continue;
68170
+ }
68171
+ }
68172
+ const shape = parseShape(child, scale, themeColors, themeFonts);
68173
+ if (shape)
68174
+ elements.push({ kind: "shape", data: shape });
68175
+ } else if (child.localName === "pic") {
68176
+ const img = parsePicture(child, scale, imageMap);
68177
+ if (img)
68178
+ elements.push({ kind: "image", data: img });
68179
+ } else if (child.localName === "grpSp") {
68180
+ const nested = parseGroupShape(child, scale, themeColors, imageMap, themeFonts);
68181
+ elements.push(...nested);
68182
+ }
68183
+ }
68184
+ return elements;
68185
+ }
67922
68186
  function extractRunProps(rPr, scale, themeColors, themeFonts) {
67923
68187
  if (!rPr)
67924
68188
  return {};
@@ -67932,6 +68196,9 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
67932
68196
  const i = rPr.getAttribute("i");
67933
68197
  if (i === "1" || i === "true")
67934
68198
  result.italic = true;
68199
+ const u = rPr.getAttribute("u");
68200
+ if (u && u !== "none")
68201
+ result.underline = true;
67935
68202
  const solidFill = findChild2(rPr, "solidFill");
67936
68203
  if (solidFill) {
67937
68204
  const color = resolveColor2(solidFill, themeColors);
@@ -68038,14 +68305,33 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68038
68305
  return null;
68039
68306
  const wEmu = parseInt(ext.getAttribute("cx") ?? "0", 10);
68040
68307
  const hEmu = parseInt(ext.getAttribute("cy") ?? "0", 10);
68308
+ let fill = extractFill(spPr, themeColors);
68309
+ if (!fill && !findChild2(spPr, "noFill")) {
68310
+ const styleEl = findChild2(sp, "style");
68311
+ if (styleEl) {
68312
+ const fillRef = findChild2(styleEl, "fillRef");
68313
+ if (fillRef) {
68314
+ const fillIdx = parseInt(fillRef.getAttribute("idx") ?? "0", 10);
68315
+ if (fillIdx > 0) {
68316
+ fill = resolveColor2(fillRef, themeColors) ?? void 0;
68317
+ }
68318
+ }
68319
+ }
68320
+ }
68041
68321
  const shape = {
68042
68322
  x: Math.round(emuToPx2(parseInt(off.getAttribute("x") ?? "0", 10)) * scale),
68043
68323
  y: Math.round(emuToPx2(parseInt(off.getAttribute("y") ?? "0", 10)) * scale),
68044
68324
  w: Math.round(emuToPx2(wEmu) * scale),
68045
68325
  h: Math.round(emuToPx2(hEmu) * scale),
68046
- fill: extractFill(spPr, themeColors),
68326
+ fill,
68047
68327
  paragraphs: []
68048
68328
  };
68329
+ const rotAttr = xfrm.getAttribute("rot");
68330
+ if (rotAttr) {
68331
+ const rotDeg = parseInt(rotAttr, 10) / 6e4;
68332
+ if (rotDeg !== 0)
68333
+ shape.rotation = rotDeg;
68334
+ }
68049
68335
  const prstGeom = findChild2(spPr, "prstGeom");
68050
68336
  const prstType = prstGeom?.getAttribute("prst");
68051
68337
  if (prstType === "roundRect" && prstGeom) {
@@ -68057,6 +68343,10 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68057
68343
  shape.borderRadius = Math.round(emuToPx2(radiusEmu) * scale);
68058
68344
  } else if (prstType === "ellipse") {
68059
68345
  shape.isEllipse = true;
68346
+ } else if (prstType === "rtTriangle") {
68347
+ shape.clipPath = "polygon(0 0, 0 100%, 100% 100%)";
68348
+ } else if (prstType === "triangle" || prstType === "isoTriangle") {
68349
+ shape.clipPath = "polygon(50% 0, 0 100%, 100% 100%)";
68060
68350
  }
68061
68351
  const ln = findChild2(spPr, "ln");
68062
68352
  if (ln) {
@@ -68151,6 +68441,10 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68151
68441
  if (buChar) {
68152
68442
  para.bulletChar = buChar.getAttribute("char") ?? void 0;
68153
68443
  }
68444
+ const buFont = findChild2(pPr, "buFont");
68445
+ if (buFont) {
68446
+ para.bulletFont = buFont.getAttribute("typeface") ?? void 0;
68447
+ }
68154
68448
  const buClr = findChild2(pPr, "buClr");
68155
68449
  if (buClr) {
68156
68450
  para.bulletColor = resolveColor2(buClr, themeColors);
@@ -68171,6 +68465,7 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68171
68465
  text,
68172
68466
  bold: props.bold ?? defaults?.bold,
68173
68467
  italic: props.italic ?? defaults?.italic,
68468
+ underline: props.underline ?? defaults?.underline,
68174
68469
  fontSize: props.fontSize ?? defaults?.fontSize,
68175
68470
  color: props.color ?? defaults?.color,
68176
68471
  fontFamily: props.fontFamily ?? defaults?.fontFamily,
@@ -68241,12 +68536,16 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68241
68536
  const alt = cNvPr?.getAttribute("descr") ?? void 0;
68242
68537
  const srcRect = findChild2(blipFill, "srcRect");
68243
68538
  let hasCrop = false;
68539
+ let cropLeft = 0;
68540
+ let cropTop = 0;
68541
+ let cropRight = 0;
68542
+ let cropBottom = 0;
68244
68543
  if (srcRect) {
68245
- const l = parseInt(srcRect.getAttribute("l") ?? "0", 10);
68246
- const r = parseInt(srcRect.getAttribute("r") ?? "0", 10);
68247
- const t = parseInt(srcRect.getAttribute("t") ?? "0", 10);
68248
- const b = parseInt(srcRect.getAttribute("b") ?? "0", 10);
68249
- hasCrop = l > 0 || r > 0 || t > 0 || b > 0;
68544
+ cropLeft = parseInt(srcRect.getAttribute("l") ?? "0", 10) / 1e3;
68545
+ cropRight = parseInt(srcRect.getAttribute("r") ?? "0", 10) / 1e3;
68546
+ cropTop = parseInt(srcRect.getAttribute("t") ?? "0", 10) / 1e3;
68547
+ cropBottom = parseInt(srcRect.getAttribute("b") ?? "0", 10) / 1e3;
68548
+ hasCrop = cropLeft > 0 || cropRight > 0 || cropTop > 0 || cropBottom > 0;
68250
68549
  }
68251
68550
  let borderRadius;
68252
68551
  const prstGeom = findChild2(spPr, "prstGeom");
@@ -68260,6 +68559,13 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68260
68559
  const radiusEmu = minDim * Math.min(adjVal, 5e4) / 1e5;
68261
68560
  borderRadius = Math.round(emuToPx2(radiusEmu) * scale);
68262
68561
  }
68562
+ let rotation;
68563
+ const rotAttr = xfrm.getAttribute("rot");
68564
+ if (rotAttr) {
68565
+ const rotDeg = parseInt(rotAttr, 10) / 6e4;
68566
+ if (rotDeg !== 0)
68567
+ rotation = rotDeg;
68568
+ }
68263
68569
  return {
68264
68570
  x: Math.round(emuToPx2(parseInt(off.getAttribute("x") ?? "0", 10)) * scale),
68265
68571
  y: Math.round(emuToPx2(parseInt(off.getAttribute("y") ?? "0", 10)) * scale),
@@ -68268,7 +68574,12 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68268
68574
  dataUri,
68269
68575
  alt,
68270
68576
  borderRadius,
68271
- hasCrop
68577
+ hasCrop,
68578
+ cropLeft: hasCrop ? cropLeft : void 0,
68579
+ cropTop: hasCrop ? cropTop : void 0,
68580
+ cropRight: hasCrop ? cropRight : void 0,
68581
+ cropBottom: hasCrop ? cropBottom : void 0,
68582
+ rotation
68272
68583
  };
68273
68584
  }
68274
68585
  async function parseTableStyles(zip, parser, themeColors) {
@@ -68396,6 +68707,10 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68396
68707
  if (buChar) {
68397
68708
  para.bulletChar = buChar.getAttribute("char") ?? void 0;
68398
68709
  }
68710
+ const buFont = findChild2(pPr, "buFont");
68711
+ if (buFont) {
68712
+ para.bulletFont = buFont.getAttribute("typeface") ?? void 0;
68713
+ }
68399
68714
  const buClr = findChild2(pPr, "buClr");
68400
68715
  if (buClr) {
68401
68716
  para.bulletColor = resolveColor2(buClr, themeColors);
@@ -68416,6 +68731,7 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68416
68731
  text,
68417
68732
  bold: props.bold ?? defaults?.bold,
68418
68733
  italic: props.italic ?? defaults?.italic,
68734
+ underline: props.underline ?? defaults?.underline,
68419
68735
  fontSize: props.fontSize ?? defaults?.fontSize,
68420
68736
  color: props.color ?? defaults?.color,
68421
68737
  fontFamily: props.fontFamily ?? defaults?.fontFamily,
@@ -68573,15 +68889,523 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68573
68889
  }
68574
68890
  return table;
68575
68891
  }
68576
- function renderSlideHtml(elements, bgColor) {
68892
+ function resolveChartColor(parent, themeColors) {
68893
+ const solidFill = findChild2(parent, "solidFill");
68894
+ if (!solidFill)
68895
+ return void 0;
68896
+ return resolveColor2(solidFill, themeColors);
68897
+ }
68898
+ function parseChartRichText(richEl) {
68899
+ const paragraphs = findChildren2(richEl, "p");
68900
+ let text = "";
68901
+ let font;
68902
+ let color;
68903
+ let size;
68904
+ for (const p of paragraphs) {
68905
+ const runs = findChildren2(p, "r");
68906
+ for (const r of runs) {
68907
+ const tEl = findChild2(r, "t");
68908
+ if (tEl?.textContent)
68909
+ text += tEl.textContent;
68910
+ if (font === void 0) {
68911
+ const rPr = findChild2(r, "rPr");
68912
+ if (rPr) {
68913
+ const szAttr = rPr.getAttribute("sz");
68914
+ if (szAttr)
68915
+ size = hptToPx(parseInt(szAttr, 10));
68916
+ const latin = findChild2(rPr, "latin");
68917
+ if (latin)
68918
+ font = latin.getAttribute("typeface") ?? void 0;
68919
+ const fill = findChild2(rPr, "solidFill");
68920
+ if (fill) {
68921
+ const srgb = findChild2(fill, "srgbClr");
68922
+ if (srgb)
68923
+ color = "#" + (srgb.getAttribute("val") ?? "000000");
68924
+ }
68925
+ }
68926
+ }
68927
+ }
68928
+ }
68929
+ return { text, font, color, size };
68930
+ }
68931
+ function parseChartAxis(axEl, themeColors) {
68932
+ const axis = {
68933
+ position: "b"
68934
+ };
68935
+ const axPos = findChild2(axEl, "axPos");
68936
+ if (axPos) {
68937
+ const val = axPos.getAttribute("val");
68938
+ if (val === "b" || val === "l" || val === "r" || val === "t") {
68939
+ axis.position = val;
68940
+ }
68941
+ }
68942
+ const titleEl = findChild2(axEl, "title");
68943
+ if (titleEl) {
68944
+ const tx = findChild2(titleEl, "tx");
68945
+ if (tx) {
68946
+ const rich = findChild2(tx, "rich");
68947
+ if (rich) {
68948
+ const parsed = parseChartRichText(rich);
68949
+ axis.title = parsed.text;
68950
+ }
68951
+ }
68952
+ }
68953
+ const numFmt = findChild2(axEl, "numFmt");
68954
+ if (numFmt) {
68955
+ const fmt = numFmt.getAttribute("formatCode");
68956
+ if (fmt)
68957
+ axis.numFormat = fmt;
68958
+ }
68959
+ const txPr = findChild2(axEl, "txPr");
68960
+ if (txPr) {
68961
+ const pEls = findChildren2(txPr, "p");
68962
+ for (const p of pEls) {
68963
+ const pPr = findChild2(p, "pPr");
68964
+ if (pPr) {
68965
+ const defRPr = findChild2(pPr, "defRPr");
68966
+ if (defRPr) {
68967
+ const szAttr = defRPr.getAttribute("sz");
68968
+ if (szAttr)
68969
+ axis.labelSize = hptToPx(parseInt(szAttr, 10));
68970
+ const latin = findChild2(defRPr, "latin");
68971
+ if (latin)
68972
+ axis.labelFont = latin.getAttribute("typeface") ?? void 0;
68973
+ const fill = findChild2(defRPr, "solidFill");
68974
+ if (fill) {
68975
+ const srgb = findChild2(fill, "srgbClr");
68976
+ if (srgb)
68977
+ axis.labelColor = "#" + (srgb.getAttribute("val") ?? "000000");
68978
+ }
68979
+ }
68980
+ }
68981
+ }
68982
+ }
68983
+ const gridlines = findChild2(axEl, "majorGridlines");
68984
+ if (gridlines) {
68985
+ const spPr = findChild2(gridlines, "spPr");
68986
+ if (spPr) {
68987
+ const ln = findChild2(spPr, "ln");
68988
+ if (ln) {
68989
+ const fill = findChild2(ln, "solidFill");
68990
+ if (fill) {
68991
+ const srgb = findChild2(fill, "srgbClr");
68992
+ if (srgb) {
68993
+ axis.gridlineColor = "#" + (srgb.getAttribute("val") ?? "CCCCCC");
68994
+ const alphaEl = findChild2(srgb, "alpha");
68995
+ if (alphaEl) {
68996
+ axis.gridlineAlpha = parseInt(alphaEl.getAttribute("val") ?? "100000", 10) / 1e3;
68997
+ }
68998
+ }
68999
+ }
69000
+ }
69001
+ }
69002
+ }
69003
+ const scaling = findChild2(axEl, "scaling");
69004
+ if (scaling) {
69005
+ const minEl = findChild2(scaling, "min");
69006
+ if (minEl) {
69007
+ const val = minEl.getAttribute("val");
69008
+ if (val)
69009
+ axis.min = parseFloat(val);
69010
+ }
69011
+ }
69012
+ return axis;
69013
+ }
69014
+ async function parseChart(graphicFrame, scale, themeColors, zip, slideRelsDoc, parser) {
69015
+ const xfrm = findChild2(graphicFrame, "xfrm");
69016
+ if (!xfrm)
69017
+ return null;
69018
+ const off = findChild2(xfrm, "off");
69019
+ const ext = findChild2(xfrm, "ext");
69020
+ if (!off || !ext)
69021
+ return null;
69022
+ const graphic = findChild2(graphicFrame, "graphic");
69023
+ if (!graphic)
69024
+ return null;
69025
+ const graphicData = findChild2(graphic, "graphicData");
69026
+ if (!graphicData)
69027
+ return null;
69028
+ const uri2 = graphicData.getAttribute("uri") ?? "";
69029
+ if (!uri2.includes("chart"))
69030
+ return null;
69031
+ let chartRId;
69032
+ for (let i = 0; i < graphicData.children.length; i++) {
69033
+ const child = graphicData.children[i];
69034
+ if (child.localName === "chart") {
69035
+ chartRId = child.getAttribute("r:id") ?? child.getAttributeNS("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "id") ?? void 0;
69036
+ break;
69037
+ }
69038
+ }
69039
+ if (!chartRId)
69040
+ return null;
69041
+ let chartTarget;
69042
+ const rels = slideRelsDoc.getElementsByTagName("Relationship");
69043
+ for (let ri = 0; ri < rels.length; ri++) {
69044
+ const rel = rels[ri];
69045
+ if (rel.getAttribute("Id") === chartRId) {
69046
+ chartTarget = rel.getAttribute("Target") ?? void 0;
69047
+ break;
69048
+ }
69049
+ }
69050
+ if (!chartTarget)
69051
+ return null;
69052
+ const chartPath = chartTarget.startsWith("../") ? "ppt/" + chartTarget.slice(3) : chartTarget;
69053
+ const chartXml = await zip.file(chartPath)?.async("text");
69054
+ if (!chartXml)
69055
+ return null;
69056
+ const chartDoc = parser.parseFromString(chartXml, "application/xml");
69057
+ const chartSpace = chartDoc.documentElement;
69058
+ const x = Math.round(emuToPx2(parseInt(off.getAttribute("x") ?? "0", 10)) * scale);
69059
+ const y = Math.round(emuToPx2(parseInt(off.getAttribute("y") ?? "0", 10)) * scale);
69060
+ const w = Math.round(emuToPx2(parseInt(ext.getAttribute("cx") ?? "0", 10)) * scale);
69061
+ const h = Math.round(emuToPx2(parseInt(ext.getAttribute("cy") ?? "0", 10)) * scale);
69062
+ const chartEl = findChild2(chartSpace, "chart");
69063
+ if (!chartEl)
69064
+ return null;
69065
+ let title;
69066
+ let titleFont;
69067
+ let titleColor;
69068
+ let titleSize;
69069
+ const titleEl = findChild2(chartEl, "title");
69070
+ if (titleEl) {
69071
+ const tx = findChild2(titleEl, "tx");
69072
+ if (tx) {
69073
+ const rich = findChild2(tx, "rich");
69074
+ if (rich) {
69075
+ const parsed = parseChartRichText(rich);
69076
+ title = parsed.text;
69077
+ titleFont = parsed.font;
69078
+ titleColor = parsed.color;
69079
+ titleSize = parsed.size;
69080
+ }
69081
+ }
69082
+ }
69083
+ const plotArea = findChild2(chartEl, "plotArea");
69084
+ if (!plotArea)
69085
+ return null;
69086
+ const barChart = findChild2(plotArea, "barChart");
69087
+ if (!barChart)
69088
+ return null;
69089
+ const barDirEl = findChild2(barChart, "barDir");
69090
+ const barDir = barDirEl?.getAttribute("val") ?? "col";
69091
+ const chartType = barDir === "bar" ? "bar" : "column";
69092
+ const gapWidthEl = findChild2(barChart, "gapWidth");
69093
+ const gapWidth = gapWidthEl ? parseInt(gapWidthEl.getAttribute("val") ?? "150", 10) : 150;
69094
+ const roundedCornersEl = findChild2(chartSpace, "roundedCorners");
69095
+ const roundedCorners = roundedCornersEl?.getAttribute("val") === "1";
69096
+ const series = [];
69097
+ const serEls = findChildren2(barChart, "ser");
69098
+ for (const ser of serEls) {
69099
+ const seriesData = {
69100
+ categories: [],
69101
+ values: [],
69102
+ fillColors: []
69103
+ };
69104
+ const txEl = findChild2(ser, "tx");
69105
+ if (txEl) {
69106
+ const strRef = findChild2(txEl, "strRef");
69107
+ if (strRef) {
69108
+ const strCache = findChild2(strRef, "strCache");
69109
+ if (strCache) {
69110
+ const pt = findChild2(strCache, "pt");
69111
+ if (pt) {
69112
+ const v = findChild2(pt, "v");
69113
+ if (v?.textContent)
69114
+ seriesData.name = v.textContent;
69115
+ }
69116
+ }
69117
+ }
69118
+ }
69119
+ const serSpPr = findChild2(ser, "spPr");
69120
+ if (serSpPr) {
69121
+ const color = resolveChartColor(serSpPr, themeColors);
69122
+ if (color)
69123
+ seriesData.seriesColor = color;
69124
+ }
69125
+ const dPtMap = /* @__PURE__ */ new Map();
69126
+ const dPtEls = findChildren2(ser, "dPt");
69127
+ for (const dPt of dPtEls) {
69128
+ const idxEl = findChild2(dPt, "idx");
69129
+ const idx = idxEl ? parseInt(idxEl.getAttribute("val") ?? "0", 10) : 0;
69130
+ const spPr = findChild2(dPt, "spPr");
69131
+ if (spPr) {
69132
+ const color = resolveChartColor(spPr, themeColors);
69133
+ if (color)
69134
+ dPtMap.set(idx, color);
69135
+ }
69136
+ }
69137
+ const catEl = findChild2(ser, "cat");
69138
+ if (catEl) {
69139
+ const strRef = findChild2(catEl, "strRef");
69140
+ if (strRef) {
69141
+ const strCache = findChild2(strRef, "strCache");
69142
+ if (strCache) {
69143
+ const pts = findChildren2(strCache, "pt");
69144
+ for (const pt of pts) {
69145
+ const v = findChild2(pt, "v");
69146
+ seriesData.categories.push(v?.textContent ?? "");
69147
+ }
69148
+ }
69149
+ }
69150
+ }
69151
+ const valEl = findChild2(ser, "val");
69152
+ if (valEl) {
69153
+ const numRef = findChild2(valEl, "numRef");
69154
+ if (numRef) {
69155
+ const numCache = findChild2(numRef, "numCache");
69156
+ if (numCache) {
69157
+ const pts = findChildren2(numCache, "pt");
69158
+ for (const pt of pts) {
69159
+ const v = findChild2(pt, "v");
69160
+ seriesData.values.push(parseFloat(v?.textContent ?? "0"));
69161
+ }
69162
+ }
69163
+ }
69164
+ }
69165
+ for (let i = 0; i < seriesData.values.length; i++) {
69166
+ seriesData.fillColors.push(dPtMap.get(i) ?? void 0);
69167
+ }
69168
+ series.push(seriesData);
69169
+ }
69170
+ if (series.length === 0)
69171
+ return null;
69172
+ let categoryAxis;
69173
+ let valueAxis;
69174
+ const catAx = findChild2(plotArea, "catAx");
69175
+ if (catAx) {
69176
+ categoryAxis = parseChartAxis(catAx, themeColors);
69177
+ }
69178
+ const valAx = findChild2(plotArea, "valAx");
69179
+ if (valAx) {
69180
+ valueAxis = parseChartAxis(valAx, themeColors);
69181
+ }
69182
+ return {
69183
+ x,
69184
+ y,
69185
+ w,
69186
+ h,
69187
+ chartType,
69188
+ title,
69189
+ titleFont,
69190
+ titleColor,
69191
+ titleSize,
69192
+ series,
69193
+ categoryAxis,
69194
+ valueAxis,
69195
+ gapWidth,
69196
+ roundedCorners
69197
+ };
69198
+ }
69199
+ function formatChartValue(value, numFormat) {
69200
+ if (!numFormat || numFormat === "General") {
69201
+ return Number.isInteger(value) ? value.toString() : value.toFixed(1);
69202
+ }
69203
+ let prefix = "";
69204
+ let suffix = "";
69205
+ let fmt = numFormat;
69206
+ const prefixMatch = fmt.match(/^"([^"]*)"(.*)$/);
69207
+ if (prefixMatch) {
69208
+ prefix = prefixMatch[1];
69209
+ fmt = prefixMatch[2];
69210
+ }
69211
+ const suffixMatch = fmt.match(/^(.*)"([^"]*)"$/);
69212
+ if (suffixMatch) {
69213
+ fmt = suffixMatch[1];
69214
+ suffix = suffixMatch[2];
69215
+ }
69216
+ const decimalMatch = fmt.match(/\.(0+)/);
69217
+ const decimals = decimalMatch ? decimalMatch[1].length : 0;
69218
+ const absVal = Math.abs(value);
69219
+ let formatted;
69220
+ if (fmt.includes(",")) {
69221
+ const parts = absVal.toFixed(decimals).split(".");
69222
+ parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
69223
+ formatted = parts.join(".");
69224
+ } else {
69225
+ formatted = absVal.toFixed(decimals);
69226
+ }
69227
+ const sign2 = value < 0 ? "-" : "";
69228
+ return sign2 + prefix + formatted + suffix;
69229
+ }
69230
+ function escSvg(text) {
69231
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
69232
+ }
69233
+ function renderChartSvg(chart, elId) {
69234
+ const { x, y, w, h } = chart;
69235
+ const titleHeight = chart.title ? Math.max(24, (chart.titleSize ?? 16) + 12) : 0;
69236
+ const axisLabelHeight = 16;
69237
+ const axisTitleHeight = chart.categoryAxis?.title ? 18 : 0;
69238
+ const valAxisTitleWidth = chart.valueAxis?.title ? 20 : 0;
69239
+ const allValues = chart.series.flatMap((s) => s.values);
69240
+ const maxValue = Math.max(...allValues, 0);
69241
+ const valNumFormat = chart.valueAxis?.numFormat;
69242
+ const maxFormattedLabel = formatChartValue(maxValue, valNumFormat);
69243
+ const valLabelCharWidth = (chart.valueAxis?.labelSize ?? 11) * 0.6;
69244
+ const valLabelWidth = Math.max(30, maxFormattedLabel.length * valLabelCharWidth + 8);
69245
+ const marginTop = 8 + titleHeight;
69246
+ const marginBottom = 8 + axisLabelHeight + axisTitleHeight + 4;
69247
+ const marginLeft = 4 + valAxisTitleWidth + valLabelWidth;
69248
+ const marginRight = 12;
69249
+ const plotX = marginLeft;
69250
+ const plotY = marginTop;
69251
+ const plotW = w - marginLeft - marginRight;
69252
+ const plotH = h - marginTop - marginBottom;
69253
+ if (plotW <= 0 || plotH <= 0)
69254
+ return "";
69255
+ const minValue = chart.valueAxis?.min ?? 0;
69256
+ const valueRange = maxValue - minValue;
69257
+ if (valueRange <= 0)
69258
+ return "";
69259
+ const rawInterval = valueRange / 5;
69260
+ const magnitude = Math.pow(10, Math.floor(Math.log10(rawInterval)));
69261
+ const normalized = rawInterval / magnitude;
69262
+ let niceInterval;
69263
+ if (normalized <= 1)
69264
+ niceInterval = 1 * magnitude;
69265
+ else if (normalized <= 2)
69266
+ niceInterval = 2 * magnitude;
69267
+ else if (normalized <= 5)
69268
+ niceInterval = 5 * magnitude;
69269
+ else
69270
+ niceInterval = 10 * magnitude;
69271
+ const ticks = [];
69272
+ let tickVal = Math.ceil(minValue / niceInterval) * niceInterval;
69273
+ while (tickVal <= maxValue) {
69274
+ ticks.push(tickVal);
69275
+ tickVal += niceInterval;
69276
+ }
69277
+ if (minValue <= 0 && !ticks.includes(0)) {
69278
+ ticks.unshift(0);
69279
+ ticks.sort((a, b) => a - b);
69280
+ }
69281
+ const labelFont = chart.categoryAxis?.labelFont ?? chart.titleFont ?? "sans-serif";
69282
+ const labelColor = chart.categoryAxis?.labelColor ?? "#333";
69283
+ const labelSize = chart.categoryAxis?.labelSize ?? 11;
69284
+ const valLabelColor = chart.valueAxis?.labelColor ?? labelColor;
69285
+ const valLabelSize = chart.valueAxis?.labelSize ?? 11;
69286
+ let svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${w}" height="${h}" viewBox="0 0 ${w} ${h}" style="overflow:visible">`;
69287
+ if (chart.title) {
69288
+ const tFont = chart.titleFont ? `font-family:${cssFontFamily(chart.titleFont)};` : `font-family:${cssFontFamily(labelFont)};`;
69289
+ const tColor = chart.titleColor ?? "#000";
69290
+ const tSize = chart.titleSize ?? 16;
69291
+ svg += `<text x="${w / 2}" y="${8 + tSize}" text-anchor="middle" style="${tFont}font-size:${tSize}px;font-weight:bold;fill:${tColor}">${escSvg(chart.title)}</text>`;
69292
+ }
69293
+ if (chart.valueAxis) {
69294
+ const gColor = chart.valueAxis.gridlineColor ?? "#e0e0e0";
69295
+ const gAlpha = chart.valueAxis.gridlineAlpha !== void 0 ? chart.valueAxis.gridlineAlpha / 100 : 0.3;
69296
+ for (const tick of ticks) {
69297
+ const tickY = plotY + plotH - (tick - minValue) / valueRange * plotH;
69298
+ svg += `<line x1="${plotX}" y1="${tickY}" x2="${plotX + plotW}" y2="${tickY}" stroke="${gColor}" stroke-opacity="${gAlpha}" stroke-width="1"/>`;
69299
+ }
69300
+ }
69301
+ const numCategories = chart.series[0]?.categories.length ?? 0;
69302
+ const numSeries = chart.series.length;
69303
+ if (numCategories > 0) {
69304
+ const gapFraction = (chart.gapWidth ?? 150) / 100;
69305
+ const categoryWidth = plotW / numCategories;
69306
+ const barGroupWidth = categoryWidth / (1 + gapFraction);
69307
+ const gapSpace = categoryWidth - barGroupWidth;
69308
+ const barWidth = barGroupWidth / numSeries;
69309
+ const cornerRadius = chart.roundedCorners ? Math.min(barWidth * 0.15, 4) : 0;
69310
+ for (let si = 0; si < numSeries; si++) {
69311
+ const s = chart.series[si];
69312
+ for (let ci = 0; ci < s.values.length; ci++) {
69313
+ const val = s.values[ci];
69314
+ const barH = (val - minValue) / valueRange * plotH;
69315
+ const barX = plotX + ci * categoryWidth + gapSpace / 2 + si * barWidth;
69316
+ const barY = plotY + plotH - barH;
69317
+ const fillColor = s.fillColors[ci] ?? s.seriesColor ?? "#4472C4";
69318
+ if (cornerRadius > 0) {
69319
+ const r = Math.min(cornerRadius, barH / 2, barWidth / 2);
69320
+ svg += `<path d="M${barX},${barY + barH} L${barX},${barY + r} Q${barX},${barY} ${barX + r},${barY} L${barX + barWidth - r},${barY} Q${barX + barWidth},${barY} ${barX + barWidth},${barY + r} L${barX + barWidth},${barY + barH} Z" fill="${fillColor}"/>`;
69321
+ } else {
69322
+ svg += `<rect x="${barX}" y="${barY}" width="${barWidth}" height="${barH}" fill="${fillColor}"/>`;
69323
+ }
69324
+ }
69325
+ }
69326
+ }
69327
+ svg += `<line x1="${plotX}" y1="${plotY + plotH}" x2="${plotX + plotW}" y2="${plotY + plotH}" stroke="${labelColor}" stroke-width="1"/>`;
69328
+ svg += `<line x1="${plotX}" y1="${plotY}" x2="${plotX}" y2="${plotY + plotH}" stroke="${valLabelColor}" stroke-width="1"/>`;
69329
+ if (numCategories > 0) {
69330
+ const categoryWidth = plotW / numCategories;
69331
+ const cats = chart.series[0]?.categories ?? [];
69332
+ for (let ci = 0; ci < cats.length; ci++) {
69333
+ const labelX = plotX + ci * categoryWidth + categoryWidth / 2;
69334
+ const labelY = plotY + plotH + 4;
69335
+ const catText = cats[ci];
69336
+ const lines = catText.split("\n");
69337
+ const lineH = labelSize + 2;
69338
+ for (let li = 0; li < lines.length; li++) {
69339
+ svg += `<text x="${labelX}" y="${labelY + labelSize + li * lineH}" text-anchor="middle" style="font-family:${cssFontFamily(labelFont)};font-size:${labelSize}px;fill:${labelColor}">${escSvg(lines[li])}</text>`;
69340
+ }
69341
+ }
69342
+ }
69343
+ for (const tick of ticks) {
69344
+ const tickY = plotY + plotH - (tick - minValue) / valueRange * plotH;
69345
+ const label = formatChartValue(tick, valNumFormat);
69346
+ svg += `<text x="${plotX - 6}" y="${tickY + valLabelSize * 0.35}" text-anchor="end" style="font-family:${cssFontFamily(labelFont)};font-size:${valLabelSize}px;fill:${valLabelColor}">${escSvg(label)}</text>`;
69347
+ }
69348
+ if (chart.categoryAxis?.title) {
69349
+ const axTitleY = plotY + plotH + axisLabelHeight + axisTitleHeight + 2;
69350
+ svg += `<text x="${plotX + plotW / 2}" y="${axTitleY}" text-anchor="middle" style="font-family:${cssFontFamily(labelFont)};font-size:${labelSize}px;fill:${labelColor}">${escSvg(chart.categoryAxis.title)}</text>`;
69351
+ }
69352
+ if (chart.valueAxis?.title) {
69353
+ const axTitleX = 4 + (chart.titleSize ?? 12) * 0.5;
69354
+ const axTitleY = plotY + plotH / 2;
69355
+ svg += `<text x="${axTitleX}" y="${axTitleY}" text-anchor="middle" transform="rotate(-90, ${axTitleX}, ${axTitleY})" style="font-family:${cssFontFamily(labelFont)};font-size:${labelSize}px;fill:${valLabelColor}">${escSvg(chart.valueAxis.title)}</text>`;
69356
+ }
69357
+ svg += `</svg>`;
69358
+ const wrapperStyles = [
69359
+ "position:absolute",
69360
+ `left:${x}px`,
69361
+ `top:${y}px`,
69362
+ `width:${w}px`,
69363
+ `height:${h}px`
69364
+ ];
69365
+ return `<div id="${elId}" data-elementType="chart" style="${wrapperStyles.join(";")}">${svg}</div>
69366
+ `;
69367
+ }
69368
+ function renderSlideHtml(elements, bgColor, contentOffsetX = 0) {
68577
69369
  let inner = "";
68578
69370
  let elementIndex = 0;
68579
69371
  for (const el of elements) {
68580
69372
  const elId = `el-${elementIndex++}`;
68581
69373
  if (el.kind === "image") {
68582
69374
  const img = el.data;
69375
+ const altAttr = img.alt ? ` alt="${img.alt.replace(/"/g, "&quot;")}"` : "";
68583
69376
  const isFullbleed = img.x <= 10 && img.y <= 10 && img.w >= TARGET_WIDTH - 20 && img.h >= TARGET_HEIGHT - 20;
68584
- const objectFit = isFullbleed || img.hasCrop ? "cover" : "contain";
69377
+ if (img.hasCrop && img.cropLeft !== void 0 && img.cropTop !== void 0 && img.cropRight !== void 0 && img.cropBottom !== void 0) {
69378
+ const visW = (100 - img.cropLeft - img.cropRight) / 100;
69379
+ const visH = (100 - img.cropTop - img.cropBottom) / 100;
69380
+ if (visW > 0 && visH > 0) {
69381
+ const displayW = img.w / visW;
69382
+ const displayH = img.h / visH;
69383
+ const offsetX = -(img.cropLeft / 100) * displayW;
69384
+ const offsetY = -(img.cropTop / 100) * displayH;
69385
+ const wrapperStyles = [
69386
+ "position:absolute",
69387
+ `left:${img.x}px`,
69388
+ `top:${img.y}px`,
69389
+ `width:${img.w}px`,
69390
+ `height:${img.h}px`,
69391
+ "overflow:hidden"
69392
+ ];
69393
+ if (img.rotation) {
69394
+ wrapperStyles.push(`transform:rotate(${img.rotation}deg)`);
69395
+ wrapperStyles.push("transform-origin:center center");
69396
+ }
69397
+ if (img.borderRadius && img.borderRadius > 0) {
69398
+ wrapperStyles.push(`border-radius:${img.borderRadius}px`);
69399
+ }
69400
+ const imgStyle = `position:absolute;width:${Math.round(displayW)}px;height:${Math.round(displayH)}px;left:${Math.round(offsetX)}px;top:${Math.round(offsetY)}px`;
69401
+ inner += `<div id="${elId}" data-elementType="image" style="${wrapperStyles.join(";")}">`;
69402
+ inner += `<img src="${img.dataUri}"${altAttr} style="${imgStyle}" />`;
69403
+ inner += `</div>
69404
+ `;
69405
+ continue;
69406
+ }
69407
+ }
69408
+ const objectFit = isFullbleed ? "cover" : "contain";
68585
69409
  const stylesList = [
68586
69410
  "position:absolute",
68587
69411
  `left:${img.x}px`,
@@ -68590,11 +69414,14 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68590
69414
  `height:${img.h}px`,
68591
69415
  `object-fit:${objectFit}`
68592
69416
  ];
69417
+ if (img.rotation) {
69418
+ stylesList.push(`transform:rotate(${img.rotation}deg)`);
69419
+ stylesList.push("transform-origin:center center");
69420
+ }
68593
69421
  if (img.borderRadius && img.borderRadius > 0) {
68594
69422
  stylesList.push(`border-radius:${img.borderRadius}px`);
68595
69423
  }
68596
69424
  const styles2 = stylesList.join(";");
68597
- const altAttr = img.alt ? ` alt="${img.alt.replace(/"/g, "&quot;")}"` : "";
68598
69425
  inner += `<img id="${elId}" data-elementType="image" src="${img.dataUri}"${altAttr} style="${styles2}" />
68599
69426
  `;
68600
69427
  continue;
@@ -68683,6 +69510,8 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68683
69510
  rStyles.push("font-weight:bold");
68684
69511
  if (run.italic)
68685
69512
  rStyles.push("font-style:italic");
69513
+ if (run.underline)
69514
+ rStyles.push("text-decoration:underline");
68686
69515
  if (run.fontFamily)
68687
69516
  rStyles.push(`font-family:${cssFontFamily(run.fontFamily)}`);
68688
69517
  if (run.textShadow)
@@ -68705,6 +69534,11 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68705
69534
  `;
68706
69535
  continue;
68707
69536
  }
69537
+ if (el.kind === "chart") {
69538
+ const chart = el.data;
69539
+ inner += renderChartSvg(chart, elId);
69540
+ continue;
69541
+ }
68708
69542
  const shape = el.data;
68709
69543
  const styles = [
68710
69544
  "position:absolute",
@@ -68717,6 +69551,12 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68717
69551
  if (shape.fill) {
68718
69552
  styles.push(`background:${shape.fill}`);
68719
69553
  }
69554
+ if (shape.clipPath) {
69555
+ styles.push(`clip-path:${shape.clipPath}`);
69556
+ }
69557
+ if (shape.rotation) {
69558
+ styles.push(`transform:rotate(${shape.rotation}deg)`);
69559
+ }
68720
69560
  if (shape.borderRadius) {
68721
69561
  styles.push(`border-radius:${shape.borderRadius}px`);
68722
69562
  } else if (shape.isEllipse) {
@@ -68750,7 +69590,10 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68750
69590
  else if (shape.verticalAlign === "bottom")
68751
69591
  styles.push("justify-content:flex-end");
68752
69592
  }
68753
- if (shape.paragraphs.length === 0 && !shape.fill) {
69593
+ if (shape.w <= 0 || shape.h <= 0) {
69594
+ continue;
69595
+ }
69596
+ if (shape.paragraphs.length === 0 && !shape.fill && !shape.borderWidth && !shape.isEllipse) {
68754
69597
  continue;
68755
69598
  }
68756
69599
  const hasText = shape.paragraphs.length > 0;
@@ -68772,8 +69615,15 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68772
69615
  pStyles.push(`text-indent:${para.indentPx}px`);
68773
69616
  let runHtml = "";
68774
69617
  if (para.bulletChar) {
68775
- const bulletStyle = para.bulletColor ? `margin-right:4px;color:${para.bulletColor}` : "margin-right:4px";
68776
- runHtml += `<span style="${bulletStyle}">${para.bulletChar}</span>`;
69618
+ const bulletStyleParts = ["margin-right:4px"];
69619
+ if (para.bulletColor)
69620
+ bulletStyleParts.push(`color:${para.bulletColor}`);
69621
+ if (para.bulletFont)
69622
+ bulletStyleParts.push(`font-family:${cssFontFamily(para.bulletFont)}`);
69623
+ const firstRunFontSize = para.runs[0]?.fontSize;
69624
+ if (firstRunFontSize)
69625
+ bulletStyleParts.push(`font-size:${firstRunFontSize}px`);
69626
+ runHtml += `<span style="${bulletStyleParts.join(";")}">${para.bulletChar}</span>`;
68777
69627
  }
68778
69628
  for (const run of para.runs) {
68779
69629
  const rStyles = [];
@@ -68791,6 +69641,8 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68791
69641
  rStyles.push("font-weight:bold");
68792
69642
  if (run.italic)
68793
69643
  rStyles.push("font-style:italic");
69644
+ if (run.underline)
69645
+ rStyles.push("text-decoration:underline");
68794
69646
  if (run.fontFamily)
68795
69647
  rStyles.push(`font-family:${cssFontFamily(run.fontFamily)}`);
68796
69648
  if (run.textShadow)
@@ -68808,8 +69660,12 @@ ${validationErrors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")}`;
68808
69660
  `;
68809
69661
  }
68810
69662
  const bg = bgColor ?? "#fff";
69663
+ const offsetPx = Math.round(contentOffsetX);
69664
+ const innerWrapStyle = offsetPx > 0 ? ` style="position:absolute;left:${offsetPx}px;top:0"` : "";
68811
69665
  return `<div style="position:relative;width:${TARGET_WIDTH}px;height:${TARGET_HEIGHT}px;overflow:hidden;font-family:'Segoe UI',Arial,sans-serif;background:${bg}">
68812
- ${inner}</div>`;
69666
+ <div${innerWrapStyle}>
69667
+ ${inner}</div>
69668
+ </div>`;
68813
69669
  }
68814
69670
  async function importPptx(arrayBuffer) {
68815
69671
  const zip = await import_jszip2.default.loadAsync(arrayBuffer);
@@ -68824,6 +69680,8 @@ ${inner}</div>`;
68824
69680
  const slideWPx = emuToPx2(slideWEmu);
68825
69681
  const slideHPx = emuToPx2(slideHEmu);
68826
69682
  const scale = Math.min(TARGET_WIDTH / slideWPx, TARGET_HEIGHT / slideHPx);
69683
+ const scaledContentW = slideWPx * scale;
69684
+ const contentOffsetX = (TARGET_WIDTH - scaledContentW) / 2;
68827
69685
  const sldIdLst = presDoc.getElementsByTagName("p:sldIdLst")[0];
68828
69686
  const visibleSlideRIds = [];
68829
69687
  if (sldIdLst) {
@@ -68872,6 +69730,7 @@ ${inner}</div>`;
68872
69730
  }
68873
69731
  const themeColors = /* @__PURE__ */ new Map();
68874
69732
  const themeXml = await zip.file("ppt/theme/theme1.xml")?.async("text");
69733
+ const bgFillStyles = [];
68875
69734
  if (themeXml) {
68876
69735
  const themeDoc = parser.parseFromString(themeXml, "application/xml");
68877
69736
  const clrScheme = themeDoc.getElementsByTagName("a:clrScheme")[0];
@@ -68917,6 +69776,12 @@ ${inner}</div>`;
68917
69776
  const lt2Color = themeColors.get("lt2");
68918
69777
  if (lt2Color)
68919
69778
  themeColors.set("bg2", lt2Color);
69779
+ const bgFillStyleLst = themeDoc.getElementsByTagName("a:bgFillStyleLst")[0];
69780
+ if (bgFillStyleLst) {
69781
+ for (let i = 0; i < bgFillStyleLst.children.length; i++) {
69782
+ bgFillStyles.push(bgFillStyleLst.children[i]);
69783
+ }
69784
+ }
68920
69785
  }
68921
69786
  let themeFonts;
68922
69787
  if (themeXml) {
@@ -68953,6 +69818,96 @@ ${inner}</div>`;
68953
69818
  fontStyleBlock = `<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=${fontFamilies}&display=swap">`;
68954
69819
  }
68955
69820
  const slides = [];
69821
+ let masterBg;
69822
+ let masterDecorativeElements = [];
69823
+ const masterXml = await zip.file("ppt/slideMasters/slideMaster1.xml")?.async("text");
69824
+ if (masterXml) {
69825
+ const masterDoc = parser.parseFromString(masterXml, "application/xml");
69826
+ const masterBgEl = masterDoc.getElementsByTagName("p:bg")[0];
69827
+ if (masterBgEl) {
69828
+ masterBg = extractBgFill(masterBgEl, bgFillStyles, themeColors);
69829
+ }
69830
+ const masterImageMap = /* @__PURE__ */ new Map();
69831
+ const masterRelsXml = await zip.file("ppt/slideMasters/_rels/slideMaster1.xml.rels")?.async("text");
69832
+ if (masterRelsXml) {
69833
+ const relsDoc = parser.parseFromString(masterRelsXml, "application/xml");
69834
+ const rels = relsDoc.getElementsByTagName("Relationship");
69835
+ for (let ri = 0; ri < rels.length; ri++) {
69836
+ const rel = rels[ri];
69837
+ const type2 = rel.getAttribute("Type") ?? "";
69838
+ if (!type2.includes("/image"))
69839
+ continue;
69840
+ const rId = rel.getAttribute("Id");
69841
+ const target = rel.getAttribute("Target");
69842
+ if (!rId || !target)
69843
+ continue;
69844
+ const mediaPath = target.startsWith("../") ? "ppt/" + target.slice(3) : target;
69845
+ const imgFile = zip.file(mediaPath);
69846
+ if (!imgFile)
69847
+ continue;
69848
+ const imgData = await imgFile.async("base64");
69849
+ const ext = mediaPath.split(".").pop()?.toLowerCase() ?? "png";
69850
+ const mime = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : ext === "svg" ? "image/svg+xml" : `image/${ext}`;
69851
+ masterImageMap.set(rId, `data:${mime};base64,${imgData}`);
69852
+ }
69853
+ }
69854
+ const masterSpTree = masterDoc.getElementsByTagName("p:spTree")[0];
69855
+ if (masterSpTree) {
69856
+ masterDecorativeElements = parseDecorativeShapes(masterSpTree, scale, themeColors, masterImageMap, themeFonts);
69857
+ }
69858
+ }
69859
+ const layoutCache = /* @__PURE__ */ new Map();
69860
+ async function getLayoutInfo(layoutPath) {
69861
+ if (layoutCache.has(layoutPath))
69862
+ return layoutCache.get(layoutPath);
69863
+ const result = { bg: void 0, showMasterSp: true, decorativeElements: [] };
69864
+ const layoutXml = await zip.file(layoutPath)?.async("text");
69865
+ if (layoutXml) {
69866
+ const layoutDoc = parser.parseFromString(layoutXml, "application/xml");
69867
+ const cSld = layoutDoc.getElementsByTagName("p:cSld")[0];
69868
+ const rootEl = layoutDoc.documentElement;
69869
+ const showMasterSpAttr = rootEl.getAttribute("showMasterSp");
69870
+ if (showMasterSpAttr === "0") {
69871
+ result.showMasterSp = false;
69872
+ }
69873
+ const layoutBgEl = layoutDoc.getElementsByTagName("p:bg")[0];
69874
+ if (layoutBgEl) {
69875
+ result.bg = extractBgFill(layoutBgEl, bgFillStyles, themeColors);
69876
+ }
69877
+ const layoutImageMap = /* @__PURE__ */ new Map();
69878
+ const layoutBaseName = layoutPath.split("/").pop();
69879
+ const layoutRelsPath = layoutPath.replace(layoutBaseName, `_rels/${layoutBaseName}.rels`);
69880
+ const layoutRelsXml = await zip.file(layoutRelsPath)?.async("text");
69881
+ if (layoutRelsXml) {
69882
+ const relsDoc = parser.parseFromString(layoutRelsXml, "application/xml");
69883
+ const rels = relsDoc.getElementsByTagName("Relationship");
69884
+ for (let ri = 0; ri < rels.length; ri++) {
69885
+ const rel = rels[ri];
69886
+ const type2 = rel.getAttribute("Type") ?? "";
69887
+ if (!type2.includes("/image"))
69888
+ continue;
69889
+ const rId = rel.getAttribute("Id");
69890
+ const target = rel.getAttribute("Target");
69891
+ if (!rId || !target)
69892
+ continue;
69893
+ const mediaPath = target.startsWith("../") ? "ppt/" + target.slice(3) : target;
69894
+ const imgFile = zip.file(mediaPath);
69895
+ if (!imgFile)
69896
+ continue;
69897
+ const imgData = await imgFile.async("base64");
69898
+ const ext = mediaPath.split(".").pop()?.toLowerCase() ?? "png";
69899
+ const mime = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : ext === "svg" ? "image/svg+xml" : `image/${ext}`;
69900
+ layoutImageMap.set(rId, `data:${mime};base64,${imgData}`);
69901
+ }
69902
+ }
69903
+ const layoutSpTree = layoutDoc.getElementsByTagName("p:spTree")[0];
69904
+ if (layoutSpTree) {
69905
+ result.decorativeElements = parseDecorativeShapes(layoutSpTree, scale, themeColors, layoutImageMap, themeFonts);
69906
+ }
69907
+ }
69908
+ layoutCache.set(layoutPath, result);
69909
+ return result;
69910
+ }
68956
69911
  for (const slideFile of slideFiles) {
68957
69912
  const slideXml = await zip.file(slideFile)?.async("text");
68958
69913
  if (!slideXml)
@@ -68962,24 +69917,47 @@ ${inner}</div>`;
68962
69917
  let slideBg = void 0;
68963
69918
  const bgEl = slideDoc.getElementsByTagName("p:bg")[0];
68964
69919
  if (bgEl) {
68965
- const bgPr = findChild2(bgEl, "bgPr");
68966
- if (bgPr) {
68967
- slideBg = extractFill(bgPr, themeColors);
68968
- }
69920
+ slideBg = extractBgFill(bgEl, bgFillStyles, themeColors);
68969
69921
  }
68970
- if (!spTree) {
68971
- slides.push(renderSlideHtml([], slideBg));
68972
- continue;
68973
- }
68974
- const imageMap = /* @__PURE__ */ new Map();
68975
69922
  const slideBaseName = slideFile.split("/").pop();
68976
69923
  const relsPath = slideFile.replace(slideBaseName, `_rels/${slideBaseName}.rels`);
68977
69924
  const relsXml = await zip.file(relsPath)?.async("text");
69925
+ let layoutPath;
68978
69926
  if (relsXml) {
68979
69927
  const relsDoc = parser.parseFromString(relsXml, "application/xml");
68980
69928
  const rels = relsDoc.getElementsByTagName("Relationship");
68981
- for (let i = 0; i < rels.length; i++) {
68982
- const rel = rels[i];
69929
+ for (let ri = 0; ri < rels.length; ri++) {
69930
+ const rel = rels[ri];
69931
+ const type2 = rel.getAttribute("Type") ?? "";
69932
+ if (type2.includes("/slideLayout")) {
69933
+ const target = rel.getAttribute("Target");
69934
+ if (target) {
69935
+ layoutPath = target.startsWith("../") ? "ppt/" + target.slice(3) : "ppt/slides/" + target;
69936
+ }
69937
+ break;
69938
+ }
69939
+ }
69940
+ }
69941
+ let layoutInfo;
69942
+ if (layoutPath) {
69943
+ layoutInfo = await getLayoutInfo(layoutPath);
69944
+ }
69945
+ if (!slideBg && layoutInfo?.bg) {
69946
+ slideBg = layoutInfo.bg;
69947
+ }
69948
+ if (!slideBg && masterBg) {
69949
+ slideBg = masterBg;
69950
+ }
69951
+ if (!spTree) {
69952
+ slides.push(renderSlideHtml([], slideBg, contentOffsetX));
69953
+ continue;
69954
+ }
69955
+ const imageMap = /* @__PURE__ */ new Map();
69956
+ const slideRelsDoc = relsXml ? parser.parseFromString(relsXml, "application/xml") : null;
69957
+ if (slideRelsDoc) {
69958
+ const rels = slideRelsDoc.getElementsByTagName("Relationship");
69959
+ for (let ri = 0; ri < rels.length; ri++) {
69960
+ const rel = rels[ri];
68983
69961
  const type2 = rel.getAttribute("Type") ?? "";
68984
69962
  if (!type2.includes("/image"))
68985
69963
  continue;
@@ -68998,6 +69976,12 @@ ${inner}</div>`;
68998
69976
  }
68999
69977
  }
69000
69978
  const elements = [];
69979
+ if (layoutInfo?.showMasterSp !== false) {
69980
+ elements.push(...masterDecorativeElements);
69981
+ }
69982
+ if (layoutInfo?.decorativeElements) {
69983
+ elements.push(...layoutInfo.decorativeElements);
69984
+ }
69001
69985
  for (let i = 0; i < spTree.children.length; i++) {
69002
69986
  const child = spTree.children[i];
69003
69987
  if (child.localName === "sp") {
@@ -69010,11 +69994,16 @@ ${inner}</div>`;
69010
69994
  elements.push({ kind: "image", data: img });
69011
69995
  } else if (child.localName === "graphicFrame") {
69012
69996
  const table = parseTable2(child, scale, themeColors, themeFonts, tableStyleMap);
69013
- if (table)
69997
+ if (table) {
69014
69998
  elements.push({ kind: "table", data: table });
69999
+ } else if (slideRelsDoc) {
70000
+ const chart = await parseChart(child, scale, themeColors, zip, slideRelsDoc, parser);
70001
+ if (chart)
70002
+ elements.push({ kind: "chart", data: chart });
70003
+ }
69015
70004
  }
69016
70005
  }
69017
- slides.push(renderSlideHtml(elements, slideBg));
70006
+ slides.push(renderSlideHtml(elements, slideBg, contentOffsetX));
69018
70007
  }
69019
70008
  if (fontStyleBlock && slides.length > 0) {
69020
70009
  slides[0] = fontStyleBlock + slides[0];