@json-to-office/core-pptx 0.35.0 → 0.36.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.
@@ -1 +1 @@
1
- {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/core/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAEH,OAAO,SAAS,MAAM,WAAW,CAAC;AAElC,OAAO,KAAK,EACV,+BAA+B,EAC/B,eAAe,EACf,eAAe,EACf,cAAc,EACf,MAAM,UAAU,CAAC;AAElB,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAK9E,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,2BAA2B;IAC1C,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,4BAA4B;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC/C;;;;OAIG;IACH,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,UAAU,CAAC,EAAE,2BAA2B,CAAC;IACzC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED,6EAA6E;AAC7E,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,SAAgB,MAAM,EAAE,eAAe,EAAE,CAAC;gBAE9B,MAAM,EAAE,eAAe,EAAE;CAStC;AAqBD;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAYhE;AAED;;GAEG;AACH,wBAAgB,iCAAiC,CAC/C,UAAU,EAAE,OAAO,GAClB,UAAU,IAAI,+BAA+B,CAI/C;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,+BAA+B,EACzC,OAAO,CAAC,EAAE,iBAAiB,EAC3B,QAAQ,CAAC,EAAE,eAAe,EAAE,EAC5B,YAAY,CAAC,EAAE,cAAc,EAAE,GAC9B,OAAO,CAAC,SAAS,CAAC,CAgBpB;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,gBAAgB,CAAC,CAwD3B;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,SAAS,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,4BAA4B,GACrC,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;CAQjC,CAAC"}
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/core/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAEH,OAAO,SAAS,MAAM,WAAW,CAAC;AAElC,OAAO,KAAK,EACV,+BAA+B,EAC/B,eAAe,EACf,eAAe,EACf,cAAc,EACf,MAAM,UAAU,CAAC;AAElB,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAK9E,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,2BAA2B;IAC1C,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,4BAA4B;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC/C;;;;OAIG;IACH,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,UAAU,CAAC,EAAE,2BAA2B,CAAC;IACzC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED,6EAA6E;AAC7E,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,SAAgB,MAAM,EAAE,eAAe,EAAE,CAAC;gBAE9B,MAAM,EAAE,eAAe,EAAE;CAStC;AAqBD;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAYhE;AAED;;GAEG;AACH,wBAAgB,iCAAiC,CAC/C,UAAU,EAAE,OAAO,GAClB,UAAU,IAAI,+BAA+B,CAI/C;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,+BAA+B,EACzC,OAAO,CAAC,EAAE,iBAAiB,EAC3B,QAAQ,CAAC,EAAE,eAAe,EAAE,EAC5B,YAAY,CAAC,EAAE,cAAc,EAAE,GAC9B,OAAO,CAAC,SAAS,CAAC,CAgBpB;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,gBAAgB,CAAC,CAyD3B;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,GAAG,+BAA+B,EACpD,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,SAAS,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,4BAA4B,GACrC,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;CAQjC,CAAC"}
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import type { PendingXmlFill } from '../types';
2
+ import type { PendingXmlFill, PipelineWarning } from '../types';
3
3
  /** Stable default shared by package entries and OOXML core metadata. */
4
4
  export declare const DEFAULT_GENERATED_AT = "2000-01-01T00:00:00.000Z";
5
5
  export interface PresentationPackagingOptions {
@@ -13,6 +13,11 @@ export interface PresentationPackagingOptions {
13
13
  * the registered fill XML.
14
14
  */
15
15
  pendingFills?: PendingXmlFill[];
16
+ /**
17
+ * Warning sink for post-generation repairs. Only the SVG raster fallback
18
+ * pass reports here; when omitted its failures go to `console.warn`.
19
+ */
20
+ warnings?: PipelineWarning[];
16
21
  }
17
22
  /**
18
23
  * Apply post-generation OOXML fixes and deterministic package metadata.
@@ -1 +1 @@
1
- {"version":3,"file":"packagePresentation.d.ts","sourceRoot":"","sources":["../../src/core/packagePresentation.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAK/C,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,6BAA6B,CAAC;AAE/D,MAAM,WAAW,4BAA4B;IAC3C,+DAA+D;IAC/D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAC5B;;;;OAIG;IACH,YAAY,CAAC,EAAE,cAAc,EAAE,CAAC;CACjC;AAqLD;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,4BAAiC,GACzC,OAAO,CAAC,MAAM,CAAC,CAmCjB"}
1
+ {"version":3,"file":"packagePresentation.d.ts","sourceRoot":"","sources":["../../src/core/packagePresentation.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAMhE,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,6BAA6B,CAAC;AAE/D,MAAM,WAAW,4BAA4B;IAC3C,+DAA+D;IAC/D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAC5B;;;;OAIG;IACH,YAAY,CAAC,EAAE,cAAc,EAAE,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;CAC9B;AAqLD;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,4BAAiC,GACzC,OAAO,CAAC,MAAM,CAAC,CAqCjB"}
@@ -0,0 +1,12 @@
1
+ import type JSZip from 'jszip';
2
+ import type { PipelineWarning } from '../types';
3
+ /**
4
+ * Replace the broken-image placeholders PptxGenJS writes for inline SVG
5
+ * pictures with real rasterizations of those SVGs. Never throws: a missing
6
+ * native binding or an SVG resvg rejects degrades to a warning and leaves the
7
+ * package as generated.
8
+ *
9
+ * @returns whether any part of the zip was rewritten.
10
+ */
11
+ export declare function repairSvgRasterFallbacks(zip: JSZip, warnings?: PipelineWarning[]): Promise<boolean>;
12
+ //# sourceMappingURL=svgRasterFallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svgRasterFallback.d.ts","sourceRoot":"","sources":["../../src/core/svgRasterFallback.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAyIhD;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,KAAK,EACV,QAAQ,CAAC,EAAE,eAAe,EAAE,GAC3B,OAAO,CAAC,OAAO,CAAC,CAkElB"}
package/dist/index.js CHANGED
@@ -21,6 +21,7 @@ var W = {
21
21
  IMAGE_NO_SOURCE: "IMAGE_NO_SOURCE",
22
22
  IMAGE_PROBE_FAILED: "IMAGE_PROBE_FAILED",
23
23
  IMAGE_PATH_OUTSIDE_ROOTS: "IMAGE_PATH_OUTSIDE_ROOTS",
24
+ IMAGE_SVG_RASTER_FAILED: "IMAGE_SVG_RASTER_FAILED",
24
25
  MISSING_TEMPLATE: "MISSING_TEMPLATE",
25
26
  UNKNOWN_PLACEHOLDER: "UNKNOWN_PLACEHOLDER",
26
27
  PLACEHOLDER_NO_POSITION: "PLACEHOLDER_NO_POSITION",
@@ -2074,6 +2075,142 @@ import {
2074
2075
 
2075
2076
  // src/core/packagePresentation.ts
2076
2077
  import JSZip from "jszip";
2078
+
2079
+ // src/core/svgRasterFallback.ts
2080
+ import path3 from "path";
2081
+ var EMU_PER_INCH = 914400;
2082
+ var RASTER_SCALE = 3;
2083
+ var MAX_EDGE_PX = 4096;
2084
+ var MIN_EDGE_PX = 16;
2085
+ var DEFAULT_EDGE_PX = 1024;
2086
+ var PART_PATTERNS = [
2087
+ /^ppt\/slides\/slide\d+\.xml$/,
2088
+ /^ppt\/slideLayouts\/[^/]+\.xml$/,
2089
+ /^ppt\/slideMasters\/[^/]+\.xml$/
2090
+ ];
2091
+ var SVG_BLIP = /<asvg:svgBlip\b[^>]*r:embed="([^"]+)"/g;
2092
+ var BLIP = /<a:blip\b[^>]*r:embed="([^"]+)"/g;
2093
+ var EXTENT = /<a:ext\s+cx="(\d+)"\s+cy="(\d+)"/;
2094
+ var RELATIONSHIP = /<Relationship\b([^>]*)>/g;
2095
+ var resvgModule;
2096
+ function loadResvg() {
2097
+ resvgModule ??= import("@resvg/resvg-js");
2098
+ return resvgModule;
2099
+ }
2100
+ async function readRelationships(zip, partPath) {
2101
+ const dir = path3.posix.dirname(partPath);
2102
+ const relsPath = `${dir}/_rels/${path3.posix.basename(partPath)}.rels`;
2103
+ const targets = /* @__PURE__ */ new Map();
2104
+ const entry = zip.file(relsPath);
2105
+ if (!entry) return targets;
2106
+ const xml = await entry.async("string");
2107
+ for (const match of xml.matchAll(RELATIONSHIP)) {
2108
+ const attrs = match[1];
2109
+ if (/\bTargetMode="External"/.test(attrs)) continue;
2110
+ const id = /\bId="([^"]+)"/.exec(attrs)?.[1];
2111
+ const target = /\bTarget="([^"]+)"/.exec(attrs)?.[1];
2112
+ if (!id || !target) continue;
2113
+ targets.set(
2114
+ id,
2115
+ target.startsWith("/") ? target.slice(1) : path3.posix.normalize(path3.posix.join(dir, target))
2116
+ );
2117
+ }
2118
+ return targets;
2119
+ }
2120
+ function collectWorkItems(xml, rels, items) {
2121
+ const blips = [...xml.matchAll(BLIP)];
2122
+ for (const svgBlip of xml.matchAll(SVG_BLIP)) {
2123
+ const at = svgBlip.index ?? 0;
2124
+ const preview = blips.filter((blip) => (blip.index ?? 0) < at).pop();
2125
+ if (!preview) continue;
2126
+ const pngPart = rels.get(preview[1]);
2127
+ const svgPart = rels.get(svgBlip[1]);
2128
+ if (!pngPart || !svgPart) continue;
2129
+ const picEnd = xml.indexOf("</p:pic>", at);
2130
+ const extent = EXTENT.exec(picEnd === -1 ? "" : xml.slice(at, picEnd));
2131
+ const cx = extent ? Number(extent[1]) : void 0;
2132
+ const cy = extent ? Number(extent[2]) : void 0;
2133
+ const existing = items.get(pngPart);
2134
+ items.set(pngPart, {
2135
+ svgPart,
2136
+ cx: Math.max(cx ?? 0, existing?.cx ?? 0) || void 0,
2137
+ cy: Math.max(cy ?? 0, existing?.cy ?? 0) || void 0
2138
+ });
2139
+ }
2140
+ }
2141
+ function toPixels(emu) {
2142
+ const px = Math.round(emu / EMU_PER_INCH * 96 * RASTER_SCALE);
2143
+ return Math.min(MAX_EDGE_PX, Math.max(MIN_EDGE_PX, px));
2144
+ }
2145
+ function resolveFitTo(intrinsicAspect, cx, cy) {
2146
+ if (!cx || !cy) return { mode: "width", value: DEFAULT_EDGE_PX };
2147
+ const wide = intrinsicAspect > cx / cy;
2148
+ const mode = wide ? "height" : "width";
2149
+ let value = wide ? toPixels(cy) : toPixels(cx);
2150
+ const other = wide ? Math.round(value * intrinsicAspect) : Math.round(value / intrinsicAspect);
2151
+ const longest = Math.max(value, other);
2152
+ if (longest > MAX_EDGE_PX) {
2153
+ value = Math.max(MIN_EDGE_PX, Math.floor(value * MAX_EDGE_PX / longest));
2154
+ }
2155
+ return { mode, value };
2156
+ }
2157
+ async function repairSvgRasterFallbacks(zip, warnings) {
2158
+ const pending = /* @__PURE__ */ new Map();
2159
+ for (const [partPath, entry] of Object.entries(zip.files)) {
2160
+ if (entry.dir || !PART_PATTERNS.some((rule) => rule.test(partPath))) {
2161
+ continue;
2162
+ }
2163
+ const xml = await entry.async("string");
2164
+ if (!xml.includes("asvg:svgBlip")) continue;
2165
+ collectWorkItems(xml, await readRelationships(zip, partPath), pending);
2166
+ }
2167
+ if (pending.size === 0) return false;
2168
+ let Resvg;
2169
+ try {
2170
+ ({ Resvg } = await loadResvg());
2171
+ } catch (error) {
2172
+ warn(
2173
+ warnings,
2174
+ W.IMAGE_SVG_RASTER_FAILED,
2175
+ `Could not load the SVG rasterizer, so inline SVG images keep PowerPoint's broken-image fallback: ${String(error)}`,
2176
+ { component: "image" }
2177
+ );
2178
+ return false;
2179
+ }
2180
+ const rendered = /* @__PURE__ */ new Map();
2181
+ let changed = false;
2182
+ for (const [pngPart, item] of pending) {
2183
+ try {
2184
+ if (!zip.file(pngPart)) {
2185
+ throw new Error(`missing preview part ${pngPart}`);
2186
+ }
2187
+ const source = zip.file(item.svgPart);
2188
+ if (!source) throw new Error(`missing part ${item.svgPart}`);
2189
+ const svg = await source.async("string");
2190
+ const probe2 = new Resvg(svg);
2191
+ const fitTo = resolveFitTo(probe2.width / probe2.height, item.cx, item.cy);
2192
+ const key = `${fitTo.mode}:${fitTo.value}
2193
+ ${svg}`;
2194
+ let png = rendered.get(key);
2195
+ if (!png) {
2196
+ png = Buffer.from(new Resvg(svg, { fitTo }).render().asPng());
2197
+ rendered.set(key, png);
2198
+ }
2199
+ zip.file(pngPart, png);
2200
+ changed = true;
2201
+ } catch (error) {
2202
+ warn(
2203
+ warnings,
2204
+ W.IMAGE_SVG_RASTER_FAILED,
2205
+ `Could not rasterize ${item.svgPart}, so it keeps PowerPoint's broken-image fallback: ${String(error)}`,
2206
+ { component: "image" }
2207
+ );
2208
+ }
2209
+ }
2210
+ return changed;
2211
+ }
2212
+
2213
+ // src/core/packagePresentation.ts
2077
2214
  var MEDIUM_STYLE_2_ACCENT_1 = "{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}";
