@json-to-office/core-pptx 7.0.0 → 7.0.1
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/index.js +401 -58
- package/dist/index.js.map +1 -1
- package/dist/ir/compiler.d.ts.map +1 -1
- package/dist/ir/types.d.ts +7 -0
- package/dist/ir/types.d.ts.map +1 -1
- package/dist/quality/facts.d.ts.map +1 -1
- package/dist/renderers/office-open/chartParts.d.ts.map +1 -1
- package/dist/renderers/office-open/index.d.ts.map +1 -1
- package/dist/renderers/pptxgenjs/emit.d.ts +7 -1
- package/dist/renderers/pptxgenjs/emit.d.ts.map +1 -1
- package/dist/renderers/pptxgenjs/fills.d.ts +21 -1
- package/dist/renderers/pptxgenjs/fills.d.ts.map +1 -1
- package/dist/renderers/pptxgenjs/index.d.ts +2 -1
- package/dist/renderers/pptxgenjs/index.d.ts.map +1 -1
- package/dist/renderers/pptxgenjs/packaging.d.ts +3 -0
- package/dist/renderers/pptxgenjs/packaging.d.ts.map +1 -1
- package/dist/renderers/pptxgenjs/radialRaster.d.ts +49 -0
- package/dist/renderers/pptxgenjs/radialRaster.d.ts.map +1 -0
- package/dist/themes/defaults.d.ts +8 -0
- package/dist/themes/defaults.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -121,6 +121,9 @@ var init_units = __esm({
|
|
|
121
121
|
});
|
|
122
122
|
|
|
123
123
|
// src/renderers/pptxgenjs/fills.ts
|
|
124
|
+
function buildImageFillXml() {
|
|
125
|
+
return `<a:blipFill rotWithShape="1"><a:blip r:embed="${IMAGE_FILL_RID}"/><a:stretch><a:fillRect/></a:stretch></a:blipFill>`;
|
|
126
|
+
}
|
|
124
127
|
function colorXml(color2) {
|
|
125
128
|
const alpha = color2.transparency !== void 0 ? `<a:alpha val="${Math.round((100 - color2.transparency) * PCT_UNIT)}"/>` : "";
|
|
126
129
|
return `<a:srgbClr val="${color2.hex.toUpperCase()}">${alpha}</a:srgbClr>`;
|
|
@@ -142,18 +145,27 @@ function radialShadeXml(focus) {
|
|
|
142
145
|
function buildPatternFillXml(preset, foreground, background2) {
|
|
143
146
|
return `<a:pattFill prst="${preset}"><a:fgClr>${opaqueColorXml(foreground)}</a:fgClr><a:bgClr>${opaqueColorXml(background2)}</a:bgClr></a:pattFill>`;
|
|
144
147
|
}
|
|
145
|
-
function registerAdvancedFill(opts, fill2, elementPath, sink) {
|
|
148
|
+
function registerAdvancedFill(opts, fill2, elementPath, sink, raster) {
|
|
146
149
|
const sentinel = fill2.kind === "gradient" ? fill2.gradient.stops[0].color : fill2.foreground;
|
|
147
150
|
if (sink) {
|
|
148
|
-
const xml = fill2.kind === "gradient" ? buildGradientFillXml(fill2.gradient) : buildPatternFillXml(fill2.preset, fill2.foreground, fill2.background);
|
|
149
151
|
const objectName = `__jto_fill_${sink.length}__`;
|
|
150
|
-
|
|
152
|
+
if (fill2.kind === "gradient" && fill2.gradient.type === "radial" && raster) {
|
|
153
|
+
const image = raster.rasterize(
|
|
154
|
+
fill2.gradient,
|
|
155
|
+
raster.widthEmu,
|
|
156
|
+
raster.heightEmu
|
|
157
|
+
);
|
|
158
|
+
sink.push({ objectName, xml: buildImageFillXml(), image });
|
|
159
|
+
} else {
|
|
160
|
+
const xml = fill2.kind === "gradient" ? buildGradientFillXml(fill2.gradient) : buildPatternFillXml(fill2.preset, fill2.foreground, fill2.background);
|
|
161
|
+
sink.push({ objectName, xml });
|
|
162
|
+
}
|
|
151
163
|
opts.objectName = objectName;
|
|
152
164
|
}
|
|
153
165
|
void elementPath;
|
|
154
166
|
opts.fill = { color: sentinel.hex };
|
|
155
167
|
}
|
|
156
|
-
var ANGLE_UNIT, PCT_UNIT, RADIAL_FOCUS_RECTS;
|
|
168
|
+
var ANGLE_UNIT, PCT_UNIT, RADIAL_FOCUS_RECTS, IMAGE_FILL_RID;
|
|
157
169
|
var init_fills = __esm({
|
|
158
170
|
"src/renderers/pptxgenjs/fills.ts"() {
|
|
159
171
|
"use strict";
|
|
@@ -166,6 +178,7 @@ var init_fills = __esm({
|
|
|
166
178
|
bottomLeft: { l: 0, t: 1e5, r: 1e5, b: 0 },
|
|
167
179
|
bottomRight: { l: 1e5, t: 1e5, r: 0, b: 0 }
|
|
168
180
|
};
|
|
181
|
+
IMAGE_FILL_RID = "__jto_fill_rid__";
|
|
169
182
|
}
|
|
170
183
|
});
|
|
171
184
|
|
|
@@ -243,7 +256,13 @@ function chartOpts(element) {
|
|
|
243
256
|
face: "catAxisLabelFontFace",
|
|
244
257
|
bold: "catAxisLabelFontBold",
|
|
245
258
|
size: "catAxisLabelFontSize",
|
|
246
|
-
color: "catAxisLabelColor"
|
|
259
|
+
color: "catAxisLabelColor",
|
|
260
|
+
titleFont: {
|
|
261
|
+
face: "catAxisTitleFontFace",
|
|
262
|
+
size: "catAxisTitleFontSize",
|
|
263
|
+
color: "catAxisTitleColor"
|
|
264
|
+
},
|
|
265
|
+
titleRotate: "catAxisTitleRotate"
|
|
247
266
|
});
|
|
248
267
|
applyValueAxis(opts, o.valueAxis);
|
|
249
268
|
if (o.dataBorder) {
|
|
@@ -264,6 +283,10 @@ function applyAxis(opts, axis, keys) {
|
|
|
264
283
|
if (axis.title !== void 0) {
|
|
265
284
|
opts[keys.title] = axis.title;
|
|
266
285
|
opts[keys.showTitle] = true;
|
|
286
|
+
applyLabelFont(opts, axis.titleFont, keys.titleFont);
|
|
287
|
+
if (axis.titleRotate !== void 0) {
|
|
288
|
+
opts[keys.titleRotate] = axis.titleRotate;
|
|
289
|
+
}
|
|
267
290
|
}
|
|
268
291
|
if (axis.hidden !== void 0) opts[keys.hidden] = axis.hidden;
|
|
269
292
|
if (axis.labelRotate !== void 0) opts[keys.labelRotate] = axis.labelRotate;
|
|
@@ -282,7 +305,13 @@ function applyValueAxis(opts, axis) {
|
|
|
282
305
|
face: "valAxisLabelFontFace",
|
|
283
306
|
bold: "valAxisLabelFontBold",
|
|
284
307
|
size: "valAxisLabelFontSize",
|
|
285
|
-
color: "valAxisLabelColor"
|
|
308
|
+
color: "valAxisLabelColor",
|
|
309
|
+
titleFont: {
|
|
310
|
+
face: "valAxisTitleFontFace",
|
|
311
|
+
size: "valAxisTitleFontSize",
|
|
312
|
+
color: "valAxisTitleColor"
|
|
313
|
+
},
|
|
314
|
+
titleRotate: "valAxisTitleRotate"
|
|
286
315
|
});
|
|
287
316
|
assignDefined(opts, {
|
|
288
317
|
valAxisMinVal: axis.minValue,
|
|
@@ -546,7 +575,7 @@ function shadowOpts(shadow) {
|
|
|
546
575
|
function hyperlinkOpts(link) {
|
|
547
576
|
return link.kind === "external" ? { url: link.url, tooltip: link.tooltip } : { slide: link.slideIndex, tooltip: link.tooltip };
|
|
548
577
|
}
|
|
549
|
-
function applyFill(opts, fill2, elementPath, ctx) {
|
|
578
|
+
function applyFill(opts, fill2, elementPath, ctx, transform) {
|
|
550
579
|
switch (fill2.kind) {
|
|
551
580
|
case "none":
|
|
552
581
|
opts.fill = { type: "none" };
|
|
@@ -561,7 +590,17 @@ function applyFill(opts, fill2, elementPath, ctx) {
|
|
|
561
590
|
}
|
|
562
591
|
case "gradient":
|
|
563
592
|
case "pattern":
|
|
564
|
-
registerAdvancedFill(
|
|
593
|
+
registerAdvancedFill(
|
|
594
|
+
opts,
|
|
595
|
+
fill2,
|
|
596
|
+
elementPath,
|
|
597
|
+
ctx.pendingFills,
|
|
598
|
+
ctx.rasterizeRadial && transform ? {
|
|
599
|
+
rasterize: ctx.rasterizeRadial,
|
|
600
|
+
widthEmu: transform.widthEmu,
|
|
601
|
+
heightEmu: transform.heightEmu
|
|
602
|
+
} : void 0
|
|
603
|
+
);
|
|
565
604
|
return;
|
|
566
605
|
case "image":
|
|
567
606
|
throw new Error(
|
|
@@ -668,7 +707,9 @@ function emitTextBox(slide, element, ctx) {
|
|
|
668
707
|
...bodyDefaultOpts(element.style),
|
|
669
708
|
...textBodyOpts(element.style)
|
|
670
709
|
};
|
|
671
|
-
if (element.fill)
|
|
710
|
+
if (element.fill) {
|
|
711
|
+
applyFill(opts, element.fill, element.path, ctx, element.transform);
|
|
712
|
+
}
|
|
672
713
|
if (element.shadow) opts.shadow = shadowOpts(element.shadow);
|
|
673
714
|
if (element.hyperlink) opts.hyperlink = hyperlinkOpts(element.hyperlink);
|
|
674
715
|
if (element.altText) opts.altText = element.altText;
|
|
@@ -703,7 +744,9 @@ function emitShape(slide, element, ctx) {
|
|
|
703
744
|
return;
|
|
704
745
|
}
|
|
705
746
|
const opts = { ...transformOpts(element.transform) };
|
|
706
|
-
if (element.fill)
|
|
747
|
+
if (element.fill) {
|
|
748
|
+
applyFill(opts, element.fill, element.path, ctx, element.transform);
|
|
749
|
+
}
|
|
707
750
|
if (element.line) opts.line = lineOpts(element.line);
|
|
708
751
|
if (element.shadow) opts.shadow = shadowOpts(element.shadow);
|
|
709
752
|
if (element.cornerRadius !== void 0)
|
|
@@ -1059,7 +1102,7 @@ var init_svgRasterFallback = __esm({
|
|
|
1059
1102
|
});
|
|
1060
1103
|
|
|
1061
1104
|
// src/renderers/pptxgenjs/packaging.ts
|
|
1062
|
-
function applyPendingFills(xml, pendingFills) {
|
|
1105
|
+
function applyPendingFills(xml, pendingFills, spliced = []) {
|
|
1063
1106
|
let out = xml;
|
|
1064
1107
|
for (const [index, fill2] of pendingFills.entries()) {
|
|
1065
1108
|
const marker = `name="${fill2.objectName}"`;
|
|
@@ -1070,15 +1113,52 @@ function applyPendingFills(xml, pendingFills) {
|
|
|
1070
1113
|
const solidEndTag = "</a:solidFill>";
|
|
1071
1114
|
const solidEnd = out.indexOf(solidEndTag, solidStart);
|
|
1072
1115
|
if (solidStart !== -1 && solidEnd !== -1 && spEnd !== -1 && solidStart < spEnd) {
|
|
1073
|
-
|
|
1116
|
+
let fillXml = fill2.xml;
|
|
1117
|
+
if (fill2.image) {
|
|
1118
|
+
const token = `${IMAGE_FILL_RID}${index}`;
|
|
1119
|
+
fillXml = fillXml.replace(IMAGE_FILL_RID, token);
|
|
1120
|
+
spliced.push({ token, image: fill2.image });
|
|
1121
|
+
}
|
|
1122
|
+
out = out.slice(0, solidStart) + fillXml + out.slice(solidEnd + solidEndTag.length);
|
|
1074
1123
|
}
|
|
1075
1124
|
out = out.slice(0, markerIdx) + `name="Fill ${index + 1}"` + out.slice(markerIdx + marker.length);
|
|
1076
1125
|
}
|
|
1077
1126
|
return out;
|
|
1078
1127
|
}
|
|
1128
|
+
async function linkImageFills(zip, slidePath, xml, images, media) {
|
|
1129
|
+
if (images.length === 0) return xml;
|
|
1130
|
+
const relsPath = slidePath.replace(
|
|
1131
|
+
/^ppt\/slides\/(slide\d+\.xml)$/,
|
|
1132
|
+
"ppt/slides/_rels/$1.rels"
|
|
1133
|
+
);
|
|
1134
|
+
let rels = await zip.file(relsPath)?.async("string") ?? '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>';
|
|
1135
|
+
let nextId = Math.max(
|
|
1136
|
+
0,
|
|
1137
|
+
...[...rels.matchAll(/\bId="rId(\d+)"/g)].map((match) => Number(match[1]))
|
|
1138
|
+
) + 1;
|
|
1139
|
+
let out = xml;
|
|
1140
|
+
for (const { token, image } of images) {
|
|
1141
|
+
let part = media.get(image);
|
|
1142
|
+
if (!part) {
|
|
1143
|
+
part = `ppt/media/jto-gradient-${media.size + 1}.png`;
|
|
1144
|
+
media.set(image, part);
|
|
1145
|
+
zip.file(part, image);
|
|
1146
|
+
}
|
|
1147
|
+
const rId = `rId${nextId}`;
|
|
1148
|
+
nextId += 1;
|
|
1149
|
+
rels = rels.replace(
|
|
1150
|
+
"</Relationships>",
|
|
1151
|
+
`<Relationship Id="${rId}" Type="${IMAGE_REL_TYPE}" Target="../media/${part.slice("ppt/media/".length)}"/></Relationships>`
|
|
1152
|
+
);
|
|
1153
|
+
out = out.replace(`r:embed="${token}"`, `r:embed="${rId}"`);
|
|
1154
|
+
}
|
|
1155
|
+
zip.file(relsPath, rels);
|
|
1156
|
+
return out;
|
|
1157
|
+
}
|
|
1079
1158
|
async function packagePptxGenJsBuffer(buffer, options = {}) {
|
|
1080
1159
|
const zip = await readPackage(buffer);
|
|
1081
1160
|
let changed = false;
|
|
1161
|
+
const media = /* @__PURE__ */ new Map();
|
|
1082
1162
|
for (const [path4, entry] of Object.entries(zip.files)) {
|
|
1083
1163
|
if (!SLIDE_PART.test(path4)) continue;
|
|
1084
1164
|
let xml = await entry.async("string");
|
|
@@ -1088,7 +1168,9 @@ async function packagePptxGenJsBuffer(buffer, options = {}) {
|
|
|
1088
1168
|
fileChanged = true;
|
|
1089
1169
|
}
|
|
1090
1170
|
if (options.pendingFills?.length) {
|
|
1091
|
-
const
|
|
1171
|
+
const spliced = [];
|
|
1172
|
+
let withFills = applyPendingFills(xml, options.pendingFills, spliced);
|
|
1173
|
+
withFills = await linkImageFills(zip, path4, withFills, spliced, media);
|
|
1092
1174
|
if (withFills !== xml) {
|
|
1093
1175
|
xml = withFills;
|
|
1094
1176
|
fileChanged = true;
|
|
@@ -1107,15 +1189,190 @@ async function packagePptxGenJsBuffer(buffer, options = {}) {
|
|
|
1107
1189
|
if (!changed) return buffer;
|
|
1108
1190
|
return writePackage(zip);
|
|
1109
1191
|
}
|
|
1110
|
-
var MEDIUM_STYLE_2_ACCENT_1, NO_STYLE_NO_GRID, SLIDE_PART;
|
|
1192
|
+
var MEDIUM_STYLE_2_ACCENT_1, NO_STYLE_NO_GRID, SLIDE_PART, IMAGE_REL_TYPE;
|
|
1111
1193
|
var init_packaging = __esm({
|
|
1112
1194
|
"src/renderers/pptxgenjs/packaging.ts"() {
|
|
1113
1195
|
"use strict";
|
|
1114
1196
|
init_finalizePackage();
|
|
1115
1197
|
init_svgRasterFallback();
|
|
1198
|
+
init_fills();
|
|
1116
1199
|
MEDIUM_STYLE_2_ACCENT_1 = "{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}";
|
|
1117
1200
|
NO_STYLE_NO_GRID = "{2D5ABB26-0587-4C30-8999-92F81FD0307C}";
|
|
1118
1201
|
SLIDE_PART = /^ppt\/slides\/slide\d+\.xml$/;
|
|
1202
|
+
IMAGE_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
|
|
1203
|
+
}
|
|
1204
|
+
});
|
|
1205
|
+
|
|
1206
|
+
// src/renderers/pptxgenjs/radialRaster.ts
|
|
1207
|
+
import pako from "pako";
|
|
1208
|
+
function radialRasterSize(widthEmu, heightEmu) {
|
|
1209
|
+
const w = Math.max(widthEmu, 1);
|
|
1210
|
+
const h = Math.max(heightEmu, 1);
|
|
1211
|
+
const longInches = Math.max(w, h) / EMU_PER_INCH3;
|
|
1212
|
+
const longPx = Math.min(
|
|
1213
|
+
MAX_EDGE_PX2,
|
|
1214
|
+
Math.max(MIN_EDGE_PX2, Math.round(longInches * PX_PER_INCH))
|
|
1215
|
+
);
|
|
1216
|
+
const scale = longPx / Math.max(w, h);
|
|
1217
|
+
return {
|
|
1218
|
+
width: Math.max(1, Math.round(w * scale)),
|
|
1219
|
+
height: Math.max(1, Math.round(h * scale))
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
function parseStops(gradient) {
|
|
1223
|
+
return gradient.stops.map((stop, index) => ({ stop, index })).sort((a, b) => a.stop.position - b.stop.position || a.index - b.index).map(({ stop }) => {
|
|
1224
|
+
const hex = parseInt(stop.color.hex, 16);
|
|
1225
|
+
const alpha = stop.color.transparency !== void 0 ? 255 * (1 - Math.min(100, Math.max(0, stop.color.transparency)) / 100) : 255;
|
|
1226
|
+
return {
|
|
1227
|
+
at: Math.min(100, Math.max(0, stop.position)) / 100,
|
|
1228
|
+
rgba: [hex >> 16 & 255, hex >> 8 & 255, hex & 255, alpha]
|
|
1229
|
+
};
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1232
|
+
function paintRadialGradient(gradient, width, height) {
|
|
1233
|
+
const stops = parseStops(gradient);
|
|
1234
|
+
const channels = stops.every((stop) => stop.rgba[3] === 255) ? 3 : 4;
|
|
1235
|
+
const [fx, fy] = FOCUS_POINTS[gradient.focus] ?? FOCUS_POINTS.center;
|
|
1236
|
+
const cx = fx * width;
|
|
1237
|
+
const cy = fy * height;
|
|
1238
|
+
const radius = Math.sqrt(width * width + height * height) / 2;
|
|
1239
|
+
const pixels = new Uint8Array(width * height * channels);
|
|
1240
|
+
for (let y = 0; y < height; y += 1) {
|
|
1241
|
+
const dy = y + 0.5 - cy;
|
|
1242
|
+
for (let x = 0; x < width; x += 1) {
|
|
1243
|
+
const dx = x + 0.5 - cx;
|
|
1244
|
+
const t = Math.min(1, Math.sqrt(dx * dx + dy * dy) / radius);
|
|
1245
|
+
let next = 0;
|
|
1246
|
+
while (next < stops.length && stops[next].at < t) next += 1;
|
|
1247
|
+
const offset = (y * width + x) * channels;
|
|
1248
|
+
if (next === 0 || next === stops.length) {
|
|
1249
|
+
const only = stops[next === 0 ? 0 : stops.length - 1].rgba;
|
|
1250
|
+
for (let c = 0; c < channels; c += 1) pixels[offset + c] = only[c];
|
|
1251
|
+
continue;
|
|
1252
|
+
}
|
|
1253
|
+
const from = stops[next - 1];
|
|
1254
|
+
const to = stops[next];
|
|
1255
|
+
const u = (t - from.at) / (to.at - from.at);
|
|
1256
|
+
for (let c = 0; c < channels; c += 1) {
|
|
1257
|
+
pixels[offset + c] = Math.round(
|
|
1258
|
+
from.rgba[c] + (to.rgba[c] - from.rgba[c]) * u
|
|
1259
|
+
);
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
return { pixels, channels };
|
|
1264
|
+
}
|
|
1265
|
+
function crc32(bytes) {
|
|
1266
|
+
let c = 4294967295;
|
|
1267
|
+
for (let i = 0; i < bytes.length; i += 1) {
|
|
1268
|
+
c = CRC_TABLE[(c ^ bytes[i]) & 255] ^ c >>> 8;
|
|
1269
|
+
}
|
|
1270
|
+
return (c ^ 4294967295) >>> 0;
|
|
1271
|
+
}
|
|
1272
|
+
function chunk(type, data) {
|
|
1273
|
+
const out = new Uint8Array(12 + data.length);
|
|
1274
|
+
const view = new DataView(out.buffer);
|
|
1275
|
+
view.setUint32(0, data.length);
|
|
1276
|
+
for (let i = 0; i < 4; i += 1) out[4 + i] = type.charCodeAt(i);
|
|
1277
|
+
out.set(data, 8);
|
|
1278
|
+
view.setUint32(8 + data.length, crc32(out.subarray(4, 8 + data.length)));
|
|
1279
|
+
return out;
|
|
1280
|
+
}
|
|
1281
|
+
function paethFiltered(pixels, width, height, channels) {
|
|
1282
|
+
const stride = width * channels;
|
|
1283
|
+
const out = new Uint8Array(height * (stride + 1));
|
|
1284
|
+
for (let y = 0; y < height; y += 1) {
|
|
1285
|
+
const row = y * stride;
|
|
1286
|
+
const up = row - stride;
|
|
1287
|
+
const at = y * (stride + 1);
|
|
1288
|
+
out[at] = 4;
|
|
1289
|
+
for (let i = 0; i < stride; i += 1) {
|
|
1290
|
+
const a = i >= channels ? pixels[row + i - channels] : 0;
|
|
1291
|
+
const b = y > 0 ? pixels[up + i] : 0;
|
|
1292
|
+
const c = y > 0 && i >= channels ? pixels[up + i - channels] : 0;
|
|
1293
|
+
const pa = Math.abs(b - c);
|
|
1294
|
+
const pb = Math.abs(a - c);
|
|
1295
|
+
const pc = Math.abs(a + b - 2 * c);
|
|
1296
|
+
const predictor = pa <= pb && pa <= pc ? a : pb <= pc ? b : c;
|
|
1297
|
+
out[at + 1 + i] = pixels[row + i] - predictor & 255;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
return out;
|
|
1301
|
+
}
|
|
1302
|
+
function encodePng(pixels, width, height, channels) {
|
|
1303
|
+
const header = new Uint8Array(13);
|
|
1304
|
+
const view = new DataView(header.buffer);
|
|
1305
|
+
view.setUint32(0, width);
|
|
1306
|
+
view.setUint32(4, height);
|
|
1307
|
+
header[8] = 8;
|
|
1308
|
+
header[9] = channels === 4 ? 6 : 2;
|
|
1309
|
+
const parts = [
|
|
1310
|
+
new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]),
|
|
1311
|
+
chunk("IHDR", header),
|
|
1312
|
+
chunk(
|
|
1313
|
+
"IDAT",
|
|
1314
|
+
pako.deflate(paethFiltered(pixels, width, height, channels), {
|
|
1315
|
+
level: 6
|
|
1316
|
+
})
|
|
1317
|
+
),
|
|
1318
|
+
chunk("IEND", new Uint8Array(0))
|
|
1319
|
+
];
|
|
1320
|
+
const png = new Uint8Array(parts.reduce((sum, p) => sum + p.length, 0));
|
|
1321
|
+
let offset = 0;
|
|
1322
|
+
for (const part of parts) {
|
|
1323
|
+
png.set(part, offset);
|
|
1324
|
+
offset += part.length;
|
|
1325
|
+
}
|
|
1326
|
+
return png;
|
|
1327
|
+
}
|
|
1328
|
+
function pngDataUri(png) {
|
|
1329
|
+
return `data:image/png;base64,${Buffer.from(png).toString("base64")}`;
|
|
1330
|
+
}
|
|
1331
|
+
var MAX_EDGE_PX2, PX_PER_INCH, MIN_EDGE_PX2, EMU_PER_INCH3, CACHE_LIMIT, FOCUS_POINTS, CRC_TABLE, cache, rasterizeRadialGradient;
|
|
1332
|
+
var init_radialRaster = __esm({
|
|
1333
|
+
"src/renderers/pptxgenjs/radialRaster.ts"() {
|
|
1334
|
+
"use strict";
|
|
1335
|
+
MAX_EDGE_PX2 = 1600;
|
|
1336
|
+
PX_PER_INCH = 160;
|
|
1337
|
+
MIN_EDGE_PX2 = 32;
|
|
1338
|
+
EMU_PER_INCH3 = 914400;
|
|
1339
|
+
CACHE_LIMIT = 32;
|
|
1340
|
+
FOCUS_POINTS = {
|
|
1341
|
+
center: [0.5, 0.5],
|
|
1342
|
+
topLeft: [0, 0],
|
|
1343
|
+
topRight: [1, 0],
|
|
1344
|
+
bottomLeft: [0, 1],
|
|
1345
|
+
bottomRight: [1, 1]
|
|
1346
|
+
};
|
|
1347
|
+
CRC_TABLE = (() => {
|
|
1348
|
+
const table = new Uint32Array(256);
|
|
1349
|
+
for (let n = 0; n < 256; n += 1) {
|
|
1350
|
+
let c = n;
|
|
1351
|
+
for (let k = 0; k < 8; k += 1) {
|
|
1352
|
+
c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
1353
|
+
}
|
|
1354
|
+
table[n] = c >>> 0;
|
|
1355
|
+
}
|
|
1356
|
+
return table;
|
|
1357
|
+
})();
|
|
1358
|
+
cache = /* @__PURE__ */ new Map();
|
|
1359
|
+
rasterizeRadialGradient = (gradient, widthEmu, heightEmu) => {
|
|
1360
|
+
const { width, height } = radialRasterSize(widthEmu, heightEmu);
|
|
1361
|
+
const key = JSON.stringify([gradient.focus, gradient.stops, width, height]);
|
|
1362
|
+
const hit = cache.get(key);
|
|
1363
|
+
if (hit) {
|
|
1364
|
+
cache.delete(key);
|
|
1365
|
+
cache.set(key, hit);
|
|
1366
|
+
return hit;
|
|
1367
|
+
}
|
|
1368
|
+
const { pixels, channels } = paintRadialGradient(gradient, width, height);
|
|
1369
|
+
const png = encodePng(pixels, width, height, channels);
|
|
1370
|
+
cache.set(key, png);
|
|
1371
|
+
if (cache.size > CACHE_LIMIT) {
|
|
1372
|
+
cache.delete(cache.keys().next().value);
|
|
1373
|
+
}
|
|
1374
|
+
return png;
|
|
1375
|
+
};
|
|
1119
1376
|
}
|
|
1120
1377
|
});
|
|
1121
1378
|
|
|
@@ -1126,6 +1383,9 @@ __export(pptxgenjs_exports, {
|
|
|
1126
1383
|
buildPresentation: () => buildPresentation,
|
|
1127
1384
|
createPptxGenJsRenderer: () => createPptxGenJsRenderer
|
|
1128
1385
|
});
|
|
1386
|
+
import { readFile } from "fs/promises";
|
|
1387
|
+
import { imageIntegrityDefect as imageIntegrityDefect2 } from "@json-to-office/shared/images/node";
|
|
1388
|
+
import { assetUnreadableError as assetUnreadableError2 } from "@json-to-office/shared/rendering";
|
|
1129
1389
|
import PptxGenJS from "pptxgenjs";
|
|
1130
1390
|
function createPptxGenJsRenderer() {
|
|
1131
1391
|
return {
|
|
@@ -1133,6 +1393,7 @@ function createPptxGenJsRenderer() {
|
|
|
1133
1393
|
format: "pptx",
|
|
1134
1394
|
capabilities: PPTXGENJS_CAPABILITIES,
|
|
1135
1395
|
async render(ir, options) {
|
|
1396
|
+
await assertFileImagesDecode(ir.resources);
|
|
1136
1397
|
const pendingFills = [];
|
|
1137
1398
|
const pptx = buildPresentation(ir, pendingFills, options?.warnings);
|
|
1138
1399
|
const raw = await pptx.write({
|
|
@@ -1148,7 +1409,21 @@ function createPptxGenJsRenderer() {
|
|
|
1148
1409
|
}
|
|
1149
1410
|
};
|
|
1150
1411
|
}
|
|
1151
|
-
function
|
|
1412
|
+
async function assertFileImagesDecode(resources) {
|
|
1413
|
+
await Promise.all(
|
|
1414
|
+
resources.map(async ({ origin }) => {
|
|
1415
|
+
if (origin.kind !== "file") return;
|
|
1416
|
+
let defect;
|
|
1417
|
+
try {
|
|
1418
|
+
defect = imageIntegrityDefect2(await readFile(origin.path));
|
|
1419
|
+
} catch (error) {
|
|
1420
|
+
throw assetUnreadableError2(origin.path, error);
|
|
1421
|
+
}
|
|
1422
|
+
if (defect) throw assetUnreadableError2(origin.path, new Error(defect));
|
|
1423
|
+
})
|
|
1424
|
+
);
|
|
1425
|
+
}
|
|
1426
|
+
function buildPresentation(ir, pendingFills, warnings, rasterizeRadial = rasterizeRadialGradient) {
|
|
1152
1427
|
const pptx = new PptxGenJS();
|
|
1153
1428
|
if (ir.metadata.title) pptx.title = ir.metadata.title;
|
|
1154
1429
|
if (ir.metadata.author) pptx.author = ir.metadata.author;
|
|
@@ -1168,9 +1443,15 @@ function buildPresentation(ir, pendingFills, warnings) {
|
|
|
1168
1443
|
const resources = new Map(
|
|
1169
1444
|
ir.resources.map((resource) => [resource.id, resource])
|
|
1170
1445
|
);
|
|
1171
|
-
const ctx = {
|
|
1446
|
+
const ctx = {
|
|
1447
|
+
pptx,
|
|
1448
|
+
resources,
|
|
1449
|
+
pendingFills,
|
|
1450
|
+
warnings,
|
|
1451
|
+
rasterizeRadial
|
|
1452
|
+
};
|
|
1172
1453
|
for (const slide of ir.slides) {
|
|
1173
|
-
emitSlide(pptx, slide, ctx);
|
|
1454
|
+
emitSlide(pptx, slide, ir.size, ctx);
|
|
1174
1455
|
}
|
|
1175
1456
|
return pptx;
|
|
1176
1457
|
}
|
|
@@ -1181,12 +1462,36 @@ function backgroundProps(background2, resources) {
|
|
|
1181
1462
|
if (!resource) return void 0;
|
|
1182
1463
|
return imageSourceOpts(resource);
|
|
1183
1464
|
}
|
|
1184
|
-
function
|
|
1465
|
+
function radialBackdrop(element, size) {
|
|
1466
|
+
if (element?.kind !== "shape") return void 0;
|
|
1467
|
+
const { transform, fill: fill2 } = element;
|
|
1468
|
+
if (fill2?.kind !== "gradient" || fill2.gradient.type !== "radial") {
|
|
1469
|
+
return void 0;
|
|
1470
|
+
}
|
|
1471
|
+
const bare = element.geometry === "rect" && !element.line && !element.shadow && !element.hyperlink && !element.altText && !(element.runs && element.runs.length > 0) && !transform.rotationDegrees && !transform.flipHorizontal && !transform.flipVertical;
|
|
1472
|
+
const fullBleed = transform.xEmu === 0 && transform.yEmu === 0 && transform.widthEmu === size.widthEmu && transform.heightEmu === size.heightEmu;
|
|
1473
|
+
return bare && fullBleed ? fill2.gradient : void 0;
|
|
1474
|
+
}
|
|
1475
|
+
function emitSlide(pptx, slideIr, size, ctx) {
|
|
1185
1476
|
const slide = pptx.addSlide();
|
|
1477
|
+
let elements = slideIr.elements;
|
|
1186
1478
|
const background2 = backgroundProps(slideIr.background, ctx.resources);
|
|
1187
|
-
if (background2)
|
|
1479
|
+
if (background2) {
|
|
1480
|
+
slide.background = background2;
|
|
1481
|
+
} else if (ctx.rasterizeRadial) {
|
|
1482
|
+
const gradient = radialBackdrop(elements[0], size);
|
|
1483
|
+
if (gradient) {
|
|
1484
|
+
const png = ctx.rasterizeRadial(
|
|
1485
|
+
gradient,
|
|
1486
|
+
elements[0].transform.widthEmu,
|
|
1487
|
+
elements[0].transform.heightEmu
|
|
1488
|
+
);
|
|
1489
|
+
slide.background = { data: pngDataUri(png) };
|
|
1490
|
+
elements = elements.slice(1);
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1188
1493
|
if (slideIr.hidden) slide.hidden = true;
|
|
1189
|
-
for (const element of
|
|
1494
|
+
for (const element of elements) {
|
|
1190
1495
|
emitElement(slide, element, ctx);
|
|
1191
1496
|
}
|
|
1192
1497
|
if (slideIr.notes) slide.addNotes(slideIr.notes);
|
|
@@ -1198,6 +1503,7 @@ var init_pptxgenjs = __esm({
|
|
|
1198
1503
|
init_units();
|
|
1199
1504
|
init_emit();
|
|
1200
1505
|
init_packaging();
|
|
1506
|
+
init_radialRaster();
|
|
1201
1507
|
PPTXGENJS_RENDERER_ID = "pptxgenjs";
|
|
1202
1508
|
PPTXGENJS_CAPABILITIES = /* @__PURE__ */ new Set([
|
|
1203
1509
|
"rich-text",
|
|
@@ -1300,6 +1606,8 @@ function axisEdits(axis) {
|
|
|
1300
1606
|
const value = axis;
|
|
1301
1607
|
return {
|
|
1302
1608
|
...axis.title !== void 0 ? { title: axis.title } : {},
|
|
1609
|
+
...axis.title !== void 0 && textStyle(axis.titleFont) ? { titleFont: textStyle(axis.titleFont) } : {},
|
|
1610
|
+
...axis.title !== void 0 && axis.titleRotate !== void 0 ? { titleRotation: axis.titleRotate } : {},
|
|
1303
1611
|
...axis.hidden !== void 0 ? { hidden: axis.hidden } : {},
|
|
1304
1612
|
...axis.showLine !== void 0 ? { lineVisible: axis.showLine } : {},
|
|
1305
1613
|
...axis.labelRotate !== void 0 ? { labelRotation: axis.labelRotate } : {},
|
|
@@ -1894,8 +2202,9 @@ __export(office_open_exports, {
|
|
|
1894
2202
|
buildPresentationOptions: () => buildPresentationOptions,
|
|
1895
2203
|
createOfficeOpenPptxRenderer: () => createOfficeOpenPptxRenderer
|
|
1896
2204
|
});
|
|
1897
|
-
import { readFile } from "fs/promises";
|
|
1898
|
-
import {
|
|
2205
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
2206
|
+
import { imageIntegrityDefect as imageIntegrityDefect3 } from "@json-to-office/shared/images/node";
|
|
2207
|
+
import { assetUnreadableError as assetUnreadableError3 } from "@json-to-office/shared/rendering";
|
|
1899
2208
|
async function createOfficeOpenPptxRenderer() {
|
|
1900
2209
|
const backend = await import(
|
|
1901
2210
|
/* @vite-ignore */
|
|
@@ -2004,16 +2313,21 @@ async function resourceBytes(origin) {
|
|
|
2004
2313
|
if (origin.kind === "inline") return origin.bytes;
|
|
2005
2314
|
const location = origin.kind === "file" ? origin.path : origin.url;
|
|
2006
2315
|
try {
|
|
2316
|
+
let bytes;
|
|
2007
2317
|
if (origin.kind === "file") {
|
|
2008
|
-
|
|
2009
|
-
}
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2318
|
+
bytes = new Uint8Array(await readFile2(origin.path));
|
|
2319
|
+
} else {
|
|
2320
|
+
const response = await fetch(origin.url);
|
|
2321
|
+
if (!response.ok) {
|
|
2322
|
+
throw new Error(`HTTP ${response.status} ${response.statusText}`);
|
|
2323
|
+
}
|
|
2324
|
+
bytes = new Uint8Array(await response.arrayBuffer());
|
|
2013
2325
|
}
|
|
2014
|
-
|
|
2326
|
+
const defect = imageIntegrityDefect3(bytes);
|
|
2327
|
+
if (defect) throw new Error(defect);
|
|
2328
|
+
return bytes;
|
|
2015
2329
|
} catch (error) {
|
|
2016
|
-
throw
|
|
2330
|
+
throw assetUnreadableError3(location, error);
|
|
2017
2331
|
}
|
|
2018
2332
|
}
|
|
2019
2333
|
var OFFICE_OPEN_PPTX_RENDERER_ID, OFFICE_OPEN_PPTX, OFFICE_OPEN_CAPABILITIES, SCHEME_SLOTS;
|
|
@@ -2101,7 +2415,9 @@ function resolveFromBaseDir(filePath) {
|
|
|
2101
2415
|
}
|
|
2102
2416
|
|
|
2103
2417
|
// src/ir/compiler.ts
|
|
2418
|
+
import { imageIntegrityDefect } from "@json-to-office/shared/images/node";
|
|
2104
2419
|
import {
|
|
2420
|
+
assetUnreadableError,
|
|
2105
2421
|
FeatureRequirementCollector
|
|
2106
2422
|
} from "@json-to-office/shared/rendering";
|
|
2107
2423
|
import { PATTERN_FILL_PRESETS } from "@json-to-office/shared-pptx";
|
|
@@ -3097,6 +3413,8 @@ function compileImage(component, scope) {
|
|
|
3097
3413
|
function internImageSource(source, path4, ctx) {
|
|
3098
3414
|
const inline = parseDataUri(source);
|
|
3099
3415
|
if (inline) {
|
|
3416
|
+
const defect = imageIntegrityDefect(inline.bytes);
|
|
3417
|
+
if (defect) throw assetUnreadableError(source, new Error(defect));
|
|
3100
3418
|
return ctx.resources.intern({
|
|
3101
3419
|
kind: "inline",
|
|
3102
3420
|
bytes: inline.bytes,
|
|
@@ -3456,6 +3774,16 @@ function compileChartLabelFont(ctx, slot, face, weight, hasBoldToggle, extra = {
|
|
|
3456
3774
|
}
|
|
3457
3775
|
return font;
|
|
3458
3776
|
}
|
|
3777
|
+
var DEFAULT_AXIS_TITLE_POINTS = 12;
|
|
3778
|
+
function axisTitleFont(ctx, labelFont, resolved, authored) {
|
|
3779
|
+
const fontFamily = authored.face ?? labelFont.fontFamily ?? ctx.theme.fonts?.body;
|
|
3780
|
+
return {
|
|
3781
|
+
...fontFamily !== void 0 ? { fontFamily } : {},
|
|
3782
|
+
fontSize: authored.size ?? labelFont.fontSize ?? DEFAULT_AXIS_TITLE_POINTS,
|
|
3783
|
+
bold: false,
|
|
3784
|
+
color: authored.color !== void 0 ? resolved(authored.color) : labelFont.color ?? resolved(void 0)
|
|
3785
|
+
};
|
|
3786
|
+
}
|
|
3459
3787
|
function compileChartOptions(props, ctx) {
|
|
3460
3788
|
const colorSources = props.chartColors ?? definedChartColorTokens(ctx.theme);
|
|
3461
3789
|
const colors = colorSources.map(
|
|
@@ -3463,6 +3791,28 @@ function compileChartOptions(props, ctx) {
|
|
|
3463
3791
|
);
|
|
3464
3792
|
const themeTextColor = irColor(resolveColor("text", ctx.theme, ctx.warnings));
|
|
3465
3793
|
const resolved = (value) => value ? irColor(resolveColor(value, ctx.theme, ctx.warnings)) : themeTextColor;
|
|
3794
|
+
const catLabelFont = compileChartLabelFont(
|
|
3795
|
+
ctx,
|
|
3796
|
+
"catAxisLabelFontFace",
|
|
3797
|
+
props.catAxisLabelFontFace,
|
|
3798
|
+
props.catAxisLabelFontWeight,
|
|
3799
|
+
true,
|
|
3800
|
+
{
|
|
3801
|
+
...props.catAxisLabelFontSize !== void 0 ? { fontSize: props.catAxisLabelFontSize } : {},
|
|
3802
|
+
color: resolved(props.catAxisLabelColor)
|
|
3803
|
+
}
|
|
3804
|
+
);
|
|
3805
|
+
const valLabelFont = compileChartLabelFont(
|
|
3806
|
+
ctx,
|
|
3807
|
+
"valAxisLabelFontFace",
|
|
3808
|
+
props.valAxisLabelFontFace,
|
|
3809
|
+
props.valAxisLabelFontWeight,
|
|
3810
|
+
true,
|
|
3811
|
+
{
|
|
3812
|
+
...props.valAxisLabelFontSize !== void 0 ? { fontSize: props.valAxisLabelFontSize } : {},
|
|
3813
|
+
color: resolved(props.valAxisLabelColor)
|
|
3814
|
+
}
|
|
3815
|
+
);
|
|
3466
3816
|
return {
|
|
3467
3817
|
colors,
|
|
3468
3818
|
...pick(props, {
|
|
@@ -3499,24 +3849,26 @@ function compileChartOptions(props, ctx) {
|
|
|
3499
3849
|
),
|
|
3500
3850
|
categoryAxis: {
|
|
3501
3851
|
...props.catAxisTitle !== void 0 ? { title: props.catAxisTitle } : {},
|
|
3852
|
+
titleFont: axisTitleFont(ctx, catLabelFont, resolved, {
|
|
3853
|
+
face: props.catAxisTitleFontFace,
|
|
3854
|
+
size: props.catAxisTitleFontSize,
|
|
3855
|
+
color: props.catAxisTitleColor
|
|
3856
|
+
}),
|
|
3857
|
+
...props.catAxisTitleRotate !== void 0 ? { titleRotate: props.catAxisTitleRotate } : {},
|
|
3502
3858
|
...props.catAxisHidden !== void 0 ? { hidden: props.catAxisHidden } : {},
|
|
3503
3859
|
...props.catAxisLabelRotate !== void 0 ? { labelRotate: props.catAxisLabelRotate } : {},
|
|
3504
3860
|
...props.catAxisLineShow !== void 0 ? { showLine: props.catAxisLineShow } : {},
|
|
3505
3861
|
...props.catGridLine !== void 0 ? { gridLine: compileGridLine(props.catGridLine, ctx) } : {},
|
|
3506
|
-
labelFont:
|
|
3507
|
-
ctx,
|
|
3508
|
-
"catAxisLabelFontFace",
|
|
3509
|
-
props.catAxisLabelFontFace,
|
|
3510
|
-
props.catAxisLabelFontWeight,
|
|
3511
|
-
true,
|
|
3512
|
-
{
|
|
3513
|
-
...props.catAxisLabelFontSize !== void 0 ? { fontSize: props.catAxisLabelFontSize } : {},
|
|
3514
|
-
color: resolved(props.catAxisLabelColor)
|
|
3515
|
-
}
|
|
3516
|
-
)
|
|
3862
|
+
labelFont: catLabelFont
|
|
3517
3863
|
},
|
|
3518
3864
|
valueAxis: {
|
|
3519
3865
|
...props.valAxisTitle !== void 0 ? { title: props.valAxisTitle } : {},
|
|
3866
|
+
titleFont: axisTitleFont(ctx, valLabelFont, resolved, {
|
|
3867
|
+
face: props.valAxisTitleFontFace,
|
|
3868
|
+
size: props.valAxisTitleFontSize,
|
|
3869
|
+
color: props.valAxisTitleColor
|
|
3870
|
+
}),
|
|
3871
|
+
...props.valAxisTitleRotate !== void 0 ? { titleRotate: props.valAxisTitleRotate } : {},
|
|
3520
3872
|
...props.valAxisHidden !== void 0 ? { hidden: props.valAxisHidden } : {},
|
|
3521
3873
|
...props.valAxisMinVal !== void 0 ? { minValue: props.valAxisMinVal } : {},
|
|
3522
3874
|
...props.valAxisMaxVal !== void 0 ? { maxValue: props.valAxisMaxVal } : {},
|
|
@@ -3524,17 +3876,7 @@ function compileChartOptions(props, ctx) {
|
|
|
3524
3876
|
...props.valAxisLabelFormatCode !== void 0 ? { labelFormatCode: props.valAxisLabelFormatCode } : {},
|
|
3525
3877
|
...props.valAxisLineShow !== void 0 ? { showLine: props.valAxisLineShow } : {},
|
|
3526
3878
|
...props.valGridLine !== void 0 ? { gridLine: compileGridLine(props.valGridLine, ctx) } : {},
|
|
3527
|
-
labelFont:
|
|
3528
|
-
ctx,
|
|
3529
|
-
"valAxisLabelFontFace",
|
|
3530
|
-
props.valAxisLabelFontFace,
|
|
3531
|
-
props.valAxisLabelFontWeight,
|
|
3532
|
-
true,
|
|
3533
|
-
{
|
|
3534
|
-
...props.valAxisLabelFontSize !== void 0 ? { fontSize: props.valAxisLabelFontSize } : {},
|
|
3535
|
-
color: resolved(props.valAxisLabelColor)
|
|
3536
|
-
}
|
|
3537
|
-
)
|
|
3879
|
+
labelFont: valLabelFont
|
|
3538
3880
|
},
|
|
3539
3881
|
...props.dataBorder !== void 0 ? {
|
|
3540
3882
|
dataBorder: {
|
|
@@ -3949,7 +4291,7 @@ function isNodeEnvironment() {
|
|
|
3949
4291
|
}
|
|
3950
4292
|
|
|
3951
4293
|
// src/core/expandHighcharts.ts
|
|
3952
|
-
var
|
|
4294
|
+
var PX_PER_INCH2 = 96;
|
|
3953
4295
|
var DEFAULT_CHART_WIDTH_PX = 960;
|
|
3954
4296
|
var DEFAULT_EXPORT_SERVER_URL = "http://localhost:7801";
|
|
3955
4297
|
async function expandHighchartsComponents(presentation, services, warnings, chartFonts) {
|
|
@@ -4021,8 +4363,8 @@ async function expandOne(component, path4, scope) {
|
|
|
4021
4363
|
base64: chart.dataUri,
|
|
4022
4364
|
x: props.x ?? 0,
|
|
4023
4365
|
y: props.y ?? 0,
|
|
4024
|
-
w: props.w ?? chart.widthPx /
|
|
4025
|
-
h: props.h ?? chart.heightPx /
|
|
4366
|
+
w: props.w ?? chart.widthPx / PX_PER_INCH2,
|
|
4367
|
+
h: props.h ?? chart.heightPx / PX_PER_INCH2
|
|
4026
4368
|
}
|
|
4027
4369
|
};
|
|
4028
4370
|
}
|
|
@@ -4039,7 +4381,7 @@ function assertExportServerAllowed(serverUrl, services, warnings) {
|
|
|
4039
4381
|
message: notice
|
|
4040
4382
|
});
|
|
4041
4383
|
}
|
|
4042
|
-
async function renderChart(config, services, warnings,
|
|
4384
|
+
async function renderChart(config, services, warnings, cache2) {
|
|
4043
4385
|
if (!isNodeEnvironment()) {
|
|
4044
4386
|
throw new Error(
|
|
4045
4387
|
"Highcharts export server requires a Node.js environment. Chart generation is not available in browser environments."
|
|
@@ -4057,7 +4399,7 @@ async function renderChart(config, services, warnings, cache) {
|
|
|
4057
4399
|
...config.resources ? { resources: config.resources } : {}
|
|
4058
4400
|
};
|
|
4059
4401
|
return sendChartRequest({
|
|
4060
|
-
cache,
|
|
4402
|
+
cache: cache2,
|
|
4061
4403
|
serverUrl,
|
|
4062
4404
|
concurrency: services?.concurrency,
|
|
4063
4405
|
requestBody,
|
|
@@ -4104,7 +4446,7 @@ function placedWidthPt(props, slideWidth) {
|
|
|
4104
4446
|
return parseFloat(w) / 100 * slideWidth * 72;
|
|
4105
4447
|
}
|
|
4106
4448
|
if (w === void 0 && props.grid === void 0) {
|
|
4107
|
-
return (props.options.chart?.width ?? DEFAULT_CHART_WIDTH_PX) /
|
|
4449
|
+
return (props.options.chart?.width ?? DEFAULT_CHART_WIDTH_PX) / PX_PER_INCH2 * 72;
|
|
4108
4450
|
}
|
|
4109
4451
|
return void 0;
|
|
4110
4452
|
}
|
|
@@ -6038,6 +6380,7 @@ function fillColorHexes(fill2, theme) {
|
|
|
6038
6380
|
return [...new Set(found)];
|
|
6039
6381
|
}
|
|
6040
6382
|
var FOCUS_CORNERS = {
|
|
6383
|
+
center: [0.5, 0.5],
|
|
6041
6384
|
topLeft: [0, 0],
|
|
6042
6385
|
topRight: [1, 0],
|
|
6043
6386
|
bottomLeft: [0, 1],
|
|
@@ -6053,7 +6396,7 @@ function lerpHex(a, b, t) {
|
|
|
6053
6396
|
}
|
|
6054
6397
|
function gradientPosition(gradient, fx, fy, widthUnits, heightUnits) {
|
|
6055
6398
|
if (gradient.type === "radial") {
|
|
6056
|
-
const focus = FOCUS_CORNERS[typeof gradient.focus === "string" ? gradient.focus : "
|
|
6399
|
+
const focus = FOCUS_CORNERS[typeof gradient.focus === "string" ? gradient.focus : "center"] ?? FOCUS_CORNERS.center;
|
|
6057
6400
|
const radius = Math.hypot(widthUnits, heightUnits) / 2;
|
|
6058
6401
|
if (radius === 0) return 0;
|
|
6059
6402
|
const distance = Math.hypot(
|