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 +1074 -85
- package/dist/bundle.min.js +96 -91
- package/dist/cli.js +1203 -24044
- package/dist/packages/cli/commands/common.d.ts +2 -0
- package/dist/packages/cli/commands/common.d.ts.map +1 -0
- package/dist/packages/cli/commands/common.js +22 -0
- package/dist/packages/cli/commands/common.js.map +1 -0
- package/dist/packages/cli/commands/export-docs.d.ts +3 -4
- package/dist/packages/cli/commands/export-docs.d.ts.map +1 -1
- package/dist/packages/cli/commands/export-docs.js +245 -303
- package/dist/packages/cli/commands/export-docs.js.map +1 -1
- package/dist/packages/cli/commands/export-slides.d.ts.map +1 -1
- package/dist/packages/cli/commands/export-slides.js +1 -25
- package/dist/packages/cli/commands/export-slides.js.map +1 -1
- package/dist/packages/docs/create-document.d.ts.map +1 -1
- package/dist/packages/docs/create-document.js +39 -22
- package/dist/packages/docs/create-document.js.map +1 -1
- package/dist/packages/docs/export.d.ts.map +1 -1
- package/dist/packages/docs/export.js +25 -89
- package/dist/packages/docs/export.js.map +1 -1
- package/dist/packages/docs/parse-colors.d.ts.map +1 -1
- package/dist/packages/docs/parse-colors.js +85 -10
- package/dist/packages/docs/parse-colors.js.map +1 -1
- package/dist/packages/slides/import-pptx.d.ts.map +1 -1
- package/dist/packages/slides/import-pptx.js +1180 -47
- package/dist/packages/slides/import-pptx.js.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
-
|
|
46793
|
-
|
|
46794
|
-
"Helvetica Neue",
|
|
46791
|
+
"BlinkMacSystemFont"
|
|
46792
|
+
]);
|
|
46793
|
+
const systemFonts = /* @__PURE__ */ new Set([
|
|
46795
46794
|
"Arial",
|
|
46796
46795
|
"Helvetica",
|
|
46797
|
-
"
|
|
46798
|
-
"
|
|
46799
|
-
"
|
|
46800
|
-
"
|
|
46801
|
-
"
|
|
46802
|
-
|
|
46803
|
-
|
|
46804
|
-
|
|
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 (
|
|
46808
|
-
|
|
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
|
|
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
|
-
|
|
52297
|
-
|
|
52298
|
-
|
|
52299
|
-
|
|
52300
|
-
|
|
52301
|
-
|
|
52302
|
-
|
|
52303
|
-
|
|
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
|
-
|
|
52308
|
-
|
|
52309
|
-
|
|
52310
|
-
|
|
52311
|
-
|
|
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
|
-
|
|
52314
|
-
|
|
52315
|
-
|
|
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
|
-
|
|
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
|
-
|
|
52563
|
-
|
|
52564
|
-
|
|
52565
|
-
|
|
52566
|
-
|
|
52567
|
-
|
|
52568
|
-
|
|
52569
|
-
|
|
52570
|
-
|
|
52571
|
-
|
|
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
|
-
|
|
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
|
|
67855
|
-
if (
|
|
67856
|
-
|
|
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
|
|
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
|
|
67867
|
-
if (
|
|
67868
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
68246
|
-
|
|
68247
|
-
|
|
68248
|
-
|
|
68249
|
-
hasCrop =
|
|
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
|
|
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, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
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, """)}"` : "";
|
|
68583
69376
|
const isFullbleed = img.x <= 10 && img.y <= 10 && img.w >= TARGET_WIDTH - 20 && img.h >= TARGET_HEIGHT - 20;
|
|
68584
|
-
|
|
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, """)}"` : "";
|
|
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.
|
|
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
|
|
68776
|
-
|
|
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
|
-
${
|
|
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
|
-
|
|
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
|
|
68982
|
-
const rel = rels[
|
|
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];
|