2078
2215
  var NO_STYLE_NO_GRID = "{2D5ABB26-0587-4C30-8999-92F81FD0307C}";
2079
2216
  var DEFAULT_GENERATED_AT = "2000-01-01T00:00:00.000Z";
@@ -2127,24 +2264,24 @@ function remapChartReferences(value, chartIds) {
2127
2264
  );
2128
2265
  }
2129
2266
  async function canonicalizeChartIds(zip) {
2130
- const sourceIds = Object.keys(zip.files).map((path3) => path3.match(/^ppt\/charts\/chart(\d+)\.xml$/)?.[1]).filter((value) => value !== void 0).map(Number).sort((a, b) => a - b);
2267
+ const sourceIds = Object.keys(zip.files).map((path4) => path4.match(/^ppt\/charts\/chart(\d+)\.xml$/)?.[1]).filter((value) => value !== void 0).map(Number).sort((a, b) => a - b);
2131
2268
  const chartIds = new Map(sourceIds.map((id, index) => [id, index + 1]));
2132
2269
  if (chartIds.size === 0) return;
2133
- for (const [path3, entry] of Object.entries(zip.files)) {
2134
- if (entry.dir || !path3.endsWith(".xml") && !path3.endsWith(".rels")) {
2270
+ for (const [path4, entry] of Object.entries(zip.files)) {
2271
+ if (entry.dir || !path4.endsWith(".xml") && !path4.endsWith(".rels")) {
2135
2272
  continue;
2136
2273
  }
2137
2274
  const xml = await entry.async("string");
2138
2275
  const remapped = remapChartReferences(xml, chartIds);
2139
- if (remapped !== xml) zip.file(path3, remapped);
2276
+ if (remapped !== xml) zip.file(path4, remapped);
2140
2277
  }
2141
2278
  const renames = [];
2142
- for (const [path3, entry] of Object.entries(zip.files)) {
2279
+ for (const [path4, entry] of Object.entries(zip.files)) {
2143
2280
  if (entry.dir) continue;
2144
- const remappedPath = remapChartReferences(path3, chartIds);
2145
- if (remappedPath === path3) continue;
2281
+ const remappedPath = remapChartReferences(path4, chartIds);
2282
+ if (remappedPath === path4) continue;
2146
2283
  renames.push({
2147
- from: path3,
2284
+ from: path4,
2148
2285
  to: remappedPath,
2149
2286
  data: await entry.async("nodebuffer"),
2150
2287
  date: entry.date
@@ -2174,12 +2311,12 @@ async function canonicalizePackage(zip, generatedAt, depth = 0) {
2174
2311
  zip.file("docProps/core.xml", coreXml);
2175
2312
  }
2176
2313
  if (depth < 3) {
2177
- for (const [path3, entry] of Object.entries(zip.files)) {
2178
- if (entry.dir || !EMBEDDED_OFFICE_PACKAGE.test(path3)) continue;
2314
+ for (const [path4, entry] of Object.entries(zip.files)) {
2315
+ if (entry.dir || !EMBEDDED_OFFICE_PACKAGE.test(path4)) continue;
2179
2316
  try {
2180
2317
  const nested = await JSZip.loadAsync(await entry.async("nodebuffer"));
2181
2318
  await canonicalizePackage(nested, generatedAt, depth + 1);
2182
- zip.file(path3, await generateZip(nested));
2319
+ zip.file(path4, await generateZip(nested));
2183
2320
  } catch {
2184
2321
  }
2185
2322
  }
@@ -2191,8 +2328,8 @@ async function canonicalizePackage(zip, generatedAt, depth = 0) {
2191
2328
  async function packagePresentationBuffer(buffer, options = {}) {
2192
2329
  const zip = await JSZip.loadAsync(buffer);
2193
2330
  let changed = false;
2194
- for (const [path3, entry] of Object.entries(zip.files)) {
2195
- if (!path3.match(/^ppt\/slides\/slide\d+\.xml$/)) continue;
2331
+ for (const [path4, entry] of Object.entries(zip.files)) {
2332
+ if (!path4.match(/^ppt\/slides\/slide\d+\.xml$/)) continue;
2196
2333
  let xml = await entry.async("string");
2197
2334
  let fileChanged = false;
2198
2335
  if (xml.includes(MEDIUM_STYLE_2_ACCENT_1)) {
@@ -2207,10 +2344,11 @@ async function packagePresentationBuffer(buffer, options = {}) {
2207
2344
  }
2208
2345
  }
2209
2346
  if (fileChanged) {
2210
- zip.file(path3, xml);
2347
+ zip.file(path4, xml);
2211
2348
  changed = true;
2212
2349
  }
2213
2350
  }
2351
+ changed = await repairSvgRasterFallbacks(zip, options.warnings) || changed;
2214
2352
  if (options.deterministic !== false) {
2215
2353
  const generatedAt = resolveGeneratedAt(options.generatedAt);
2216
2354
  await canonicalizeChartIds(zip);
@@ -2314,7 +2452,8 @@ async function generateBufferWithWarnings(jsonConfig, options) {
2314
2452
  const data = await pptx.write({ outputType: "nodebuffer" });
2315
2453
  const buffer = await packagePresentationBuffer(data, {
2316
2454
  ...options,
2317
- pendingFills
2455
+ pendingFills,
2456
+ warnings
2318
2457
  });
2319
2458
  return { buffer, warnings };
2320
2459
  }
@@ -2702,7 +2841,8 @@ function createBuilderImpl(state) {
2702
2841
  const buffer = await packagePresentationBuffer(data, {
2703
2842
  deterministic: options?.deterministic ?? state.packaging.deterministic,
2704
2843
  generatedAt: options?.generatedAt ?? state.packaging.generatedAt,
2705
- pendingFills
2844
+ pendingFills,
2845
+ warnings
2706
2846
  });
2707
2847
  return { buffer, warnings };
2708
2848
  } catch (error) {