@shbernal/pptxgenjs 5.1.0 → 5.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{browser-tG59vAUr.js → browser-CzGC6NnM.js} +5 -5
- package/dist/browser-CzGC6NnM.js.map +1 -0
- package/dist/browser.d.ts +3 -3
- package/dist/browser.js +4 -4
- package/dist/{core-enums-BCaI1VAf.js → core-interfaces-BFXQk67T.js} +134 -9
- package/dist/core-interfaces-BFXQk67T.js.map +1 -0
- package/dist/core.d.ts +2 -2
- package/dist/core.js +3 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +4 -4
- package/dist/inspect.js +1 -1
- package/dist/node.d.ts +3 -3
- package/dist/node.js +5 -5
- package/dist/node.js.map +1 -1
- package/dist/{pptxgen-3gNqxx8n.js → pptxgen-B-mAxCRC.js} +1093 -337
- package/dist/pptxgen-B-mAxCRC.js.map +1 -0
- package/dist/{pptxgen-CKBnfeDh.d.ts → pptxgen-Clv3zz3l.d.ts} +32 -2
- package/dist/pptxgen-Clv3zz3l.d.ts.map +1 -0
- package/dist/standalone.d.ts +630 -31
- package/dist/standalone.d.ts.map +1 -1
- package/dist/standalone.js +1268 -343
- package/dist/standalone.js.map +1 -1
- package/dist/units-BMrBTU0-.js +106 -0
- package/dist/units-BMrBTU0-.js.map +1 -0
- package/dist/{units-Bv8xqGyH.d.ts → units-BPRPrYRg.d.ts} +601 -32
- package/dist/units-BPRPrYRg.d.ts.map +1 -0
- package/package.json +1 -1
- package/dist/browser-tG59vAUr.js.map +0 -1
- package/dist/core-enums-BCaI1VAf.js.map +0 -1
- package/dist/pptxgen-3gNqxx8n.js.map +0 -1
- package/dist/pptxgen-CKBnfeDh.d.ts.map +0 -1
- package/dist/units-Bv8xqGyH.d.ts.map +0 -1
- package/dist/units-DmzbVUNp.js +0 -62
- package/dist/units-DmzbVUNp.js.map +0 -1
package/dist/standalone.js
CHANGED
|
@@ -3137,6 +3137,10 @@ while (n === a[++i] && n === a[++i] && n === a[++i] && n === a[++i] && n === a[+
|
|
|
3137
3137
|
const EMU_PER_INCH = 914400;
|
|
3138
3138
|
const EMU_PER_POINT = 12700;
|
|
3139
3139
|
const POINTS_PER_INCH = 72;
|
|
3140
|
+
/** A bare number larger than this (in inches) is almost certainly a mistake — likely a raw EMU
|
|
3141
|
+
* value passed where inches are expected. We interpret it as inches (the documented contract) but
|
|
3142
|
+
* warn, pointing at the explicit `"<n>emu"` form. ~1000in is far beyond any real slide. */
|
|
3143
|
+
const IMPLAUSIBLE_INCHES = 1e3;
|
|
3140
3144
|
function inchesToEmu(inches) {
|
|
3141
3145
|
assertFiniteNumber(inches, "inches");
|
|
3142
3146
|
return Math.round(inches * EMU_PER_INCH);
|
|
@@ -3150,6 +3154,46 @@ function pixelsToEmu(pixels, dpi) {
|
|
|
3150
3154
|
assertPositiveFiniteNumber(dpi, "dpi");
|
|
3151
3155
|
return inchesToEmu(pixels / dpi);
|
|
3152
3156
|
}
|
|
3157
|
+
/**
|
|
3158
|
+
* Resolve a percentage of an axis length to EMU.
|
|
3159
|
+
* @param percent - percentage value (e.g. `50` for 50%)
|
|
3160
|
+
* @param axisEmu - the axis length in EMU (slide width for x/w, height for y/h)
|
|
3161
|
+
*/
|
|
3162
|
+
function percentToEmu(percent, axisEmu) {
|
|
3163
|
+
assertFiniteNumber(percent, "percent");
|
|
3164
|
+
assertFiniteNumber(axisEmu, "axisEmu");
|
|
3165
|
+
return Math.round(percent / 100 * axisEmu);
|
|
3166
|
+
}
|
|
3167
|
+
/**
|
|
3168
|
+
* The single user-coordinate → EMU boundary. Convert each user-supplied coordinate exactly once.
|
|
3169
|
+
*
|
|
3170
|
+
* Accepts (see {@link Coord}):
|
|
3171
|
+
* - a bare `number` → **always inches** (the documented unit); no magnitude guessing
|
|
3172
|
+
* - `"<n>%"` → percentage of `axisEmu`
|
|
3173
|
+
* - `"<n>in"` / `"<n>pt"` / `"<n>emu"` → explicit units (the escape hatch for non-inch values)
|
|
3174
|
+
*
|
|
3175
|
+
* Throws on non-finite or unparseable input rather than silently emitting a degenerate 0-size.
|
|
3176
|
+
* @param value - user coordinate
|
|
3177
|
+
* @param axisEmu - axis length in EMU, used only to resolve percentages
|
|
3178
|
+
*/
|
|
3179
|
+
function coordToEmu(value, axisEmu) {
|
|
3180
|
+
if (typeof value === "number") {
|
|
3181
|
+
assertFiniteNumber(value, "coordinate");
|
|
3182
|
+
if (Math.abs(value) > IMPLAUSIBLE_INCHES) console.warn(`PptxGenJS: coordinate ${value} interpreted as ${value} inches. A bare number is always inches; if you meant EMU, pass it as a string like "${Math.round(value)}emu".`);
|
|
3183
|
+
return inchesToEmu(value);
|
|
3184
|
+
}
|
|
3185
|
+
const match = /^\s*(-?\d*\.?\d+)\s*(%|in|pt|emu)\s*$/.exec(value);
|
|
3186
|
+
if (!match) throw new Error(`PptxGenJS: invalid coordinate "${value}". Expected a number (inches) or a string like "50%", "5in", "72pt", or "914400emu".`);
|
|
3187
|
+
const n = Number(match[1]);
|
|
3188
|
+
switch (match[2]) {
|
|
3189
|
+
case "%": return percentToEmu(n, axisEmu);
|
|
3190
|
+
case "in": return inchesToEmu(n);
|
|
3191
|
+
case "pt": return pointsToEmu(n);
|
|
3192
|
+
default:
|
|
3193
|
+
assertFiniteNumber(n, "coordinate");
|
|
3194
|
+
return Math.round(n);
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
3153
3197
|
function emuToInches(emu) {
|
|
3154
3198
|
assertFiniteNumber(emu, "emu");
|
|
3155
3199
|
return emu / EMU_PER_INCH;
|
|
@@ -3433,7 +3477,7 @@ let ShapeType = /* @__PURE__ */ function(ShapeType) {
|
|
|
3433
3477
|
ShapeType["flowChartSort"] = "flowChartSort";
|
|
3434
3478
|
ShapeType["flowChartSummingJunction"] = "flowChartSummingJunction";
|
|
3435
3479
|
ShapeType["flowChartTerminator"] = "flowChartTerminator";
|
|
3436
|
-
ShapeType["
|
|
3480
|
+
ShapeType["foldedCorner"] = "foldedCorner";
|
|
3437
3481
|
ShapeType["frame"] = "frame";
|
|
3438
3482
|
ShapeType["funnel"] = "funnel";
|
|
3439
3483
|
ShapeType["gear6"] = "gear6";
|
|
@@ -3636,7 +3680,7 @@ let SHAPE_TYPE = /* @__PURE__ */ function(SHAPE_TYPE) {
|
|
|
3636
3680
|
SHAPE_TYPE["FLOWCHART_STORED_DATA"] = "flowChartOnlineStorage";
|
|
3637
3681
|
SHAPE_TYPE["FLOWCHART_SUMMING_JUNCTION"] = "flowChartSummingJunction";
|
|
3638
3682
|
SHAPE_TYPE["FLOWCHART_TERMINATOR"] = "flowChartTerminator";
|
|
3639
|
-
SHAPE_TYPE["FOLDED_CORNER"] = "
|
|
3683
|
+
SHAPE_TYPE["FOLDED_CORNER"] = "foldedCorner";
|
|
3640
3684
|
SHAPE_TYPE["FRAME"] = "frame";
|
|
3641
3685
|
SHAPE_TYPE["FUNNEL"] = "funnel";
|
|
3642
3686
|
SHAPE_TYPE["GEAR_6"] = "gear6";
|
|
@@ -3671,10 +3715,6 @@ let SHAPE_TYPE = /* @__PURE__ */ function(SHAPE_TYPE) {
|
|
|
3671
3715
|
SHAPE_TYPE["LINE_CALLOUT_3_ACCENT_BAR"] = "accentCallout3";
|
|
3672
3716
|
SHAPE_TYPE["LINE_CALLOUT_3_BORDER_AND_ACCENT_BAR"] = "accentBorderCallout3";
|
|
3673
3717
|
SHAPE_TYPE["LINE_CALLOUT_3_NO_BORDER"] = "callout3";
|
|
3674
|
-
SHAPE_TYPE["LINE_CALLOUT_4"] = "borderCallout4";
|
|
3675
|
-
SHAPE_TYPE["LINE_CALLOUT_4_ACCENT_BAR"] = "accentCallout3=4";
|
|
3676
|
-
SHAPE_TYPE["LINE_CALLOUT_4_BORDER_AND_ACCENT_BAR"] = "accentBorderCallout4";
|
|
3677
|
-
SHAPE_TYPE["LINE_CALLOUT_4_NO_BORDER"] = "callout4";
|
|
3678
3718
|
SHAPE_TYPE["LINE"] = "line";
|
|
3679
3719
|
SHAPE_TYPE["LINE_INVERSE"] = "lineInv";
|
|
3680
3720
|
SHAPE_TYPE["MATH_DIVIDE"] = "mathDivide";
|
|
@@ -3742,6 +3782,31 @@ let SHAPE_TYPE = /* @__PURE__ */ function(SHAPE_TYPE) {
|
|
|
3742
3782
|
SHAPE_TYPE["WAVE"] = "wave";
|
|
3743
3783
|
return SHAPE_TYPE;
|
|
3744
3784
|
}({});
|
|
3785
|
+
/**
|
|
3786
|
+
* Valid ECMA-376 `ST_ShapeType` presets that are not surfaced with a friendly
|
|
3787
|
+
* `SHAPE_TYPE` name. They are still legal geometries PowerPoint renders, so the
|
|
3788
|
+
* preset-validation set must accept them.
|
|
3789
|
+
*/
|
|
3790
|
+
const EXTRA_SHAPE_PRESETS = [
|
|
3791
|
+
"straightConnector1",
|
|
3792
|
+
"bentConnector2",
|
|
3793
|
+
"bentConnector3",
|
|
3794
|
+
"bentConnector4",
|
|
3795
|
+
"bentConnector5",
|
|
3796
|
+
"curvedConnector2",
|
|
3797
|
+
"curvedConnector3",
|
|
3798
|
+
"curvedConnector4",
|
|
3799
|
+
"curvedConnector5"
|
|
3800
|
+
];
|
|
3801
|
+
/**
|
|
3802
|
+
* Every shape geometry name PptxGenJS can serialize without corrupting the
|
|
3803
|
+
* package: the OOXML preset geometries (`ST_ShapeType` — `SHAPE_TYPE` values
|
|
3804
|
+
* plus the unexposed connectors above) and `custGeom` (freeform paths, emitted
|
|
3805
|
+
* as `<a:custGeom>` rather than `<a:prstGeom>`). Used to reject bogus presets
|
|
3806
|
+
* before they become an invalid `<a:prstGeom prst="...">` that triggers
|
|
3807
|
+
* PowerPoint's "needs repair" dialog and drops the shape.
|
|
3808
|
+
*/
|
|
3809
|
+
const VALID_SHAPE_PRESETS = new Set([...Object.values(SHAPE_TYPE), ...EXTRA_SHAPE_PRESETS]);
|
|
3745
3810
|
let CHART_TYPE = /* @__PURE__ */ function(CHART_TYPE) {
|
|
3746
3811
|
CHART_TYPE["AREA"] = "area";
|
|
3747
3812
|
CHART_TYPE["BAR"] = "bar";
|
|
@@ -3811,7 +3876,98 @@ let BULLET_TYPES = /* @__PURE__ */ function(BULLET_TYPES) {
|
|
|
3811
3876
|
BULLET_TYPES["TRIANGLE"] = "▶";
|
|
3812
3877
|
return BULLET_TYPES;
|
|
3813
3878
|
}({});
|
|
3879
|
+
/**
|
|
3880
|
+
* Built-in PowerPoint table style IDs.
|
|
3881
|
+
*
|
|
3882
|
+
* Each value is the GUID that goes into `<a:tableStyleId>` inside `<a:tblPr>`.
|
|
3883
|
+
* These 74 GUIDs are the complete set defined in [MS-OE376] §5.1.6.10 and are
|
|
3884
|
+
* resolved by PowerPoint without embedding any style definition in the file.
|
|
3885
|
+
*
|
|
3886
|
+
* Only these enum members are supported. Raw GUID strings are not accepted;
|
|
3887
|
+
* use `TABLE_STYLE` members exclusively.
|
|
3888
|
+
*/
|
|
3889
|
+
let TABLE_STYLE = /* @__PURE__ */ function(TABLE_STYLE) {
|
|
3890
|
+
TABLE_STYLE["NO_STYLE_NO_GRID"] = "{2D5ABB26-0587-4C30-8999-92F81FD0307C}";
|
|
3891
|
+
TABLE_STYLE["NO_STYLE_TABLE_GRID"] = "{5940675A-B579-460E-94D1-54222C63F5DA}";
|
|
3892
|
+
TABLE_STYLE["THEMED_STYLE_1_ACCENT_1"] = "{3C2FFA5D-87B4-456A-9821-1D502468CF0F}";
|
|
3893
|
+
TABLE_STYLE["THEMED_STYLE_1_ACCENT_2"] = "{284E427A-3D55-4303-BF80-6455036E1DE7}";
|
|
3894
|
+
TABLE_STYLE["THEMED_STYLE_1_ACCENT_3"] = "{69C7853C-536D-4A76-A0AE-DD22124D55A5}";
|
|
3895
|
+
TABLE_STYLE["THEMED_STYLE_1_ACCENT_4"] = "{775DCB02-9BB8-47FD-8907-85C794F793BA}";
|
|
3896
|
+
TABLE_STYLE["THEMED_STYLE_1_ACCENT_5"] = "{35758FB7-9AC5-4552-8A53-C91805E547FA}";
|
|
3897
|
+
TABLE_STYLE["THEMED_STYLE_1_ACCENT_6"] = "{08FB837D-C827-4EFA-A057-4D05807E0F7C}";
|
|
3898
|
+
TABLE_STYLE["THEMED_STYLE_2_ACCENT_1"] = "{D113A9D2-9D6B-4929-AA2D-F23B5EE8CBE7}";
|
|
3899
|
+
TABLE_STYLE["THEMED_STYLE_2_ACCENT_2"] = "{18603FDC-E32A-4AB5-989C-0864C3EAD2B8}";
|
|
3900
|
+
TABLE_STYLE["THEMED_STYLE_2_ACCENT_3"] = "{306799F8-075E-4A3A-A7F6-7FBC6576F1A4}";
|
|
3901
|
+
TABLE_STYLE["THEMED_STYLE_2_ACCENT_4"] = "{E269D01E-BC32-4049-B463-5C60D7B0CCD2}";
|
|
3902
|
+
TABLE_STYLE["THEMED_STYLE_2_ACCENT_5"] = "{327F97BB-C833-4FB7-BDE5-3F7075034690}";
|
|
3903
|
+
TABLE_STYLE["THEMED_STYLE_2_ACCENT_6"] = "{638B1855-1B75-4FBE-930C-398BA8C253C6}";
|
|
3904
|
+
TABLE_STYLE["LIGHT_STYLE_1"] = "{9D7B26C5-4107-4FEC-AEDC-1716B250A1EF}";
|
|
3905
|
+
TABLE_STYLE["LIGHT_STYLE_1_ACCENT_1"] = "{3B4B98B0-60AC-42C2-AFA5-B58CD77FA1E5}";
|
|
3906
|
+
TABLE_STYLE["LIGHT_STYLE_1_ACCENT_2"] = "{0E3FDE45-AF77-4B5C-9715-49D594BDF05E}";
|
|
3907
|
+
TABLE_STYLE["LIGHT_STYLE_1_ACCENT_3"] = "{C083E6E3-FA7D-4D7B-A595-EF9225AFEA82}";
|
|
3908
|
+
TABLE_STYLE["LIGHT_STYLE_1_ACCENT_4"] = "{D27102A9-8310-4765-A935-A1911B00CA55}";
|
|
3909
|
+
TABLE_STYLE["LIGHT_STYLE_1_ACCENT_5"] = "{5FD0F851-EC5A-4D38-B0AD-8093EC10F338}";
|
|
3910
|
+
TABLE_STYLE["LIGHT_STYLE_1_ACCENT_6"] = "{68D230F3-CF80-4859-8CE7-A43EE81993B5}";
|
|
3911
|
+
TABLE_STYLE["LIGHT_STYLE_2"] = "{7E9639D4-E3E2-4D34-9284-5A2195B3D0D7}";
|
|
3912
|
+
TABLE_STYLE["LIGHT_STYLE_2_ACCENT_1"] = "{69012ECD-51FC-41F1-AA8D-1B2483CD663E}";
|
|
3913
|
+
TABLE_STYLE["LIGHT_STYLE_2_ACCENT_2"] = "{72833802-FEF1-4C79-8D5D-14CF1EAF98D9}";
|
|
3914
|
+
TABLE_STYLE["LIGHT_STYLE_2_ACCENT_3"] = "{F2DE63D5-997A-4646-A377-4702673A728D}";
|
|
3915
|
+
TABLE_STYLE["LIGHT_STYLE_2_ACCENT_4"] = "{17292A2E-F333-43FB-9621-5CBBE7FDCDCB}";
|
|
3916
|
+
TABLE_STYLE["LIGHT_STYLE_2_ACCENT_5"] = "{5A111915-BE36-4E01-A7E5-04B1672EAD32}";
|
|
3917
|
+
TABLE_STYLE["LIGHT_STYLE_2_ACCENT_6"] = "{912C8C85-51F0-491E-9774-3900AFEF0FD7}";
|
|
3918
|
+
TABLE_STYLE["LIGHT_STYLE_3"] = "{616DA210-FB5B-4158-B5E0-FEB733F419BA}";
|
|
3919
|
+
TABLE_STYLE["LIGHT_STYLE_3_ACCENT_1"] = "{BC89EF96-8CEA-46FF-86C4-4CE0E7609802}";
|
|
3920
|
+
TABLE_STYLE["LIGHT_STYLE_3_ACCENT_2"] = "{5DA37D80-6434-44D0-A028-1B22A696006F}";
|
|
3921
|
+
TABLE_STYLE["LIGHT_STYLE_3_ACCENT_3"] = "{8799B23B-EC83-4686-B30A-512413B5E67A}";
|
|
3922
|
+
TABLE_STYLE["LIGHT_STYLE_3_ACCENT_4"] = "{ED083AE6-46FA-4A59-8FB0-9F97EB10719F}";
|
|
3923
|
+
TABLE_STYLE["LIGHT_STYLE_3_ACCENT_5"] = "{BDBED569-4797-4DF1-A0F4-6AAB3CD982D8}";
|
|
3924
|
+
TABLE_STYLE["LIGHT_STYLE_3_ACCENT_6"] = "{E8B1032C-EA38-4F05-BA0D-38AFFFC7BED3}";
|
|
3925
|
+
TABLE_STYLE["MEDIUM_STYLE_1"] = "{793D81CF-94F2-401A-BA57-92F5A7B2D0C5}";
|
|
3926
|
+
TABLE_STYLE["MEDIUM_STYLE_1_ACCENT_1"] = "{B301B821-A1FF-4177-AEE7-76D212191A09}";
|
|
3927
|
+
TABLE_STYLE["MEDIUM_STYLE_1_ACCENT_2"] = "{9DCAF9ED-07DC-4A11-8D7F-57B35C25682E}";
|
|
3928
|
+
TABLE_STYLE["MEDIUM_STYLE_1_ACCENT_3"] = "{1FECB4D8-DB02-4DC6-A0A2-4F2EBAE1DC90}";
|
|
3929
|
+
TABLE_STYLE["MEDIUM_STYLE_1_ACCENT_4"] = "{1E171933-4619-4E11-9A3F-F7608DF75F80}";
|
|
3930
|
+
TABLE_STYLE["MEDIUM_STYLE_1_ACCENT_5"] = "{FABFCF23-3B69-468F-B69F-88F6DE6A72F2}";
|
|
3931
|
+
TABLE_STYLE["MEDIUM_STYLE_1_ACCENT_6"] = "{10A1B5D5-9B99-4C35-A422-299274C87663}";
|
|
3932
|
+
TABLE_STYLE["MEDIUM_STYLE_2"] = "{073A0DAA-6AF3-43AB-8588-CEC1D06C72B9}";
|
|
3933
|
+
TABLE_STYLE["MEDIUM_STYLE_2_ACCENT_1"] = "{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}";
|
|
3934
|
+
TABLE_STYLE["MEDIUM_STYLE_2_ACCENT_2"] = "{21E4AEA4-8DFA-4A89-87EB-49C32662AFE0}";
|
|
3935
|
+
TABLE_STYLE["MEDIUM_STYLE_2_ACCENT_3"] = "{F5AB1C69-6EDB-4FF4-983F-18BD219EF322}";
|
|
3936
|
+
TABLE_STYLE["MEDIUM_STYLE_2_ACCENT_4"] = "{00A15C55-8517-42AA-B614-E9B94910E393}";
|
|
3937
|
+
TABLE_STYLE["MEDIUM_STYLE_2_ACCENT_5"] = "{7DF18680-E054-41AD-8BC1-D1AEF772440D}";
|
|
3938
|
+
TABLE_STYLE["MEDIUM_STYLE_2_ACCENT_6"] = "{93296810-A885-4BE3-A3E7-6D5BEEA58F35}";
|
|
3939
|
+
TABLE_STYLE["MEDIUM_STYLE_3"] = "{8EC20E35-A176-4012-BC5E-935CFFF8708E}";
|
|
3940
|
+
TABLE_STYLE["MEDIUM_STYLE_3_ACCENT_1"] = "{6E25E649-3F16-4E02-A733-19D2CDBF48F0}";
|
|
3941
|
+
TABLE_STYLE["MEDIUM_STYLE_3_ACCENT_2"] = "{85BE263C-DBD7-4A20-BB59-AAB30ACAA65A}";
|
|
3942
|
+
TABLE_STYLE["MEDIUM_STYLE_3_ACCENT_3"] = "{EB344D84-9AFB-497E-A393-DC336BA19D2E}";
|
|
3943
|
+
TABLE_STYLE["MEDIUM_STYLE_3_ACCENT_4"] = "{EB9631B5-78F2-41C9-869B-9F39066F8104}";
|
|
3944
|
+
TABLE_STYLE["MEDIUM_STYLE_3_ACCENT_5"] = "{74C1A8A3-306A-4EB7-A6B1-4F7E0EB9C5D6}";
|
|
3945
|
+
TABLE_STYLE["MEDIUM_STYLE_3_ACCENT_6"] = "{2A488322-F2BA-4B5B-9748-0D474271808F}";
|
|
3946
|
+
TABLE_STYLE["MEDIUM_STYLE_4"] = "{D7AC3CCA-C797-4891-BE02-D94E43425B78}";
|
|
3947
|
+
TABLE_STYLE["MEDIUM_STYLE_4_ACCENT_1"] = "{69CF1AB2-1976-4502-BF36-3FF5EA218861}";
|
|
3948
|
+
TABLE_STYLE["MEDIUM_STYLE_4_ACCENT_2"] = "{8A107856-5554-42FB-B03E-39F5DBC370BA}";
|
|
3949
|
+
TABLE_STYLE["MEDIUM_STYLE_4_ACCENT_3"] = "{0505E3EF-67EA-436B-97B2-0124C06EBD24}";
|
|
3950
|
+
TABLE_STYLE["MEDIUM_STYLE_4_ACCENT_4"] = "{C4B1156A-380E-4F78-BDF5-A606A8083BF9}";
|
|
3951
|
+
TABLE_STYLE["MEDIUM_STYLE_4_ACCENT_5"] = "{22838BEF-8BB2-4498-84A7-C5851F593DF1}";
|
|
3952
|
+
TABLE_STYLE["MEDIUM_STYLE_4_ACCENT_6"] = "{16D9F66E-5EB9-4882-86FB-DCBF35E3C3E4}";
|
|
3953
|
+
TABLE_STYLE["DARK_STYLE_1"] = "{E8034E78-7F5D-4C2E-B375-FC64B27BC917}";
|
|
3954
|
+
TABLE_STYLE["DARK_STYLE_1_ACCENT_1"] = "{125E5076-3810-47DD-B79F-674D7AD40C01}";
|
|
3955
|
+
TABLE_STYLE["DARK_STYLE_1_ACCENT_2"] = "{37CE84F3-28C3-443E-9E96-99CF82512B78}";
|
|
3956
|
+
TABLE_STYLE["DARK_STYLE_1_ACCENT_3"] = "{D03447BB-5D67-496B-8E87-E561075AD55C}";
|
|
3957
|
+
TABLE_STYLE["DARK_STYLE_1_ACCENT_4"] = "{E929F9F4-4A8F-4326-A1B4-22849713DDAB}";
|
|
3958
|
+
TABLE_STYLE["DARK_STYLE_1_ACCENT_5"] = "{8FD4443E-F989-4FC4-A0C8-D5A2AF1F390B}";
|
|
3959
|
+
TABLE_STYLE["DARK_STYLE_1_ACCENT_6"] = "{AF606853-7671-496A-8E4F-DF71F8EC918B}";
|
|
3960
|
+
TABLE_STYLE["DARK_STYLE_2"] = "{5202B0CA-FC54-4496-8BCA-5EF66A818D29}";
|
|
3961
|
+
/** Header uses Accent 2, body rows use Accent 1 */
|
|
3962
|
+
TABLE_STYLE["DARK_STYLE_2_ACCENT_1_ACCENT_2"] = "{0660B408-B3CF-4A94-85FC-2B1E0A45F4A2}";
|
|
3963
|
+
/** Header uses Accent 4, body rows use Accent 3 */
|
|
3964
|
+
TABLE_STYLE["DARK_STYLE_2_ACCENT_3_ACCENT_4"] = "{91EBBBCC-DAD2-459C-BE2E-F6DE35CF9A28}";
|
|
3965
|
+
/** Header uses Accent 6, body rows use Accent 5 */
|
|
3966
|
+
TABLE_STYLE["DARK_STYLE_2_ACCENT_5_ACCENT_6"] = "{46F890A9-2807-4EBB-B81D-B2AA78EC7F39}";
|
|
3967
|
+
return TABLE_STYLE;
|
|
3968
|
+
}({});
|
|
3814
3969
|
const IMG_BROKEN = "data:image/png;base64,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";
|
|
3970
|
+
const IMG_SVG_PLACEHOLDER = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==";
|
|
3815
3971
|
const IMG_PLAYBTN = "data:image/png;base64,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AAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKSEAhgAAAAAAAAgJRTAAAAAAAAAACmhAAYAAAAAAABICQUwAAAAAAAAQEoogAEAAAAAAABSQgEMAAAAAAAAkBIKYAAAAAAAAICUUAADAAAAAAAApIQCGAAAAAAAACAlFMAAAAAAAAAAKaEABgAAAAAAAEgJBTAAAAAAAABASiiAAQAAAAAAAFJCAQwAAAAAAACQEgpgAAAAAAAAgJRQAAMAAAAAAACkhAIYAAAAAAAAICUUwAAAAAAAAAApoQAGAAAAAAAASAkFMAAAAAAAAEBKKIABAAAAAAAAUkIBDAAAAAAAAJASCmAAAAAAAACAlFAAAwAAAAAAAKREkRUAAACwrUpLSwuGDRvWfMCAAS26du3avKysrLiioqKkZcuWzZs1a1bcvHnz0tLS0rJsNtusuLi4ebNmzUoLCgo+8/eijY2N9Zs3b66pra2tqqur21xTU1NdVVVVs2nTptqNGzdWbdiwoeYvf/nL5hUrVlQtWLBgw6xZs6pqamoaJQYAAEDaKYABAACIiIghQ4aUHnTQQW379u3bql27dq3at2/fpkWLFq2bN29eWVpa2qpZs2bNCwsLm2ez2fLCwsLyoqKi8sLCwtKknK+hoaG6vr6+qqGh4S91dXV/aWhoqNq8eXNVTU3NuqqqqvUbNmxYu2rVqjWrV69e99Zbb6177rnnPpgzZ06NTwYAAABJogAGAADIA8OGDWt+xBFHdBwwYECnLl26dGjdunXHFi1adCgtLe1YUlLSvlmzZq0KCgqK07yDwsLCssLCwrKIaPdp/zuNjY21mzdvXrdp06ZVNTU172/YsGHl2rVr31+2bNnKBQsWrHjyySffnzVrVpVPGAAAAE1Fpuexsd9HfaF+ZcSal0ptCAAAIAE6deqUPf744zvtueeeXbp3796lbdu2XSorKzuXlpZ2KS0t7VBYWFhhSztGQ0PDxpqampU1NTXL169fv+yDDz5Y9s477yybPXv2sj/96U8rVqxYUWdLAAAAbE9t9q6Jog4f/TUFMAAAQEJks9nMt7/97Y4jRozo1bdv397t2rXrXl5e3rWsrKxzcXFx+4gosKUmp7G2tnZVTU3Nso0bNy5btWrV0tdff/2tJ598cvG999672noAAADYFgpgAACAhPne977X6a9Fb/v27Xu1bNmyV1lZWa8kvXOXLauvr9/wl7/8ZdG6desWL1u2bNHChQsX/fGPf1w8derUjbYDAADAliiAAQAAmqhsNps59dRTuxx66KH9+/Tp87n27dv3Ly8v719UVOSRzXlq06ZNKzZu3Pj6+++//8abb775xqOPPvrG3XffvcpmAAAA+CsFMAAAQBNx6qmndvniF784qHfv3v3btWv3uYqKis8VFhaW2wxbUl9fv37Dhg1vfPDBB68vXrz4jccee2z+jTfeuNxmAAAA8pMCGAAAYBc45phjWn/rW9/aq3///kPatGnTv6Kiop9HOLO9NDQ0VG/cuPGtNWvWLFy4cOGcO+6445WHHnporc0AAACknwIYAABgJzjjjDO6f+lLX9qrV69eg1u3bj2orKysR0RkbIadJFddXb103bp18xcvXjz30UcffeXqq69+x1oAAADSRwEMAACwnZWWlhb86le/2u3QQw8d1r17931btmw5qLCwsMxmaEoaGhqqP/zww/nvvPPOzGeeeWbW2LFj36ipqWm0GQAAgGRTAAMAAGwHP/7xj7t+9atf3bdXr15D27Ztu1c2m21jKyRJXV3dmg8++OCVRYsWvfznP/95xh/+8IdltgIAAJA8CmAAAIBtcOKJJ7Y75ZRTDujXr9+w1q1bD81ms61shTSpq6tbt3bt2pfffPPNWbfccsvUe++9d7WtAAAANH0KYAAAgE+hoqKi4IILLhg0YsSI/bp27bpfy5YtB2YymUKbIR/kcrmGDz/8cP6777474/nnn59x4YUXvrZx40aPiwYAAGiCFMAAAAAf4/jjj2/7/e9//8D+/fsf2Lp1630KCgpKbAUiGhsbN61fv37eW2+9NeWGG2545u67715lKwAAAE2DAhgAAOB/ZLPZzAUXXPC5I4888sDu3bsfWFFRsVtEFNgMbFl1dfWSd999d8qsWbNmnnvuuS+vW7euwVYAAAB2DQUwAACQ10pLSwsuvfTSQYcccsjBXbt2HVFWVtbDVmDb1dbWrnr//fdfmDp16uRf/vKXL65evbreVgAAAHYeBTAAAJB3Bg0aVHrBBRd8fs899zywQ4cOBxQVFbWwFdj+Ghsba9euXTtrzpw5T59//vmTX3755WpbAQAA2LEUwAAAQF4YNmxY8/POO+/gIUOGHOZ9vrDz/W0ZfNFFFz07a9asKlsBAADY/hTAAABAarVq1arwyiuv3HfEiBEjO3TocFBhYWGZrcCu19DQUP3+++8/O2XKlIk/+clPZm7cuLHRVgAAALYPBTAAAJAqrVq1Kvztb3+7/3777Xd4x44dRxQWFpbbCjRdDQ0NG99///0pM2bMeOqHP/zhC8pgAACAz0YBDAAApMJZZ53V45vf/OaRvXr1GllaWtrVRiB5ampq3l28ePHEO++8c9LVV1/9jo0AAABsPQUwAACQWMOHDy+/6KKLvjB48OCjW7RoMdBGID0+/PDDV+fNmzfhvPPOe3L69Ol/sREAAIBPRwEMAAAkSqtWrQpvuOGGQ/bbb79/atOmzX6ZTCZrK5BeuVyubs2aNTNmzJjx2JgxYyavW7euwVYAAAA+ngIYAABIhB//+Mddv/e9732lZ8+e/1RcXNzWRiD/1NbWfvD2228/dssttzz029/+9l0bAQAA+L8UwAAAQJNVUVFRcO21137+4IMPPrZ169b7ZTKZAlsBIqJxzZo1M59//vnxp5122hR3BQMAAPx/CmAAAKDJOeWUUzqefvrpx/bu3ftL2Wy2jY0AH6e+vn7j0qVLH/vd7373x+uvv36ZjQAAAPlOAQwAADQJ2Ww2c+uttx5wyCGHnNC6deu9I8LdvsDWaFy7du1L06ZN+/OPfvSjZ1evXl1vJQAAQD5SAAMAALtU//79S6655pp/2nPPPY8tLy/vayPAZ1VTU7NswYIF488999wHp06dutFGAACAfKIABgAAdomf//znPU855ZQTu3btemRhYWGZjQDbW2NjY92KFSuevOWWW+689NJLF9kIAACQDxTAAADATuMxz8Cusn79+rlPP/30f5188slT6+rqcjYCAACklQIYAADY4fr27Vv8hz/84a+Pee5nI8CuUlNT8+68efPu/8EPfvDgwoULN9kIAACQNgpgAABghxkyZEjpNddc89XBgwefWFxc3MFGgKaitrZ21dy5c+/5yU9+8uc5c+bU2AgAAJAWWyqAPYoNAADYJqNHj+4wb968n06ZMuXRYcOGnaH8BZqa4uLi9sOGDTtjypQpj86bN++nJ510UntbAQAA0s4dwAAAwFY599xze33/+9//dufOnY/IZDJZGwGSIpfL1S1fvvzJG2644fbLLrvsbRsBAACSyiOgAQCAz+y8887r+53vfOfbHTt2PDyTyRTaCJBUuVyuYcWKFU/cdNNN//XrX/96sY0AAABJowAGAAC22WWXXTboG9/4xg9at249zDaAtFm7du2su++++9pzzjnnNdsAAACSQgEMAABsNcUvkE8UwQAAQJIogAEAgE9N8Qvks7Vr18665557rvv5z38+3zYAAICmaksFcGHlwOj6UV9orIqoWZG1PQAAyBO/+MUvet9xxx3nHHrooT8pLS3tYiNAPiotLe2y7777HvP973+/X1lZ2ZIpU6assxUAAKCpKetcHwXlH/01BTAAAOS5M844o/u99957zpe//OWflZeX94qIjK0AeS5TXl7e8+CDDx71/e9/v3dEvDVjxowPrQUAAGgqFMAAAMD/ceKJJ7a77777fjJq1Kh/KS8v7xOKX4B/lCkvL+99+OGHj/rWt77VfvXq1Qvnz59fbS0AAMCutqUC2DuAAQAgzwwdOrTs+uuvP6l///4nFRYWltkI20NjY2Ns2rQpqquro6amJurr62PTpk2xefPmqK+vj+rq6qivr4/NmzfHpk2boqGhYZv/fxUWFkZJSUk0a9YsioqKoqysLIqKiqJZs2ZRUlISRUVFUVpa+r9/FRQUCIjtoqGhoeq11167a8yYMffMmTOnxkYAAIBdZUvvAFYAAwBAnujUqVP2nnvuGbXXXnudnM1mK22Ej9PQ0BAbN26MDRs2/J+/Nm7cGBs3boyamprYtGlTbNq0KWpqaqK2trbJnqe4uDhKSkqitLT0f/9eUVERFRUV0aJFi//zV0VFRRQWFvog8LHq6urWvvjii7eceOKJf169enW9jQAAADubAhgAAPLcXXfdddAXv/jF00tLS7vZRn7L5XKxYcOGWLt2baxbty7Wrl37d3+tW7cuNmzYkPd7atGiRbRu3TpatWoVrVu3jjZt2vzvf27dunW0aNHCh4morq5e+sgjj1zzne98Z6ptAAAAO5MCGAAA8tTVV189+MQTTzyzoqJioG3kj8bGxli5cmUsX748Pvjgg1i9evX//n3t2rXR2NhoSZ9RYWFhtGrVKtq1axdt27b937937tw5OnTo4LHTeWbDhg3z77333qvOPPPMebYBAADsDApgAADIM1/72tfaXHrppad27979qIjQRKVUQ0NDrFq1KlasWBHvv//+//595cqVTfqRzGlXXFwcHTp0iI4dO0bnzp2jY8eO0alTp2jXrp1HS6dYLpdrfOeddx76+c9/fv2ECRPW2QgAALAjKYABACBP9OrVq9ldd931jT322OM7hYWFZTaSHh9++GG88847sXTp0njvvfdixYoVsXr16mhoaLCchCgsLIz27dtHp06dolu3btG9e/fo3r27x0mnTENDQ9W8efNu++Y3v/nHJUuWbLYRAABgR1AAAwBAHrjrrrtG/NM//dOZJSUlXWwj2davXx9Lly6Nd955539L3w8//NBiUqqysvJ/y+C//tWqVSuLSbiamppljz322G9Gjx49xTYAAIDtTQEMAAAp9qtf/arPD3/4w5+1atVqL9tIno0bN8aSJUvirbfeikWLFsV7770XmzZtspg8V1JSEl27do0+ffpE3759o3fv3lFeXm4xCbRu3bqXr7322ivGjh27yDYAAIDtRQEMAAApNGjQoNI77rjju7vttttJBQUFWRtJhtWrV8ebb74ZixcvjiVLlsTy5cujsbHRYtiigoKC6Ny5c/Tu3Tt69+4d/fr1i7Zt21pMQjQ2Nta98cYbd33rW9+6ff78+TU2AgAAfFYKYAAASJHS0tKCBx988Jj99tvvn7PZbBsbaboaGhri7bffjrfeeisWLFgQS5YscXcv201FRUX06tUr+vbtG3379o2ePXtGYWGhxTRhdXV1a2bMmHHjV77ylYdqamr85gcAALDNFMAAAJASp59+erdf/vKX51ZWVu5jG03T6tWr47XXXouFCxfGm2++GRs3brQUdooWLVpE3759Y8CAATFw4EB3CDdh69evf/E//uM//vPqq69+xzYAAIBtoQAGAICEGzRoUOm99977w969ex+byWTc4teErF+/PubNmxcLFiyIN954Q+FLk9GiRYvo169fDBgwIPbYY4+orKy0lCYkl8s1LF68eNyJJ554rcdCAwAAW0sBDAAACXbNNdcMOemkk35RVlbWyzZ2vVwuF++++27MnTs3XnvttViyZIl3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B7lcrm7y5Mm//vKXv/yIbQAAwK63pXcAK4ABAMg7paWlBTNnzjyzT58+x9vG39uwYUOMGzcuZsyY4VHPQF7KZDKx3377xde//vWoqKiwkH+waNGiP+27775X1dTUeCwEAADsQgpgAAD4H926dctOnjz5V506dRppG/9fLpeLqVOnxp///OfYuHGjhQB5r6KiIkaNGhX777+/x0L/g+XLlz9+6KGHXvLuu+/W2QYAAOwaWyqAvQMYAIC8MXz48PInnnjiynbt2o2wjf/vnXfeiWuvvTaee+652Lx5s4UARMTmzZtjzpw58dprr0XPnj2jRYsWlvI/Kioq+n7rW98aMnXq1Ofee+89f3AAAMAusKV3ACuAAQDIC9/+9rc73n777X9o0aLFANv4b1VVVXHXXXfFvffeG+vXr7cQgI+wbt26eP7552P9+vWx2267RVFRkaVERElJSefjjjvuoA8++GDKK6+88hcbAQCAnUsBDABAXjv//PP7XXzxxX8oKSnpbBv/bfr06XHttdfGokWLLAPgU3jnnXdi2rRp0bp16+jc2R8nERHZbLbyC1/4whElJSUvTp48eY2NAADAzqMABgAgb/3ud7/b60c/+tFVRUVFrWwjYs2aNXHzzTfHpEmTora21kIAtkJtbW289NJL8c4770Tfvn2jtLQ073dSWFhYNnz48C/26dNn4UMPPbTMpwQAAHYOBTAAAHnp1ltv3f+b3/zmfxYWFjbP913kcrl4/vnn4/rrr4/ly5f7cAB8BitXroxp06ZFRUVFdOvWLTKZTF7vo6CgIDto0KBDBw0atOiBBx54xycEAAB2vC0VwJmex8Z+H/WF+pURa17ym6wAACTTww8//KXDDjvsXzKZTN6/rPGDDz6I22+/Pd544w0fDIDtbMCAAfGtb30r2rRpk/e7yOVyjVOmTPn1yJEjH/LJAACAHavN3jVR1OGjv6YABgAgdV555ZXTPve5z30r3/fQ0NAQjz32WDz++ONRV1fngwGwg2Sz2Tj66KPjC1/4QhQUFOT9Pl5//fU79tprr9/7ZAAAwI6jAAYAIC9ks9nMyy+/fFafPn2Oz/ddvPvuu3HbbbfFe++954MBsJN069YtvvOd70S3bt3yfhdLliy5f5999rmypqam0ScDAAC2PwUwAACpV1paWjBr1qyzevfufVw+7yGXy8WTTz4ZDz74oLt+AXaBbDYbxxxzTBxxxBF5fzfw0qVLHxg6dOjlSmAAANj+FMAAAKRar169mk2ePHlsu3btDsrnPaxcuTJuueWWePvtt30oAHaxnj17ximnnBIdOnTI6z2sXr16yiGHHPIvS5Ys2exTAQAA28+WCuDCyoHR9aO+0FgVUbMia3sAADRpQ4cOLXvqqacub9Omzf75uoNcLhfPPPNMXH/99bF27VofCoAmYP369TFlypQoKSmJnj17RiaTycs9NG/evPtJJ500ZPLkyc+sWLHCoykAAGA7KetcHwXlH/01BTAAAIk1ZMiQ0kceeeSKVq1a7Z2vO6iuro7bb789nnjiiWhs9IRNgKaksbEx5s+fH++//34MGDAgstn8/DlLaWlpp6997WuDn3rqqadXrlxZ75MBAACfnQIYAIDUOfTQQ1s8+OCDv2/ZsuUe+bqDOXPmxNVXX+2RzwBN3PLly+OFF16Ijh075u0joUtLSzudcMIJ+7/00ktPv/3227U+FQAA8NkogAEASJVhw4Y1v++++37TsmXLQfl4/vr6+hg/fnz88Y9/jNpaP0MHSILNmzfHiy++GJs3b47ddtstCgoK8m4HxcXFbY866qg9n3vuuaeXL1/ucdAAAPAZKIABAEiNI488snLcuHG/b9GixcB8PP97770XV111VcyZM8eHASCBFi1aFC+//HL069cvWrRokXfnLykp6XDcccftP2fOnGcWLVq0yScCAAC2jQIYAIBUOPLIIyvvvPPO35aXl++Wj+d/+umn48Ybb4wPP/zQhwEgwf7yl7/ECy+8ECUlJdGrV6+8O3+zZs3aHHXUUfspgQEAYNspgAEASLxjjz227W233faH5s2b98m3s1dVVcXNN98cTz31VDQ2NvowAKRAY2NjzJ8/P5YtWxYDBgyIZs2a5dX5mzVr1uaYY4458M0333xm4cKFNT4RAACwdRTAAAAk2qGHHtritttuuzofy9+33347rrnmmli8eLEPAkAKvf/++/HKK69Enz59orKyMq/Ons1mK4888sh9Zs6c+dTSpUs3+zQAAMCnpwAGACCxjjjiiJb33nvvteXl5f3y6dy5XC4mTZoUN998c1RVVfkgAKRYVVVVTJ06NbLZbPTp0ycymUzenL24uLjtV7/61c+/8sorTy1evLjWpwEAAD4dBTAAAIl06KGHtrj33nt/l2/lb3V1ddx0000xefLkyOVyPggAeSCXy8WCBQvi3Xffjd133z2y2fz5mUyzZs1aH3300fvNmDHjSXcCAwDAp6MABgAgcYYOHVo2fvz4qysqKgbk07mXLVsWV111lUc+A+SplStXxiuvvBKf+9znoqKiIm/O3axZszZHH3300GeeeebJFStW1PkkAADAlimAAQBIlCFDhpQ++uij17Rs2XL3fDr31KlT49prr42NGzf6EADksaqqqpg+fXq0bds2unTpkjfnLikpaT9q1KihTz755JMrV66s90kAAICPt6UCuMB6AABoSjp16pSdMGHCv1dWVu6RL2dubGyMcePGxR133BF1dW56AiCitrY2br755hg/fnw0NjbmzbkrKyv3mDBhwr9369bNXQkAALCNFMAAADQZrVq1Kpw+ffolbdq02T9fzlxdXR2/+93vYtKkSd73C8DfyeVy8fjjj8fvf//7qK6uzptzt2nTZv8pU6Zc0qpVq0KfAgAA2HoKYAAAmoSKioqC2bNnX9KuXbuD8uXMS5cujYsuuijmz5/vAwDAx3r11VfjoosuiqVLl+bNmdu1a3fQ7Nmz/72iosLPrgAAYCu5iAYAoEmYOXPmz9q1a3dIvpz35ZdfjiuuuCLWrVsnfAA+0bp16+KKK66Il19+OW/O3K5du4Nnzpz5M+kDAMDWUQADALDLvfjii2N69OgxKh/Omsvl4oEHHogbbrghamtrhQ/Ap1ZbWxs33HBDPPDAA3nz2oAePXqMevHFF8dIHwAAPj0FMAAAu9SkSZO+NnDgwFPy4ax1dXVx8803x8SJE73vF4BtksvlYuLEiXHLLbdEXV1dXpx54MCBJ0+aNOlr0gcAgE9HAQwAwC7z6KOPHnXggQeekw9nXbduXfz617+OWbNmCR6Az2zmzJnx61//Ol9eJZA58MADz3n00UePkjwAAHyywsqB0fWjvtBYFVGzImtDAADsEDfeeOO+Rx999EWZTKYw7Wddvnx5XHXVVbFy5UrBA7DdbNiwIWbPnh0DBw6MioqKtB8307179/179uz56sMPP7xc+gAA5LuyzvVRUP7RX1MAAwCw011xxRV7fPe7372qoKCgWdrPOmfOnPjtb38bGzduFDwA2111dXVMmzYtOnfuHB07dkz1WTOZTOHuu+9+eJs2bV6aNGnSKukDAJDPFMAAADQZZ5xxRvef/exnvy0sLCxP+1knTJgQd999d9TX1wsegB2moaEhXnrppchms9G3b99UnzWTyRTttddeB/3lL395dubMmRukDwBAvlIAAwDQJBx00EEVf/jDH64pLi7ulOZz5nK5eOCBB+Kxxx4TOgA77c+eBQsWRF1dXfTv3z8ymUxqz1pQUFBywAEHDJs+ffqkpUuXbpY+AAD5aEsFcIH1AACwMwwaNKj0vvvuu7qsrKxXms9ZV1cX1113XUyaNEnoAOx0EydOjOuvvz7q6upSfc6ysrJef/rTn67u379/idQBAODvKYABANjhKioqCh577LGLKyoqBqb5nNXV1XHNNdfE7NmzhQ7ALvPKK6/ElVdeGVVVVak+Z4sWLQZOnDhxbEVFhZ9vAQDA33CBDADADjdz5syftW3b9sA0n3HdunVx2WWXxRtvvCFwAHa5xYsXx2WXXRZr165N9TnbtWt34MyZM38mcQAA+P8UwAAA7FBPPvnkqB49eoxK8xlXrVoVV1xxRSxfvlzgADQZK1asiCuuuCJWrlyZ6nP26NFj1KRJk0ZJHAAA/lth5cDo+lFfaKyKqFmRtSEAALbZjTfeuO+XvvSlCzOZTGp/8fDdd9+NK6+8MtatWydwAJqc6urqmDVrVvTv3z8qKytTe85u3boN79mz57yHH37Yb2MBAJAXyjrXR0H5R39NAQwAwA5x3nnn9T311FOvLigoKE7rGV977bW45pprorq6WuAANFmbN2+OGTNmRI8ePaJ9+/apPGMmkykYNGjQIYWFhVOee+45v5UFAEDqKYABANipjjrqqFb/8R//8YdmzZq1SusZX3755bj++uujrq5O4AA0eQ0NDfHSSy9Fp06dolOnTqk8Y0FBQXbYsGGfnz9//qQ33nhjk9QBAEizLRXA3gEMAMB21a1bt+wNN9zwnyUlJR3TesYpU6bEjTfeGPX19QIHIDHq6+vjxhtvjKlTp6b2jCUlJZ1uuOGG/+jWrZu7GgAAyFsKYAAAtqunn376XyorK/dI6/kmTZoUd955ZzQ2NgobgMRpbGyMO+64I5588snUnrGysnLw008//UtpAwCQrxTAAABsN88///w3unTp8k9pPd/EiRNj3LhxkcvlhA1AYuVyubj//vtTXQJ36dLlS88+++yJ0gYAIB95BzAAANvFTTfdNPzII488L5PJZNJ4vsceeyzGjx8vaABS47XXXotmzZpF3759U3m+zp0779urV695Dz/88DJpAwCQNlt6B7ACGACAz+wXv/hF7x/+8IdXFxQUNEvj+R544IF45JFHBA1A6ixYsCDq6upiwIABqTtbJpPJDBo06ODGxsbnpk6dul7aAACkiQIYAIAd5oADDqj43e9+99tmzZq1TeP5xo0bF5MmTRI0AKm1aNGi2Lx5cwwcODB1ZysoKMjut99+w5577rnH33vvvc3SBgAgLbZUAHsHMAAA2yybzWbuvPPOfyktLe2exvNNmDBB+QtAXpg0aVI89NBDqTxbaWlpj3vuuedfstlsRtIAAOQDBTAAANvs+eef/06HDh0OTePZHn744Xj44YeFDEDeeOSRR+LPf/5zKs/WoUOHw5599tlvSxkAgHygAAYAYJvcd999hw8ePPjUNJ7t/vvvjwkTJggZgLzz2GOPxX333ZfKs+25554/+NOf/nSYlAEASDvvAAYAYKudccYZ3ceMGXN5QUFBcdrONnHixHjkkUeEDEDeWrx4cWSz2ejbt2/ajpbp06fPvn/5y18mz5w5c4OkAQBIsi29A1gBDADAVhk2bFjzG2+88Q/NmjVrl7azPfroo6l99CUAbI2FCxdGUVFR9OvXL1XnKigoKD7wwAP3e/LJJx9dsWJFnaQBAEiqLRXAHgENAMBWuffee39ZWlraPW3nevzxx+PBBx8UMAD8jz//+c8xceLE1J2rtLS0x3333fdLCQMAkFYKYAAAPrVJkyaN6tSp0xEpPFeMHz9ewADwD8aPHx+TJ09O3bk6der0hUmTJn1VwgAApJFHQAMA8Kmcd955fU888cR/z2QyRWk618yZM+Puu+8WMAB8jNdeey06duwYnTt3TtW5unbtuk9BQcHzzz333DopAwCQNN4BDADAZ3LEEUe0vOKKK67NZrOVaTrXyy+/HDfffHPkcjkhA8DHyOVyMXv27OjSpUt06tQpNefKZDJF++yzz/CpU6c+9u67726WNAAASeIdwAAAbLNsNpu55ZZb/q2kpKRjms61YMGCuPnmm6OxsVHIAPAJGhsb4+abb44333wzVecqLS3tcvfdd5+fzWYzUgYAIC0UwAAAbNGkSZO+3rZt2wPTdKZly5bFDTfcEPX19QIGgE+prq4urr322li+fHmqztWuXbsDH3/88VESBgAgLTwCGgCAj3XZZZcN+upXvzo2k8mk5hcH33///bjyyiujqqpKwACwlerq6uLll1+OIUOGRHl5eWrO1aVLl31LS0unPvPMM2ukDABAEngENAAAW61///4lJ5988q8ymUxRWs60YcOG+P3vfx8bN24UMABso40bN8bvfve7VP15WlBQkP3hD394ft++fYslDABA4q9vrQAAgI/y4IMPnl1WVtYrLeeprq6O3/zmN7Fq1SrhAsBntGrVqrjyyiujuro6NWcqKyvr8/DDD58lXQAAkk4BDADA/zF+/Pgju3XrdnRazlNfX5/KdxYCwK60fPnyuO6666K+vj41Z+rRo8dXx40bd4R0AQBIMgUwAAB/53vf+16nI4444py0nCeXy8Vtt90Wb7zxhnABYDt7/fXX47bbbotcLpeaMx155JHnfvvb3+4oXQAAkkoBDADA/6qoqCi4+OKLLywsLCxPy5nGjx8fs2bNEi4A7CCzZs2Khx56KDXnKSwsrPj1r399QUVFhZ+bAQCQSC5kAQD4XxMnThxdWVk5OC3nef7552PixImCBYAd7LHHHosXXnghNeeprKzc89FHHz1RsgAAJFFh5cDo+lFfaKyKqFmRtSEAgDxxwQUX7DZq1KgLM5lMYRrO8+qrr8Ytt9ySqkdSAkBT/7O3d+/e0a5du1Scp2PHjkNzudxzU6ZMWSddAACamrLO9VHwMc/wcwcwAADRt2/f4h//+McXZzKZVPwG4HvvvRc33HBDNDY2ChcAdpKGhoa47rrrYtmyZak4T0FBQfbss88e27dv32LpAgCQqGtZKwAAYPz48T8qKyvrkYazbNiwIX7/+99HbW2tYAFgJ9u0aVP8/ve/j40bN6biPGVlZb3GjRs3RrIAACSJAhgAIM/ddNNNw/v06XN8Gs5SX18f1157baxdu1awALCLrFmzJq699tqor69PxXn69ev3jd///vdDJQsAQFIogAEA8thBBx1Uceyxx/5rRGTScJ477rgjFi9eLFgA2MUWLVoUd955Z1qOU/CNb3zj34YNG9ZcsgAAJOIC1goAAPLXzTfffFZxcXG7NJxl4sSJMX36dKECQBMxbdq0mDRpUirOUlJS0unOO+88Q6oAACSBAhgAIE/913/914FdunT5UhrO8tprr8Wf//xnoQJAEzN+/PhYsGBBKs7SrVu3o2+66abhUgUAoKlTAAMA5KEvfelLlV/5yld+lYazrFixIq6//vpobGwULAA0MY2NjXHdddfFihUr0nCczHHHHfergw46qEKyAAA0ZQpgAIA8dPXVV5+ezWYrk36OmpqauPbaa2PTpk1CBYAmatOmTXHttddGTU1N4s+SzWbb3njjjT+RKgAATZkCGAAgz9x6663Du3Tp8uWknyOXy8Utt9wSK1euFCoANHErV66MW2+9NXK5XOLP4lHQAAA0dQpgAIA8MnTo0LKvfvWrv0jDWSZMmBBz584VKgAkxJw5c+Kxxx5LxVlGjRr1i6FDh5ZJFQCApkgBDACQR+64444fFRcXd0z6OV5++eV45JFHBAoACfPQQw+l4he4SkpKOt5xxx0/lCgAAE2RAhgAIE9cfvnlu/fs2XNU0s/xwQcfxB133JGKR0gCQL7J5XJx2223xZo1axJ/lp49ex57+eWX7y5VAACaGgUwAEAe6NatW/a73/3uv2YymURf/9XX18cNN9wQ1dXVQgWAhKqqqoobb7wx6uvrE32OTCZT8N3vfvdX3bp1y0oVAICmRAEMAJAHxo8ff0pZWVmvpJ/jnnvuiaVLlwoUABJuyZIlcd999yX+HGVlZT3Hjx9/ikQBAGhKFMAAACn385//vOeAAQNGJ/0c06dPjylTpggUAFJi8uTJMWPGjMSfY8CAAaN//vOf95QoAABNhQIYACDFstls5qyzzjo3k8kk+tGEK1asiLvvvlugAJAyd911V6xYsSLRZ8hkMtmzzjrr3Gw2m5EoAABNgQIYACDFxo0b98XKysq9knyG2trauOGGG6K2tlagAJAyf/1zfvPmzYk+R2Vl5V7jxo0bKVEAAJoCBTAAQEoNHz68/OCDDz4t6ee4//77Y/ny5QIFgJRavnx5jBs3LvHnGDFixI+HDRvWXKIAAOxqCmAAgJS69dZbT8tms22TfIYZM2bEc889J0wASLnJkyfHzJkzE32G4uLitrfffvtp0gQAYFdTAAMApNBVV121R48ePb6S5DOsXLky7rrrLmECQJ64++6744MPPkj0GXr27PnVK664Yg9pAgCwKymAAQBSprS0tOAb3/jGT5N8rdfY2Bi333679/4CQB6pqamJ2267LRobG5N8jIJvfvObZ5aWlvqZGwAAu+6i1AoAANJlwoQJX6uoqBiQ5DOMHz8+Fi1aJEwAyDNvvvlmPPjgg4k+Q4sWLQY9+OCDx0gTAIBdRQEMAJAiRx55ZOWwYcN+kOQzzJ07N5544glhAkCemjhxYixYsCDRZxg+fPiPjjjiiJbSBABgV1AAAwCkyBVXXHFyUVFRRVLnr6qqijvvvDNyuZwwASBP5XK5uP3226O6ujqxZygqKmrxm9/85mRpAgCwKyiAAQBS4vzzz+/Xu3fv45J8httvvz0+/PBDYQJAnlu3bl3cfvvtiT5D7969jz///PP7SRMAgJ1NAQwAkALZbDZz6qmn/jyTyST2+m769OkxZ84cYQIAERExe/bsmDFjRmLnz2QyBaeeeurPs9lsRpoAAOxMCmAAgBT44x//eERlZeXgpM6/du3auPfeewUJAPyde+65J9atW5fY+SsrKwf/6U9/+oIkAQDYmRTAAAAJ17dv3+JDDjnkR0k+w9133x01NTXCBAD+Tk1NTdx9992JPsPBBx/8o759+xZLEwCAnUUBDACQcHfdddc3S0pKOiV1/smTJ8e8efMECQB8pLlz58azzz6b2PlLSko63nPPPd+SJAAAO4sCGAAgwb70pS9VDhw48KSkzr9mzZoYP368IAGALXrggQdizZo1iZ2/f//+Jx111FGtJAkAwM6gAAYASLArrrji1MLCwvIkzp7L5eK2226LTZs2CRIA2KJNmzbFbbfdFrlcLpHzFxYWll1++eU/kCQAADuDAhgAIKF+8Ytf9O7evftXkjr/s88+G2+88YYgAYBP5Y033ojnn38+sfN369bt6F/96ld9JAkAwI6mAAYASKgf/vCHP8pkMom8nvvggw/igQceECIAsFXGjRsX69atS+TsmUym4NRTT/2xFAEA2NEUwAAACXTdddcNa9eu3YFJnD2Xy8Udd9wRtbW1ggQAtsqmTZvizjvvTOz8bdq02f+mm27aT5IAAOxICmAAgIQpLS0t+NrXvnZ6Uud/4YUXYuHChYIEALbJq6++GjNmzEjs/Mccc8zpFRUVfiYHAMAO42ITACBhbr/99oMrKip2S+LsGzZsiHHjxgkRAPhM7r///qiqqkrk7OXl5X3/67/+6wgpAgCwoyiAAQASpKKiouCwww47Nanz33vvvYn9YS0A0HRs2LAh7r///sTOf9BBB/1zq1atCiUJAMCOoAAGAEiQ+++//+iysrKeSZx9zpw58dJLLwkRANguXnjhhViwYEEiZy8tLe32xz/+8StSBABgR1AAAwAkRN++fYv33Xfff07i7LW1tXHvvfcKEQDYru6+++6oq6tL5Oz77bffKf379y+RIgAA25sCGAAgIW6++eZRxcXFbZM4+yOPPBJr164VIgCwXa1atSoee+yxRM6ezWbb3njjjV+TIgAA25sCGAAgAYYOHVq21157fSeJs7/33nvxxBNPCBEA2CEmTpwYK1asSOTsQ4YM+c7QoUPLpAgAwPakAAYASIBrr732xKKiosqkzZ3L5eKee+6JxsZGIQIAO0R9fX3cddddkcvlEjd7UVFR5bXXXnuCFAEA2J4UwAAATdwBBxxQMWDAgG8kcfYZM2bEW2+9JUQAYId6880348UXX0zk7AMGDPjG8OHDy6UIAMD2ogAGAGjirrrqqhOKiooqkjb3pk2b4oEHHhAgALBT3H///VFbW5u4uYuKilpcffXV7gIGAGC7UQADADRhBx10UEX//v0Teffvww8/HB9++KEQAYCdYv369TFhwoREzj5w4MBvHHDAARVSBABge1AAAwA0Yf/5n/95bGFhYfOkzb1q1aqYPHmyAAGAnerpp5+O1atXJ27uwsLC8ssuu2yUBAEA2B4UwAAATdQBBxxQMWjQoNFJnP3uu++O+vp6IQIAO1V9fX3cddddiZx99913/+bQoUPLpAgAwGelAAYAaKIuv/zyYwsLC8uTNvfcuXNjwYIFAgQAdokFCxbE3LlzEzd3UVFRi9/97ndflyAAAJ+VAhgAoAkaOnRo2aBBgxL37t+6urr405/+JEAAYJf605/+FHV1dYmbe/fdd//mkCFDSiUIAMBnoQAGAGiCfvOb33ylqKioZdLmfu655xL53j0AIF1Wr14dzz33XOLmLioqann11VcfLUEAAD4LBTAAQBPTq1evZoMHD/5m0uaurq6ORx55RIAAQJPwyCOPRHV1deLmHjJkyLe6deuWlSAAANtKAQwA0MTcdNNNxxQXF7dN2twTJkyIqqoqAQIATUJVVVUifzmtuLi43a233uouYAAAtpkCGACgCWnVqlXhXnvtdVLS5l61alU8++yzAgQAmpTJkyfHqlWrEjf30KFDR7dq1apQggAAbAsFMABAE3LLLbccXlJS0jlpcz/44INRX18vQACgSamvr48HH3wwcXOXlJR0vummmw6VIAAA20IBDADQRGSz2cwBBxzw7aTNvWjRonjppZcECAA0SS+99FIsXrw4cXOPGDHiO9lsNiNBAAC2lgIYAKCJuOaaa/YuLy/vm7S5H3roocjlcgIEAJqkXC6XyLuAy8vL+1111VV7SRAAgK2lAAYAaCK+8pWvfDdpM8+bNy8WLlwoPACgSVu4cGG8+uqrrg8BAMgLCmAAgCbgsssuG1RZWblPkmbO5XIxfvx44QEAifDAAw8k7qklrVu33veSSy7pLz0AALaGAhgAoAkYNWrUCUmbefbs2bFs2TLhAQCJsGzZsnjllVcSN/cJJ5xwovQAANgaCmAAgF3sn//5nzt37NjxiCTN3NjYGA888IDwAIBEGT9+fDQ0NCRq5k6dOn1h9OjRHaQHAMCnpQAGANjFfvSjH30tk8kk6rps2rRpsWrVKuEBAImyatWqeOGFFxI1cyaTKfzpT386SnoAAHxaCmAAgF1o0KBBpX369Plqkmaur6+PCRMmCA8ASKQJEyZEXV1dombu27fvV/r27VssPQAAPg0FMADALnTZZZcdXlRUVJGkmadOnRpr164VHgCQSOvXr48pU6YkauaioqLK3/zmN0dIDwCAT0MBDACwi2Sz2cy+++57UpJmrqurc/cvAJB4jz76aOLuAt5///1PymazGekBAPBJFMAAALvI1VdfPbSsrKx3kmaeMmVKbNiwQXgAQKJt2LAhnn/++UTNXFZW1ueqq67aS3oAAHwSBTAAwC7y5S9/+bgkzVtfXx8TJ04UHACQCo8//nji7gL+0pe+dLzkAAD4JApgAIBdYPTo0R3atm07IkkzT5s2LdatWyc8ACAVPvzww5g+fXqiZm7fvv2I0aNHd5AeAABbogAGANgFfvrTn47KZDKFSZm3vr4+HnnkEcEBAKnyyCOPRH19fWLmzWQyhT/96U+/JjkAALZEAQwAsJN16tQp26dPn6OTNLO7fwGANFq3bl1MmzYtUTP36dPnmE6dOmWlBwDAx1EAAwDsZFddddUB2Wy2dVLmbWxsjEmTJgmOVOvYsWN06OCJmgD5aNKkSdHY2JiYebPZbOurrrrqAMkBAPBxFMAAADvZiBEjvp6keV988cVYtWqV4Ei1Ll26xIUXXhinnXZadO3a1UIA8siqVavipZdecj0JAEBqKIABAHaiM844o3tlZeXeSZk3l8vFxIkTBUdeyGQyMXjw4PjVr34VY8aMcUcwQB55/PHHI5fLJWbeysrKvc8444zukgMA4KMogAEAdqJTTjnlqxGRScq8CxYsiPfee09w5JVMJhN77713XHjhhTFmzJho3769pQCk3HvvvRcLFy5M1B9X/3NdCQAA/4cCGABgJ+nVq1ezXr16fTlJM3v3L/nsr0XwBRdcECeffHK0bdvWUgBSLGnXPb169fpyr169mkkOAIB/pAAGANhJrrjiioOLiopaJmXeBN4JAztEYWFhDB8+PC688MIYPXp0VFZWWgpACi1YsCCWLVuWmHmLiopaXnnllYdIDgCAf6QABgDYSYYPH/6VJM2btHfhwY5WVFQUI0aMiEsuuSRGjx4dLVu2tBSAFMnlcvH4448naub99tvvK5IDAOAfKYABAHaC0aNHd6isrByalHnXrl0bL7/8suDgI/y1CL744ovjhBNOiBYtWlgKQEq89NJLsW7dusTMW1lZudfo0aM7SA4AgL+lAAYA2AlOP/30o5J07fXMM89EQ0OD4GALiouL47DDDouxY8fGqFGjoqyszFIAEq6hoSGeeeaZJI1c8D/XmQAA8P8vEq0AAGDHymazmX79+n05KfPW1tbGlClTBAefUnFxcYwcOTIuvfTSGDVqVJSWlloKQII9//zzUVtbm5h5+/Xr9+VsNpuRHAAAf6UABgDYwX7zm9/sWVJS0jkp886YMSOqq6sFB1uppKQkRo4cGZdcckkcffTRUVJSYikACVRdXR0zZ85M0p8/na+44orBkgMA4K8UwAAAO9gXvvCFLyVl1lwuF08//bTQ4DNo3rx5HHXUUXHJJZfEyJEjI5vNWgpAwjz11FORy+USM++RRx75ZakBAPBXCmAAgB1oyJAhpZ07dz4iKfO+/vrrsWLFCsHBdlBeXh6jRo2KSy+9VBEMkDArVqyI119/PTHzdunS5fD+/ft79AQAABGhAAYA2KHGjh17aGFhYWJeCOruX9j+KioqYtSoUXHxxRfH4YcfHkVFRZYC4LpouyosLGz+H//xHwdLDQCACAUwAMAOteeeex6ZlFnXrl0b8+bNExrsIK1atYrjjz8+LrroohgxYkQUFPh2DKApmzdvXqxZsyYx8+61115HSg0AgAgFMADADnPMMce0bt269b5Jmfe5556LxsZGwcEO1qZNmxg9enRcfPHFimCAJqyxsTGee+65JP35MvyYY45pLTkAAPykAQBgBznzzDMPz2Qyibje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FpafffbZvaQFAJA+CmAAgE9p//3375+EOV9//XVhAXmjvLw8Ro0aFf/+7/8eI0eOjGw2aymA67FP6fOf//xAaQEApI8CGADgU+rRo8fuTX3G2traePvtt4UF5J2KiooYNWpUXHzxxXH44Yc3+XdvAum2ePHiRLySo1evXoOkBQCQPgpgAIBPqXXr1k3+DoklS5ZEQ0ODsIC81apVqzj++OPj4osvjhEjRkRBgW97gZ2voaEhlixZ0uTnbNOmjQIYACCFfCcMAPApDBkypLR58+a9m/qcb775prAAIqJ169YxevToGDt2rCIYcF32MZo3b95n0KBBpdICAEgX3wEDAHwKp556av9MJtPkr53eeustYQH8jTZt2sTo0aPjvPPOi+HDhyuCAddlfyOTyRT84Ac/+Jy0AADSxXe+AACfwuDBg5v84/Hq6+tj0aJFwgL4CJ06dYqTTz45/u3f/i323nvvyGQylgLsUIsXL07Eqzn23HPPgdICAEgXBTAAwKfQpUuXAU19xnfeeSfq6uqEBbAFnTt3jjFjxiiCgR2utrY23n333SRc53oPMABAyiiAAQA+hZYtW/Zv6jN6/DPAp9elS5cYM2ZMnHvuuTF48GALAfL2+iwJ17kAAGwdBTAAwCcYPnx4eUlJSeemPqfHPwNsvV69esVpp50W55xzTvTvrwMB8u/6rLS0tPPw4cPLpQUAkB4KYACAT/Ctb31rt4ho8s8IXbx4sbAAtlGfPn3irLPOinPOOSd22203CwG2i4T8gl7m29/+dj9pAQCkhwIYAOAT7L777k2+CVi7dm1s2LBBWACfUZ8+feLss8+OM888M3r27GkhwGfy4Ycfxrp165r8nAMHDlQAAwCkSJEVAABsWadOnZr8D8TefvttQQFsRwMGDIgBAwbEggULYvz48bF06VJLAbb5Oq1Vq1audwEA2GkUwAAAn6CyslIBDJCnBgwYEP3794958+bFQw89FO+++66lAFtlyZIlsddeezX1613PvgcASBEFMADAFnTq1CnbvHnzXk19ziVLlggLYAfJZDIxePDg2GOPPeLll1+OBx98MFauXGkxQGqu05o3b967Xbt2RatXr66XGABA8nkHMADAFowZM6ZnJpPJNuUZGxsbPZoUYCfIZDKx9957x4UXXhhjxoyJ9u3bWwrwiZYuXRqNjY1NesaCgoLsqaee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k8nE7NmzY+LEibFmzRoNAXif/VNSzJo161kTAwBongTAAAC70O233/7KOeecszU/P78022sdMGBAtG/f3tWu0My9+uqrMWnSpFi1apVmALyPjh07xgEHHJCIWhsbG6u/8Y1v/NXUAACaJwEwAMAutHLlyob169fP6tat2+hsrzWVSsXhhx8ekyZNMjhohubMmROTJ0+OJUuWaAbAh3D44YdHKpVKRK3r16+fVVFR0WhqAADNU54WAADsWq+++mpirts77LDDDAyamTfffDP+/d//PX7yk58IfwE+pFQqFSNGjEhMva+88sozpgYA0Hw5AQwAsIvddNNNz5166qnV+fn5rbO91m7dukX//v1j4cKFBgc5btmyZfHYY4/F/PnzNQPgIzrggAOic+fOiai1sbFxy4033jjL1AAAmi8BMADALrZy5cqG8vLyGT179vx0Euo9+uijBcCQw5YvXx7jxo0T/AJ8wv1SUpSXlz9TXl7eYGoAAM2XABgAYDeYMWPGUxdccEEiAuAhQ4ZE69ato7q62uAgh6xcuTImTJgQc+fOjUwmoyEAH1ObNm3i0EMPTUy9zz777FOmBgDQvPkGMADAbvDVr371lYaGhk1JqLWgoCCOOOIIQ4McsW7duvj5z38ed955Z8yZM0f4C/AJjRw5MvLz8xNRa0NDw8abbrrpVVMDAGjenAAGANgNKisrm1atWjW9T58+5ySh3qOPPjqefPJJQREk2Pr16+Oxxx6L2bNn+3cZYBdJpVIxatSoxNS7cuXKadXV1WmTAwBo3pwABgDYTaZNm5aY6/c6duwYAwYMMDRIoA0bNsSvf/3r+Nd//dd49dVXhb8Au9CAAQOiY8eOian36aefftLUAAAQAAMA7CZf+9rX5tTX11ckpd6jjjrK0CBBqqqq4v77749vf/vb8eKLL0ZTU5OmAOxiRx55ZGJqra+vX/eNb3zjdVMDAMAV0AAAu0ltbW16xYoVT++///6fT0K9hx56aLRt2zaqqqoMD7LYli1bYsqUKfHcc8/F9u3bNQRgN2nbtm0MGTIkMfUuX778qdraWtc/AwDgBDAAwO70xz/+cUJSas3Pz4/jjjvO0CBL1dTUxKOPPhq33XZb/OUvfxH+Auxmxx57bOTn5yel3Myvf/3rCaYGAECEABgAYLe66667llZXV89PSr1HH310tGjRwuAgi7wd/H7jG9+IqVOnRn19vaYA7GYtWrSIo48+OjH1btmy5Y177rlnhckBABDhCmgAgN3u9ddfn3T44YcPSEKtxcXFcdhhh8XMmTMNDvayurq6ePrpp2PatGmxbds2DQHYgw477LAoKSlJTL3z5s17wtQAAHibE8AAALvZ9773vanpdLohKfWecMIJkUqlDA72koaGhpg6dWrceuut8fjjjwt/AfawVCoVJ5xwQmLqTafT27/73e8+ZXIAALzNCWAAgN1s+vTpWyoqKmZ26dIlER/Y7d69e/Tv3z/efPNNw4M9qKGhIaZNmxZPPfVUVFdXawjAXnLAAQdE9+7dE1NvRUXFczNmzPAXBwAA/+QEMADAHjBr1qxEXcuXpFMvkHTpdDqee+65uP322+PRRx8V/gLsZccff3yi6p0xY8YkUwMA4J2cAAYA2AO++tWvvnT66adXFRYWtk1CvQMHDoyOHTvGhg0bDA92k3Q6HbNmzYrJkyfHxo0bNQQgC3Ts2DEGDhyYmHobGhoqb7755pdMDgCAd3ICGABgDygvL29YsWLF1MRsEvPy4sQTTzQ42A3S6XS8+OKL8Z3vfCfuv/9+4S9AFjnppJMiLy85r8tWrFgxpaKiotHkAAB4JwEwAMAe8qtf/erRiMgkpd6jjjoqysrKDA52kUwmE6+++mp873vfi1//+texdu1aTQHIImVlZXHUUUcl6q+W//7v//6zyQEA8G4CYACAPeQ///M/l1dWVv4tKfUWFhbGMcccY3CwC7wd/P785z+PNWvWaAhAFjruuOOioCA5X0urqqqa/dOf/nS1yQEA8G4CYACAPeill14al6R6jzvuuCgqKjI4+JjmzJkTd911V/z85z+P1au9owfIVkVFRYn7xbcXXnhhnMkBALAzBVoAALDnjB079pkFCxZUFhYWtktCvSUlJXHEEUfE9OnTDQ8+gjfffDPGjx8fb731lmYAJMCRRx4ZJSUliam3oaFh0zXXXPOsyQEAsDMCYACAPai8vLxh6dKlE/v3739xUmo+8cQT49lnn410Om2A8AEWLVoUjz32WCxevFgzABIiLy8vTjzxxETVvGTJkifKy8sbTA8AgJ3ucbUAAGDP+u1vfzsxIjJJqbdjx44xdOhQg4P3sXz58rj77rvjRz/6kfAXIGGGDRsWHTp0SFLJmd/85jePmxwAAO9FAAwAsIf953/+5/JNmza9kqSaTz/99EilUoYH77Jy5cr4yU9+Et///vdj/vz5GgKQMHl5eXHGGWckquZNmza9fM8996wwPQAA3osroAEA9oKXXnpp/KmnnnpYUurt2rVrDBkyJGbPnm14EBHr1q2L8ePHx+zZsyOTyWgIQEINHTo0OnfunKiaX3jhhQkmBwDA+xEAAwDsBZdffvkzS5YsWVdUVNQlKTWfccYZ8be//U3YRbO2fv36eOyxxwS/ADkglUrF6aefnqia6+rq1lx22WXTTQ8AgPcjAAYA2AsqKyub5s+f/8ihhx56dVJq7tatm1PANFsbNmyIxx9/PF555ZVoamrSEIAc8KlPfSq6du2aqJrfeOONcdXV1WnTAwDg/fgGMADAXvL1r399XDqdrktSzb4FTHNTVVUV999/f3z729+OF198UfgLkCNSqVR8+tOfTlTN6XS69pvf/OZjpgcAwAdxAhgAYC+ZMWNG9Zo1a/7Ss2fPxLx97N69ewwcODDmzJljgOS0LVu2xIQJE+KFF16IxsZGDQHIMYceemh069YtUTWvXr36qRkzZlSbHgAAH8QJYACAvejXv/71HyMiUR8SPeuss5wCJmdt27YtHn300bjtttviueeeE/4C5KC8vLwYM2ZM0srO/OpXv/qT6QEA8KH2vFoAALD3fP/733+rqqoqUR/V7dGjR3zqU58yPHJKfX19TJ06Nb71rW/F1KlTo76+XlMActSIESOiS5cuiap506ZNf73rrruWmh4AAB+GABgAYC975plnHkpazWeccUbk5dlKkjvmzZsXjz76aGzdulUzAHJYQUFBnH766Ymre9q0aQ+aHgAAH5a3dgAAe9nYsWNn1tfXr01SzZ07d47DDjvM8ACARBk5cmR06NAhUTXX1dWtHjt27POmBwDAhyUABgDYyyorK5tee+21Pyat7jPPPDMKCgoMEABIhBYtWiTy9O/s2bP/UF1dnTZBAAA+LAEwAEAWuOqqqyY0NjZWJanm9u3bx9FHH214AEAiHHfccdGmTZtE1dzQ0LDxiiuumGh6AAB8FAJgAIAssGDBgrqFCxc+lrS6R48eHYWFhQYIAGS1li1bxsknn5y4uhcuXDhu6dKl200QAICPQgAMAJAlvv71r/8pnU7XJqnmtm3bximnnGJ4AEBWO+2006K0tDRRNTc1NdV+7Wtfe8j0AAD4qATAAABZ4umnn968fPnyxF3xN3r06GjXrp0BAgBZqUOHDnH88ccnru5ly5ZNmD59+hYTBADgoxIAAwBkkbvvvvtPmUymKUk1FxYWxumnn254AEBWOvPMMxP3yYpMJtN41113/dH0AAD4OATAAABZ5Be/+MWatWvXTkta3UcccUT06tXLAAGArNK7d+847LDDEld3eXn5X+6///51JggAwMchAAYAyDIPP/zwn5JWcyqVijPPPNPwAICsMmbMmEilUomr+8EHH/yT6QEA8HEJgAEAsszXv/71NzZs2DAraXUPHDgwDj74YAMEALLCoEGDYsCAAYmru6KiYuatt966wAQBAPi4BMAAAFlo3Lhxv01i3WPGjIm8PFtMAGDvysvLizFjxiSy9j//+c+/NUEAAD7RflgLAACyz/XXXz+nqqrqr0mru1evXnHUUUcZIACwVx1zzDHRvXv3xNW9adOmV2666aa5JggAwCchAAYAyFJ/+tOf7k1i3WPGjInS0lIDBAD2ijZt2sRZZ52VyNofeOCBe00QAIBPSgAMAJClbrrpprlJPAVcXFwcZ555pgECAHvFWWedFS1btkxc3Zs2bXrl5ptvnmeCAAB8UgJgAIAsNm7cuF8lse5Ro0ZF7969DRAA2KP69OkTI0eOTGTtjz322K9MEACAXUEADACQxcaOHTu7qqrqb0mrO5VKxfnnnx+pVMoQAYA9tv/4/Oc/n8j9R2Vl5d+uueaav5kiAAC7ggAYACDLTZ069bdJrLtv374xZMgQAwQA9ojDDjsssTeQTJ48+TcmCADAriIABgDIcpdeeumLVVVVryax9s9//vNRXFxsiADAblVaWhrnn39+Imuvqqr66+WXX/6SKQIAsKsIgAEAEuChhx76WRLrLisri9NPP90AAYDd6qyzzoqSkpIklp753e9+91MTBABgVxIAAwAkwA033DB3w4YNs5JY+3HHHRd9+vQxRABgt+jbt28cddRRiay9oqJi1te//vU3TBEAgF1JAAwAkBA///nPfxoR6aTVnUql4vOf/3zk5dl6AgC7Vn5+flx00UWRSqWSWH76F7/4xX+bIgAAu5q3cAAACXHHHXe8tW7duulJrL13795xzDHHGCIAsEudcMIJ0b1790TWXl5e/pc77rjjLVMEAGBXEwADACTI3XfffW8mk2lKYu1nnXVWtG3b1hAB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onv37vEv//IvccABBzSrdWcymaYnnnji9s997nPPeAoAAODDEQADAJBYDz/88NJjjjlmY+/evY+KiGZzFKq0tDSGDx8eq1evjvXr13sQAHLcwIED45prrol27do1t6VnZsyY8YOzzjprqqcAAAA+PAEwAACJdv/99795zDHHVO6zzz5HRDMKgVu0aBGHHXZYtGzZMhYuXBjpdNrDAJBjCgoK4pxzzonzzz8/WrRo0dyWn37uuefuOuWUUyZ4EgAA4KMRAAMAkHi///3v5w8bNmxF3759j2lO10GnUqno27dvDB06NBYvXhxbtmzxMADkiJ49e8YNN9wQgwcPblbf+434x7XPU6ZM+fbpp58+2ZMAAAAfnQAYAICc8OCDDy4ZNmzYin79+jWrEDgionXr1nHEEUdEfX19LF261MMAkGCpVCpOOOGEuOKKK6JNmzbNbv07wt9vnXPOOX/xNAAAwMcjAAYAIGc89NBDS4YNG7a8X79+xza3EDg/Pz8OPvjg6NWrV8yfPz8aGho8EAAJU1JSEpdffnmccMIJkZ+f3+zWn8lkGp944olvffazn53maQAAgI9PAAwAQE556KGHlo4cOXJdnz59RqWa252ZEdG1a9cYNmxYLFu2LCorKz0QAAnRt2/fuO6662K//fZrluvPZDLpp59++rvnnHPO054GAAD4ZATAAADknD/96U+LDj300KX7779/s7sOOiKiuLg4jjzyyCgpKYk333wz0um0hwIgSxUUFMRnP/vZuPDCC6OkpKRZ9iCdTjc88sgjt5x//vnTPREAAPDJCYABAMhJDz/88NId3wQelUqlmt09mqlUKvr06RMHH3xwLFy4MLZt2+ahAMgynTt3jrFjx8bQoUOjGV5aERH/CH+feOKJ2y+88MLnPBEAALBrCIABAMhZDz300JIePXq8NmjQoGPz8vJaNMcetG3bNkaNGhVNTU2xZMkSDwVAFkilUjF69Oi48soro0OHDs22D01NTdt++9vf/stll132oqcCAAB2HQEwAAA5bdKkSeXdu3efM3jw4GYbAufn58eAAQOiV69esWDBgti+fbsHA2Avad26dVx66aVx/PHHR35+frPtQ2NjY/WvfvWrf7nuuute81QAAMCuJQAGACDnTZ48eW1jY+OMI4444uiCgoKS5tqHrl27xqhRo2Lbtm2xcuVKDwbAHpRKpWLUqFExduzY6NWrV7PuRX19/fo77rjjK9/61rcWejIAAGDXEwADANAsPP/881UbNmx45rjjjjuqsLCwrLn2obCwMAYNGhT77bdfLF68OGpraz0cALtZ+/bt44orrogTTzwxCgub9/uU2tralTfffPPVP/nJT1Z7MgAAYPcQAAMA0Gz87W9/27p27doZJ5xwwsjCwsK2zbkXnTp1ipEjR0Z1dbXTwAC70ciRI+Pqq6+OHj16NPte1NTULL/hhhuu/e1vf7vOkwEAALuPABgAgGbltdde2zpv3rynTznllKFFRUWdmnMvCgsL49BDD4399tsvFi1a5DQwwC709qnfk08+udmf+o2I2Lx587yLL774unHjxm30dAAAwO71fgFwat9zYsTOftC4LmLjq610DwCAxOrVq1fhs88++69du3Y9QTciGhoaYurUqTF58uRobGzUEICPqaCgIE499dQYPXq04HeH8vLyp4499tjvrly5skE3AABg9+swrDYKuuz8ZwJgAAByWuvWrfNeeumlm/fdd9+zdeMfVq9eHffff38sWbJEMwA+ov322y8uuugi1z2/w8KFC38/fPjwnzY0NGR0AwAA9gwBMAAAzd7zzz9/8aGHHnp1RKR0IyKTycTMmTPjz3/+c9TV1WkIwAcoKSmJ8847L0aMGBGplL9Kdki//PLL9xx77LEPagUAAOxZ7xcA+wYwAADNwn333Tfn+OOP39yrV6/DQwgcqVQqevfuHcOHD49169ZFRUWFhwTgPRxyyCExduzY6N+/v/B3h0wm0/jMM8/828knnzxONwAAYM97v28AC4ABAGg2fve7370xePDgJf369Ts6lUrl60hEcXFxjBgxInr06BFLly6N2tpaTQHYoUOHDvGFL3whzjzzzCguLtaQHZqammoeeOCBWz73uc9N1w0AANg7BMAAALDDww8/vKygoOC54cOHH1FQUFCqI//QrVu3OO6446K0tDQWL14cTU1NmgI0Wy1btoxzzjknLr300ujevbuGvENtbe2K22677arbbrvtDd0AAIC9RwAMAADv8Oyzz25avHjx0yeddNKQoqKiTjryD3l5edGnT58YOXJkbN26NVatWqUpQLNz+OGHx1e+8pUYMGBA5OXlacg7VFVV/e3CCy+8/oEHHvDdAAAA2MsEwAAA8C7z58+vefbZZ58+44wz+hcX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OigOOOCAKCoq0pQs0djYuGXmzJk/PvPMMyc2NDS4XgAAAPjQBMAAAJADjjzyyNY/+9nPrujbt++5EZGnI9mluro6Fi5cGPPnz4958+ZFZWWlprBXtGvXLg455JAYMGBA9O/fP1q39nsjWSj91ltv/fmqq676xaxZs6q1AwAA+KgEwAAAkEN++ctfjhgzZsyNrVq16q0b2SmdTsfKlStj0aJFsXDhwli8eHFs27ZNY9gtSkpKol+/ftG/f//Yf//9o1evXpGX53dEslVNTc3yRx999EdXXnnlK7oBAAB8XAJgAADIMd26dSt8+OGHPzd48ODL8vPzbdyzXCaTiTVr1sTChQtj0aJFsWjRotiyZYvG8LGUlZVF//79/xn6du/ePVKplMZkuaampprXXnvtV2PGjHmgoqKiUUcAAIBPQgAMAAA56rjjjiv7r//6r8tdC508mzdvjuXLl8eKFSti+fLlsXjx4qipqdEY/pfi4uLo169f9O7dO/bZZ5/Yd999o6ysTGMSJJPJpJcsWfLn66677pfTp0/3mx8AAMAuIQAGAIAc99Of/nTIueeee3NpaWlf3UimxsbGWLlyZSxdujSWLVsWy5cvj3Xr1kUmk9GcZiKVSkWXLl1in332iT59+kSfPn2iV69eUVBQoDkJtXXr1sUPPvjgj6699tq/6wYAALArCYABAKAZaNeuXf64cePOGTp06BUFBQWtdST56uvrY+XKlf88KbxixYpYu3ZtpNNpzUm4vLy86Nq1a+yzzz7//KdXr17RsmVLzckBjY2NW/7617/+4pxzznm0srKySUcAAIBdTQAMAADNyIknntjmnnvuuXzfffcdk0qlHB3MMdu3b481a9bEmjVrYu3atbF27dooLy+PDRs2CIazUF5eXnTs2DG6desWXbt2jW7dukW3bt2iR48eUVhYqEE5JpPJNC5ZsuRR1z0DAAC7mwAYAACaoa9+9av7Xnfdddd16NDhCN3IfY2Njf8MhNetWxfr1q2LioqKWLduXWzbtk2DdrPS0tLo3LnzP//p0qVLdO3aNbp27eoK52Ziw4YNM//rv/7rxz/60Y+W6wYAALC7CYABAKAZ++UvfznirLPOuq64uNj3gZupmpqaWL9+/T//qaioiMrKyqisrIxNmzZFY2OjJn2AgoKCaN++fbRr1y7at28fHTt2jC5dukSnTp2ic+fOUVxcrEnN1NatW98aP378PVdcccXLugEAAOwpAmAAAGjm2rVrl//ggw+eOWLEiCsLCwvb6gjvtHnz5n+GwZs2bYrKysqorq6OLVu2xJYtW6K6ujqqq6sjk8nk3NpTqVS0bt06WrduHWVlZdGmTZsoLS39X2Fvu3btok2bNh4U/peGhobKl1566efnnHPO+OrqavevAwAAe5QAGAAAiIiIoUOHFt97770XHHjggRfk5+c7ssiHlk6n/xkEV1dXR01Nzfv+k8lkora2NtLpdNTX10dTU1PU1dXt0u8U5+XlRcuWLSM/Pz+KiooiLy8vWrVqFalUKoqLi3f6T0lJSbRq1eqfgW9paWnk5eUZMB9aU1NTzYIFC/745S9/+Y+zZ8+u0REAAGBvEAADAAD/y2mnndb2rrvuurRPnz5n5+XlFeoIe9LbgfDbtm/f/r7XUBcUFESLFi3++b/fDnxhT8pkMg1LliwZd8stt/xq0qRJVToCAADsTQJgAABgp0477bS2d95554X777//5wTBAP9XJpNpWLhw4QO33nrrHwS/AABAtni/ADi/7UHRc2c/SG+LqC33/gcAAHLZokWL6u69995X0un0swcddFCnkpKS3roC8A8VFRUz/7//7/+77aKLLpq6aNGiOh0BAACyRXH3xsgr3fnPBMAAAEDMnDmz8u67736qqalpWr9+/Ypbt27dN5VKpXQGaG4ymUx6zZo1U+65555/Peeccx6cOXNmpa4AAADZRgAMAAB8KDNnzqz88Y9//Gw6nZ4uCAaak7eD37vvvvtfzz///McEvwAAQDYTAAMAAB+JIBhoLgS/AABAEgmAAQCAj+XtILisrOyFvn37diwuLu4VEYJgIBdkKioqnrv33nu/PWbMmEcEvwAAQJK8XwCc2vecGLGzHzSui9j4aivdAwAA/unqq6/u8ZWvfOX8Pn36nJWXl9dCR4CkSafT9UuXLh3/X//1Xw/84he/WKMjAABAEnUYVhsFXXb+MwEwAADwkZ1xxhntb7/99rMPPPDA8/Pz81vrCJDtmpqaqhcsWPDgd77znUcmTpzotC8AAJBoAmAAAGC3GD58eMkPf/jDzwwePPjioqKijjoCZJv6+voNr7322u9vvPHGx2fPnl2jIwAAQC4QAAMAALvV0KFDi++5556zDjnkkPOKioq66giwt9XV1a19/fXXH7z++uvHC34BAIBcIwAGAAD2iFatWuXdc889w0455ZTzO3bseJSOAHtYZsOGDbOmTJny4PXXX/9qbW1tWksAAIBcJAAGAAD2uH/913/tf/7555/dq1ev0/Ly8lroCLC7pNPp+pUrV05+4IEHHvnOd76zSEcAAIBcJwAGAAD2mjPOOKP97bfffvYBBxzw2YKCgjY6AuwqjY2NVW+++eafv/e97z06YcKETToCAAA0FwJgAABgrxs+fHjJ97///dGDBg0aU1paur+OAB9XdXX1wtdee+3Rr371q1Nfe+21Wh0BAACaGwEwAACQVb761a/ue8EFF3y6b9++ZxUUFLTWEeCDNDY2bnnrrbfG/+EPf5j4ox/9aLmOAAAAzZkAGAAAyEpDhw4t/sEPfnDy4MGDz27dunV/HQHerbq6+s2XX375weuuu+7ppUuXbtcRAAAAATAAAJDlCgsLU3ffffeQ0aNHn9G1a9fj8vLyinQFmq90Ol1XXl4+bcqUKROuvfbav+sIAADA/yYABgAAEqNPnz4t/v3f/33UyJEjz2rfvv2nIiKlK9AsZDZt2vTXF1544bGvfe1rzzntCwAA8N4EwAAAQCJddNFFXa6++uqTDzzwwLNbtmzZTUcg99TV1a1ZsGDBuJ/+9KdP3n///et0BAAA4IMJgAEAgETr1q1b4d13333k4YcffmqHDh2OyMvLK9QVSK50Ot2wcePGWbNmzZp8/fXXz6qoqGjUFQAAgA9PAAwAAOSMo48+uvWtt956/CGHHHJKu3btBkdEnq5AIqQrKytfmzdv3uQ777xz+owZM6q1BAAA4OMRAAMAADnpuOOOK/vGN75x/CGHHHJa27ZtB4bvBUO2yVRVVc2dN2/epO9///vTpk+fvkVLAAAAPjkBMAAAkPNuu+22vmedddZJffr0Oa5Vq1a9dQT2ntra2uXLly+f/uijjz51xx13vKUjAAAAu5YAGAAAaFa+9KUvdbv44ouP7t+//wlOBsMekamqqpq7cOHCv/z+97+fcd9995VrCQAAwO4jAAYAAJqtSy65pOtll112jDAYdrl0VVXVvIULF/7lV7/61bO/+93v1moJAADAniEABgAAiIirr766x/nnnz9q//33P7JNmzZDUqlUga7Ah5fJZBoqKyv/vnjx4uf+9Kc/zbr33ntX6woAAMCeJwAGAAB4l379+hV97WtfGzRy5MhRPXv2PLaoqKizrsD/VV9fv37VqlXPvPDCC8/9+7//+5zFixfX6woAAMDeJQAGAAB4H61bt8678847Bx599NFHde/efURpaen+4apomq/M1q1bF69Zs+bF5557btY3v/nNOdXV1WltAQAAyB4CYAAAgI9g8ODBrcaOHXvI8OHDD+vevfvw1q1bHxACYXJXprq6+s01a9a88sorr7z8k5/8ZN5rr71Wqy0AAADZSwAMAADwCVx//fX7nHHGGYf169dvePv27Yfm5+e31hWSrLGxsXrjxo2vvvXWWy+PHz/+lR//+McrdQUAACA5BMAAAAC70Je//OUe55xzzvA+ffoM7tix45CioqKuukI2q6+vX7t27doXFy9ePGfixImv3Xvvvat1BQAAILkEwAAAALvRl7/85R6f+cxnBvfr129Qly5dDm/ZsqVAmL2qrq5u7bp16wS+AAAAOUoADAAAsIe0atUq75prrtnn2GOPPXi//fY7uH379oeUlpb2TaVS+brDbpKuqalZtnHjxnlvvfXW3GeffXbef/3Xfy2vra1Naw0AAEBuEgADAADsRQceeGDLq6+++oAhQ4Yc3LNnz4Pbtm17sGuj+biampqqq6qqXi8vL583Z86ceb/85S/nvfjii1t1BgAAoPkQAAMAAGSZoUOHFn/xi1/cf9CgQQf26NHjwHbt2h3YqlWr3qlUKk932CFdU1OzvLKycsHq1asXzJkzZ8Gf//znJTNmzKjWGgAAgOZNAAwAAJAAxx13XNkFF1xw4MEHH3xA165dDywtLd23pKRkn1QqVag7uS2TyTRs27ZtRXV19dJ169YtfOONNxZOmDBh4YQJEzbpDgAAAO8mAAYAAEiw8847r+OJJ57Yp3///vt16dKlT5s2bfZr3bp1v/z8/GLdSZampqaa6urqxZs3b16ybt26pQsXLlzy9NNPL33ooYc26A4AAAAflgAYAAAgx7Rr1y7/kksu6TFkyJCe++67b89OnTr1Kisr61VcXNyzZcuW3VKpVL4u7R2ZTKaprq6uvKamZtWWLVtWVlRUrFy6dOnK2bNnr7r//vvXVFZWNukSAAAAn4QAGAAAoBnp1KlTwec+97luQ4cO7bnPPvv0aNeuXafWrVt3Li4u7tqyZcvORUVFnfLy8lro1MeTTqe319fXr6+rq6uoqalZW11dvb6y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AACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoIQADAAAAAAAAlBCAAQAAAAAAAEoIwAAAAAAAAAAlBGAAAAAAAACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoIQADAAAAAAAAlBCAAQAAAAAAAEoIwAAAAAAAAAAlBGAAAAAAAACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoIQADAAAAAAAAlBCAAQAAAAAAAEoIwAAAAAAAAAAlBGAAAAAAAACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoIQADAAAAAAAAlBCAAQAAAAAAAEoIwAAAAAAAAAAlBGAAAAAAAACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoIQADAAAAAAAAlBCAAQAAAAAAAEoIwAAAAAAAAAAlBGAAAAAAAACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoIQADAAAAAAAAlBCAAQAAAAAAAEoIwAAAAAAAAAAlBGAAAAAAAACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoIQADAAAAAAAAlBCAAQAAAAAAAEoIwAAAAAAAAAAlBGAAAAAAAACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoIQADAAAAAAAAlBCAAQAAAAAAAEoIwAAAAAAAAAAlBGAAAAAAAACAEgIwAAAAAAAAQAkBGAAAAAAAAKCEAAwAAAAAAABQQgAGAAAAAAAAKCEAAwAAAAAAAJQQgAEAAAAAAABKCMAAAAAAAAAAJQRgAAAAAAAAgBICMAAAAAAAAEAJARgAAAAAAACghAAMAAAAAAAAUEIABgAAAAAAACghAAMAAAAAAACUEIABAAAAAAAASgjAAAAAAAAAACUEYAAAAAAAAIASAjAAAAAAAABACQEYAAAAAAAAoIQADAAAAAAAAFBCAAYAAAAAAAAoMY3JP//9K8My551lzpAk293a7QAAAAAAAAD8iIw3r+SL7TpPxuSt4/ibJJuz20QDBgAAAAAAAHhzrJPp6NvHYcyyjLl7dJTPbl/Jp6sPLufSsM+5ec7q5YOrF0OeP/SVaAAAAAAAAIA3weH7u6zfm79dWDIMSw6225w785vsx3XyzasOby5ssz69c4sAAAAAAAAAr9n69C6bC9sT93a7rKdnORin5Otxynzi1JQcfiwCAwAAAAAAALxO69O7HH68TaaT98cp85R8vbp3Nfszv8q0LHn7xMF1sjk/ZzUPmZ/MmWefhAYAAAAAAAD4oayPdjn7223Gn7x6ZrXPnetX8mBKkpv3cufDd/Pufn5FL56SzcVtNheT3dNt8tQlAwAAAAAAAHyv1sm0ySv/9XtsNWZ3I/lHkgzHi7/4XY7WYz5yiwAAAAAAAAA/Ivtcv/3nPEyS1fHa42t5+vNLyX7JoRsCAAAAAAAAePPt1/nbV3/KvePn1Xc371/NYxEYAAAAAAAA4M0yTHk2rvNo2WdzvHZqzN9v/SF3vju3evng/at5fPDLPDu1yuGyZHSVAAAAAAAAAK/XOGe4ueSvZ4e8M8xZbVe5ceuPufvy3Oqkw4+v5emDX+fuuTlLhhwsEYIBAAAAAAAAXpclGR8OuXP0TR4cPM/9z/+SRyfNDf/1TZezOp/87KdjzizJZkhO7edMy/w/nAUAAAAAAADg/zaMWcZkP8/ZLsmLacr2/MV8+cnvs/tP5/4FmLjAq1ifcioAAAAASUVORK5CYII=";
|
|
3816
3972
|
//#endregion
|
|
3817
3973
|
//#region src/gen-utils.ts
|
|
@@ -3819,27 +3975,20 @@ const IMG_PLAYBTN = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAB4AAAAVnCAYAA
|
|
|
3819
3975
|
* PptxGenJS: Utility Methods
|
|
3820
3976
|
*/
|
|
3821
3977
|
/**
|
|
3822
|
-
*
|
|
3823
|
-
* -
|
|
3824
|
-
*
|
|
3825
|
-
* -
|
|
3826
|
-
* -
|
|
3827
|
-
* @param {
|
|
3828
|
-
* @param {'X' | 'Y'} xyDir -
|
|
3829
|
-
* @param {PresLayout} layout - presentation layout
|
|
3830
|
-
* @returns {
|
|
3978
|
+
* Resolve a user `Coord` (x/y/w/h) to EMU — the single user-coordinate → EMU boundary.
|
|
3979
|
+
* - bare `number` → **inches** (no magnitude guessing); `"<n>%"` → percent of the slide axis;
|
|
3980
|
+
* `"<n>in"`/`"<n>pt"`/`"<n>emu"` → explicit units (see {@link Coord} / {@link coordToEmu})
|
|
3981
|
+
* - `null`/`undefined` → 0 (callers may omit a coordinate)
|
|
3982
|
+
* - throws on a non-finite number rather than silently collapsing the object to zero size
|
|
3983
|
+
* @param {Coord|null|undefined} size - user coordinate
|
|
3984
|
+
* @param {'X' | 'Y'} xyDir - axis (selects slide width vs height for percentages)
|
|
3985
|
+
* @param {PresLayout} layout - presentation layout (EMU dimensions)
|
|
3986
|
+
* @returns {Emu} resolved EMU value
|
|
3831
3987
|
*/
|
|
3832
3988
|
function getSmartParseNumber(size, xyDir, layout) {
|
|
3833
|
-
if (
|
|
3989
|
+
if (size === null || size === void 0) return 0;
|
|
3834
3990
|
if (typeof size === "number" && !isFinite(size)) throw new Error(`Invalid ${xyDir || "coordinate"} value: expected a finite number but received ${String(size)}. This usually means a layout dimension was read from a missing property (e.g. \`layout.width\` returning \`undefined\`). Use \`slide.width\`/\`slide.height\` or \`STANDARD_LAYOUTS.<NAME>.width\`/\`.height\` (inches).`);
|
|
3835
|
-
|
|
3836
|
-
if (typeof size === "number" && size >= 100) return size;
|
|
3837
|
-
if (typeof size === "string" && size.includes("%")) {
|
|
3838
|
-
if (xyDir && xyDir === "X") return Math.round(parseFloat(size) / 100 * layout.width);
|
|
3839
|
-
if (xyDir && xyDir === "Y") return Math.round(parseFloat(size) / 100 * layout.height);
|
|
3840
|
-
return Math.round(parseFloat(size) / 100 * layout.width);
|
|
3841
|
-
}
|
|
3842
|
-
return 0;
|
|
3991
|
+
return coordToEmu(size, xyDir === "Y" ? layout.height : layout.width);
|
|
3843
3992
|
}
|
|
3844
3993
|
/**
|
|
3845
3994
|
* Basic UUID Generator Adapted
|
|
@@ -3912,14 +4061,16 @@ function getDuplicateObjectNames(names) {
|
|
|
3912
4061
|
return Array.from(dupes);
|
|
3913
4062
|
}
|
|
3914
4063
|
/**
|
|
3915
|
-
* Convert inches into EMU
|
|
3916
|
-
*
|
|
3917
|
-
* @
|
|
4064
|
+
* Convert inches into EMU.
|
|
4065
|
+
* - accepts a number (inches) or a numeric/`"<n>in"` string
|
|
4066
|
+
* - no magnitude guessing: values are always treated as inches (use {@link coordToEmu} for
|
|
4067
|
+
* user coordinates that may carry other units)
|
|
4068
|
+
* @param {number|string} inches - inches as number or string
|
|
4069
|
+
* @returns {Emu} EMU value
|
|
3918
4070
|
*/
|
|
3919
4071
|
function inch2Emu(inches) {
|
|
3920
|
-
if (typeof inches === "number" && inches > 100) return inches;
|
|
3921
4072
|
if (typeof inches === "string") inches = Number(inches.replace(/in*/gi, ""));
|
|
3922
|
-
return
|
|
4073
|
+
return inchesToEmu(inches);
|
|
3923
4074
|
}
|
|
3924
4075
|
/**
|
|
3925
4076
|
* Convert `pt` into points (using `ONEPT`)
|
|
@@ -3931,6 +4082,33 @@ function valToPts(pt) {
|
|
|
3931
4082
|
return isNaN(points) ? 0 : Math.round(points * ONEPT);
|
|
3932
4083
|
}
|
|
3933
4084
|
/**
|
|
4085
|
+
* Convert a transparency percentage (0-100) into a schema-valid `<a:alpha>` value
|
|
4086
|
+
* (ST_PositiveFixedPercentage, 0-100000). Out-of-range transparency yields an
|
|
4087
|
+
* alpha that PowerPoint rejects as needing repair, so clamp into range and warn.
|
|
4088
|
+
*/
|
|
4089
|
+
function transparencyToAlpha(transparency) {
|
|
4090
|
+
const pct = Math.min(100, Math.max(0, transparency));
|
|
4091
|
+
if (pct !== transparency) console.warn(`Warning: transparency ${transparency} is outside the valid range 0-100; using ${pct}.`);
|
|
4092
|
+
return Math.round((100 - pct) * 1e3);
|
|
4093
|
+
}
|
|
4094
|
+
/** Convert an opacity (0-1) into a schema-valid `<a:alpha>` value (0-100000); clamps + warns on out-of-range input. */
|
|
4095
|
+
function opacityToAlpha(opacity) {
|
|
4096
|
+
const o = Math.min(1, Math.max(0, opacity));
|
|
4097
|
+
if (o !== opacity) console.warn(`Warning: opacity ${opacity} is outside the valid range 0-1; using ${o}.`);
|
|
4098
|
+
return Math.round(o * 1e5);
|
|
4099
|
+
}
|
|
4100
|
+
/**
|
|
4101
|
+
* Convert a line width (points) to EMU clamped into ST_LineWidth (0..20116800 EMU,
|
|
4102
|
+
* i.e. 0-1584pt). Out-of-range widths make PowerPoint report the package as needing
|
|
4103
|
+
* repair, so clamp into range and warn.
|
|
4104
|
+
*/
|
|
4105
|
+
function lineWidthToEmu(widthPts) {
|
|
4106
|
+
const raw = valToPts(widthPts);
|
|
4107
|
+
const clamped = Math.min(20116800, Math.max(0, raw));
|
|
4108
|
+
if (clamped !== raw) console.warn(`Warning: line width ${widthPts} is outside the valid range 0-1584pt; using ${clamped / ONEPT}.`);
|
|
4109
|
+
return clamped;
|
|
4110
|
+
}
|
|
4111
|
+
/**
|
|
3934
4112
|
* Convert degrees (0..360) to PowerPoint `rot` value
|
|
3935
4113
|
* @param {number} d degrees
|
|
3936
4114
|
* @returns {number} calculated `rot` value
|
|
@@ -3978,8 +4156,10 @@ function createColorElement(colorStr, innerElements) {
|
|
|
3978
4156
|
}
|
|
3979
4157
|
let colorVal = (colorStr || "").replace("#", "");
|
|
3980
4158
|
if (/^[0-9a-fA-F]{8}$/.test(colorVal)) {
|
|
3981
|
-
|
|
3982
|
-
|
|
4159
|
+
if (!innerElements?.includes("<a:alpha")) {
|
|
4160
|
+
const alphaHex = colorVal.slice(6, 8);
|
|
4161
|
+
innerElements = `<a:alpha val="${Math.round(parseInt(alphaHex, 16) / 255 * 1e5)}"/>${innerElements || ""}`;
|
|
4162
|
+
}
|
|
3983
4163
|
colorVal = colorVal.slice(0, 6);
|
|
3984
4164
|
}
|
|
3985
4165
|
if (!REGEX_HEX_COLOR.test(colorVal) && colorVal !== "bg1" && colorVal !== "bg2" && colorVal !== "tx1" && colorVal !== "tx2" && colorVal !== "accent1" && colorVal !== "accent2" && colorVal !== "accent3" && colorVal !== "accent4" && colorVal !== "accent5" && colorVal !== "accent6") {
|
|
@@ -4005,12 +4185,38 @@ function createGlowElement(options, defaults) {
|
|
|
4005
4185
|
};
|
|
4006
4186
|
const size = Math.round(opts.size * ONEPT);
|
|
4007
4187
|
const color = opts.color || "000000";
|
|
4008
|
-
const opacity =
|
|
4188
|
+
const opacity = opacityToAlpha(opts.opacity ?? 0);
|
|
4009
4189
|
strXml += `<a:glow rad="${size}">`;
|
|
4010
4190
|
strXml += createColorElement(color, `<a:alpha val="${opacity}"/>`);
|
|
4011
4191
|
strXml += "</a:glow>";
|
|
4012
4192
|
return strXml;
|
|
4013
4193
|
}
|
|
4194
|
+
/**
|
|
4195
|
+
* Creates an `a:outerShdw`/`a:innerShdw` element for a text run or shape.
|
|
4196
|
+
* Returns the shadow element only (no wrapping `a:effectLst`) so callers can
|
|
4197
|
+
* combine it with other effects (e.g. glow) inside a single `a:effectLst`.
|
|
4198
|
+
* @param {ShadowProps} options shadow properties
|
|
4199
|
+
* @param {ShadowProps} defaults defaults for unspecified properties in `options`
|
|
4200
|
+
* @see http://officeopenxml.com/drwSp-effects.php
|
|
4201
|
+
* @returns {string} XML string, or '' when type is 'none'
|
|
4202
|
+
*/
|
|
4203
|
+
function createShadowElement$1(options, defaults) {
|
|
4204
|
+
const opts = {
|
|
4205
|
+
...defaults,
|
|
4206
|
+
...options
|
|
4207
|
+
};
|
|
4208
|
+
if (opts.type === "none") return "";
|
|
4209
|
+
const type = opts.type || "outer";
|
|
4210
|
+
const blur = valToPts(opts.blur ?? 0);
|
|
4211
|
+
const offset = valToPts(opts.offset ?? 0);
|
|
4212
|
+
const angle = Math.round((opts.angle ?? 0) * 6e4);
|
|
4213
|
+
const opacity = Math.round((opts.opacity ?? .75) * 1e5);
|
|
4214
|
+
const color = opts.color || "000000";
|
|
4215
|
+
let strXml = `<a:${type}Shdw ${type === "outer" ? "sx=\"100000\" sy=\"100000\" kx=\"0\" ky=\"0\" algn=\"bl\" rotWithShape=\"0\" " : ""}blurRad="${blur}" dist="${offset}" dir="${angle}">`;
|
|
4216
|
+
strXml += createColorElement(color, `<a:alpha val="${opacity}"/>`);
|
|
4217
|
+
strXml += `</a:${type}Shdw>`;
|
|
4218
|
+
return strXml;
|
|
4219
|
+
}
|
|
4014
4220
|
function boolToXml(value) {
|
|
4015
4221
|
return value ? "1" : "0";
|
|
4016
4222
|
}
|
|
@@ -4021,8 +4227,8 @@ function normalizeGradientAngle(angle) {
|
|
|
4021
4227
|
}
|
|
4022
4228
|
function gradientStopColorAdjustments(stop) {
|
|
4023
4229
|
let internalElements = "";
|
|
4024
|
-
if (stop.alpha) internalElements += `<a:alpha val="${
|
|
4025
|
-
if (stop.transparency) internalElements += `<a:alpha val="${
|
|
4230
|
+
if (stop.alpha) internalElements += `<a:alpha val="${transparencyToAlpha(stop.alpha)}"/>`;
|
|
4231
|
+
if (stop.transparency) internalElements += `<a:alpha val="${transparencyToAlpha(stop.transparency)}"/>`;
|
|
4026
4232
|
return internalElements;
|
|
4027
4233
|
}
|
|
4028
4234
|
function normalizeGradientStops(stops) {
|
|
@@ -4057,10 +4263,32 @@ function genXmlGradientFill(gradient) {
|
|
|
4057
4263
|
return strXml;
|
|
4058
4264
|
}
|
|
4059
4265
|
/**
|
|
4266
|
+
* Create a native DrawingML pattern fill.
|
|
4267
|
+
* @param {PatternFillProps} pattern pattern fill options
|
|
4268
|
+
* @returns XML string
|
|
4269
|
+
*/
|
|
4270
|
+
function genXmlPatternFill(pattern) {
|
|
4271
|
+
if (!pattern) throw new Error("Pattern fill requires a pattern object.");
|
|
4272
|
+
const fgColor = pattern.fgColor ?? "000000";
|
|
4273
|
+
const bgColor = pattern.bgColor ?? "FFFFFF";
|
|
4274
|
+
return `<a:pattFill prst="${pattern.preset}"><a:fgClr>${createColorElement(fgColor)}</a:fgClr><a:bgClr>${createColorElement(bgColor)}</a:bgClr></a:pattFill>`;
|
|
4275
|
+
}
|
|
4276
|
+
/**
|
|
4060
4277
|
* Create color selection
|
|
4061
4278
|
* @param {Color | ShapeFillProps | ShapeLineProps} props fill props
|
|
4062
4279
|
* @returns XML string
|
|
4063
4280
|
*/
|
|
4281
|
+
/**
|
|
4282
|
+
* Map a friendly `LineCap` value to the OOXML `cap` attribute value (`flat`/`sq`/`rnd`).
|
|
4283
|
+
* @param {LineCap} [lineCap] - line cap style (defaults to `flat`)
|
|
4284
|
+
* @returns {string} value for the `cap` attribute on `<a:ln>`
|
|
4285
|
+
*/
|
|
4286
|
+
function createLineCap(lineCap) {
|
|
4287
|
+
if (!lineCap || lineCap === "flat") return "flat";
|
|
4288
|
+
else if (lineCap === "square") return "sq";
|
|
4289
|
+
else if (lineCap === "round") return "rnd";
|
|
4290
|
+
else throw new Error(`Invalid line cap: ${String(lineCap)}`);
|
|
4291
|
+
}
|
|
4064
4292
|
function genXmlColorSelection(props) {
|
|
4065
4293
|
let fillType = "solid";
|
|
4066
4294
|
let colorVal = "";
|
|
@@ -4071,8 +4299,8 @@ function genXmlColorSelection(props) {
|
|
|
4071
4299
|
else {
|
|
4072
4300
|
if (props.type) fillType = props.type;
|
|
4073
4301
|
if (props.color) colorVal = props.color;
|
|
4074
|
-
if (props.alpha) internalElements += `<a:alpha val="${
|
|
4075
|
-
if (props.transparency) internalElements += `<a:alpha val="${
|
|
4302
|
+
if (props.alpha) internalElements += `<a:alpha val="${transparencyToAlpha(props.alpha)}"/>`;
|
|
4303
|
+
if (props.transparency) internalElements += `<a:alpha val="${transparencyToAlpha(props.transparency)}"/>`;
|
|
4076
4304
|
}
|
|
4077
4305
|
switch (fillType) {
|
|
4078
4306
|
case "solid":
|
|
@@ -4081,6 +4309,9 @@ function genXmlColorSelection(props) {
|
|
|
4081
4309
|
case "gradient":
|
|
4082
4310
|
outText += genXmlGradientFill(typeof props === "string" ? void 0 : props.gradient);
|
|
4083
4311
|
break;
|
|
4312
|
+
case "pattern":
|
|
4313
|
+
outText += genXmlPatternFill(typeof props === "string" ? void 0 : props.pattern);
|
|
4314
|
+
break;
|
|
4084
4315
|
default:
|
|
4085
4316
|
outText += "";
|
|
4086
4317
|
break;
|
|
@@ -4146,6 +4377,123 @@ function svgMarkupToDataUri(svg) {
|
|
|
4146
4377
|
for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
|
|
4147
4378
|
return `data:image/svg+xml;base64,${btoa(binary)}`;
|
|
4148
4379
|
}
|
|
4380
|
+
/**
|
|
4381
|
+
* Decode a base64 image payload (raw base64 or a `data:` URI) to bytes.
|
|
4382
|
+
* - tolerant of the `data:[mime];base64,` prefix and of whitespace in the payload
|
|
4383
|
+
* @param {string} b64 - base64 string or data URI
|
|
4384
|
+
* @returns {Uint8Array | null} decoded bytes, or `null` when the payload is empty/undecodable
|
|
4385
|
+
*/
|
|
4386
|
+
function decodeBase64ToBytes(b64) {
|
|
4387
|
+
if (!b64) return null;
|
|
4388
|
+
const comma = b64.indexOf("base64,");
|
|
4389
|
+
const payload = (comma >= 0 ? b64.slice(comma + 7) : b64).replace(/\s/g, "");
|
|
4390
|
+
if (!payload) return null;
|
|
4391
|
+
try {
|
|
4392
|
+
const binary = atob(payload);
|
|
4393
|
+
const bytes = new Uint8Array(binary.length);
|
|
4394
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
4395
|
+
return bytes;
|
|
4396
|
+
} catch {
|
|
4397
|
+
return null;
|
|
4398
|
+
}
|
|
4399
|
+
}
|
|
4400
|
+
/**
|
|
4401
|
+
* Read the intrinsic pixel dimensions of a raster image from its header bytes.
|
|
4402
|
+
* - synchronous: parses only file-format headers, never decodes pixels
|
|
4403
|
+
* - supports PNG, JPEG, GIF, BMP, and WebP (VP8 / VP8L / VP8X)
|
|
4404
|
+
* - vector (SVG) and unrecognized formats return `null` (no intrinsic pixel size)
|
|
4405
|
+
*
|
|
4406
|
+
* Used by image `sizing: 'cover' | 'contain'` to compute an aspect-correct
|
|
4407
|
+
* `<a:srcRect>` crop from the *natural* image ratio rather than the displayed box.
|
|
4408
|
+
* @param {string} dataB64 - base64 image payload or `data:` URI
|
|
4409
|
+
* @returns {{ w: number, h: number } | null} natural pixel size, or `null` when unmeasurable
|
|
4410
|
+
*/
|
|
4411
|
+
function getImageSizeFromBase64(dataB64) {
|
|
4412
|
+
const b = decodeBase64ToBytes(dataB64);
|
|
4413
|
+
if (!b || b.length < 24) return null;
|
|
4414
|
+
if (b[0] === 137 && b[1] === 80 && b[2] === 78 && b[3] === 71) {
|
|
4415
|
+
const w = b[16] << 24 | b[17] << 16 | b[18] << 8 | b[19];
|
|
4416
|
+
const h = b[20] << 24 | b[21] << 16 | b[22] << 8 | b[23];
|
|
4417
|
+
return w > 0 && h > 0 ? {
|
|
4418
|
+
w,
|
|
4419
|
+
h
|
|
4420
|
+
} : null;
|
|
4421
|
+
}
|
|
4422
|
+
if (b[0] === 71 && b[1] === 73 && b[2] === 70) {
|
|
4423
|
+
const w = b[6] | b[7] << 8;
|
|
4424
|
+
const h = b[8] | b[9] << 8;
|
|
4425
|
+
return w > 0 && h > 0 ? {
|
|
4426
|
+
w,
|
|
4427
|
+
h
|
|
4428
|
+
} : null;
|
|
4429
|
+
}
|
|
4430
|
+
if (b[0] === 66 && b[1] === 77) {
|
|
4431
|
+
const w = b[18] | b[19] << 8 | b[20] << 16 | b[21] << 24;
|
|
4432
|
+
const h = b[22] | b[23] << 8 | b[24] << 16 | b[25] << 24;
|
|
4433
|
+
const aw = Math.abs(w);
|
|
4434
|
+
const ah = Math.abs(h);
|
|
4435
|
+
return aw > 0 && ah > 0 ? {
|
|
4436
|
+
w: aw,
|
|
4437
|
+
h: ah
|
|
4438
|
+
} : null;
|
|
4439
|
+
}
|
|
4440
|
+
if (b[0] === 82 && b[1] === 73 && b[2] === 70 && b[3] === 70 && b[8] === 87 && b[9] === 69 && b[10] === 66 && b[11] === 80) {
|
|
4441
|
+
const fourCC = String.fromCharCode(b[12], b[13], b[14], b[15]);
|
|
4442
|
+
if (fourCC === "VP8 " && b.length >= 30) {
|
|
4443
|
+
const w = (b[26] | b[27] << 8) & 16383;
|
|
4444
|
+
const h = (b[28] | b[29] << 8) & 16383;
|
|
4445
|
+
return w > 0 && h > 0 ? {
|
|
4446
|
+
w,
|
|
4447
|
+
h
|
|
4448
|
+
} : null;
|
|
4449
|
+
}
|
|
4450
|
+
if (fourCC === "VP8L" && b.length >= 25) {
|
|
4451
|
+
const bits = b[21] | b[22] << 8 | b[23] << 16 | b[24] << 24;
|
|
4452
|
+
const w = (bits & 16383) + 1;
|
|
4453
|
+
const h = (bits >> 14 & 16383) + 1;
|
|
4454
|
+
return w > 0 && h > 0 ? {
|
|
4455
|
+
w,
|
|
4456
|
+
h
|
|
4457
|
+
} : null;
|
|
4458
|
+
}
|
|
4459
|
+
if (fourCC === "VP8X" && b.length >= 30) {
|
|
4460
|
+
const w = (b[24] | b[25] << 8 | b[26] << 16) + 1;
|
|
4461
|
+
const h = (b[27] | b[28] << 8 | b[29] << 16) + 1;
|
|
4462
|
+
return w > 0 && h > 0 ? {
|
|
4463
|
+
w,
|
|
4464
|
+
h
|
|
4465
|
+
} : null;
|
|
4466
|
+
}
|
|
4467
|
+
return null;
|
|
4468
|
+
}
|
|
4469
|
+
if (b[0] === 255 && b[1] === 216) {
|
|
4470
|
+
let i = 2;
|
|
4471
|
+
while (i + 9 < b.length) {
|
|
4472
|
+
if (b[i] !== 255) {
|
|
4473
|
+
i++;
|
|
4474
|
+
continue;
|
|
4475
|
+
}
|
|
4476
|
+
const marker = b[i + 1];
|
|
4477
|
+
if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) {
|
|
4478
|
+
const h = b[i + 5] << 8 | b[i + 6];
|
|
4479
|
+
const w = b[i + 7] << 8 | b[i + 8];
|
|
4480
|
+
return w > 0 && h > 0 ? {
|
|
4481
|
+
w,
|
|
4482
|
+
h
|
|
4483
|
+
} : null;
|
|
4484
|
+
}
|
|
4485
|
+
if (marker >= 208 && marker <= 217 || marker === 1) {
|
|
4486
|
+
i += 2;
|
|
4487
|
+
continue;
|
|
4488
|
+
}
|
|
4489
|
+
const segLen = b[i + 2] << 8 | b[i + 3];
|
|
4490
|
+
if (segLen < 2) break;
|
|
4491
|
+
i += 2 + segLen;
|
|
4492
|
+
}
|
|
4493
|
+
return null;
|
|
4494
|
+
}
|
|
4495
|
+
return null;
|
|
4496
|
+
}
|
|
4149
4497
|
//#endregion
|
|
4150
4498
|
//#region src/gen-tables.ts
|
|
4151
4499
|
/**
|
|
@@ -4199,52 +4547,62 @@ function parseTextToLines(cell, colWidth, verbose) {
|
|
|
4199
4547
|
*/
|
|
4200
4548
|
let newLine = [];
|
|
4201
4549
|
inputCells.forEach((cell) => {
|
|
4202
|
-
if (typeof cell.text
|
|
4203
|
-
|
|
4204
|
-
|
|
4550
|
+
if (typeof cell.text !== "string") return;
|
|
4551
|
+
if (cell.text.includes("\n")) {
|
|
4552
|
+
const parts = cell.text.split("\n");
|
|
4553
|
+
parts.forEach((part, partIdx) => {
|
|
4554
|
+
if (partIdx === parts.length - 1) newLine.push({
|
|
4205
4555
|
_type: "tablecell",
|
|
4206
|
-
text:
|
|
4207
|
-
options:
|
|
4208
|
-
...cell.options,
|
|
4209
|
-
breakLine: true
|
|
4210
|
-
}
|
|
4556
|
+
text: part,
|
|
4557
|
+
options: cell.options
|
|
4211
4558
|
});
|
|
4559
|
+
else {
|
|
4560
|
+
newLine.push({
|
|
4561
|
+
_type: "tablecell",
|
|
4562
|
+
text: part,
|
|
4563
|
+
options: {
|
|
4564
|
+
...cell.options,
|
|
4565
|
+
breakLine: true
|
|
4566
|
+
}
|
|
4567
|
+
});
|
|
4568
|
+
inputLines1.push(newLine);
|
|
4569
|
+
newLine = [];
|
|
4570
|
+
}
|
|
4212
4571
|
});
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
inputLines1.push(newLine);
|
|
4221
|
-
newLine = [];
|
|
4222
|
-
}
|
|
4223
|
-
}
|
|
4224
|
-
if (newLine.length > 0) {
|
|
4572
|
+
} else newLine.push({
|
|
4573
|
+
_type: "tablecell",
|
|
4574
|
+
text: cell.text.trim(),
|
|
4575
|
+
options: cell.options
|
|
4576
|
+
});
|
|
4577
|
+
if (cell.options?.breakLine) {
|
|
4578
|
+
if (verbose) console.log(`inputCells: new line > ${JSON.stringify(newLine)}`);
|
|
4225
4579
|
inputLines1.push(newLine);
|
|
4226
4580
|
newLine = [];
|
|
4227
4581
|
}
|
|
4228
4582
|
});
|
|
4583
|
+
if (newLine.length > 0) {
|
|
4584
|
+
inputLines1.push(newLine);
|
|
4585
|
+
newLine = [];
|
|
4586
|
+
}
|
|
4229
4587
|
if (verbose) {
|
|
4230
4588
|
console.log(`[2/4] inputLines1 (${inputLines1.length})`);
|
|
4231
4589
|
inputLines1.forEach((line, idx) => console.log(`[2/4] [${idx + 1}] line: ${JSON.stringify(line)}`));
|
|
4232
4590
|
}
|
|
4233
4591
|
inputLines1.forEach((line) => {
|
|
4592
|
+
const lineTokens = [];
|
|
4234
4593
|
line.forEach((cell) => {
|
|
4235
|
-
const lineCells = [];
|
|
4236
4594
|
const lineWords = String(cell.text).split(" ");
|
|
4237
4595
|
lineWords.forEach((word, idx) => {
|
|
4238
4596
|
const cellProps = { ...cell.options };
|
|
4239
4597
|
if (cellProps?.breakLine) cellProps.breakLine = idx + 1 === lineWords.length;
|
|
4240
|
-
|
|
4598
|
+
lineTokens.push({
|
|
4241
4599
|
_type: "tablecell",
|
|
4242
4600
|
text: word + (idx + 1 < lineWords.length ? " " : ""),
|
|
4243
4601
|
options: cellProps
|
|
4244
4602
|
});
|
|
4245
4603
|
});
|
|
4246
|
-
inputLines2.push(lineCells);
|
|
4247
4604
|
});
|
|
4605
|
+
inputLines2.push(lineTokens);
|
|
4248
4606
|
});
|
|
4249
4607
|
if (verbose) {
|
|
4250
4608
|
console.log(`[3/4] inputLines2 (${inputLines2.length})`);
|
|
@@ -4352,6 +4710,7 @@ function getSlidesForTableRows(tableRows = [], tableProps = {}, presLayout, mast
|
|
|
4352
4710
|
numCols += Number(cellOpts?.colspan ? cellOpts.colspan : 1);
|
|
4353
4711
|
});
|
|
4354
4712
|
if (tableProps.verbose) console.log(`| numCols ......................................... = ${numCols}`);
|
|
4713
|
+
const colSpanDepths = new Array(numCols).fill(0);
|
|
4355
4714
|
if (!tablePropW && tableProps.colW) {
|
|
4356
4715
|
tableCalcW = Array.isArray(tableProps.colW) ? tableProps.colW.reduce((p, n) => p + n) * EMU : tableProps.colW * numCols || 0;
|
|
4357
4716
|
if (tableProps.verbose) console.log(`| tableCalcW ...................................... = ${tableCalcW / EMU}`);
|
|
@@ -4372,6 +4731,7 @@ function getSlidesForTableRows(tableRows = [], tableProps = {}, presLayout, mast
|
|
|
4372
4731
|
}
|
|
4373
4732
|
let newTableRowSlide = { rows: [] };
|
|
4374
4733
|
tableRows.forEach((row, iRow) => {
|
|
4734
|
+
const hasActiveRowSpan = colSpanDepths.some((d) => d > 0);
|
|
4375
4735
|
const rowCellLines = [];
|
|
4376
4736
|
let maxCellMarTopEmu = 0;
|
|
4377
4737
|
let maxCellMarBtmEmu = 0;
|
|
@@ -4468,7 +4828,7 @@ function getSlidesForTableRows(tableRows = [], tableProps = {}, presLayout, mast
|
|
|
4468
4828
|
rowCellLines.forEach((cell) => {
|
|
4469
4829
|
if (cell._lineHeight >= emuLineMaxH) emuLineMaxH = cell._lineHeight;
|
|
4470
4830
|
});
|
|
4471
|
-
if (emuTabCurrH + emuLineMaxH > emuSlideTabH) {
|
|
4831
|
+
if (emuTabCurrH + emuLineMaxH > emuSlideTabH && !hasActiveRowSpan) {
|
|
4472
4832
|
if (tableProps.verbose) {
|
|
4473
4833
|
console.log("\n|-----------------------------------------------------------------------|");
|
|
4474
4834
|
console.log(`|-- NEW SLIDE CREATED (currTabH+currLineH > maxH) => ${(emuTabCurrH / EMU).toFixed(2)} + ${(srcCell._lineHeight / EMU).toFixed(2)} > ${emuSlideTabH / EMU}`);
|
|
@@ -4512,6 +4872,16 @@ function getSlidesForTableRows(tableRows = [], tableProps = {}, presLayout, mast
|
|
|
4512
4872
|
if (rowCellLines.map((cell) => cell._lines.length).reduce((prev, next) => prev + next) === 0) isDone = true;
|
|
4513
4873
|
}
|
|
4514
4874
|
if (currTableRow.length > 0) newTableRowSlide.rows.push(currTableRow);
|
|
4875
|
+
const occupiedBefore = [...colSpanDepths];
|
|
4876
|
+
let colCursor = 0;
|
|
4877
|
+
row.forEach((cell) => {
|
|
4878
|
+
while (colCursor < numCols && occupiedBefore[colCursor] > 0) colCursor++;
|
|
4879
|
+
const cellColspan = cell.options?.colspan ?? 1;
|
|
4880
|
+
const cellRowspan = cell.options?.rowspan ?? 1;
|
|
4881
|
+
if (cellRowspan > 1) for (let c = 0; c < cellColspan && colCursor + c < numCols; c++) colSpanDepths[colCursor + c] = cellRowspan;
|
|
4882
|
+
colCursor += cellColspan;
|
|
4883
|
+
});
|
|
4884
|
+
for (let c = 0; c < numCols; c++) if (colSpanDepths[c] > 0) colSpanDepths[c]--;
|
|
4515
4885
|
if (tableProps.verbose) console.log(`- SLIDE [${tableRowSlides.length}]: ROW [${iRow}]: ...COMPLETE ...... emuTabCurrH = ${(emuTabCurrH / EMU).toFixed(2)} ( emuSlideTabH = ${(emuSlideTabH / EMU).toFixed(2)} )`);
|
|
4516
4886
|
});
|
|
4517
4887
|
tableRowSlides.push(newTableRowSlide);
|
|
@@ -4524,6 +4894,28 @@ function getSlidesForTableRows(tableRows = [], tableProps = {}, presLayout, mast
|
|
|
4524
4894
|
return tableRowSlides;
|
|
4525
4895
|
}
|
|
4526
4896
|
/**
|
|
4897
|
+
* Convert a computed CSS border (width string + color string) from `getComputedStyle` into a
|
|
4898
|
+
* pptx `BorderProps`.
|
|
4899
|
+
*
|
|
4900
|
+
* Preserves *fractional* widths: a hairline CSS border such as `0.5px` must not be rounded to
|
|
4901
|
+
* `0pt` and silently vanish — the table serializer (`valToPts`) emits fractional points just
|
|
4902
|
+
* fine, so there is no reason to integer-round here (upstream gitbrent/PptxGenJS#1235). A
|
|
4903
|
+
* computed width of `0` (or a non-finite value) yields `{ type: 'none' }` so we never emit a
|
|
4904
|
+
* zero-width line.
|
|
4905
|
+
* @param {string} widthStr - computed `border-<side>-width`, e.g. `"0.5px"`
|
|
4906
|
+
* @param {string} colorStr - computed `border-<side>-color`, e.g. `"rgb(102, 102, 102)"`
|
|
4907
|
+
* @returns {BorderProps} border props for the cell side
|
|
4908
|
+
*/
|
|
4909
|
+
function htmlBorderToProps(widthStr, colorStr) {
|
|
4910
|
+
const pt = Number(String(widthStr).replace("px", ""));
|
|
4911
|
+
if (!isFinite(pt) || pt <= 0) return { type: "none" };
|
|
4912
|
+
const arrRGB = String(colorStr).replace(/\s+/gi, "").replace("rgba(", "").replace("rgb(", "").replace(")", "").split(",");
|
|
4913
|
+
return {
|
|
4914
|
+
pt,
|
|
4915
|
+
color: rgbToHex(Number(arrRGB[0]), Number(arrRGB[1]), Number(arrRGB[2]))
|
|
4916
|
+
};
|
|
4917
|
+
}
|
|
4918
|
+
/**
|
|
4527
4919
|
* Reproduces an HTML table as a PowerPoint table - including column widths, style, etc. - creates 1 or more slides as needed
|
|
4528
4920
|
* @param {TableToSlidesHost} pptx - pptxgenjs instance
|
|
4529
4921
|
* @param {string} tabEleId - HTMLElementID of the table
|
|
@@ -4671,12 +5063,8 @@ function genTableToSlides(pptx, tabEleId, options = {}, masterSlide) {
|
|
|
4671
5063
|
"bottom",
|
|
4672
5064
|
"left"
|
|
4673
5065
|
].forEach((val, idxb) => {
|
|
4674
|
-
const
|
|
4675
|
-
|
|
4676
|
-
cellBorder[idxb] = {
|
|
4677
|
-
pt: intBorderW,
|
|
4678
|
-
color: rgbToHex(Number(arrRGB[0]), Number(arrRGB[1]), Number(arrRGB[2]))
|
|
4679
|
-
};
|
|
5066
|
+
const style = window.getComputedStyle(cell);
|
|
5067
|
+
cellBorder[idxb] = htmlBorderToProps(style.getPropertyValue("border-" + val + "-width"), style.getPropertyValue("border-" + val + "-color"));
|
|
4680
5068
|
});
|
|
4681
5069
|
cellOpts.border = cellBorder;
|
|
4682
5070
|
}
|
|
@@ -4746,6 +5134,8 @@ function genTableToSlides(pptx, tabEleId, options = {}, masterSlide) {
|
|
|
4746
5134
|
*/
|
|
4747
5135
|
/** counter for included charts (used for index in their filenames) */
|
|
4748
5136
|
let _chartCounter = 0;
|
|
5137
|
+
/** DPI PowerPoint assumes when sizing an inserted raster image (natural pixels / 96 == inches) */
|
|
5138
|
+
const IMAGE_NATURAL_DPI = 96;
|
|
4749
5139
|
function normalizeBorderTuple(border) {
|
|
4750
5140
|
return Array.isArray(border) ? border : [
|
|
4751
5141
|
border,
|
|
@@ -4767,6 +5157,7 @@ function createSlideMaster(props, target) {
|
|
|
4767
5157
|
else if ("image" in object) addImageDefinition(tgt, object.image);
|
|
4768
5158
|
else if ("line" in object) addShapeDefinition(tgt, "line", object.line);
|
|
4769
5159
|
else if ("rect" in object) addShapeDefinition(tgt, "rect", object.rect);
|
|
5160
|
+
else if ("roundRect" in object) addShapeDefinition(tgt, "roundRect", object.roundRect);
|
|
4770
5161
|
else if ("text" in object) addTextDefinition(tgt, [{ text: object.text.text }], object.text.options || {}, false);
|
|
4771
5162
|
else if ("placeholder" in object) {
|
|
4772
5163
|
const placeholder = object.placeholder;
|
|
@@ -4781,6 +5172,26 @@ function createSlideMaster(props, target) {
|
|
|
4781
5172
|
if (props.slideNumber && typeof props.slideNumber === "object") target._slideNumberProps = props.slideNumber;
|
|
4782
5173
|
}
|
|
4783
5174
|
/**
|
|
5175
|
+
* Round and clamp an integer chart percentage/angle option into a schema-valid range.
|
|
5176
|
+
*
|
|
5177
|
+
* Several chart attributes are bounded integer types whose out-of-range values make
|
|
5178
|
+
* PowerPoint report the package as needing repair: `<c:overlap>` (ST_Overlap, -100..100),
|
|
5179
|
+
* `<c:gapWidth>`/`<c:gapDepth>` (ST_GapAmount, 0..500), `<c:holeSize>` (ST_HoleSize, 10..90)
|
|
5180
|
+
* and `<c:firstSliceAng>` (ST_FirstSliceAng, 0..360). Missing/non-numeric input returns
|
|
5181
|
+
* `undefined` so the caller can apply its own default; an out-of-range value is clamped
|
|
5182
|
+
* and a warning is emitted (per the library's warn-rather-than-degrade policy).
|
|
5183
|
+
* @param value - caller-supplied option value
|
|
5184
|
+
* @param min - inclusive lower bound
|
|
5185
|
+
* @param max - inclusive upper bound
|
|
5186
|
+
* @param name - option name, for the warning message
|
|
5187
|
+
*/
|
|
5188
|
+
function clampChartPct(value, min, max, name) {
|
|
5189
|
+
if (typeof value !== "number" || isNaN(value)) return void 0;
|
|
5190
|
+
const clamped = Math.min(max, Math.max(min, Math.round(value)));
|
|
5191
|
+
if (clamped !== value) console.warn(`Warning: ${name} ${value} is outside the valid range ${min}-${max}; using ${clamped}.`);
|
|
5192
|
+
return clamped;
|
|
5193
|
+
}
|
|
5194
|
+
/**
|
|
4784
5195
|
* Generate the chart based on input data.
|
|
4785
5196
|
* OOXML Chart Spec: ISO/IEC 29500-1:2016(E)
|
|
4786
5197
|
*
|
|
@@ -4952,7 +5363,13 @@ function addChartDefinition(target, type, data, opt) {
|
|
|
4952
5363
|
"marker",
|
|
4953
5364
|
"filled"
|
|
4954
5365
|
].includes(options.radarStyle || "")) options.radarStyle = "standard";
|
|
4955
|
-
|
|
5366
|
+
{
|
|
5367
|
+
const rawSymbolSize = options.lineDataSymbolSize;
|
|
5368
|
+
const hasSymbolSize = rawSymbolSize != null && !isNaN(rawSymbolSize);
|
|
5369
|
+
const symbolSize = Math.min(72, Math.max(2, Math.round(hasSymbolSize ? rawSymbolSize : 6)));
|
|
5370
|
+
if (hasSymbolSize && symbolSize !== rawSymbolSize) console.warn(`Warning: lineDataSymbolSize ${rawSymbolSize} is outside the valid marker size range (integer 2-72); using ${symbolSize}.`);
|
|
5371
|
+
options.lineDataSymbolSize = symbolSize;
|
|
5372
|
+
}
|
|
4956
5373
|
options.lineDataSymbolLineSize = options.lineDataSymbolLineSize && !isNaN(options.lineDataSymbolLineSize) ? valToPts(options.lineDataSymbolLineSize) : valToPts(.75);
|
|
4957
5374
|
const chartLayout = options.layout;
|
|
4958
5375
|
if (chartLayout) [
|
|
@@ -5002,8 +5419,11 @@ function addChartDefinition(target, type, data, opt) {
|
|
|
5002
5419
|
options.v3DRotY = typeof options.v3DRotY === "number" && !isNaN(options.v3DRotY) && options.v3DRotY >= 0 && options.v3DRotY <= 360 ? options.v3DRotY : 30;
|
|
5003
5420
|
options.v3DRAngAx = options.v3DRAngAx || !options.v3DRAngAx ? options.v3DRAngAx : true;
|
|
5004
5421
|
options.v3DPerspective = typeof options.v3DPerspective === "number" && !isNaN(options.v3DPerspective) && options.v3DPerspective >= 0 && options.v3DPerspective <= 240 ? options.v3DPerspective : 30;
|
|
5005
|
-
options.barGapWidthPct =
|
|
5006
|
-
options.barGapDepthPct =
|
|
5422
|
+
options.barGapWidthPct = clampChartPct(options.barGapWidthPct, 0, 500, "barGapWidthPct") ?? 150;
|
|
5423
|
+
options.barGapDepthPct = clampChartPct(options.barGapDepthPct, 0, 500, "barGapDepthPct") ?? 150;
|
|
5424
|
+
options.barOverlapPct = clampChartPct(options.barOverlapPct, -100, 100, "barOverlapPct");
|
|
5425
|
+
options.holeSize = clampChartPct(options.holeSize, 10, 90, "holeSize");
|
|
5426
|
+
options.firstSliceAng = clampChartPct(options.firstSliceAng, 0, 360, "firstSliceAng");
|
|
5007
5427
|
options.chartColors = Array.isArray(options.chartColors) ? options.chartColors : options._type === "pie" || options._type === "doughnut" ? PIECHART_COLORS : BARCHART_COLORS;
|
|
5008
5428
|
options.chartColorsOpacity = options.chartColorsOpacity && !isNaN(options.chartColorsOpacity) ? options.chartColorsOpacity : void 0;
|
|
5009
5429
|
options.border = options.border && typeof options.border === "object" ? options.border : void 0;
|
|
@@ -5092,23 +5512,38 @@ function addImageDefinition(target, opt) {
|
|
|
5092
5512
|
else if (strImageData?.toLowerCase().includes("image/svg+xml")) strImgExtn = "svg";
|
|
5093
5513
|
newObject._type = "image";
|
|
5094
5514
|
newObject.image = strImagePath || "preencoded.png";
|
|
5515
|
+
let defWidth = intWidth;
|
|
5516
|
+
let defHeight = intHeight;
|
|
5517
|
+
if ((!intWidth || !intHeight) && strImageData && strImgExtn !== "svg") {
|
|
5518
|
+
const natural = getImageSizeFromBase64(strImageData);
|
|
5519
|
+
if (natural) {
|
|
5520
|
+
if (!intWidth && !intHeight) {
|
|
5521
|
+
defWidth = natural.w / IMAGE_NATURAL_DPI;
|
|
5522
|
+
defHeight = natural.h / IMAGE_NATURAL_DPI;
|
|
5523
|
+
} else if (typeof intWidth === "number" && intWidth && !intHeight) defHeight = intWidth * (natural.h / natural.w);
|
|
5524
|
+
else if (typeof intHeight === "number" && intHeight && !intWidth) defWidth = intHeight * (natural.w / natural.h);
|
|
5525
|
+
}
|
|
5526
|
+
}
|
|
5095
5527
|
const objectOptions = {
|
|
5096
5528
|
x: intPosX || 0,
|
|
5097
5529
|
y: intPosY || 0,
|
|
5098
|
-
w:
|
|
5099
|
-
h:
|
|
5530
|
+
w: defWidth || 1,
|
|
5531
|
+
h: defHeight || 1,
|
|
5100
5532
|
altText: opt.altText || "",
|
|
5101
5533
|
rounding: typeof opt.rounding === "boolean" ? opt.rounding : false,
|
|
5102
5534
|
shape: opt.shape,
|
|
5103
5535
|
points: opt.points,
|
|
5104
5536
|
rectRadius: opt.rectRadius,
|
|
5537
|
+
shapeAdjust: opt.shapeAdjust,
|
|
5105
5538
|
sizing,
|
|
5106
5539
|
placeholder: opt.placeholder,
|
|
5107
5540
|
rotate: opt.rotate || 0,
|
|
5108
5541
|
flipV: opt.flipV || false,
|
|
5109
5542
|
flipH: opt.flipH || false,
|
|
5110
5543
|
transparency: opt.transparency || 0,
|
|
5544
|
+
duotone: opt.duotone,
|
|
5111
5545
|
objectName,
|
|
5546
|
+
objectLock: opt.objectLock,
|
|
5112
5547
|
shadow: correctShadowOptions(opt.shadow)
|
|
5113
5548
|
};
|
|
5114
5549
|
newObject.options = objectOptions;
|
|
@@ -5138,7 +5573,10 @@ function addImageDefinition(target, opt) {
|
|
|
5138
5573
|
});
|
|
5139
5574
|
newObject.imageRid = imageRelId + 1;
|
|
5140
5575
|
} else {
|
|
5141
|
-
const dupeItem = target._relsMedia.find((item) =>
|
|
5576
|
+
const dupeItem = target._relsMedia.find((item) => {
|
|
5577
|
+
if (item.isDuplicate || !item.Target || item.type !== "image/" + strImgExtn) return false;
|
|
5578
|
+
return strImagePath ? item.path === strImagePath : !!strImageData && item.data === strImageData;
|
|
5579
|
+
});
|
|
5142
5580
|
target._relsMedia.push({
|
|
5143
5581
|
path: strImagePath || "preencoded." + strImgExtn,
|
|
5144
5582
|
type: "image/" + strImgExtn,
|
|
@@ -5157,7 +5595,7 @@ function addImageDefinition(target, opt) {
|
|
|
5157
5595
|
type: "hyperlink",
|
|
5158
5596
|
data: objHyperlink.slide ? "slide" : "dummy",
|
|
5159
5597
|
rId: imageRelId,
|
|
5160
|
-
Target: objHyperlink.url
|
|
5598
|
+
Target: objHyperlink.url ? encodeXmlEntities(objHyperlink.url) : String(objHyperlink.slide)
|
|
5161
5599
|
});
|
|
5162
5600
|
objHyperlink._rId = imageRelId;
|
|
5163
5601
|
newObject.hyperlink = objHyperlink;
|
|
@@ -5196,6 +5634,7 @@ function addMediaDefinition(target, opt) {
|
|
|
5196
5634
|
slideData.options.h = intSizeY;
|
|
5197
5635
|
slideData.options.objectName = objectName;
|
|
5198
5636
|
if (opt.altText) slideData.options.altText = opt.altText;
|
|
5637
|
+
if (opt.objectLock) slideData.options.objectLock = opt.objectLock;
|
|
5199
5638
|
/**
|
|
5200
5639
|
* NOTE:
|
|
5201
5640
|
* - rId starts at 2 (hence the intRels+1 below) as slideLayout.xml is rId=1!
|
|
@@ -5225,7 +5664,10 @@ function addMediaDefinition(target, opt) {
|
|
|
5225
5664
|
Target: `../media/image-${target._slideNum}-${target._relsMedia.length + 1}.png`
|
|
5226
5665
|
});
|
|
5227
5666
|
} else {
|
|
5228
|
-
const dupeItem = target._relsMedia.find((item) =>
|
|
5667
|
+
const dupeItem = target._relsMedia.find((item) => {
|
|
5668
|
+
if (item.isDuplicate || !item.Target || item.type !== strType + "/" + strExtn) return false;
|
|
5669
|
+
return strPath ? item.path === strPath : !!strData && item.data === strData;
|
|
5670
|
+
});
|
|
5229
5671
|
const relId1 = getNewRelId(target);
|
|
5230
5672
|
target._relsMedia.push({
|
|
5231
5673
|
path: strPath || "preencoded" + strExtn,
|
|
@@ -5290,12 +5732,14 @@ function addShapeDefinition(target, shapeName, opts) {
|
|
|
5290
5732
|
const options = typeof opts === "object" ? opts : {};
|
|
5291
5733
|
options.line = options.line || { type: "none" };
|
|
5292
5734
|
options.shadow = correctShadowOptions(options.shadow);
|
|
5735
|
+
const resolvedShapeName = typeof shapeName === "string" && SHAPE_NAME_ALIASES[shapeName] ? SHAPE_NAME_ALIASES[shapeName] : shapeName;
|
|
5293
5736
|
const newObject = {
|
|
5294
5737
|
_type: "text",
|
|
5295
|
-
shape:
|
|
5738
|
+
shape: resolvedShapeName || "rect",
|
|
5296
5739
|
options
|
|
5297
5740
|
};
|
|
5298
5741
|
if (!shapeName) throw new Error("Missing/Invalid shape parameter! Example: `addShape(pptxgen.shapes.LINE, {x:1, y:1, w:1, h:1});`");
|
|
5742
|
+
if (!VALID_SHAPE_PRESETS.has(resolvedShapeName)) throw new Error(`Invalid shape "${String(shapeName)}"! Use a value from \`pptxgen.shapes.*\` (e.g. \`pptxgen.shapes.RECTANGLE\`). PowerPoint can't render unknown preset geometries and will drop the shape during repair.`);
|
|
5299
5743
|
const newLineOpts = {
|
|
5300
5744
|
type: options.line.type || "solid",
|
|
5301
5745
|
color: options.line.color || "333333",
|
|
@@ -5392,9 +5836,8 @@ function addTableDefinition(target, tableRows, options, slideLayout, presLayout,
|
|
|
5392
5836
|
}
|
|
5393
5837
|
arrRows.push(newRow);
|
|
5394
5838
|
});
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
if (opt.h) opt.h = getSmartParseNumber(opt.h, "Y", presLayout);
|
|
5839
|
+
if (opt.x === void 0 || opt.x === null) opt.x = .5;
|
|
5840
|
+
if (opt.y === void 0 || opt.y === null) opt.y = .5;
|
|
5398
5841
|
opt.fontSize = opt.fontSize || 12;
|
|
5399
5842
|
opt.margin = opt.margin === 0 || opt.margin ? opt.margin : DEF_CELL_MARGIN_IN;
|
|
5400
5843
|
if (typeof opt.margin === "number") opt.margin = [
|
|
@@ -5463,12 +5906,7 @@ function addTableDefinition(target, tableRows, options, slideLayout, presLayout,
|
|
|
5463
5906
|
console.warn("addTable: mismatch: (colW.length != data.length) Therefore, defaulting to evenly distributed col widths.");
|
|
5464
5907
|
opt.colW = void 0;
|
|
5465
5908
|
}
|
|
5466
|
-
} else if (opt.w) opt.w =
|
|
5467
|
-
else opt.w = Math.floor((presLayout._sizeW || presLayout.width) / EMU - arrTableMargin[1] - arrTableMargin[3]);
|
|
5468
|
-
if (opt.x && opt.x < 20) opt.x = inch2Emu(opt.x);
|
|
5469
|
-
if (opt.y && opt.y < 20) opt.y = inch2Emu(opt.y);
|
|
5470
|
-
if (opt.w && typeof opt.w === "number" && opt.w < 20) opt.w = inch2Emu(opt.w);
|
|
5471
|
-
if (opt.h && typeof opt.h === "number" && opt.h < 20) opt.h = inch2Emu(opt.h);
|
|
5909
|
+
} else if (opt.w) {} else opt.w = Math.floor((presLayout._sizeW || presLayout.width) / EMU - arrTableMargin[1] - arrTableMargin[3]);
|
|
5472
5910
|
arrRows.forEach((row) => {
|
|
5473
5911
|
row.forEach((cell, idy) => {
|
|
5474
5912
|
if (typeof cell === "number" || typeof cell === "string") row[idy] = {
|
|
@@ -5496,7 +5934,7 @@ function addTableDefinition(target, tableRows, options, slideLayout, presLayout,
|
|
|
5496
5934
|
if (opt.autoPageRepeatHeader) opt._arrObjTabHeadRows = arrRows.filter((_row, idx) => idx < (opt.autoPageHeaderRows || 1));
|
|
5497
5935
|
getSlidesForTableRows(arrRows, opt, presLayout, slideLayout).forEach((slide, idx) => {
|
|
5498
5936
|
if (!getSlide(target._slideNum + idx)) slides.push(addSlide({ masterName: slideLayout?._name || void 0 }));
|
|
5499
|
-
if (idx > 0) opt.y =
|
|
5937
|
+
if (idx > 0) opt.y = opt.autoPageSlideStartY || opt.newSlideStartY || arrTableMargin[0];
|
|
5500
5938
|
{
|
|
5501
5939
|
const newSlide = getSlide(target._slideNum + idx);
|
|
5502
5940
|
opt.autoPage = false;
|
|
@@ -5568,6 +6006,10 @@ function addTextDefinition(target, text, opts, isPlaceholder) {
|
|
|
5568
6006
|
itemOpts._bodyProp.anchor = !itemOpts.placeholder ? "ctr" : void 0;
|
|
5569
6007
|
itemOpts._bodyProp.vert = itemOpts.vert;
|
|
5570
6008
|
itemOpts._bodyProp.wrap = typeof itemOpts.wrap === "boolean" ? itemOpts.wrap : true;
|
|
6009
|
+
if (itemOpts.columns !== void 0) if (typeof itemOpts.columns !== "number" || isNaN(itemOpts.columns) || itemOpts.columns < 1 || itemOpts.columns > 16) console.warn("Warning: text `columns` must be a number 1-16 (ignoring value)");
|
|
6010
|
+
else itemOpts._bodyProp.numCol = Math.round(itemOpts.columns);
|
|
6011
|
+
if (itemOpts.columnSpacing !== void 0) if (typeof itemOpts.columnSpacing !== "number" || isNaN(itemOpts.columnSpacing) || itemOpts.columnSpacing < 0) console.warn("Warning: text `columnSpacing` must be a number >= 0 (ignoring value)");
|
|
6012
|
+
else itemOpts._bodyProp.spcCol = valToPts(itemOpts.columnSpacing);
|
|
5571
6013
|
if (itemOpts.inset && !isNaN(Number(itemOpts.inset)) || itemOpts.inset === 0) {
|
|
5572
6014
|
itemOpts._bodyProp.lIns = inch2Emu(itemOpts.inset);
|
|
5573
6015
|
itemOpts._bodyProp.rIns = inch2Emu(itemOpts.inset);
|
|
@@ -5915,7 +6357,7 @@ async function createExcelWorksheet(chartObject, zip) {
|
|
|
5915
6357
|
if (chartObject.opts._type === "bubble" || chartObject.opts._type === "bubble3D") strSharedStrings += `<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="${intBubbleCols}" uniqueCount="${intBubbleCols}">`;
|
|
5916
6358
|
else if (chartObject.opts._type === "scatter") strSharedStrings += `<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="${data.length}" uniqueCount="${data.length}">`;
|
|
5917
6359
|
else if (IS_MULTI_CAT_AXES) {
|
|
5918
|
-
let totCount = data.length;
|
|
6360
|
+
let totCount = data.length + 1;
|
|
5919
6361
|
data[0].labels.forEach((arrLabel) => totCount += arrLabel.filter((label) => label && label !== "").length);
|
|
5920
6362
|
strSharedStrings += `<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="${totCount}" uniqueCount="${totCount}">`;
|
|
5921
6363
|
strSharedStrings += "<si><t/></si>";
|
|
@@ -5983,7 +6425,7 @@ async function createExcelWorksheet(chartObject, zip) {
|
|
|
5983
6425
|
strSheetXml += "<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"x14ac\" xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\">";
|
|
5984
6426
|
if (chartObject.opts._type === "bubble" || chartObject.opts._type === "bubble3D") strSheetXml += `<dimension ref="A1:${getExcelColName(intBubbleCols)}${data[0].values.length + 1}"/>`;
|
|
5985
6427
|
else if (chartObject.opts._type === "scatter") strSheetXml += `<dimension ref="A1:${getExcelColName(data.length)}${data[0].values.length + 1}"/>`;
|
|
5986
|
-
else strSheetXml += `<dimension ref="A1:${getExcelColName(data.length +
|
|
6428
|
+
else strSheetXml += `<dimension ref="A1:${getExcelColName(data.length + data[0].labels.length)}${data[0].values.length + 1}"/>`;
|
|
5987
6429
|
strSheetXml += "<sheetViews><sheetView tabSelected=\"1\" workbookViewId=\"0\"><selection activeCell=\"B1\" sqref=\"B1\"/></sheetView></sheetViews>";
|
|
5988
6430
|
strSheetXml += "<sheetFormatPr baseColWidth=\"10\" defaultRowHeight=\"16\"/>";
|
|
5989
6431
|
if (chartObject.opts._type === "bubble" || chartObject.opts._type === "bubble3D") {
|
|
@@ -6035,82 +6477,28 @@ async function createExcelWorksheet(chartObject, zip) {
|
|
|
6035
6477
|
strSheetXml += "</row>";
|
|
6036
6478
|
});
|
|
6037
6479
|
} else {
|
|
6038
|
-
strSheetXml += `<row r="1" spans="1:${data.length + data[0].labels.length}">`;
|
|
6039
|
-
for (let idx = 0; idx < data[0].labels.length; idx++) strSheetXml += `<c r="${getExcelColName(idx + 1)}1" t="s"><v>0</v></c>`;
|
|
6040
|
-
for (let idx = data[0].labels.length - 1; idx < data.length + data[0].labels.length - 1; idx++) strSheetXml += `<c r="${getExcelColName(idx + data[0].labels.length)}1" t="s"><v>${idx}</v></c>`;
|
|
6041
|
-
strSheetXml += "</row>";
|
|
6042
|
-
/**
|
|
6043
|
-
* @example INPUT
|
|
6044
|
-
* const LABELS = [
|
|
6045
|
-
* ["Gear", "Berg", "Motr", "Swch", "Plug", "Cord", "Pump", "Leak", "Seal"],
|
|
6046
|
-
* ["Mech", "", "", "Elec", "", "", "Hydr", "", ""],
|
|
6047
|
-
* ];
|
|
6048
|
-
* const arrDataRegions = [
|
|
6049
|
-
* { name: "West", labels: LABELS, values: [11, 8, 3, 0, 11, 3, 0, 0, 0] },
|
|
6050
|
-
* { name: "Ctrl", labels: LABELS, values: [0, 11, 6, 19, 12, 5, 0, 0, 0] },
|
|
6051
|
-
* { name: "East", labels: LABELS, values: [0, 3, 2, 0, 0, 0, 4, 3, 1] },
|
|
6052
|
-
* ];
|
|
6053
|
-
*/
|
|
6054
|
-
/**
|
|
6055
|
-
* @example OUTPUT EXCEL SHEET
|
|
6056
|
-
* |/|---A--|---B--|---C--|---D--|---E--|
|
|
6057
|
-
* |1| | | West | Ctrl | East |
|
|
6058
|
-
* |2| Mech | Gear | ## | ## | ## |
|
|
6059
|
-
* |3| | Brng | ## | ## | ## |
|
|
6060
|
-
* |4| | Motr | ## | ## | ## |
|
|
6061
|
-
* |5| Elec | Swch | ## | ## | ## |
|
|
6062
|
-
* |6| | Plug | ## | ## | ## |
|
|
6063
|
-
* |7| | Cord | ## | ## | ## |
|
|
6064
|
-
* |8| Hydr | Pump | ## | ## | ## |
|
|
6065
|
-
* |9| | Leak | ## | ## | ## |
|
|
6066
|
-
*|10| | Seal | ## | ## | ## |
|
|
6067
|
-
*/
|
|
6068
|
-
/**
|
|
6069
|
-
* @example OUTPUT EXCEL SHEET XML
|
|
6070
|
-
* <row r="1" spans="1:5">
|
|
6071
|
-
* <c r="A1" t="s"><v>0</v></c>
|
|
6072
|
-
* <c r="B1" t="s"><v>0</v></c>
|
|
6073
|
-
* <c r="C1" t="s"><v>1</v></c>
|
|
6074
|
-
* <c r="D1" t="s"><v>2</v></c>
|
|
6075
|
-
* <c r="E1" t="s"><v>3</v></c>
|
|
6076
|
-
* </row>
|
|
6077
|
-
* <row r="2" spans="1:5">
|
|
6078
|
-
* <c r="A2" t="s"><v>4</v></c>
|
|
6079
|
-
* <c r="B2" t="s"><v>7</v></c>
|
|
6080
|
-
* <c r="C2" ><v>###</v></c>
|
|
6081
|
-
* </row>
|
|
6082
|
-
* <row r="3" spans="1:5">
|
|
6083
|
-
* <c r="A3" />
|
|
6084
|
-
* <c r="B3" t="s"><v>8</v></c>
|
|
6085
|
-
* <c r="C3" ><v>###</v></c>
|
|
6086
|
-
* </row>
|
|
6087
|
-
*/
|
|
6088
|
-
/**
|
|
6089
|
-
* @example SHARED-STRINGS
|
|
6090
|
-
* 1=West, 2=Ctrl, 3=East, 4=Mech, 5=Elec, 6=Mydr, 7=Gear, 8=Brng, [...], 15=Seal
|
|
6091
|
-
*/
|
|
6092
|
-
/**
|
|
6093
|
-
* const LABELS = [
|
|
6094
|
-
* ["Gear", "Berg", "Motr", "Swch", "Plug", "Cord", "Pump", "Leak", "Seal"],
|
|
6095
|
-
* ["Mech", "", "", "Elec", "", "", "Hydr", "", ""],
|
|
6096
|
-
* ["2010", "", "", "", "", "", "", "", ""],
|
|
6097
|
-
* ];
|
|
6098
|
-
*/
|
|
6099
6480
|
const TOT_SER = data.length;
|
|
6100
6481
|
const TOT_CAT = data[0].labels[0].length;
|
|
6101
6482
|
const TOT_LVL = data[0].labels.length;
|
|
6483
|
+
const revLabelGroups = data[0].labels.slice().reverse();
|
|
6484
|
+
const ssLabelMap = /* @__PURE__ */ new Map();
|
|
6485
|
+
let ssIdx = TOT_SER + 1;
|
|
6486
|
+
revLabelGroups.forEach((labelsGroup, revLevelIdx) => {
|
|
6487
|
+
labelsGroup.forEach((label, rowIdx) => {
|
|
6488
|
+
if (label && label !== "") ssLabelMap.set(`${revLevelIdx}:${rowIdx}`, ssIdx++);
|
|
6489
|
+
});
|
|
6490
|
+
});
|
|
6491
|
+
strSheetXml += `<row r="1" spans="1:${TOT_SER + TOT_LVL}">`;
|
|
6492
|
+
for (let col = 1; col <= TOT_LVL; col++) strSheetXml += `<c r="${getExcelColName(col)}1" t="s"><v>0</v></c>`;
|
|
6493
|
+
for (let ser = 0; ser < TOT_SER; ser++) strSheetXml += `<c r="${getExcelColName(TOT_LVL + ser + 1)}1" t="s"><v>${ser + 1}</v></c>`;
|
|
6494
|
+
strSheetXml += "</row>";
|
|
6102
6495
|
for (let idx = 0; idx < TOT_CAT; idx++) {
|
|
6103
6496
|
strSheetXml += `<row r="${idx + 2}" spans="1:${TOT_SER + TOT_LVL}">`;
|
|
6104
|
-
let totLabels = TOT_SER;
|
|
6105
|
-
const revLabelGroups = data[0].labels.slice().reverse();
|
|
6106
6497
|
revLabelGroups.forEach((labelsGroup, idy) => {
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
totLabels += totGrpLbls;
|
|
6110
|
-
strSheetXml += `<c r="${getExcelColName(idx + 1 + idy)}${idx + 2}" t="s"><v>${totLabels}</v></c>`;
|
|
6111
|
-
}
|
|
6498
|
+
const colLabel = labelsGroup[idx];
|
|
6499
|
+
if (colLabel && colLabel !== "") strSheetXml += `<c r="${getExcelColName(idy + 1)}${idx + 2}" t="s"><v>${ssLabelMap.get(`${idy}:${idx}`)}</v></c>`;
|
|
6112
6500
|
});
|
|
6113
|
-
for (let idy = 0; idy < TOT_SER; idy++) strSheetXml += `<c r="${getExcelColName(TOT_LVL + idy + 1)}${idx + 2}"><v>${data[idy].values[idx]
|
|
6501
|
+
for (let idy = 0; idy < TOT_SER; idy++) strSheetXml += `<c r="${getExcelColName(TOT_LVL + idy + 1)}${idx + 2}"><v>${data[idy].values[idx] ?? ""}</v></c>`;
|
|
6114
6502
|
strSheetXml += "</row>";
|
|
6115
6503
|
}
|
|
6116
6504
|
}
|
|
@@ -6131,6 +6519,22 @@ async function createExcelWorksheet(chartObject, zip) {
|
|
|
6131
6519
|
});
|
|
6132
6520
|
}
|
|
6133
6521
|
/**
|
|
6522
|
+
* Emit the `<a:latin>/<a:ea>/<a:cs>` font trio for a chart text run.
|
|
6523
|
+
*
|
|
6524
|
+
* In DrawingML run properties a typeface applies only to the script class of
|
|
6525
|
+
* its element: `<a:latin>` covers Latin/ASCII, `<a:ea>` covers East Asian, and
|
|
6526
|
+
* `<a:cs>` covers complex scripts. Emitting `<a:latin>` alone leaves East Asian
|
|
6527
|
+
* (e.g. Chinese) and complex-script glyphs falling back to the theme font, so a
|
|
6528
|
+
* user-specified font never takes effect for that text — most visibly on
|
|
6529
|
+
* PowerPoint for Mac. Stamping the same typeface onto all three classes is what
|
|
6530
|
+
* choosing a font in PowerPoint's UI does (upstream gitbrent/PptxGenJS#1420).
|
|
6531
|
+
* @param {string} typeface - font face name
|
|
6532
|
+
* @return {string} `<a:latin/><a:ea/><a:cs/>` XML
|
|
6533
|
+
*/
|
|
6534
|
+
function createChartTextFonts(typeface) {
|
|
6535
|
+
return `<a:latin typeface="${typeface}"/><a:ea typeface="${typeface}"/><a:cs typeface="${typeface}"/>`;
|
|
6536
|
+
}
|
|
6537
|
+
/**
|
|
6134
6538
|
* Main entry point method for create charts
|
|
6135
6539
|
* @see: http://www.datypic.com/sc/ooxml/s-dml-chart.xsd.html
|
|
6136
6540
|
* @param {ISlideRelChart} rel - chart object
|
|
@@ -6140,6 +6544,10 @@ function makeXmlCharts(rel) {
|
|
|
6140
6544
|
let strXml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
|
|
6141
6545
|
let usesSecondaryValAxis = false;
|
|
6142
6546
|
let usesSecondaryCatAxis = false;
|
|
6547
|
+
let primaryCatAxisValType = null;
|
|
6548
|
+
let secondaryCatAxisValType = null;
|
|
6549
|
+
let primaryCatAxisHasCategoryChart = false;
|
|
6550
|
+
let secondaryCatAxisHasCategoryChart = false;
|
|
6143
6551
|
strXml += "<c:chartSpace xmlns:c=\"http://schemas.openxmlformats.org/drawingml/2006/chart\" xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">";
|
|
6144
6552
|
strXml += "<c:date1904 val=\"0\"/>";
|
|
6145
6553
|
strXml += `<c:roundedCorners val="${rel.opts.chartArea.roundedCorners ? "1" : "0"}"/>`;
|
|
@@ -6152,6 +6560,8 @@ function makeXmlCharts(rel) {
|
|
|
6152
6560
|
fontSize: rel.opts.titleFontSize || 18,
|
|
6153
6561
|
titleAlign: rel.opts.titleAlign,
|
|
6154
6562
|
titleBold: rel.opts.titleBold,
|
|
6563
|
+
titleItalic: rel.opts.titleItalic,
|
|
6564
|
+
titleUnderline: rel.opts.titleUnderline,
|
|
6155
6565
|
titlePos: rel.opts.titlePos,
|
|
6156
6566
|
titleRotate: rel.opts.titleRotate
|
|
6157
6567
|
}, rel.opts.x, rel.opts.y);
|
|
@@ -6184,18 +6594,37 @@ function makeXmlCharts(rel) {
|
|
|
6184
6594
|
const catAxisId = options.secondaryCatAxis ? AXIS_ID_CATEGORY_SECONDARY : AXIS_ID_CATEGORY_PRIMARY;
|
|
6185
6595
|
usesSecondaryValAxis = usesSecondaryValAxis || options.secondaryValAxis;
|
|
6186
6596
|
usesSecondaryCatAxis = usesSecondaryCatAxis || options.secondaryCatAxis;
|
|
6597
|
+
const usesValueXAxis = type.type === "scatter" || type.type === "bubble" || type.type === "bubble3D";
|
|
6598
|
+
if (options.secondaryCatAxis) if (usesValueXAxis) secondaryCatAxisValType = type.type;
|
|
6599
|
+
else secondaryCatAxisHasCategoryChart = true;
|
|
6600
|
+
else if (usesValueXAxis) primaryCatAxisValType = type.type;
|
|
6601
|
+
else primaryCatAxisHasCategoryChart = true;
|
|
6187
6602
|
strXml += makeChartType(type.type, type.data, options, valAxisId, catAxisId);
|
|
6188
6603
|
});
|
|
6189
6604
|
else strXml += makeChartType(rel.opts._type, rel.data, rel.opts, AXIS_ID_VALUE_PRIMARY, AXIS_ID_CATEGORY_PRIMARY);
|
|
6190
6605
|
if (rel.opts._type !== "pie" && rel.opts._type !== "doughnut") {
|
|
6191
6606
|
if (rel.opts.valAxes && rel.opts.valAxes.length > 1 && !usesSecondaryValAxis) throw new Error("Secondary axis must be used by one of the multiple charts");
|
|
6607
|
+
const comboCatAxisType = (isSecondary) => {
|
|
6608
|
+
const valType = isSecondary ? secondaryCatAxisValType : primaryCatAxisValType;
|
|
6609
|
+
const hasCategoryChart = isSecondary ? secondaryCatAxisHasCategoryChart : primaryCatAxisHasCategoryChart;
|
|
6610
|
+
if (!valType) return {};
|
|
6611
|
+
if (hasCategoryChart) {
|
|
6612
|
+
console.warn(`A category-based chart and a scatter/bubble chart cannot share the same ${isSecondary ? "secondary" : "primary"} category axis; emitting a category axis. Put the scatter/bubble series on a separate axis.`);
|
|
6613
|
+
return {};
|
|
6614
|
+
}
|
|
6615
|
+
return { _type: valType };
|
|
6616
|
+
};
|
|
6192
6617
|
if (rel.opts.catAxes) {
|
|
6193
6618
|
if (!rel.opts.valAxes || rel.opts.valAxes.length !== rel.opts.catAxes.length) throw new Error("There must be the same number of value and category axes.");
|
|
6194
6619
|
strXml += makeCatAxis({
|
|
6195
6620
|
...rel.opts,
|
|
6196
|
-
...rel.opts.catAxes[0]
|
|
6621
|
+
...rel.opts.catAxes[0],
|
|
6622
|
+
...comboCatAxisType(false)
|
|
6197
6623
|
}, AXIS_ID_CATEGORY_PRIMARY, AXIS_ID_VALUE_PRIMARY);
|
|
6198
|
-
} else strXml += makeCatAxis(
|
|
6624
|
+
} else strXml += makeCatAxis({
|
|
6625
|
+
...rel.opts,
|
|
6626
|
+
...comboCatAxisType(false)
|
|
6627
|
+
}, AXIS_ID_CATEGORY_PRIMARY, AXIS_ID_VALUE_PRIMARY);
|
|
6199
6628
|
if (rel.opts.valAxes) {
|
|
6200
6629
|
strXml += makeValAxis({
|
|
6201
6630
|
...rel.opts,
|
|
@@ -6212,9 +6641,13 @@ function makeXmlCharts(rel) {
|
|
|
6212
6641
|
}
|
|
6213
6642
|
if (rel.opts?.catAxes && rel.opts?.catAxes[1]) strXml += makeCatAxis({
|
|
6214
6643
|
...rel.opts,
|
|
6215
|
-
...rel.opts.catAxes[1]
|
|
6644
|
+
...rel.opts.catAxes[1],
|
|
6645
|
+
...comboCatAxisType(true)
|
|
6646
|
+
}, AXIS_ID_CATEGORY_SECONDARY, AXIS_ID_VALUE_SECONDARY);
|
|
6647
|
+
else if (usesSecondaryCatAxis && (!rel.opts.catAxes || !rel.opts.catAxes[1])) strXml += makeCatAxis({
|
|
6648
|
+
...rel.opts,
|
|
6649
|
+
...comboCatAxisType(true)
|
|
6216
6650
|
}, AXIS_ID_CATEGORY_SECONDARY, AXIS_ID_VALUE_SECONDARY);
|
|
6217
|
-
else if (usesSecondaryCatAxis && (!rel.opts.catAxes || !rel.opts.catAxes[1])) strXml += makeCatAxis(rel.opts, AXIS_ID_CATEGORY_SECONDARY, AXIS_ID_VALUE_SECONDARY);
|
|
6218
6651
|
}
|
|
6219
6652
|
if (rel.opts.showDataTable) {
|
|
6220
6653
|
strXml += "<c:dTable>";
|
|
@@ -6253,6 +6686,13 @@ function makeXmlCharts(rel) {
|
|
|
6253
6686
|
if (rel.opts.showLegend) {
|
|
6254
6687
|
strXml += "<c:legend>";
|
|
6255
6688
|
strXml += "<c:legendPos val=\"" + rel.opts.legendPos + "\"/>";
|
|
6689
|
+
if (Array.isArray(rel.opts._type)) {
|
|
6690
|
+
let seriesIdx = 0;
|
|
6691
|
+
rel.opts._type.forEach((type) => {
|
|
6692
|
+
if (type.options?.showLegend === false) for (let i = 0; i < type.data.length; i++) strXml += `<c:legendEntry><c:idx val="${seriesIdx + i}"/><c:delete val="1"/></c:legendEntry>`;
|
|
6693
|
+
seriesIdx += type.data.length;
|
|
6694
|
+
});
|
|
6695
|
+
}
|
|
6256
6696
|
strXml += "<c:overlay val=\"0\"/>";
|
|
6257
6697
|
if (rel.opts.legendFontFace || rel.opts.legendFontSize || rel.opts.legendColor) {
|
|
6258
6698
|
strXml += "<c:txPr>";
|
|
@@ -6262,8 +6702,7 @@ function makeXmlCharts(rel) {
|
|
|
6262
6702
|
strXml += " <a:pPr>";
|
|
6263
6703
|
strXml += rel.opts.legendFontSize ? `<a:defRPr sz="${Math.round(Number(rel.opts.legendFontSize) * 100)}">` : "<a:defRPr>";
|
|
6264
6704
|
if (rel.opts.legendColor) strXml += genXmlColorSelection(rel.opts.legendColor);
|
|
6265
|
-
if (rel.opts.legendFontFace) strXml +=
|
|
6266
|
-
if (rel.opts.legendFontFace) strXml += "<a:cs typeface=\"" + rel.opts.legendFontFace + "\"/>";
|
|
6705
|
+
if (rel.opts.legendFontFace) strXml += createChartTextFonts(rel.opts.legendFontFace);
|
|
6267
6706
|
strXml += " </a:defRPr>";
|
|
6268
6707
|
strXml += " </a:pPr>";
|
|
6269
6708
|
strXml += " <a:endParaRPr lang=\"en-US\"/>";
|
|
@@ -6301,6 +6740,7 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6301
6740
|
let idxColLtr = 1;
|
|
6302
6741
|
let optsChartData;
|
|
6303
6742
|
let strXml = "";
|
|
6743
|
+
const valFmtCode = encodeXmlEntities(opts.valLabelFormatCode || opts.dataTableFormatCode || opts.dataLabelFormatCode || "General");
|
|
6304
6744
|
switch (chartType) {
|
|
6305
6745
|
case "area":
|
|
6306
6746
|
case "bar":
|
|
@@ -6328,20 +6768,23 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6328
6768
|
strXml += " <c:strCache><c:ptCount val=\"1\"/><c:pt idx=\"0\"><c:v>" + encodeXmlEntities(obj.name) + "</c:v></c:pt></c:strCache>";
|
|
6329
6769
|
strXml += " </c:strRef>";
|
|
6330
6770
|
strXml += " </c:tx>";
|
|
6331
|
-
const
|
|
6771
|
+
const seriesOverride = opts.seriesOptions?.[obj._dataIndex];
|
|
6772
|
+
const seriesColor = seriesOverride?.color ?? (opts.chartColors ? opts.chartColors[colorIndex % opts.chartColors.length] : null);
|
|
6332
6773
|
strXml += " <c:spPr>";
|
|
6333
6774
|
if (seriesColor === "transparent") strXml += "<a:noFill/>";
|
|
6334
6775
|
else if (opts.chartColorsOpacity) strXml += "<a:solidFill>" + createColorElement(seriesColor, `<a:alpha val="${Math.round(opts.chartColorsOpacity * 1e3)}"/>`) + "</a:solidFill>";
|
|
6335
6776
|
else strXml += "<a:solidFill>" + createColorElement(seriesColor) + "</a:solidFill>";
|
|
6336
|
-
if (chartType === "line" || chartType === "radar")
|
|
6337
|
-
|
|
6338
|
-
strXml +=
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6777
|
+
if (chartType === "line" || chartType === "radar") {
|
|
6778
|
+
const effectiveLineSize = seriesOverride?.lineSize ?? opts.lineSize;
|
|
6779
|
+
if (effectiveLineSize === 0) strXml += "<a:ln><a:noFill/></a:ln>";
|
|
6780
|
+
else {
|
|
6781
|
+
strXml += `<a:ln w="${valToPts(effectiveLineSize)}" cap="${createLineCap(opts.lineCap)}"><a:solidFill>${createColorElement(seriesColor)}</a:solidFill>`;
|
|
6782
|
+
strXml += `<a:prstDash val="${opts.lineDashValues?.[colorIndex] ?? opts.lineDash ?? "solid"}"/><a:round/></a:ln>`;
|
|
6783
|
+
}
|
|
6784
|
+
} else if (opts.dataBorder) strXml += `<a:ln w="${valToPts(opts.dataBorder.pt)}" cap="${createLineCap(opts.lineCap)}"><a:solidFill>${createColorElement(opts.dataBorder.color)}</a:solidFill><a:prstDash val="solid"/><a:round/></a:ln>`;
|
|
6342
6785
|
strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW);
|
|
6343
6786
|
strXml += " </c:spPr>";
|
|
6344
|
-
if (chartType
|
|
6787
|
+
if (chartType === "bar" || chartType === "bar3D") strXml += " <c:invertIfNegative val=\"0\"/>";
|
|
6345
6788
|
if (chartType === "line" || chartType === "radar") {
|
|
6346
6789
|
strXml += "<c:marker>";
|
|
6347
6790
|
strXml += " <c:symbol val=\"" + opts.lineDataSymbol + "\"/>";
|
|
@@ -6356,14 +6799,26 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6356
6799
|
strXml += " </c:spPr>";
|
|
6357
6800
|
strXml += "</c:marker>";
|
|
6358
6801
|
}
|
|
6802
|
+
{
|
|
6803
|
+
const barVaryColors = (chartType === "bar" || chartType === "bar3D") && data.length === 1 && (opts.chartColors && opts.chartColors !== BARCHART_COLORS && opts.chartColors.length > 1 || opts.invertedColors?.length) ? opts.chartColors || BARCHART_COLORS : null;
|
|
6804
|
+
strXml += makeSeriesDataPointsXml(chartType, obj, opts, barVaryColors);
|
|
6805
|
+
}
|
|
6359
6806
|
if (chartType !== "radar") {
|
|
6807
|
+
const lblColor = seriesOverride?.dataLabelColor ?? opts.dataLabelColor ?? "000000";
|
|
6808
|
+
const lblBold = seriesOverride?.dataLabelFontBold ?? opts.dataLabelFontBold ?? false;
|
|
6809
|
+
const lblItalic = seriesOverride?.dataLabelFontItalic ?? opts.dataLabelFontItalic ?? false;
|
|
6810
|
+
const lblSize = seriesOverride?.dataLabelFontSize ?? opts.dataLabelFontSize ?? 12;
|
|
6811
|
+
const lblFace = seriesOverride?.dataLabelFontFace ?? opts.dataLabelFontFace ?? "Arial";
|
|
6360
6812
|
strXml += "<c:dLbls>";
|
|
6813
|
+
if (obj.customLabels?.length) obj.customLabels.forEach((lbl, idx) => {
|
|
6814
|
+
if (lbl) strXml += makeCustomDLblXml(idx, lbl, opts);
|
|
6815
|
+
});
|
|
6361
6816
|
strXml += `<c:numFmt formatCode="${encodeXmlEntities(opts.dataLabelFormatCode) || "General"}" sourceLinked="0"/>`;
|
|
6362
6817
|
if (opts.dataLabelBkgrdColors) strXml += `<c:spPr><a:solidFill>${createColorElement(seriesColor)}</a:solidFill></c:spPr>`;
|
|
6363
6818
|
strXml += "<c:txPr><a:bodyPr/><a:lstStyle/><a:p><a:pPr>";
|
|
6364
|
-
strXml += `<a:defRPr b="${
|
|
6365
|
-
strXml += `<a:solidFill>${createColorElement(
|
|
6366
|
-
strXml +=
|
|
6819
|
+
strXml += `<a:defRPr b="${lblBold ? 1 : 0}" i="${lblItalic ? 1 : 0}" strike="noStrike" sz="${Math.round(lblSize * 100)}" u="none">`;
|
|
6820
|
+
strXml += `<a:solidFill>${createColorElement(lblColor)}</a:solidFill>`;
|
|
6821
|
+
strXml += createChartTextFonts(lblFace);
|
|
6367
6822
|
strXml += "</a:defRPr></a:pPr></a:p></c:txPr>";
|
|
6368
6823
|
if (opts.dataLabelPosition) strXml += `<c:dLblPos val="${opts.dataLabelPosition}"/>`;
|
|
6369
6824
|
strXml += "<c:showLegendKey val=\"0\"/>";
|
|
@@ -6372,29 +6827,6 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6372
6827
|
strXml += `<c:showLeaderLines val="${opts.showLeaderLines ? "1" : "0"}"/>`;
|
|
6373
6828
|
strXml += "</c:dLbls>";
|
|
6374
6829
|
}
|
|
6375
|
-
if ((chartType === "bar" || chartType === "bar3D") && data.length === 1 && (opts.chartColors && opts.chartColors !== BARCHART_COLORS && opts.chartColors.length > 1 || opts.invertedColors?.length)) obj.values.forEach((value, index) => {
|
|
6376
|
-
const arrColors = value < 0 ? opts.invertedColors || opts.chartColors || BARCHART_COLORS : opts.chartColors || [];
|
|
6377
|
-
strXml += " <c:dPt>";
|
|
6378
|
-
strXml += ` <c:idx val="${index}"/>`;
|
|
6379
|
-
strXml += " <c:invertIfNegative val=\"0\"/>";
|
|
6380
|
-
strXml += " <c:bubble3D val=\"0\"/>";
|
|
6381
|
-
strXml += " <c:spPr>";
|
|
6382
|
-
if (opts.lineSize === 0) strXml += "<a:ln><a:noFill/></a:ln>";
|
|
6383
|
-
else if (chartType === "bar") {
|
|
6384
|
-
strXml += "<a:solidFill>";
|
|
6385
|
-
strXml += " <a:srgbClr val=\"" + arrColors[index % arrColors.length] + "\"/>";
|
|
6386
|
-
strXml += "</a:solidFill>";
|
|
6387
|
-
} else {
|
|
6388
|
-
strXml += "<a:ln>";
|
|
6389
|
-
strXml += " <a:solidFill>";
|
|
6390
|
-
strXml += " <a:srgbClr val=\"" + arrColors[index % arrColors.length] + "\"/>";
|
|
6391
|
-
strXml += " </a:solidFill>";
|
|
6392
|
-
strXml += "</a:ln>";
|
|
6393
|
-
}
|
|
6394
|
-
strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW);
|
|
6395
|
-
strXml += " </c:spPr>";
|
|
6396
|
-
strXml += " </c:dPt>";
|
|
6397
|
-
});
|
|
6398
6830
|
strXml += "<c:cat>";
|
|
6399
6831
|
if (opts.catLabelFormatCode) {
|
|
6400
6832
|
strXml += " <c:numRef>";
|
|
@@ -6431,10 +6863,10 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6431
6863
|
strXml += " <c:numRef>";
|
|
6432
6864
|
strXml += `<c:f>Sheet1!$${getExcelColName(obj._dataIndex + obj.labels.length + 1)}$2:$${getExcelColName(obj._dataIndex + obj.labels.length + 1)}$${obj.labels[0].length + 1}</c:f>`;
|
|
6433
6865
|
strXml += " <c:numCache>";
|
|
6434
|
-
strXml += " <c:formatCode>" +
|
|
6866
|
+
strXml += " <c:formatCode>" + valFmtCode + "</c:formatCode>";
|
|
6435
6867
|
strXml += ` <c:ptCount val="${obj.labels[0].length}"/>`;
|
|
6436
6868
|
obj.values.forEach((value, idx) => {
|
|
6437
|
-
|
|
6869
|
+
strXml += numCachePt(idx, value);
|
|
6438
6870
|
});
|
|
6439
6871
|
strXml += " </c:numCache>";
|
|
6440
6872
|
strXml += " </c:numRef>";
|
|
@@ -6450,7 +6882,7 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6450
6882
|
strXml += " <a:p><a:pPr>";
|
|
6451
6883
|
strXml += ` <a:defRPr b="${opts.dataLabelFontBold ? 1 : 0}" i="${opts.dataLabelFontItalic ? 1 : 0}" strike="noStrike" sz="${Math.round((opts.dataLabelFontSize || 12) * 100)}" u="none">`;
|
|
6452
6884
|
strXml += " <a:solidFill>" + createColorElement(opts.dataLabelColor || "000000") + "</a:solidFill>";
|
|
6453
|
-
strXml += "
|
|
6885
|
+
strXml += " " + createChartTextFonts(opts.dataLabelFontFace || "Arial");
|
|
6454
6886
|
strXml += " </a:defRPr>";
|
|
6455
6887
|
strXml += " </a:pPr></a:p>";
|
|
6456
6888
|
strXml += " </c:txPr>";
|
|
@@ -6466,6 +6898,7 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6466
6898
|
if (chartType === "bar") {
|
|
6467
6899
|
strXml += ` <c:gapWidth val="${opts.barGapWidthPct}"/>`;
|
|
6468
6900
|
strXml += ` <c:overlap val="${opts.barOverlapPct != null ? opts.barOverlapPct : (opts.barGrouping || "").includes("tacked") ? 100 : 0}"/>`;
|
|
6901
|
+
strXml += createSerLinesElement(opts.barSeriesLine);
|
|
6469
6902
|
} else if (chartType === "bar3D") {
|
|
6470
6903
|
strXml += ` <c:gapWidth val="${opts.barGapWidthPct}"/>`;
|
|
6471
6904
|
strXml += ` <c:gapDepth val="${opts.barGapDepthPct}"/>`;
|
|
@@ -6517,6 +6950,10 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6517
6950
|
strXml += "<a:effectLst/>";
|
|
6518
6951
|
strXml += "</c:spPr>";
|
|
6519
6952
|
strXml += "</c:marker>";
|
|
6953
|
+
{
|
|
6954
|
+
const scatterVaryColors = data.length === 1 && opts.chartColors !== BARCHART_COLORS ? opts.chartColors || BARCHART_COLORS : null;
|
|
6955
|
+
strXml += makeSeriesDataPointsXml(chartType, obj, opts, scatterVaryColors);
|
|
6956
|
+
}
|
|
6520
6957
|
if (opts.showLabel) {
|
|
6521
6958
|
const chartUuid = getUuid("-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
|
|
6522
6959
|
if (obj.labels[0] && (opts.dataLabelFormatScatter === "custom" || opts.dataLabelFormatScatter === "customXY")) {
|
|
@@ -6535,13 +6972,13 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6535
6972
|
strXml += " <a:pPr>";
|
|
6536
6973
|
strXml += ` <a:defRPr sz="${Math.round((opts.dataLabelFontSize || 12) * 100)}" b="${opts.dataLabelFontBold ? "1" : "0"}" i="${opts.dataLabelFontItalic ? "1" : "0"}" u="none" strike="noStrike">`;
|
|
6537
6974
|
strXml += " <a:solidFill>" + createColorElement(opts.dataLabelColor || "000000") + "</a:solidFill>";
|
|
6538
|
-
strXml +=
|
|
6975
|
+
strXml += " " + createChartTextFonts(opts.dataLabelFontFace || "Arial");
|
|
6539
6976
|
strXml += " </a:defRPr>";
|
|
6540
6977
|
strXml += " </a:pPr>";
|
|
6541
6978
|
strXml += " <a:r>";
|
|
6542
6979
|
strXml += ` <a:rPr lang="${opts.lang || "en-US"}" sz="${Math.round((opts.dataLabelFontSize || 12) * 100)}" b="${opts.dataLabelFontBold ? "1" : "0"}" i="${opts.dataLabelFontItalic ? "1" : "0"}" u="none" strike="noStrike" dirty="0">`;
|
|
6543
6980
|
strXml += " <a:solidFill>" + createColorElement(opts.dataLabelColor || "000000") + "</a:solidFill>";
|
|
6544
|
-
strXml +=
|
|
6981
|
+
strXml += " " + createChartTextFonts(opts.dataLabelFontFace || "Arial");
|
|
6545
6982
|
strXml += " </a:rPr>";
|
|
6546
6983
|
strXml += " <a:t>" + encodeXmlEntities(label) + "</a:t>";
|
|
6547
6984
|
strXml += " </a:r>";
|
|
@@ -6621,7 +7058,7 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6621
7058
|
strXml += " <a:pPr>";
|
|
6622
7059
|
strXml += ` <a:defRPr sz="${Math.round((opts.dataLabelFontSize || 12) * 100)}" b="${opts.dataLabelFontBold ? "1" : "0"}" i="${opts.dataLabelFontItalic ? "1" : "0"}" u="none" strike="noStrike">`;
|
|
6623
7060
|
strXml += " <a:solidFill>" + createColorElement(opts.dataLabelColor || "000000") + "</a:solidFill>";
|
|
6624
|
-
strXml +=
|
|
7061
|
+
strXml += " " + createChartTextFonts(opts.dataLabelFontFace || "Arial");
|
|
6625
7062
|
strXml += " </a:defRPr>";
|
|
6626
7063
|
strXml += " </a:pPr>";
|
|
6627
7064
|
strXml += ` <a:endParaRPr lang="${opts.lang || "en-US"}"/>`;
|
|
@@ -6642,31 +7079,14 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6642
7079
|
strXml += "</c:dLbls>";
|
|
6643
7080
|
}
|
|
6644
7081
|
}
|
|
6645
|
-
if (data.length === 1 && opts.chartColors !== BARCHART_COLORS) obj.values.forEach((value, index) => {
|
|
6646
|
-
const arrColors = value < 0 ? opts.invertedColors || opts.chartColors || BARCHART_COLORS : opts.chartColors || [];
|
|
6647
|
-
strXml += " <c:dPt>";
|
|
6648
|
-
strXml += ` <c:idx val="${index}"/>`;
|
|
6649
|
-
strXml += " <c:invertIfNegative val=\"0\"/>";
|
|
6650
|
-
strXml += " <c:bubble3D val=\"0\"/>";
|
|
6651
|
-
strXml += " <c:spPr>";
|
|
6652
|
-
if (opts.lineSize === 0) strXml += "<a:ln><a:noFill/></a:ln>";
|
|
6653
|
-
else {
|
|
6654
|
-
strXml += "<a:solidFill>";
|
|
6655
|
-
strXml += " <a:srgbClr val=\"" + arrColors[index % arrColors.length] + "\"/>";
|
|
6656
|
-
strXml += "</a:solidFill>";
|
|
6657
|
-
}
|
|
6658
|
-
strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW);
|
|
6659
|
-
strXml += " </c:spPr>";
|
|
6660
|
-
strXml += " </c:dPt>";
|
|
6661
|
-
});
|
|
6662
7082
|
strXml += "<c:xVal>";
|
|
6663
7083
|
strXml += " <c:numRef>";
|
|
6664
7084
|
strXml += ` <c:f>Sheet1!$A$2:$A$${data[0].values.length + 1}</c:f>`;
|
|
6665
7085
|
strXml += " <c:numCache>";
|
|
6666
|
-
strXml += " <c:formatCode>
|
|
7086
|
+
strXml += " <c:formatCode>" + valFmtCode + "</c:formatCode>";
|
|
6667
7087
|
strXml += ` <c:ptCount val="${data[0].values.length}"/>`;
|
|
6668
7088
|
data[0].values.forEach((value, idx) => {
|
|
6669
|
-
|
|
7089
|
+
strXml += numCachePt(idx, value);
|
|
6670
7090
|
});
|
|
6671
7091
|
strXml += " </c:numCache>";
|
|
6672
7092
|
strXml += " </c:numRef>";
|
|
@@ -6675,10 +7095,10 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6675
7095
|
strXml += " <c:numRef>";
|
|
6676
7096
|
strXml += ` <c:f>Sheet1!$${getExcelColName(idx + 2)}$2:$${getExcelColName(idx + 2)}$${data[0].values.length + 1}</c:f>`;
|
|
6677
7097
|
strXml += " <c:numCache>";
|
|
6678
|
-
strXml += " <c:formatCode>
|
|
7098
|
+
strXml += " <c:formatCode>" + valFmtCode + "</c:formatCode>";
|
|
6679
7099
|
strXml += ` <c:ptCount val="${data[0].values.length}"/>`;
|
|
6680
7100
|
data[0].values.forEach((_value, idx) => {
|
|
6681
|
-
|
|
7101
|
+
strXml += numCachePt(idx, obj.values[idx]);
|
|
6682
7102
|
});
|
|
6683
7103
|
strXml += " </c:numCache>";
|
|
6684
7104
|
strXml += " </c:numRef>";
|
|
@@ -6694,7 +7114,7 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6694
7114
|
strXml += " <a:p><a:pPr>";
|
|
6695
7115
|
strXml += ` <a:defRPr b="${opts.dataLabelFontBold ? "1" : "0"}" i="${opts.dataLabelFontItalic ? "1" : "0"}" strike="noStrike" sz="${Math.round((opts.dataLabelFontSize || 12) * 100)}" u="none">`;
|
|
6696
7116
|
strXml += " <a:solidFill>" + createColorElement(opts.dataLabelColor || "000000") + "</a:solidFill>";
|
|
6697
|
-
strXml += "
|
|
7117
|
+
strXml += " " + createChartTextFonts(opts.dataLabelFontFace || "Arial");
|
|
6698
7118
|
strXml += " </a:defRPr>";
|
|
6699
7119
|
strXml += " </a:pPr></a:p>";
|
|
6700
7120
|
strXml += " </c:txPr>";
|
|
@@ -6744,10 +7164,10 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6744
7164
|
strXml += " <c:numRef>";
|
|
6745
7165
|
strXml += ` <c:f>Sheet1!$A$2:$A$${data[0].values.length + 1}</c:f>`;
|
|
6746
7166
|
strXml += " <c:numCache>";
|
|
6747
|
-
strXml += " <c:formatCode>
|
|
7167
|
+
strXml += " <c:formatCode>" + valFmtCode + "</c:formatCode>";
|
|
6748
7168
|
strXml += ` <c:ptCount val="${data[0].values.length}"/>`;
|
|
6749
7169
|
data[0].values.forEach((value, idx) => {
|
|
6750
|
-
strXml +=
|
|
7170
|
+
strXml += numCachePt(idx, value);
|
|
6751
7171
|
});
|
|
6752
7172
|
strXml += " </c:numCache>";
|
|
6753
7173
|
strXml += " </c:numRef>";
|
|
@@ -6757,10 +7177,10 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6757
7177
|
strXml += `<c:f>Sheet1!$${getExcelColName(idxColLtr + 1)}$2:$${getExcelColName(idxColLtr + 1)}$${data[0].values.length + 1}</c:f>`;
|
|
6758
7178
|
idxColLtr++;
|
|
6759
7179
|
strXml += " <c:numCache>";
|
|
6760
|
-
strXml += " <c:formatCode>
|
|
7180
|
+
strXml += " <c:formatCode>" + valFmtCode + "</c:formatCode>";
|
|
6761
7181
|
strXml += ` <c:ptCount val="${data[0].values.length}"/>`;
|
|
6762
7182
|
data[0].values.forEach((_value, idx) => {
|
|
6763
|
-
strXml +=
|
|
7183
|
+
strXml += numCachePt(idx, obj.values[idx]);
|
|
6764
7184
|
});
|
|
6765
7185
|
strXml += " </c:numCache>";
|
|
6766
7186
|
strXml += " </c:numRef>";
|
|
@@ -6773,7 +7193,7 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6773
7193
|
strXml += " <c:formatCode>General</c:formatCode>";
|
|
6774
7194
|
strXml += ` <c:ptCount val="${obj.sizes.length}"/>`;
|
|
6775
7195
|
obj.sizes.forEach((value, idx) => {
|
|
6776
|
-
strXml +=
|
|
7196
|
+
strXml += numCachePt(idx, value);
|
|
6777
7197
|
});
|
|
6778
7198
|
strXml += " </c:numCache>";
|
|
6779
7199
|
strXml += " </c:numRef>";
|
|
@@ -6786,12 +7206,12 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6786
7206
|
strXml += "<c:txPr><a:bodyPr/><a:lstStyle/><a:p><a:pPr>";
|
|
6787
7207
|
strXml += `<a:defRPr b="${opts.dataLabelFontBold ? 1 : 0}" i="${opts.dataLabelFontItalic ? 1 : 0}" strike="noStrike" sz="${Math.round(Math.round(opts.dataLabelFontSize || 12) * 100)}" u="none">`;
|
|
6788
7208
|
strXml += `<a:solidFill>${createColorElement(opts.dataLabelColor || "000000")}</a:solidFill>`;
|
|
6789
|
-
strXml +=
|
|
7209
|
+
strXml += createChartTextFonts(opts.dataLabelFontFace || "Arial");
|
|
6790
7210
|
strXml += "</a:defRPr></a:pPr></a:p></c:txPr>";
|
|
6791
7211
|
if (opts.dataLabelPosition) strXml += `<c:dLblPos val="${opts.dataLabelPosition}"/>`;
|
|
6792
7212
|
strXml += "<c:showLegendKey val=\"0\"/>";
|
|
6793
7213
|
strXml += `<c:showVal val="${opts.showValue ? "1" : "0"}"/>`;
|
|
6794
|
-
strXml += `<c:showCatName val="0"/><c:showSerName val="${opts.showSerName ? "1" : "0"}"/><c:showPercent val="0"/><c:showBubbleSize val="0"/>`;
|
|
7214
|
+
strXml += `<c:showCatName val="0"/><c:showSerName val="${opts.showSerName ? "1" : "0"}"/><c:showPercent val="0"/><c:showBubbleSize val="${opts.showBubbleSize ? "1" : "0"}"/>`;
|
|
6795
7215
|
strXml += "<c:extLst>";
|
|
6796
7216
|
strXml += " <c:ext uri=\"{CE6537A1-D6FC-4f65-9D91-7224C49458BB}\" xmlns:c15=\"http://schemas.microsoft.com/office/drawing/2012/chart\">";
|
|
6797
7217
|
strXml += " <c15:showLeaderLines val=\"" + (opts.showLeaderLines ? "1" : "0") + "\"/>";
|
|
@@ -6825,33 +7245,37 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6825
7245
|
else strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW);
|
|
6826
7246
|
strXml += " </c:spPr>";
|
|
6827
7247
|
optsChartData.labels[0].forEach((_label, idx) => {
|
|
7248
|
+
const ptStyle = optsChartData.pointStyles?.[idx];
|
|
6828
7249
|
strXml += "<c:dPt>";
|
|
6829
7250
|
strXml += ` <c:idx val="${idx}"/>`;
|
|
6830
7251
|
strXml += " <c:bubble3D val=\"0\"/>";
|
|
6831
7252
|
strXml += " <c:spPr>";
|
|
6832
|
-
strXml += `<a:solidFill>${createColorElement(opts.chartColors[idx + 1 > opts.chartColors.length ? Math.floor(Math.random() * opts.chartColors.length) : idx])}</a:solidFill>`;
|
|
6833
|
-
if (
|
|
7253
|
+
strXml += `<a:solidFill>${createColorElement(ptStyle?.fill || opts.chartColors[idx + 1 > opts.chartColors.length ? Math.floor(Math.random() * opts.chartColors.length) : idx])}</a:solidFill>`;
|
|
7254
|
+
if (ptStyle?.border) strXml += createChartBorderLine(ptStyle.border);
|
|
7255
|
+
else if (opts.dataBorder) strXml += `<a:ln w="${valToPts(opts.dataBorder.pt)}" cap="flat"><a:solidFill>${createColorElement(opts.dataBorder.color)}</a:solidFill><a:prstDash val="solid"/><a:round/></a:ln>`;
|
|
6834
7256
|
strXml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW);
|
|
6835
7257
|
strXml += " </c:spPr>";
|
|
6836
7258
|
strXml += "</c:dPt>";
|
|
6837
7259
|
});
|
|
6838
7260
|
strXml += "<c:dLbls>";
|
|
6839
7261
|
optsChartData.labels[0].forEach((_label, idx) => {
|
|
7262
|
+
const customLbl = optsChartData.customLabels?.[idx];
|
|
6840
7263
|
strXml += "<c:dLbl>";
|
|
6841
7264
|
strXml += ` <c:idx val="${idx}"/>`;
|
|
7265
|
+
if (customLbl) strXml += `<c:tx><c:rich><a:bodyPr/><a:lstStyle/><a:p><a:r><a:rPr lang="${opts.lang || "en-US"}" dirty="0"/><a:t>${encodeXmlEntities(customLbl)}</a:t></a:r></a:p></c:rich></c:tx>`;
|
|
6842
7266
|
strXml += ` <c:numFmt formatCode="${encodeXmlEntities(opts.dataLabelFormatCode) || "General"}" sourceLinked="0"/>`;
|
|
6843
7267
|
strXml += " <c:spPr/><c:txPr>";
|
|
6844
7268
|
strXml += " <a:bodyPr/><a:lstStyle/>";
|
|
6845
7269
|
strXml += " <a:p><a:pPr>";
|
|
6846
7270
|
strXml += ` <a:defRPr sz="${Math.round((opts.dataLabelFontSize || 12) * 100)}" b="${opts.dataLabelFontBold ? 1 : 0}" i="${opts.dataLabelFontItalic ? 1 : 0}" u="none" strike="noStrike">`;
|
|
6847
7271
|
strXml += " <a:solidFill>" + createColorElement(opts.dataLabelColor || "000000") + "</a:solidFill>";
|
|
6848
|
-
strXml +=
|
|
7272
|
+
strXml += " " + createChartTextFonts(opts.dataLabelFontFace || "Arial");
|
|
6849
7273
|
strXml += " </a:defRPr>";
|
|
6850
7274
|
strXml += " </a:pPr></a:p>";
|
|
6851
7275
|
strXml += " </c:txPr>";
|
|
6852
7276
|
if (chartType === "pie" && opts.dataLabelPosition) strXml += `<c:dLblPos val="${opts.dataLabelPosition}"/>`;
|
|
6853
7277
|
strXml += " <c:showLegendKey val=\"0\"/>";
|
|
6854
|
-
strXml += " <c:showVal val=\"" + (opts.showValue ? "1" : "0") + "\"/>";
|
|
7278
|
+
strXml += " <c:showVal val=\"" + (customLbl ? "0" : opts.showValue ? "1" : "0") + "\"/>";
|
|
6855
7279
|
strXml += " <c:showCatName val=\"" + (opts.showLabel ? "1" : "0") + "\"/>";
|
|
6856
7280
|
strXml += " <c:showSerName val=\"" + (opts.showSerName ? "1" : "0") + "\"/>";
|
|
6857
7281
|
strXml += " <c:showPercent val=\"" + (opts.showPercent ? "1" : "0") + "\"/>";
|
|
@@ -6866,7 +7290,7 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6866
7290
|
strXml += " <a:pPr>";
|
|
6867
7291
|
strXml += ` <a:defRPr sz="${Math.round((opts.dataLabelFontSize || 12) * 100)}" b="${opts.dataLabelFontBold ? "1" : "0"}" i="${opts.dataLabelFontItalic ? "1" : "0"}" u="none" strike="noStrike">`;
|
|
6868
7292
|
strXml += " <a:solidFill>" + createColorElement(opts.dataLabelColor || "000000") + "</a:solidFill>";
|
|
6869
|
-
strXml +=
|
|
7293
|
+
strXml += " " + createChartTextFonts(opts.dataLabelFontFace || "Arial");
|
|
6870
7294
|
strXml += " </a:defRPr>";
|
|
6871
7295
|
strXml += " </a:pPr>";
|
|
6872
7296
|
strXml += " </a:p>";
|
|
@@ -6895,6 +7319,7 @@ function makeChartType(chartType, data, opts, valAxisId, catAxisId) {
|
|
|
6895
7319
|
strXml += " <c:numRef>";
|
|
6896
7320
|
strXml += ` <c:f>Sheet1!$B$2:$B$${optsChartData.labels[0].length + 1}</c:f>`;
|
|
6897
7321
|
strXml += " <c:numCache>";
|
|
7322
|
+
strXml += " <c:formatCode>" + valFmtCode + "</c:formatCode>";
|
|
6898
7323
|
strXml += ` <c:ptCount val="${optsChartData.labels[0].length}"/>`;
|
|
6899
7324
|
optsChartData.values.forEach((value, idx) => {
|
|
6900
7325
|
strXml += `<c:pt idx="${idx}"><c:v>${value || value === 0 ? value : ""}</c:v></c:pt>`;
|
|
@@ -6970,7 +7395,7 @@ function makeCatAxis(opts, axisId, valAxisId) {
|
|
|
6970
7395
|
strXml += " <a:pPr>";
|
|
6971
7396
|
strXml += ` <a:defRPr sz="${Math.round((opts.catAxisLabelFontSize || 12) * 100)}" b="${opts.catAxisLabelFontBold ? 1 : 0}" i="${opts.catAxisLabelFontItalic ? 1 : 0}" u="none" strike="noStrike">`;
|
|
6972
7397
|
strXml += " <a:solidFill>" + createColorElement(opts.catAxisLabelColor || "000000") + "</a:solidFill>";
|
|
6973
|
-
strXml += "
|
|
7398
|
+
strXml += " " + createChartTextFonts(opts.catAxisLabelFontFace || "Arial");
|
|
6974
7399
|
strXml += " </a:defRPr>";
|
|
6975
7400
|
strXml += " </a:pPr>";
|
|
6976
7401
|
strXml += " <a:endParaRPr lang=\"" + (opts.lang || "en-US") + "\"/>";
|
|
@@ -7063,7 +7488,7 @@ function makeValAxis(opts, valAxisId) {
|
|
|
7063
7488
|
strXml += " <a:pPr>";
|
|
7064
7489
|
strXml += ` <a:defRPr sz="${Math.round((opts.valAxisLabelFontSize || 12) * 100)}" b="${opts.valAxisLabelFontBold ? 1 : 0}" i="${opts.valAxisLabelFontItalic ? 1 : 0}" u="none" strike="noStrike">`;
|
|
7065
7490
|
strXml += " <a:solidFill>" + createColorElement(opts.valAxisLabelColor || "000000") + "</a:solidFill>";
|
|
7066
|
-
strXml += "
|
|
7491
|
+
strXml += " " + createChartTextFonts(opts.valAxisLabelFontFace || "Arial");
|
|
7067
7492
|
strXml += " </a:defRPr>";
|
|
7068
7493
|
strXml += " </a:pPr>";
|
|
7069
7494
|
strXml += " <a:endParaRPr lang=\"" + (opts.lang || "en-US") + "\"/>";
|
|
@@ -7119,7 +7544,7 @@ function makeSerAxis(opts, axisId, valAxisId) {
|
|
|
7119
7544
|
strXml += " <a:pPr>";
|
|
7120
7545
|
strXml += ` <a:defRPr sz="${Math.round((opts.serAxisLabelFontSize || 12) * 100)}" b="${opts.serAxisLabelFontBold ? "1" : "0"}" i="${opts.serAxisLabelFontItalic ? "1" : "0"}" u="none" strike="noStrike">`;
|
|
7121
7546
|
strXml += ` <a:solidFill>${createColorElement(opts.serAxisLabelColor || "000000")}</a:solidFill>`;
|
|
7122
|
-
strXml +=
|
|
7547
|
+
strXml += " " + createChartTextFonts(opts.serAxisLabelFontFace || "Arial");
|
|
7123
7548
|
strXml += " </a:defRPr>";
|
|
7124
7549
|
strXml += " </a:pPr>";
|
|
7125
7550
|
strXml += " <a:endParaRPr lang=\"" + (opts.lang || "en-US") + "\"/>";
|
|
@@ -7159,17 +7584,31 @@ function genXmlTitle(opts, chartX, chartY) {
|
|
|
7159
7584
|
const rotate = opts.titleRotate ? `<a:bodyPr rot="${convertRotationDegrees(opts.titleRotate)}"/>` : "<a:bodyPr/>";
|
|
7160
7585
|
const sizeAttr = opts.fontSize ? `sz="${Math.round(opts.fontSize * 100)}"` : "";
|
|
7161
7586
|
const titleBold = opts.titleBold ? 1 : 0;
|
|
7587
|
+
const titleItalic = opts.titleItalic ? 1 : 0;
|
|
7588
|
+
const titleUnderline = opts.titleUnderline ? "sng" : "none";
|
|
7162
7589
|
let layout = "<c:layout/>";
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
let
|
|
7167
|
-
|
|
7168
|
-
if (
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7590
|
+
const hasX = opts.titlePos && typeof opts.titlePos.x === "number";
|
|
7591
|
+
const hasY = opts.titlePos && typeof opts.titlePos.y === "number";
|
|
7592
|
+
if (hasX || hasY) {
|
|
7593
|
+
let modes = "";
|
|
7594
|
+
let vals = "";
|
|
7595
|
+
if (hasX) {
|
|
7596
|
+
const totalX = opts.titlePos.x + chartX;
|
|
7597
|
+
let valX = totalX === 0 ? 0 : totalX * (totalX / 5) / 10;
|
|
7598
|
+
if (valX >= 1) valX = valX / 10;
|
|
7599
|
+
if (valX >= .1) valX = valX / 10;
|
|
7600
|
+
modes += "<c:xMode val=\"edge\"/>";
|
|
7601
|
+
vals += `<c:x val="${valX}"/>`;
|
|
7602
|
+
}
|
|
7603
|
+
if (hasY) {
|
|
7604
|
+
const totalY = opts.titlePos.y + chartY;
|
|
7605
|
+
let valY = totalY === 0 ? 0 : totalY * (totalY / 5) / 10;
|
|
7606
|
+
if (valY >= 1) valY = valY / 10;
|
|
7607
|
+
if (valY >= .1) valY = valY / 10;
|
|
7608
|
+
modes += "<c:yMode val=\"edge\"/>";
|
|
7609
|
+
vals += `<c:y val="${valY}"/>`;
|
|
7610
|
+
}
|
|
7611
|
+
layout = `<c:layout><c:manualLayout>${modes}${vals}</c:manualLayout></c:layout>`;
|
|
7173
7612
|
}
|
|
7174
7613
|
return `<c:title>
|
|
7175
7614
|
<c:tx>
|
|
@@ -7178,15 +7617,15 @@ function genXmlTitle(opts, chartX, chartY) {
|
|
|
7178
7617
|
<a:lstStyle/>
|
|
7179
7618
|
<a:p>
|
|
7180
7619
|
${align}
|
|
7181
|
-
<a:defRPr ${sizeAttr} b="${titleBold}" i="
|
|
7620
|
+
<a:defRPr ${sizeAttr} b="${titleBold}" i="${titleItalic}" u="${titleUnderline}" strike="noStrike">
|
|
7182
7621
|
<a:solidFill>${createColorElement(opts.color || "000000")}</a:solidFill>
|
|
7183
|
-
|
|
7622
|
+
${createChartTextFonts(opts.fontFace || "Arial")}
|
|
7184
7623
|
</a:defRPr>
|
|
7185
7624
|
</a:pPr>
|
|
7186
7625
|
<a:r>
|
|
7187
|
-
<a:rPr ${sizeAttr} b="${titleBold}" i="
|
|
7626
|
+
<a:rPr ${sizeAttr} b="${titleBold}" i="${titleItalic}" u="${titleUnderline}" strike="noStrike">
|
|
7188
7627
|
<a:solidFill>${createColorElement(opts.color || "000000")}</a:solidFill>
|
|
7189
|
-
|
|
7628
|
+
${createChartTextFonts(opts.fontFace || "Arial")}
|
|
7190
7629
|
</a:rPr>
|
|
7191
7630
|
<a:t>${encodeXmlEntities(opts.title) || ""}</a:t>
|
|
7192
7631
|
</a:r>
|
|
@@ -7260,11 +7699,105 @@ function createGridLineElement(glOpts) {
|
|
|
7260
7699
|
strXml += "</c:majorGridlines>";
|
|
7261
7700
|
return strXml;
|
|
7262
7701
|
}
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
|
|
7267
|
-
|
|
7702
|
+
/**
|
|
7703
|
+
* Build a `<c:pt>` numeric-cache data point, or '' to leave a gap.
|
|
7704
|
+
*
|
|
7705
|
+
* `<c:v>` inside a `<c:numCache>` is an `xsd:double`; emitting `NaN`, `Infinity`
|
|
7706
|
+
* or an empty string yields an invalid value that makes PowerPoint report the
|
|
7707
|
+
* package as needing repair. Null/undefined are intentional gaps and are skipped
|
|
7708
|
+
* silently (a sparse, idx-keyed cache is valid); other non-finite numbers are
|
|
7709
|
+
* skipped with a warning, per the library's "warn rather than emit a degenerate
|
|
7710
|
+
* result" policy.
|
|
7711
|
+
* @param idx - zero-based data-point index (emitted as `idx`)
|
|
7712
|
+
* @param value - numeric value (or null/undefined gap)
|
|
7713
|
+
*/
|
|
7714
|
+
function numCachePt(idx, value) {
|
|
7715
|
+
if (value == null) return "";
|
|
7716
|
+
if (!Number.isFinite(value)) {
|
|
7717
|
+
console.warn(`Warning: chart value "${value}" at index ${idx} is not a finite number; data point omitted.`);
|
|
7718
|
+
return "";
|
|
7719
|
+
}
|
|
7720
|
+
return `<c:pt idx="${idx}"><c:v>${value}</c:v></c:pt>`;
|
|
7721
|
+
}
|
|
7722
|
+
/**
|
|
7723
|
+
* Build a `<c:serLines>` ("Series Lines") element for a bar chart.
|
|
7724
|
+
* @param opt - `true` for PowerPoint automatic styling, an {@link OptsChartGridLine}
|
|
7725
|
+
* to customize the line, or falsy / `{ style: 'none' }` to omit the element.
|
|
7726
|
+
*/
|
|
7727
|
+
function createSerLinesElement(opt) {
|
|
7728
|
+
if (!opt) return "";
|
|
7729
|
+
if (opt === true) return "<c:serLines/>";
|
|
7730
|
+
if (opt.style === "none") return "";
|
|
7731
|
+
let strXml = "<c:serLines><c:spPr>";
|
|
7732
|
+
strXml += `<a:ln w="${valToPts(opt.size || DEF_CHART_GRIDLINE.size)}" cap="${createLineCap(opt.cap || DEF_CHART_GRIDLINE.cap)}">`;
|
|
7733
|
+
strXml += `<a:solidFill><a:srgbClr val="${opt.color || DEF_CHART_GRIDLINE.color}"/></a:solidFill>`;
|
|
7734
|
+
strXml += `<a:prstDash val="${opt.style || DEF_CHART_GRIDLINE.style}"/><a:round/>`;
|
|
7735
|
+
strXml += "</a:ln></c:spPr></c:serLines>";
|
|
7736
|
+
return strXml;
|
|
7737
|
+
}
|
|
7738
|
+
function makeCustomDLblXml(idx, text, opts) {
|
|
7739
|
+
const sz = Math.round((opts.dataLabelFontSize || 12) * 100);
|
|
7740
|
+
const bold = opts.dataLabelFontBold ? "1" : "0";
|
|
7741
|
+
const italic = opts.dataLabelFontItalic ? "1" : "0";
|
|
7742
|
+
const color = createColorElement(opts.dataLabelColor || "000000");
|
|
7743
|
+
const face = opts.dataLabelFontFace || "Arial";
|
|
7744
|
+
const lang = opts.lang || "en-US";
|
|
7745
|
+
return `<c:dLbl><c:idx val="${idx}"/><c:tx><c:rich><a:bodyPr/><a:lstStyle/><a:p><a:pPr><a:defRPr sz="${sz}" b="${bold}" i="${italic}" u="none" strike="noStrike"><a:solidFill>${color}</a:solidFill>${createChartTextFonts(face)}</a:defRPr></a:pPr><a:r><a:rPr lang="${lang}" sz="${sz}" b="${bold}" i="${italic}" u="none" strike="noStrike" dirty="0"><a:solidFill>${color}</a:solidFill>${createChartTextFonts(face)}</a:rPr><a:t>${encodeXmlEntities(text)}</a:t></a:r></a:p></c:rich></c:tx><c:showLegendKey val="0"/><c:showVal val="0"/><c:showCatName val="0"/><c:showSerName val="0"/><c:showPercent val="0"/><c:showBubbleSize val="0"/></c:dLbl>`;
|
|
7746
|
+
}
|
|
7747
|
+
/**
|
|
7748
|
+
* Build an `<a:ln>` border element from a per-data-point `BorderProps`.
|
|
7749
|
+
* @param border - point border style (`type`, `color`, `pt`)
|
|
7750
|
+
*/
|
|
7751
|
+
function createChartBorderLine(border) {
|
|
7752
|
+
if (border.type === "none") return "<a:ln><a:noFill/></a:ln>";
|
|
7753
|
+
const dash = border.type === "dash" ? "dash" : "solid";
|
|
7754
|
+
return `<a:ln w="${valToPts(border.pt ?? 1)}" cap="flat"><a:solidFill>${createColorElement(border.color || "666666")}</a:solidFill><a:prstDash val="${dash}"/><a:round/></a:ln>`;
|
|
7755
|
+
}
|
|
7756
|
+
/**
|
|
7757
|
+
* Build `<c:dPt>` entries for a series in the bar/line/area/scatter loops.
|
|
7758
|
+
*
|
|
7759
|
+
* Merges two sources into a single `c:dPt` per index so we never emit a
|
|
7760
|
+
* duplicate `<c:idx>` (which corrupts the chart):
|
|
7761
|
+
* - legacy single-series color-vary fills (bar/scatter), supplied via `varyColors`
|
|
7762
|
+
* - per-point `pointStyles` border/fill overrides
|
|
7763
|
+
*
|
|
7764
|
+
* Must be emitted in schema position *before* `c:dLbls` (CT_*Ser order).
|
|
7765
|
+
* RADAR is skipped: extra per-point markup historically corrupts the chart.
|
|
7766
|
+
*
|
|
7767
|
+
* @param chartType - series chart type
|
|
7768
|
+
* @param obj - series data (reads `values`, `pointStyles`)
|
|
7769
|
+
* @param opts - chart options (fill/shadow/lineSize context)
|
|
7770
|
+
* @param varyColors - color array when single-series color-vary applies, else `null`
|
|
7771
|
+
*/
|
|
7772
|
+
function makeSeriesDataPointsXml(chartType, obj, opts, varyColors) {
|
|
7773
|
+
if (chartType === "radar") return "";
|
|
7774
|
+
const pointStyles = obj.pointStyles;
|
|
7775
|
+
if (!varyColors && !pointStyles?.length) return "";
|
|
7776
|
+
const isBar = chartType === "bar" || chartType === "bar3D";
|
|
7777
|
+
const isScatter = chartType === "scatter";
|
|
7778
|
+
let xml = "";
|
|
7779
|
+
obj.values.forEach((value, index) => {
|
|
7780
|
+
const ptStyle = pointStyles?.[index];
|
|
7781
|
+
const arrColors = varyColors ? value < 0 ? opts.invertedColors || opts.chartColors || BARCHART_COLORS : varyColors : null;
|
|
7782
|
+
const fillColor = ptStyle?.fill || (arrColors ? arrColors[index % arrColors.length] : null);
|
|
7783
|
+
const border = ptStyle?.border;
|
|
7784
|
+
if (!fillColor && !border) return;
|
|
7785
|
+
xml += "<c:dPt>";
|
|
7786
|
+
xml += `<c:idx val="${index}"/>`;
|
|
7787
|
+
if (isBar) xml += "<c:invertIfNegative val=\"0\"/>";
|
|
7788
|
+
xml += "<c:bubble3D val=\"0\"/>";
|
|
7789
|
+
xml += "<c:spPr>";
|
|
7790
|
+
if ((isBar || isScatter) && opts.lineSize === 0 && !border && !ptStyle?.fill) xml += "<a:ln><a:noFill/></a:ln>";
|
|
7791
|
+
else {
|
|
7792
|
+
if (fillColor) if (chartType === "bar3D") xml += `<a:ln><a:solidFill>${createColorElement(fillColor)}</a:solidFill></a:ln>`;
|
|
7793
|
+
else xml += `<a:solidFill>${createColorElement(fillColor)}</a:solidFill>`;
|
|
7794
|
+
if (border) xml += createChartBorderLine(border);
|
|
7795
|
+
}
|
|
7796
|
+
xml += createShadowElement(opts.shadow, DEF_SHAPE_SHADOW);
|
|
7797
|
+
xml += "</c:spPr>";
|
|
7798
|
+
xml += "</c:dPt>";
|
|
7799
|
+
});
|
|
7800
|
+
return xml;
|
|
7268
7801
|
}
|
|
7269
7802
|
//#endregion
|
|
7270
7803
|
//#region src/gen-media.ts
|
|
@@ -7313,6 +7846,37 @@ function encodeSlideMediaRels(layout, runtime) {
|
|
|
7313
7846
|
/**
|
|
7314
7847
|
* PptxGenJS: XML Generation
|
|
7315
7848
|
*/
|
|
7849
|
+
const _warnedTextRangeMsgs = /* @__PURE__ */ new Set();
|
|
7850
|
+
function warnTextRangeOnce(msg) {
|
|
7851
|
+
if (_warnedTextRangeMsgs.has(msg)) return;
|
|
7852
|
+
_warnedTextRangeMsgs.add(msg);
|
|
7853
|
+
console.warn(msg);
|
|
7854
|
+
}
|
|
7855
|
+
/**
|
|
7856
|
+
* Clamp a font size (points) into ST_TextFontSize (1-4000pt) and return it in
|
|
7857
|
+
* hundredths of a point for the `sz` attribute. Out-of-range sizes make
|
|
7858
|
+
* PowerPoint report the package as needing repair (e.g. `sz` > 400000 or < 100).
|
|
7859
|
+
*/
|
|
7860
|
+
function clampFontSizeSz(fontSizePts) {
|
|
7861
|
+
const raw = Math.round(fontSizePts * 100);
|
|
7862
|
+
const clamped = Math.min(4e5, Math.max(100, raw));
|
|
7863
|
+
if (clamped !== raw) warnTextRangeOnce(`Warning: fontSize ${fontSizePts} is outside the valid range 1-4000pt; using ${clamped / 100}.`);
|
|
7864
|
+
return clamped;
|
|
7865
|
+
}
|
|
7866
|
+
/** Clamp character spacing (points) into ST_TextPoint (-4000..4000pt); returns hundredths for the `spc` attribute. */
|
|
7867
|
+
function clampCharSpacingSpc(charSpacingPts) {
|
|
7868
|
+
const raw = Math.round(charSpacingPts * 100);
|
|
7869
|
+
const clamped = Math.min(4e5, Math.max(-4e5, raw));
|
|
7870
|
+
if (clamped !== raw) warnTextRangeOnce(`Warning: charSpacing ${charSpacingPts} is outside the valid range -4000..4000pt; using ${clamped / 100}.`);
|
|
7871
|
+
return clamped;
|
|
7872
|
+
}
|
|
7873
|
+
/** Clamp line spacing (points) into ST_TextSpacingPoint (0..1584pt); returns hundredths for `<a:spcPts val>`. */
|
|
7874
|
+
function clampLineSpacingPts(lineSpacingPts) {
|
|
7875
|
+
const raw = Math.round(lineSpacingPts * 100);
|
|
7876
|
+
const clamped = Math.min(158400, Math.max(0, raw));
|
|
7877
|
+
if (clamped !== raw) warnTextRangeOnce(`Warning: lineSpacing ${lineSpacingPts} is outside the valid range 0-1584pt; using ${clamped / 100}.`);
|
|
7878
|
+
return clamped;
|
|
7879
|
+
}
|
|
7316
7880
|
const ImageSizingXml = {
|
|
7317
7881
|
cover: function(imgSize, boxDim) {
|
|
7318
7882
|
const imgRatio = imgSize.h / imgSize.w;
|
|
@@ -7337,6 +7901,15 @@ const ImageSizingXml = {
|
|
|
7337
7901
|
const r = imgSize.w - (boxDim.x + boxDim.w);
|
|
7338
7902
|
const t = boxDim.y;
|
|
7339
7903
|
const b = imgSize.h - (boxDim.y + boxDim.h);
|
|
7904
|
+
if (l < 0 || r < 0 || t < 0 || b < 0) {
|
|
7905
|
+
const over = [
|
|
7906
|
+
l < 0 && `x (${l < 0 ? -l : 0} past left edge)`,
|
|
7907
|
+
r < 0 && `x+w (${-r} past right edge)`,
|
|
7908
|
+
t < 0 && `y (${-t} past top edge)`,
|
|
7909
|
+
b < 0 && `y+h (${-b} past bottom edge)`
|
|
7910
|
+
].filter(Boolean).join(", ");
|
|
7911
|
+
throw new Error(`addImage sizing.type 'crop': crop window overflows image bounds — ${over}. Ensure x≥0, y≥0, x+w≤w, y+h≤h.`);
|
|
7912
|
+
}
|
|
7340
7913
|
return `<a:srcRect l="${Math.round(1e5 * (l / imgSize.w))}" r="${Math.round(1e5 * (r / imgSize.w))}" t="${Math.round(1e5 * (t / imgSize.h))}" b="${Math.round(1e5 * (b / imgSize.h))}"/><a:stretch/>`;
|
|
7341
7914
|
}
|
|
7342
7915
|
};
|
|
@@ -7349,18 +7922,91 @@ const ImageSizingXml = {
|
|
|
7349
7922
|
* @param {number} cy - shape height (EMU), used to scale `rectRadius`
|
|
7350
7923
|
* @return {string} `<a:prstGeom>` XML
|
|
7351
7924
|
*/
|
|
7925
|
+
const RECT_RADIUS_ADJ1_SHAPES = new Set(["round2SameRect", "round2DiagRect"]);
|
|
7926
|
+
const SHAPE_LOCK_ATTRS = [
|
|
7927
|
+
"noGrp",
|
|
7928
|
+
"noSelect",
|
|
7929
|
+
"noRot",
|
|
7930
|
+
"noChangeAspect",
|
|
7931
|
+
"noMove",
|
|
7932
|
+
"noResize",
|
|
7933
|
+
"noEditPoints",
|
|
7934
|
+
"noAdjustHandles",
|
|
7935
|
+
"noChangeArrowheads",
|
|
7936
|
+
"noChangeShapeType",
|
|
7937
|
+
"noTextEdit"
|
|
7938
|
+
];
|
|
7939
|
+
const PICTURE_LOCK_ATTRS = [
|
|
7940
|
+
"noGrp",
|
|
7941
|
+
"noSelect",
|
|
7942
|
+
"noRot",
|
|
7943
|
+
"noChangeAspect",
|
|
7944
|
+
"noMove",
|
|
7945
|
+
"noResize",
|
|
7946
|
+
"noEditPoints",
|
|
7947
|
+
"noAdjustHandles",
|
|
7948
|
+
"noChangeArrowheads",
|
|
7949
|
+
"noChangeShapeType",
|
|
7950
|
+
"noCrop"
|
|
7951
|
+
];
|
|
7952
|
+
const GRAPHIC_FRAME_LOCK_ATTRS = [
|
|
7953
|
+
"noGrp",
|
|
7954
|
+
"noDrilldown",
|
|
7955
|
+
"noSelect",
|
|
7956
|
+
"noChangeAspect",
|
|
7957
|
+
"noMove",
|
|
7958
|
+
"noResize"
|
|
7959
|
+
];
|
|
7960
|
+
/**
|
|
7961
|
+
* Serialize an object-lock element (`a:spLocks` / `a:picLocks` / `a:graphicFrameLocks`).
|
|
7962
|
+
* Only flags set to `true` AND valid for this element type are emitted; a flag set on an
|
|
7963
|
+
* unsupported element type is dropped with a warning (silent coercion is a footgun).
|
|
7964
|
+
* @param tag - locking element tag, e.g. `'a:spLocks'`
|
|
7965
|
+
* @param allowed - attribute names this element type supports, in desired emit order
|
|
7966
|
+
* @param locks - merged lock flags (callers fold any hard-coded default in first)
|
|
7967
|
+
* @param objectName - for the warning message
|
|
7968
|
+
* @returns the locking element string, or `''` when no applicable flag is set
|
|
7969
|
+
*/
|
|
7970
|
+
function genXmlObjectLock(tag, allowed, locks, objectName) {
|
|
7971
|
+
if (!locks) return "";
|
|
7972
|
+
const lockMap = locks;
|
|
7973
|
+
for (const key of Object.keys(lockMap)) if (lockMap[key] && !allowed.includes(key)) console.warn(`Warning: objectLock.${key} is not supported on <${tag}> (object "${objectName ?? ""}") and was ignored.`);
|
|
7974
|
+
const attrs = allowed.filter((name) => lockMap[name] === true).map((name) => `${name}="1"`);
|
|
7975
|
+
return attrs.length > 0 ? `<${tag} ${attrs.join(" ")}/>` : "";
|
|
7976
|
+
}
|
|
7352
7977
|
function genXmlPresetGeom(shapeName, options, cx, cy) {
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
|
|
7978
|
+
if (!VALID_SHAPE_PRESETS.has(shapeName)) throw new Error(`Invalid shape "${String(shapeName)}"! Use a value from \`pptxgen.shapes.*\` (e.g. \`pptxgen.shapes.RECTANGLE\`). PowerPoint can't render unknown preset geometries and will drop the shape during repair.`);
|
|
7979
|
+
let avLst = "";
|
|
7980
|
+
const emittedAdjNames = /* @__PURE__ */ new Set();
|
|
7981
|
+
const emitGuide = (name, fmlaVal) => {
|
|
7982
|
+
avLst += `<a:gd name="${name}" fmla="val ${fmlaVal}"/>`;
|
|
7983
|
+
emittedAdjNames.add(name);
|
|
7984
|
+
};
|
|
7985
|
+
if (options.rectRadius) {
|
|
7986
|
+
const adjVal = Math.round(options.rectRadius * EMU * 1e5 / Math.min(cx, cy));
|
|
7987
|
+
if (RECT_RADIUS_ADJ1_SHAPES.has(shapeName)) {
|
|
7988
|
+
emitGuide("adj1", adjVal);
|
|
7989
|
+
emitGuide("adj2", 0);
|
|
7990
|
+
} else emitGuide("adj", adjVal);
|
|
7991
|
+
} else if (options.angleRange) {
|
|
7356
7992
|
for (let i = 0; i < 2; i++) {
|
|
7357
7993
|
const angle = options.angleRange[i];
|
|
7358
|
-
|
|
7994
|
+
emitGuide(`adj${i + 1}`, convertRotationDegrees(angle));
|
|
7359
7995
|
}
|
|
7360
|
-
if (options.arcThicknessRatio)
|
|
7996
|
+
if (options.arcThicknessRatio) emitGuide("adj3", Math.round(options.arcThicknessRatio * 5e4));
|
|
7361
7997
|
}
|
|
7362
|
-
|
|
7363
|
-
|
|
7998
|
+
if (options.shapeAdjust) (Array.isArray(options.shapeAdjust) ? options.shapeAdjust : [options.shapeAdjust]).forEach((adj) => {
|
|
7999
|
+
if (!adj || typeof adj.name !== "string" || adj.name.length === 0 || typeof adj.value !== "number" || !isFinite(adj.value)) {
|
|
8000
|
+
console.warn(`Warning: shapeAdjust entry ${JSON.stringify(adj)} is invalid (needs { name:string, value:number }) and was ignored.`);
|
|
8001
|
+
return;
|
|
8002
|
+
}
|
|
8003
|
+
if (emittedAdjNames.has(adj.name)) {
|
|
8004
|
+
console.warn(`Warning: shapeAdjust "${adj.name}" was ignored because rectRadius/angleRange already set that handle.`);
|
|
8005
|
+
return;
|
|
8006
|
+
}
|
|
8007
|
+
emitGuide(adj.name, Math.round(adj.value * 1e5));
|
|
8008
|
+
});
|
|
8009
|
+
return `<a:prstGeom prst="${shapeName}"><a:avLst>${avLst}</a:avLst></a:prstGeom>`;
|
|
7364
8010
|
}
|
|
7365
8011
|
/**
|
|
7366
8012
|
* Emit an `<a:custGeom>` for a freeform path built from `points`.
|
|
@@ -7413,6 +8059,45 @@ function genXmlCustGeom(points, cx, cy, layout) {
|
|
|
7413
8059
|
}
|
|
7414
8060
|
const PLACEHOLDER_TYPE_MAP = PLACEHOLDER_TYPES;
|
|
7415
8061
|
/**
|
|
8062
|
+
* Emit the `<a:lnL>/<a:lnR>/<a:lnT>/<a:lnB>` border children of an `<a:tcPr>` for a table cell.
|
|
8063
|
+
* Shared by normal cells and the dummy span (`_hmerge`/`_vmerge`) cells so a merged region's
|
|
8064
|
+
* outer edges render with the same border as its origin cell (Issue #680).
|
|
8065
|
+
* @param {BorderProps[]} cellBorder - 4-tuple of border props in [top, right, bottom, left] order
|
|
8066
|
+
* @return {string} concatenated border element XML, in the LRTB document order PowerPoint expects
|
|
8067
|
+
*/
|
|
8068
|
+
function genTableCellBorderXml(cellBorder) {
|
|
8069
|
+
let strXml = "";
|
|
8070
|
+
[
|
|
8071
|
+
{
|
|
8072
|
+
idx: 3,
|
|
8073
|
+
name: "lnL"
|
|
8074
|
+
},
|
|
8075
|
+
{
|
|
8076
|
+
idx: 1,
|
|
8077
|
+
name: "lnR"
|
|
8078
|
+
},
|
|
8079
|
+
{
|
|
8080
|
+
idx: 0,
|
|
8081
|
+
name: "lnT"
|
|
8082
|
+
},
|
|
8083
|
+
{
|
|
8084
|
+
idx: 2,
|
|
8085
|
+
name: "lnB"
|
|
8086
|
+
}
|
|
8087
|
+
].forEach((obj) => {
|
|
8088
|
+
const border = cellBorder[obj.idx];
|
|
8089
|
+
if (!border) return;
|
|
8090
|
+
const cap = createLineCap(border.cap);
|
|
8091
|
+
if (border.type !== "none") {
|
|
8092
|
+
strXml += `<a:${obj.name} w="${valToPts(border.pt)}" cap="${cap}" cmpd="sng" algn="ctr">`;
|
|
8093
|
+
strXml += `<a:solidFill>${createColorElement(border.color)}</a:solidFill>`;
|
|
8094
|
+
strXml += `<a:prstDash val="${border.type === "dash" ? "sysDash" : "solid"}"/><a:round/><a:headEnd type="none" w="med" len="med"/><a:tailEnd type="none" w="med" len="med"/>`;
|
|
8095
|
+
strXml += `</a:${obj.name}>`;
|
|
8096
|
+
} else strXml += `<a:${obj.name} w="0" cap="${cap}" cmpd="sng" algn="ctr"><a:noFill/></a:${obj.name}>`;
|
|
8097
|
+
});
|
|
8098
|
+
return strXml;
|
|
8099
|
+
}
|
|
8100
|
+
/**
|
|
7416
8101
|
* Transforms a slide or slideLayout to resulting XML string - Creates `ppt/slide*.xml`
|
|
7417
8102
|
* @param {PresSlideInternal|SlideLayoutInternal} slideObject - slide object created within createSlideObject
|
|
7418
8103
|
* @return {string} XML string with <p:cSld> as the root
|
|
@@ -7471,9 +8156,16 @@ function slideObjectToXml(slide) {
|
|
|
7471
8156
|
intColCnt += cellOpts?.colspan ? Number(cellOpts.colspan) : 1;
|
|
7472
8157
|
});
|
|
7473
8158
|
strXml = `<p:graphicFrame><p:nvGraphicFramePr><p:cNvPr id="${intTableNum * slide._slideNum + 1}" name="${slideItemObj.options.objectName}" descr="${encodeXmlEntities(slideItemObj.options.altText || "")}"/>`;
|
|
7474
|
-
strXml +=
|
|
8159
|
+
strXml += `<p:cNvGraphicFramePr>${genXmlObjectLock("a:graphicFrameLocks", GRAPHIC_FRAME_LOCK_ATTRS, {
|
|
8160
|
+
noGrp: true,
|
|
8161
|
+
...slideItemObj.options.objectLock
|
|
8162
|
+
}, slideItemObj.options.objectName)}</p:cNvGraphicFramePr> <p:nvPr><p:extLst><p:ext uri="{D42A27DB-BD31-4B8C-83A1-F6EECF244321}"><p14:modId xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main" val="1579011935"/></p:ext></p:extLst></p:nvPr></p:nvGraphicFramePr>`;
|
|
7475
8163
|
strXml += `<p:xfrm><a:off x="${x || (x === 0 ? 0 : EMU)}" y="${y || (y === 0 ? 0 : EMU)}"/><a:ext cx="${cx || (cx === 0 ? 0 : EMU)}" cy="${cy || EMU}"/></p:xfrm>`;
|
|
7476
|
-
|
|
8164
|
+
{
|
|
8165
|
+
const tblPrAttrs = (objTabOpts.hasHeader ? " firstRow=\"1\"" : "") + (objTabOpts.hasFooter ? " lastRow=\"1\"" : "") + (objTabOpts.hasBandedRows ? " bandRow=\"1\"" : "") + (objTabOpts.hasBandedColumns ? " bandCol=\"1\"" : "") + (objTabOpts.hasFirstColumn ? " firstCol=\"1\"" : "") + (objTabOpts.hasLastColumn ? " lastCol=\"1\"" : "");
|
|
8166
|
+
const tblPr = objTabOpts.tableStyle ? `<a:tblPr${tblPrAttrs}><a:tableStyleId>${objTabOpts.tableStyle}</a:tableStyleId></a:tblPr>` : `<a:tblPr${tblPrAttrs}/>`;
|
|
8167
|
+
strXml += `<a:graphic><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/table"><a:tbl>${tblPr}`;
|
|
8168
|
+
}
|
|
7477
8169
|
if (Array.isArray(objTabOpts.colW)) {
|
|
7478
8170
|
strXml += "<a:tblGrid>";
|
|
7479
8171
|
for (let col = 0; col < intColCnt; col++) {
|
|
@@ -7499,7 +8191,8 @@ function slideObjectToXml(slide) {
|
|
|
7499
8191
|
return {
|
|
7500
8192
|
_type: "tablecell",
|
|
7501
8193
|
options: { rowspan },
|
|
7502
|
-
_hmerge: true
|
|
8194
|
+
_hmerge: true,
|
|
8195
|
+
_spanOrigin: cell
|
|
7503
8196
|
};
|
|
7504
8197
|
});
|
|
7505
8198
|
cells.splice(cIdx + 1, 0, ...vMergeCells);
|
|
@@ -7515,12 +8208,14 @@ function slideObjectToXml(slide) {
|
|
|
7515
8208
|
const colspan = cell.options?.colspan;
|
|
7516
8209
|
const _hmerge = cell._hmerge;
|
|
7517
8210
|
if (rowspan && rowspan > 1) {
|
|
8211
|
+
const _spanOrigin = cell._spanOrigin || cell;
|
|
7518
8212
|
const hMergeCell = {
|
|
7519
8213
|
_type: "tablecell",
|
|
7520
8214
|
options: { colspan },
|
|
7521
8215
|
_rowContinue: rowspan - 1,
|
|
7522
8216
|
_vmerge: true,
|
|
7523
|
-
_hmerge
|
|
8217
|
+
_hmerge,
|
|
8218
|
+
_spanOrigin
|
|
7524
8219
|
};
|
|
7525
8220
|
nextRow.splice(cIdx, 0, hMergeCell);
|
|
7526
8221
|
}
|
|
@@ -7530,7 +8225,7 @@ function slideObjectToXml(slide) {
|
|
|
7530
8225
|
let intRowH = 0;
|
|
7531
8226
|
if (Array.isArray(objTabOpts.rowH) && objTabOpts.rowH[rIdx]) intRowH = inch2Emu(Number(objTabOpts.rowH[rIdx]));
|
|
7532
8227
|
else if (objTabOpts.rowH && !isNaN(Number(objTabOpts.rowH))) intRowH = inch2Emu(Number(objTabOpts.rowH));
|
|
7533
|
-
else if (slideItemObj.options.cy || slideItemObj.options.h) intRowH = Math.round((slideItemObj.options.h ?
|
|
8228
|
+
else if (slideItemObj.options.cy || slideItemObj.options.h) intRowH = Math.round((slideItemObj.options.h ? cy : typeof slideItemObj.options.cy === "number" ? slideItemObj.options.cy : 1) / arrTabRows.length);
|
|
7534
8229
|
strXml += `<a:tr h="${intRowH}">`;
|
|
7535
8230
|
cells.forEach((cellObj) => {
|
|
7536
8231
|
const cell = cellObj;
|
|
@@ -7543,7 +8238,17 @@ function slideObjectToXml(slide) {
|
|
|
7543
8238
|
let cellSpanAttrStr = Object.entries(cellSpanAttrs).filter(([, v]) => !!v).map(([k, v]) => `${String(k)}="${String(v)}"`).join(" ");
|
|
7544
8239
|
if (cellSpanAttrStr) cellSpanAttrStr = " " + cellSpanAttrStr;
|
|
7545
8240
|
if (cell._hmerge || cell._vmerge) {
|
|
7546
|
-
|
|
8241
|
+
const origin = cell._spanOrigin;
|
|
8242
|
+
let spanPrXml = "";
|
|
8243
|
+
if (origin) {
|
|
8244
|
+
const originOpts = origin.options || {};
|
|
8245
|
+
const originBorder = Array.isArray(originOpts.border) ? originOpts.border : null;
|
|
8246
|
+
if (originBorder) spanPrXml += genTableCellBorderXml(originBorder);
|
|
8247
|
+
let spanFill = origin._optImp?.fill?.color ? origin._optImp.fill.color : origin._optImp?.fill && typeof origin._optImp.fill === "string" ? origin._optImp.fill : "";
|
|
8248
|
+
spanFill = spanFill || originOpts.fill ? originOpts.fill : "";
|
|
8249
|
+
if (spanFill) spanPrXml += genXmlColorSelection(spanFill);
|
|
8250
|
+
}
|
|
8251
|
+
strXml += `<a:tc${cellSpanAttrStr}><a:tcPr>${spanPrXml}</a:tcPr></a:tc>`;
|
|
7547
8252
|
return;
|
|
7548
8253
|
}
|
|
7549
8254
|
const cellOpts = cell.options || {};
|
|
@@ -7587,32 +8292,7 @@ function slideObjectToXml(slide) {
|
|
|
7587
8292
|
else cellMarginXml = ` marL="${inch2Emu(cellMargin[3])}" marR="${inch2Emu(cellMargin[1])}" marT="${inch2Emu(cellMargin[0])}" marB="${inch2Emu(cellMargin[2])}"`;
|
|
7588
8293
|
strXml += `<a:tc${cellSpanAttrStr}>${genXmlTextBody(cell)}<a:tcPr${cellMarginXml}${cellValign}${cellTextDir}>`;
|
|
7589
8294
|
const cellBorder = Array.isArray(cellOpts.border) ? cellOpts.border : null;
|
|
7590
|
-
if (cellBorder)
|
|
7591
|
-
{
|
|
7592
|
-
idx: 3,
|
|
7593
|
-
name: "lnL"
|
|
7594
|
-
},
|
|
7595
|
-
{
|
|
7596
|
-
idx: 1,
|
|
7597
|
-
name: "lnR"
|
|
7598
|
-
},
|
|
7599
|
-
{
|
|
7600
|
-
idx: 0,
|
|
7601
|
-
name: "lnT"
|
|
7602
|
-
},
|
|
7603
|
-
{
|
|
7604
|
-
idx: 2,
|
|
7605
|
-
name: "lnB"
|
|
7606
|
-
}
|
|
7607
|
-
].forEach((obj) => {
|
|
7608
|
-
const border = cellBorder[obj.idx];
|
|
7609
|
-
if (border.type !== "none") {
|
|
7610
|
-
strXml += `<a:${obj.name} w="${valToPts(border.pt)}" cap="flat" cmpd="sng" algn="ctr">`;
|
|
7611
|
-
strXml += `<a:solidFill>${createColorElement(border.color)}</a:solidFill>`;
|
|
7612
|
-
strXml += `<a:prstDash val="${border.type === "dash" ? "sysDash" : "solid"}"/><a:round/><a:headEnd type="none" w="med" len="med"/><a:tailEnd type="none" w="med" len="med"/>`;
|
|
7613
|
-
strXml += `</a:${obj.name}>`;
|
|
7614
|
-
} else strXml += `<a:${obj.name} w="0" cap="flat" cmpd="sng" algn="ctr"><a:noFill/></a:${obj.name}>`;
|
|
7615
|
-
});
|
|
8295
|
+
if (cellBorder) strXml += genTableCellBorderXml(cellBorder);
|
|
7616
8296
|
strXml += cellFill;
|
|
7617
8297
|
strXml += " </a:tcPr>";
|
|
7618
8298
|
strXml += " </a:tc>";
|
|
@@ -7631,10 +8311,10 @@ function slideObjectToXml(slide) {
|
|
|
7631
8311
|
if (!slideItemObj.options.line && cy === 0) cy = EMU * .3;
|
|
7632
8312
|
if (!slideItemObj.options._bodyProp) slideItemObj.options._bodyProp = {};
|
|
7633
8313
|
if (slideItemObj.options.margin && Array.isArray(slideItemObj.options.margin)) {
|
|
7634
|
-
slideItemObj.options._bodyProp.
|
|
8314
|
+
slideItemObj.options._bodyProp.tIns = valToPts(slideItemObj.options.margin[0] || 0);
|
|
7635
8315
|
slideItemObj.options._bodyProp.rIns = valToPts(slideItemObj.options.margin[1] || 0);
|
|
7636
8316
|
slideItemObj.options._bodyProp.bIns = valToPts(slideItemObj.options.margin[2] || 0);
|
|
7637
|
-
slideItemObj.options._bodyProp.
|
|
8317
|
+
slideItemObj.options._bodyProp.lIns = valToPts(slideItemObj.options.margin[3] || 0);
|
|
7638
8318
|
} else if (typeof slideItemObj.options.margin === "number") {
|
|
7639
8319
|
slideItemObj.options._bodyProp.lIns = valToPts(slideItemObj.options.margin);
|
|
7640
8320
|
slideItemObj.options._bodyProp.rIns = valToPts(slideItemObj.options.margin);
|
|
@@ -7646,7 +8326,11 @@ function slideObjectToXml(slide) {
|
|
|
7646
8326
|
if (slideItemObj.options.hyperlink?.url) strSlideXml += `<a:hlinkClick r:id="rId${slideItemObj.options.hyperlink._rId}" tooltip="${slideItemObj.options.hyperlink.tooltip ? encodeXmlEntities(slideItemObj.options.hyperlink.tooltip) : ""}"/>`;
|
|
7647
8327
|
if (slideItemObj.options.hyperlink?.slide) strSlideXml += `<a:hlinkClick r:id="rId${slideItemObj.options.hyperlink._rId}" tooltip="${slideItemObj.options.hyperlink.tooltip ? encodeXmlEntities(slideItemObj.options.hyperlink.tooltip) : ""}" action="ppaction://hlinksldjump"/>`;
|
|
7648
8328
|
strSlideXml += "</p:cNvPr>";
|
|
7649
|
-
|
|
8329
|
+
{
|
|
8330
|
+
const spLockXml = genXmlObjectLock("a:spLocks", SHAPE_LOCK_ATTRS, slideItemObj.options.objectLock, slideItemObj.options.objectName);
|
|
8331
|
+
strSlideXml += "<p:cNvSpPr" + (slideItemObj.options?.isTextBox ? " txBox=\"1\"" : "");
|
|
8332
|
+
strSlideXml += spLockXml ? `>${spLockXml}</p:cNvSpPr>` : "/>";
|
|
8333
|
+
}
|
|
7650
8334
|
strSlideXml += `<p:nvPr>${slideItemObj._type === "placeholder" ? genXmlPlaceholder(slideItemObj) : genXmlPlaceholder(placeholderObj)}</p:nvPr>`;
|
|
7651
8335
|
strSlideXml += "</p:nvSpPr><p:spPr>";
|
|
7652
8336
|
strSlideXml += `<a:xfrm${locationAttr}>`;
|
|
@@ -7656,7 +8340,8 @@ function slideObjectToXml(slide) {
|
|
|
7656
8340
|
else strSlideXml += genXmlPresetGeom(slideItemObj.shape, slideItemObj.options, cx, cy);
|
|
7657
8341
|
strSlideXml += slideItemObj.options.fill ? genXmlColorSelection(slideItemObj.options.fill) : "<a:noFill/>";
|
|
7658
8342
|
if (slideItemObj.options.line) {
|
|
7659
|
-
|
|
8343
|
+
const lnAttrs = (slideItemObj.options.line.width ? ` w="${lineWidthToEmu(slideItemObj.options.line.width)}"` : "") + (slideItemObj.options.line.cap ? ` cap="${createLineCap(slideItemObj.options.line.cap)}"` : "");
|
|
8344
|
+
strSlideXml += `<a:ln${lnAttrs}>`;
|
|
7660
8345
|
if (slideItemObj.options.line.color) strSlideXml += genXmlColorSelection(slideItemObj.options.line);
|
|
7661
8346
|
if (slideItemObj.options.line.dashType) strSlideXml += `<a:prstDash val="${slideItemObj.options.line.dashType}"/>`;
|
|
7662
8347
|
if (slideItemObj.options.line.beginArrowType) strSlideXml += `<a:headEnd type="${slideItemObj.options.line.beginArrowType}"/>`;
|
|
@@ -7689,13 +8374,17 @@ function slideObjectToXml(slide) {
|
|
|
7689
8374
|
if (slideItemObj.hyperlink?.url) strSlideXml += `<a:hlinkClick r:id="rId${slideItemObj.hyperlink._rId}" tooltip="${slideItemObj.hyperlink.tooltip ? encodeXmlEntities(slideItemObj.hyperlink.tooltip) : ""}"/>`;
|
|
7690
8375
|
if (slideItemObj.hyperlink?.slide) strSlideXml += `<a:hlinkClick r:id="rId${slideItemObj.hyperlink._rId}" tooltip="${slideItemObj.hyperlink.tooltip ? encodeXmlEntities(slideItemObj.hyperlink.tooltip) : ""}" action="ppaction://hlinksldjump"/>`;
|
|
7691
8376
|
strSlideXml += " </p:cNvPr>";
|
|
7692
|
-
strSlideXml +=
|
|
8377
|
+
strSlideXml += ` <p:cNvPicPr>${genXmlObjectLock("a:picLocks", PICTURE_LOCK_ATTRS, {
|
|
8378
|
+
noChangeAspect: true,
|
|
8379
|
+
...slideItemObj.options.objectLock
|
|
8380
|
+
}, slideItemObj.options.objectName)}</p:cNvPicPr>`;
|
|
7693
8381
|
strSlideXml += " <p:nvPr>" + genXmlPlaceholder(placeholderObj) + "</p:nvPr>";
|
|
7694
8382
|
strSlideXml += " </p:nvPicPr>";
|
|
7695
8383
|
strSlideXml += "<p:blipFill>";
|
|
7696
8384
|
if ((slide._relsMedia || []).find((rel) => rel.rId === slideItemObj.imageRid)?.extn === "svg") {
|
|
7697
8385
|
strSlideXml += `<a:blip r:embed="rId${slideItemObj.imageRid - 1}">`;
|
|
7698
8386
|
strSlideXml += slideItemObj.options.transparency ? ` <a:alphaModFix amt="${Math.round((100 - slideItemObj.options.transparency) * 1e3)}"/>` : "";
|
|
8387
|
+
strSlideXml += slideItemObj.options.duotone ? `<a:duotone>${createColorElement(slideItemObj.options.duotone.shadow)}${createColorElement(slideItemObj.options.duotone.highlight)}</a:duotone>` : "";
|
|
7699
8388
|
strSlideXml += " <a:extLst>";
|
|
7700
8389
|
strSlideXml += " <a:ext uri=\"{96DAC541-7B7A-43D3-8B79-37D633B846F1}\">";
|
|
7701
8390
|
strSlideXml += ` <asvg:svgBlip xmlns:asvg="http://schemas.microsoft.com/office/drawing/2016/SVG/main" r:embed="rId${slideItemObj.imageRid}"/>`;
|
|
@@ -7705,6 +8394,7 @@ function slideObjectToXml(slide) {
|
|
|
7705
8394
|
} else {
|
|
7706
8395
|
strSlideXml += `<a:blip r:embed="rId${slideItemObj.imageRid}">`;
|
|
7707
8396
|
strSlideXml += slideItemObj.options.transparency ? `<a:alphaModFix amt="${Math.round((100 - slideItemObj.options.transparency) * 1e3)}"/>` : "";
|
|
8397
|
+
strSlideXml += slideItemObj.options.duotone ? `<a:duotone>${createColorElement(slideItemObj.options.duotone.shadow)}${createColorElement(slideItemObj.options.duotone.highlight)}</a:duotone>` : "";
|
|
7708
8398
|
strSlideXml += "</a:blip>";
|
|
7709
8399
|
}
|
|
7710
8400
|
if (sizing?.type) {
|
|
@@ -7712,10 +8402,17 @@ function slideObjectToXml(slide) {
|
|
|
7712
8402
|
const boxH = sizing.h ? getSmartParseNumber(sizing.h, "Y", slide._presLayout) : cy;
|
|
7713
8403
|
const boxX = getSmartParseNumber(sizing.x || 0, "X", slide._presLayout);
|
|
7714
8404
|
const boxY = getSmartParseNumber(sizing.y || 0, "Y", slide._presLayout);
|
|
7715
|
-
|
|
8405
|
+
let cropSize = {
|
|
7716
8406
|
w: imgWidth,
|
|
7717
8407
|
h: imgHeight
|
|
7718
|
-
}
|
|
8408
|
+
};
|
|
8409
|
+
if (sizing.type === "cover" || sizing.type === "contain") {
|
|
8410
|
+
const relData = (slide._relsMedia || []).find((rel) => rel.rId === slideItemObj.imageRid)?.data;
|
|
8411
|
+
const natural = typeof relData === "string" ? getImageSizeFromBase64(relData) : null;
|
|
8412
|
+
if (natural) cropSize = natural;
|
|
8413
|
+
else console.warn(`Warning: sizing '${sizing.type}' could not measure natural dimensions for image "${slideItemObj.options.objectName}"; falling back to displayed aspect ratio (crop may be inexact). Provide a raster image (PNG/JPEG/GIF/BMP/WebP) to enable an aspect-correct crop.`);
|
|
8414
|
+
}
|
|
8415
|
+
strSlideXml += ImageSizingXml[sizing.type](cropSize, {
|
|
7719
8416
|
w: boxW,
|
|
7720
8417
|
h: boxH,
|
|
7721
8418
|
x: boxX,
|
|
@@ -7755,7 +8452,7 @@ function slideObjectToXml(slide) {
|
|
|
7755
8452
|
strSlideXml += "<p:pic>";
|
|
7756
8453
|
strSlideXml += " <p:nvPicPr>";
|
|
7757
8454
|
strSlideXml += `<p:cNvPr id="${slideItemObj.mediaRid + 2}" name="${slideItemObj.options.objectName}" descr="${encodeXmlEntities(slideItemObj.options.altText || "")}"/>`;
|
|
7758
|
-
strSlideXml +=
|
|
8455
|
+
strSlideXml += ` <p:cNvPicPr>${genXmlObjectLock("a:picLocks", PICTURE_LOCK_ATTRS, slideItemObj.options.objectLock, slideItemObj.options.objectName)}</p:cNvPicPr>`;
|
|
7759
8456
|
strSlideXml += " <p:nvPr>";
|
|
7760
8457
|
strSlideXml += ` <a:videoFile r:link="rId${slideItemObj.mediaRid}"/>`;
|
|
7761
8458
|
strSlideXml += " </p:nvPr>";
|
|
@@ -7770,7 +8467,10 @@ function slideObjectToXml(slide) {
|
|
|
7770
8467
|
strSlideXml += "<p:pic>";
|
|
7771
8468
|
strSlideXml += " <p:nvPicPr>";
|
|
7772
8469
|
strSlideXml += `<p:cNvPr id="${slideItemObj.mediaRid + 2}" name="${slideItemObj.options.objectName}" descr="${encodeXmlEntities(slideItemObj.options.altText || "")}"><a:hlinkClick r:id="" action="ppaction://media"/></p:cNvPr>`;
|
|
7773
|
-
strSlideXml +=
|
|
8470
|
+
strSlideXml += ` <p:cNvPicPr>${genXmlObjectLock("a:picLocks", PICTURE_LOCK_ATTRS, {
|
|
8471
|
+
noChangeAspect: true,
|
|
8472
|
+
...slideItemObj.options.objectLock
|
|
8473
|
+
}, slideItemObj.options.objectName)}</p:cNvPicPr>`;
|
|
7774
8474
|
strSlideXml += " <p:nvPr>";
|
|
7775
8475
|
strSlideXml += ` <a:videoFile r:link="rId${slideItemObj.mediaRid}"/>`;
|
|
7776
8476
|
strSlideXml += " <p:extLst>";
|
|
@@ -7834,7 +8534,7 @@ function slideObjectToXml(slide) {
|
|
|
7834
8534
|
strSlideXml += "/>";
|
|
7835
8535
|
strSlideXml += " <a:lstStyle><a:lvl1pPr>";
|
|
7836
8536
|
if (slide._slideNumberProps.fontFace || slide._slideNumberProps.fontSize || slide._slideNumberProps.color) {
|
|
7837
|
-
strSlideXml += `<a:defRPr sz="${
|
|
8537
|
+
strSlideXml += `<a:defRPr sz="${clampFontSizeSz(slide._slideNumberProps.fontSize || 12)}">`;
|
|
7838
8538
|
if (slide._slideNumberProps.color) strSlideXml += genXmlColorSelection(slide._slideNumberProps.color);
|
|
7839
8539
|
if (slide._slideNumberProps.fontFace) strSlideXml += `<a:latin typeface="${slide._slideNumberProps.fontFace}"/><a:ea typeface="${slide._slideNumberProps.fontFace}"/><a:cs typeface="${slide._slideNumberProps.fontFace}"/>`;
|
|
7840
8540
|
strSlideXml += "</a:defRPr>";
|
|
@@ -7923,7 +8623,7 @@ function genXmlParagraphProperties(textObj, isDefault) {
|
|
|
7923
8623
|
paragraphPropXml += "";
|
|
7924
8624
|
break;
|
|
7925
8625
|
}
|
|
7926
|
-
if (textObj.options.lineSpacing) strXmlLnSpc = `<a:lnSpc><a:spcPts val="${
|
|
8626
|
+
if (textObj.options.lineSpacing) strXmlLnSpc = `<a:lnSpc><a:spcPts val="${clampLineSpacingPts(textObj.options.lineSpacing)}"/></a:lnSpc>`;
|
|
7927
8627
|
else if (textObj.options.lineSpacingMultiple) strXmlLnSpc = `<a:lnSpc><a:spcPct val="${Math.round(textObj.options.lineSpacingMultiple * 1e5)}"/></a:lnSpc>`;
|
|
7928
8628
|
if (textObj.options.indentLevel && !isNaN(Number(textObj.options.indentLevel)) && textObj.options.indentLevel > 0) paragraphPropXml += ` lvl="${textObj.options.indentLevel}"`;
|
|
7929
8629
|
if (textObj.options.paraSpaceBefore && !isNaN(Number(textObj.options.paraSpaceBefore)) && textObj.options.paraSpaceBefore > 0) strXmlParaSpc += `<a:spcBef><a:spcPts val="${Math.round(textObj.options.paraSpaceBefore * 100)}"/></a:spcBef>`;
|
|
@@ -7977,7 +8677,7 @@ function genXmlTextRunProperties(opts, isDefault) {
|
|
|
7977
8677
|
let runProps = "";
|
|
7978
8678
|
const runPropsTag = isDefault ? "a:defRPr" : "a:rPr";
|
|
7979
8679
|
runProps += "<" + runPropsTag + " lang=\"" + (opts.lang ? opts.lang : "en-US") + "\"" + (opts.lang ? " altLang=\"en-US\"" : "");
|
|
7980
|
-
runProps += opts.fontSize ? ` sz="${
|
|
8680
|
+
runProps += opts.fontSize ? ` sz="${clampFontSizeSz(opts.fontSize)}"` : "";
|
|
7981
8681
|
runProps += opts?.bold ? ` b="${opts.bold ? "1" : "0"}"` : "";
|
|
7982
8682
|
runProps += opts?.italic ? ` i="${opts.italic ? "1" : "0"}"` : "";
|
|
7983
8683
|
runProps += opts?.strike ? ` strike="${typeof opts.strike === "string" ? opts.strike : "sngStrike"}"` : "";
|
|
@@ -7988,17 +8688,23 @@ function genXmlTextRunProperties(opts, isDefault) {
|
|
|
7988
8688
|
if (opts.baseline) runProps += ` baseline="${Math.round(opts.baseline * 50)}"`;
|
|
7989
8689
|
else if (opts.subscript) runProps += " baseline=\"-40000\"";
|
|
7990
8690
|
else if (opts.superscript) runProps += " baseline=\"30000\"";
|
|
7991
|
-
runProps += opts.charSpacing ? ` spc="${
|
|
8691
|
+
runProps += opts.charSpacing ? ` spc="${clampCharSpacingSpc(opts.charSpacing)}" kern="0"` : "";
|
|
7992
8692
|
runProps += " dirty=\"0\">";
|
|
7993
|
-
|
|
7994
|
-
|
|
8693
|
+
const hasShadow = !!opts.shadow && opts.shadow.type !== "none";
|
|
8694
|
+
if (opts.color || opts.fontFace || opts.outline || opts.glow || hasShadow || typeof opts.underline === "object" && opts.underline.color) {
|
|
8695
|
+
if (opts.outline && typeof opts.outline === "object") runProps += `<a:ln w="${lineWidthToEmu(opts.outline.size || .75)}">${genXmlColorSelection(opts.outline.color || "FFFFFF")}</a:ln>`;
|
|
7995
8696
|
if (opts.color) runProps += genXmlColorSelection({
|
|
7996
8697
|
color: opts.color,
|
|
7997
8698
|
transparency: opts.transparency
|
|
7998
8699
|
});
|
|
8700
|
+
if (opts.glow || hasShadow) {
|
|
8701
|
+
runProps += "<a:effectLst>";
|
|
8702
|
+
if (opts.glow) runProps += createGlowElement(opts.glow, DEF_TEXT_GLOW);
|
|
8703
|
+
if (hasShadow) runProps += createShadowElement$1(opts.shadow, DEF_TEXT_SHADOW);
|
|
8704
|
+
runProps += "</a:effectLst>";
|
|
8705
|
+
}
|
|
7999
8706
|
if (opts.highlight) runProps += `<a:highlight>${createColorElement(opts.highlight)}</a:highlight>`;
|
|
8000
8707
|
if (typeof opts.underline === "object" && opts.underline.color) runProps += `<a:uFill>${genXmlColorSelection(opts.underline.color)}</a:uFill>`;
|
|
8001
|
-
if (opts.glow) runProps += `<a:effectLst>${createGlowElement(opts.glow, DEF_TEXT_GLOW)}</a:effectLst>`;
|
|
8002
8708
|
if (opts.fontFace) runProps += `<a:latin typeface="${opts.fontFace}" pitchFamily="34" charset="0"/><a:ea typeface="${opts.fontFace}" pitchFamily="34" charset="-122"/><a:cs typeface="${opts.fontFace}" pitchFamily="34" charset="-120"/>`;
|
|
8003
8709
|
}
|
|
8004
8710
|
if (opts.hyperlink) {
|
|
@@ -8028,6 +8734,28 @@ function genXmlTextRun(textObj) {
|
|
|
8028
8734
|
return `<a:r>${genXmlTextRunProperties(textObj.options, false)}<a:t>${encodeXmlEntities(String(textObj.text))}</a:t></a:r>`;
|
|
8029
8735
|
}
|
|
8030
8736
|
/**
|
|
8737
|
+
* Builds `<a:normAutofit>` with explicit fontScale/lnSpcReduction for "shrink text on overflow"
|
|
8738
|
+
* @param {TextFitShrinkProps} fit - shrink fit options
|
|
8739
|
+
* @return {string} XML string (`<a:normAutofit .../>`)
|
|
8740
|
+
* @see ECMA-376 CT_TextNormAutofit (attributes in 1000ths of a percent)
|
|
8741
|
+
*/
|
|
8742
|
+
function genXmlNormAutofit(fit) {
|
|
8743
|
+
let attrs = "";
|
|
8744
|
+
const pct = (val, name) => {
|
|
8745
|
+
if (val === void 0 || val === null) return null;
|
|
8746
|
+
if (typeof val !== "number" || isNaN(val) || val < 0 || val > 100) {
|
|
8747
|
+
console.warn(`Warning: fit.${name} must be a number between 0 and 100 (percent); received ${String(val)} - attribute ignored.`);
|
|
8748
|
+
return null;
|
|
8749
|
+
}
|
|
8750
|
+
return Math.round(val * 1e3);
|
|
8751
|
+
};
|
|
8752
|
+
const fontScale = pct(fit.fontScale, "fontScale");
|
|
8753
|
+
if (fontScale !== null) attrs += ` fontScale="${fontScale}"`;
|
|
8754
|
+
const lnSpcReduction = pct(fit.lnSpcReduction, "lnSpcReduction");
|
|
8755
|
+
if (lnSpcReduction !== null) attrs += ` lnSpcReduction="${lnSpcReduction}"`;
|
|
8756
|
+
return `<a:normAutofit${attrs}/>`;
|
|
8757
|
+
}
|
|
8758
|
+
/**
|
|
8031
8759
|
* Builds `<a:bodyPr></a:bodyPr>` tag for "genXmlTextBody()"
|
|
8032
8760
|
* @param {ISlideObject | TableCell} slideObject - various options
|
|
8033
8761
|
* @return {string} XML string
|
|
@@ -8040,6 +8768,8 @@ function genXmlBodyProperties(slideObject) {
|
|
|
8040
8768
|
if (slideObject.options._bodyProp.tIns || slideObject.options._bodyProp.tIns === 0) bodyProperties += ` tIns="${slideObject.options._bodyProp.tIns}"`;
|
|
8041
8769
|
if (slideObject.options._bodyProp.rIns || slideObject.options._bodyProp.rIns === 0) bodyProperties += ` rIns="${slideObject.options._bodyProp.rIns}"`;
|
|
8042
8770
|
if (slideObject.options._bodyProp.bIns || slideObject.options._bodyProp.bIns === 0) bodyProperties += ` bIns="${slideObject.options._bodyProp.bIns}"`;
|
|
8771
|
+
if (slideObject.options._bodyProp.numCol) bodyProperties += ` numCol="${slideObject.options._bodyProp.numCol}"`;
|
|
8772
|
+
if (slideObject.options._bodyProp.spcCol) bodyProperties += ` spcCol="${slideObject.options._bodyProp.spcCol}"`;
|
|
8043
8773
|
bodyProperties += " rtlCol=\"0\"";
|
|
8044
8774
|
if (slideObject.options._bodyProp.anchor) bodyProperties += " anchor=\"" + slideObject.options._bodyProp.anchor + "\"";
|
|
8045
8775
|
if (slideObject.options._bodyProp.vert) bodyProperties += " vert=\"" + slideObject.options._bodyProp.vert + "\"";
|
|
@@ -8050,9 +8780,11 @@ function genXmlBodyProperties(slideObject) {
|
|
|
8050
8780
|
* @see: http://www.datypic.com/sc/ooxml/g-a_EG_TextAutofit.html
|
|
8051
8781
|
*/
|
|
8052
8782
|
if (slideObject.options.fit) {
|
|
8053
|
-
|
|
8054
|
-
|
|
8055
|
-
else if (
|
|
8783
|
+
const fit = slideObject.options.fit;
|
|
8784
|
+
if (fit === "none") bodyProperties += "";
|
|
8785
|
+
else if (fit === "shrink") bodyProperties += "<a:normAutofit/>";
|
|
8786
|
+
else if (fit === "resize") bodyProperties += "<a:spAutoFit/>";
|
|
8787
|
+
else if (typeof fit === "object" && fit.type === "shrink") bodyProperties += genXmlNormAutofit(fit);
|
|
8056
8788
|
}
|
|
8057
8789
|
if (slideObject.options.shrinkText) bodyProperties += "<a:normAutofit/>";
|
|
8058
8790
|
bodyProperties += slideObject.options._bodyProp.autoFit ? "<a:spAutoFit/>" : "";
|
|
@@ -8111,14 +8843,19 @@ function genXmlTextBody(slideObj) {
|
|
|
8111
8843
|
itext.options = itext.options || opts || {};
|
|
8112
8844
|
if (idx === 0 && itext.options && !itext.options.bullet && opts.bullet) itext.options.bullet = opts.bullet;
|
|
8113
8845
|
if (typeof itext.text === "string" || typeof itext.text === "number") itext.text = itext.text.toString().replace(/\r*\n/g, "\r\n");
|
|
8114
|
-
if (itext.text.includes("\r\n") && itext.text.match(/\n$/g) === null)
|
|
8115
|
-
itext.
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
|
|
8846
|
+
if (itext.text.includes("\r\n") && itext.text.match(/\n$/g) === null) {
|
|
8847
|
+
const lines = itext.text.split("\r\n");
|
|
8848
|
+
lines.forEach((line, lineIdx) => {
|
|
8849
|
+
const isLast = lineIdx === lines.length - 1;
|
|
8850
|
+
arrTextObjects.push({
|
|
8851
|
+
text: line,
|
|
8852
|
+
options: {
|
|
8853
|
+
...itext.options,
|
|
8854
|
+
breakLine: isLast ? itext.options.breakLine : true
|
|
8855
|
+
}
|
|
8856
|
+
});
|
|
8119
8857
|
});
|
|
8120
|
-
});
|
|
8121
|
-
else arrTextObjects.push(itext);
|
|
8858
|
+
} else arrTextObjects.push(itext);
|
|
8122
8859
|
});
|
|
8123
8860
|
const arrLines = [];
|
|
8124
8861
|
let arrTexts = [];
|
|
@@ -8183,13 +8920,13 @@ function genXmlTextBody(slideObj) {
|
|
|
8183
8920
|
}
|
|
8184
8921
|
});
|
|
8185
8922
|
if (slideObj._type === "tablecell" && (opts.fontSize || opts.fontFace)) if (opts.fontFace) {
|
|
8186
|
-
strSlideXml += `<a:endParaRPr lang="${opts.lang || "en-US"}"` + (opts.fontSize ? ` sz="${
|
|
8923
|
+
strSlideXml += `<a:endParaRPr lang="${opts.lang || "en-US"}"` + (opts.fontSize ? ` sz="${clampFontSizeSz(opts.fontSize)}"` : "") + " dirty=\"0\">";
|
|
8187
8924
|
strSlideXml += `<a:latin typeface="${opts.fontFace}" charset="0"/>`;
|
|
8188
8925
|
strSlideXml += `<a:ea typeface="${opts.fontFace}" charset="0"/>`;
|
|
8189
8926
|
strSlideXml += `<a:cs typeface="${opts.fontFace}" charset="0"/>`;
|
|
8190
8927
|
strSlideXml += "</a:endParaRPr>";
|
|
8191
|
-
} else strSlideXml += `<a:endParaRPr lang="${opts.lang || "en-US"}"` + (opts.fontSize ? ` sz="${
|
|
8192
|
-
else if (reqsClosingFontSize) strSlideXml += `<a:endParaRPr lang="${opts.lang || "en-US"}"` + (opts.fontSize ? ` sz="${
|
|
8928
|
+
} else strSlideXml += `<a:endParaRPr lang="${opts.lang || "en-US"}"` + (opts.fontSize ? ` sz="${clampFontSizeSz(opts.fontSize)}"` : "") + " dirty=\"0\"/>";
|
|
8929
|
+
else if (reqsClosingFontSize) strSlideXml += `<a:endParaRPr lang="${opts.lang || "en-US"}"` + (opts.fontSize ? ` sz="${clampFontSizeSz(opts.fontSize)}"` : "") + " dirty=\"0\"/>";
|
|
8193
8930
|
else strSlideXml += `<a:endParaRPr lang="${opts.lang || "en-US"}" dirty="0"/>`;
|
|
8194
8931
|
strSlideXml += "</a:p>";
|
|
8195
8932
|
});
|
|
@@ -8220,7 +8957,7 @@ function genXmlPlaceholder(placeholderObj) {
|
|
|
8220
8957
|
* @param {PresSlideInternal} masterSlide - master slide
|
|
8221
8958
|
* @returns XML
|
|
8222
8959
|
*/
|
|
8223
|
-
function makeXmlContTypes(slides, slideLayouts, masterSlide) {
|
|
8960
|
+
function makeXmlContTypes(slides, slideLayouts, masterSlide, hasCustomProps) {
|
|
8224
8961
|
let strXml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n";
|
|
8225
8962
|
strXml += "<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">";
|
|
8226
8963
|
strXml += "<Default Extension=\"xml\" ContentType=\"application/xml\"/>";
|
|
@@ -8270,6 +9007,7 @@ function makeXmlContTypes(slides, slideLayouts, masterSlide) {
|
|
|
8270
9007
|
});
|
|
8271
9008
|
strXml += " <Override PartName=\"/docProps/core.xml\" ContentType=\"application/vnd.openxmlformats-package.core-properties+xml\"/>";
|
|
8272
9009
|
strXml += " <Override PartName=\"/docProps/app.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.extended-properties+xml\"/>";
|
|
9010
|
+
if (hasCustomProps) strXml += " <Override PartName=\"/docProps/custom.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.custom-properties+xml\"/>";
|
|
8273
9011
|
strXml += "</Types>";
|
|
8274
9012
|
return strXml;
|
|
8275
9013
|
}
|
|
@@ -8277,13 +9015,15 @@ function makeXmlContTypes(slides, slideLayouts, masterSlide) {
|
|
|
8277
9015
|
* Creates `_rels/.rels`
|
|
8278
9016
|
* @returns XML
|
|
8279
9017
|
*/
|
|
8280
|
-
function makeXmlRootRels() {
|
|
8281
|
-
|
|
9018
|
+
function makeXmlRootRels(hasCustomProps) {
|
|
9019
|
+
let xml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r
|
|
8282
9020
|
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
8283
9021
|
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
|
|
8284
9022
|
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
|
|
8285
|
-
<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="ppt/presentation.xml"
|
|
8286
|
-
|
|
9023
|
+
<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="ppt/presentation.xml"/>`;
|
|
9024
|
+
if (hasCustomProps) xml += "\n <Relationship Id=\"rId4\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties\" Target=\"docProps/custom.xml\"/>";
|
|
9025
|
+
xml += "\n </Relationships>";
|
|
9026
|
+
return xml;
|
|
8287
9027
|
}
|
|
8288
9028
|
/**
|
|
8289
9029
|
* Creates `docProps/app.xml`
|
|
@@ -8349,6 +9089,23 @@ function makeXmlCore(title, subject, author, revision) {
|
|
|
8349
9089
|
<dcterms:modified xsi:type="dcterms:W3CDTF">${(/* @__PURE__ */ new Date()).toISOString().replace(/\.\d\d\dZ/, "Z")}</dcterms:modified>
|
|
8350
9090
|
</cp:coreProperties>`;
|
|
8351
9091
|
}
|
|
9092
|
+
const CUSTOM_PROPS_FMTID = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}";
|
|
9093
|
+
/**
|
|
9094
|
+
* Creates `docProps/custom.xml`
|
|
9095
|
+
* @param props - custom property name/value pairs
|
|
9096
|
+
* @returns XML
|
|
9097
|
+
*/
|
|
9098
|
+
function makeXmlCustomProperties(props) {
|
|
9099
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r
|
|
9100
|
+
<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">${props.map(({ name, value }, idx) => {
|
|
9101
|
+
let valueXml;
|
|
9102
|
+
if (typeof value === "boolean") valueXml = `<vt:bool>${value}</vt:bool>`;
|
|
9103
|
+
else if (value instanceof Date) valueXml = `<vt:filetime>${value.toISOString().replace(/\.\d{3}Z$/, "Z")}</vt:filetime>`;
|
|
9104
|
+
else if (typeof value === "number") valueXml = Number.isInteger(value) ? `<vt:i4>${value}</vt:i4>` : `<vt:r8>${value}</vt:r8>`;
|
|
9105
|
+
else valueXml = `<vt:lpwstr>${encodeXmlEntities(String(value))}</vt:lpwstr>`;
|
|
9106
|
+
return `<property fmtid="${CUSTOM_PROPS_FMTID}" pid="${idx + 2}" name="${encodeXmlEntities(name)}">${valueXml}</property>`;
|
|
9107
|
+
}).join("")}</Properties>`;
|
|
9108
|
+
}
|
|
8352
9109
|
/**
|
|
8353
9110
|
* Creates `ppt/_rels/presentation.xml.rels`
|
|
8354
9111
|
* @param {PresSlideInternal[]} slides - Presenation Slides
|
|
@@ -8525,7 +9282,7 @@ function makeXmlTheme(pres) {
|
|
|
8525
9282
|
*/
|
|
8526
9283
|
function makeXmlPresentation(pres) {
|
|
8527
9284
|
let strXml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r
|
|
8528
|
-
<p:presentation xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" ${pres.rtlMode ? "rtl=\"1\"" : ""} saveSubsetFonts="1" autoCompressPictures="0">`;
|
|
9285
|
+
<p:presentation xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" ${pres.rtlMode ? "rtl=\"1\"" : ""} saveSubsetFonts="1" autoCompressPictures="0"${pres.firstSlideNum !== 1 ? ` firstSlideNum="${pres.firstSlideNum}"` : ""}>`;
|
|
8529
9286
|
strXml += "<p:sldMasterIdLst><p:sldMasterId id=\"2147483648\" r:id=\"rId1\"/></p:sldMasterIdLst>";
|
|
8530
9287
|
strXml += `<p:notesMasterIdLst><p:notesMasterId r:id="rId${pres.slides.length + 2}"/></p:notesMasterIdLst>`;
|
|
8531
9288
|
strXml += "<p:sldIdLst>";
|
|
@@ -8564,9 +9321,96 @@ function makeXmlPresProps() {
|
|
|
8564
9321
|
* @see: http://openxmldeveloper.org/discussions/formats/f/13/p/2398/8107.aspx
|
|
8565
9322
|
* @return {string} XML
|
|
8566
9323
|
*/
|
|
8567
|
-
function makeXmlTableStyles() {
|
|
8568
|
-
|
|
8569
|
-
<a:tblStyleLst xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" def="{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}"
|
|
9324
|
+
function makeXmlTableStyles(tableStyles = []) {
|
|
9325
|
+
const open = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r
|
|
9326
|
+
<a:tblStyleLst xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" def="{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}"`;
|
|
9327
|
+
if (!tableStyles || tableStyles.length === 0) return `${open}/>`;
|
|
9328
|
+
let strXml = `${open}>`;
|
|
9329
|
+
tableStyles.forEach(({ guid, def }) => {
|
|
9330
|
+
strXml += `<a:tblStyle styleId="${guid}" styleName="${encodeXmlEntities(def.name)}">`;
|
|
9331
|
+
[
|
|
9332
|
+
["wholeTbl", def.wholeTbl],
|
|
9333
|
+
["band1H", def.band1H],
|
|
9334
|
+
["band2H", def.band2H],
|
|
9335
|
+
["band1V", def.band1V],
|
|
9336
|
+
["band2V", def.band2V],
|
|
9337
|
+
["lastCol", def.lastCol],
|
|
9338
|
+
["firstCol", def.firstCol],
|
|
9339
|
+
["lastRow", def.lastRow],
|
|
9340
|
+
["firstRow", def.firstRow]
|
|
9341
|
+
].forEach(([name, region]) => {
|
|
9342
|
+
if (region) strXml += genXmlTableStyleRegion(name, region);
|
|
9343
|
+
});
|
|
9344
|
+
strXml += "</a:tblStyle>";
|
|
9345
|
+
});
|
|
9346
|
+
strXml += "</a:tblStyleLst>";
|
|
9347
|
+
return strXml;
|
|
9348
|
+
}
|
|
9349
|
+
/**
|
|
9350
|
+
* Build one `CT_TablePartStyle` region (e.g. `firstRow`, `band1H`) for a custom table style.
|
|
9351
|
+
* Emits `tcTxStyle` (text) before `tcStyle` (cell fill/borders) per the schema sequence.
|
|
9352
|
+
* @param {string} name - region element name
|
|
9353
|
+
* @param {TableStyleRegionProps} region - region styling
|
|
9354
|
+
* @return {string} XML
|
|
9355
|
+
*/
|
|
9356
|
+
function genXmlTableStyleRegion(name, region) {
|
|
9357
|
+
let xml = `<a:${name}>`;
|
|
9358
|
+
if (region.bold !== void 0 || region.italic !== void 0 || region.color) {
|
|
9359
|
+
const b = region.bold ? " b=\"on\"" : "";
|
|
9360
|
+
const i = region.italic ? " i=\"on\"" : "";
|
|
9361
|
+
xml += `<a:tcTxStyle${b}${i}><a:fontRef idx="minor"/>`;
|
|
9362
|
+
xml += region.color ? createColorElement(region.color) : "";
|
|
9363
|
+
xml += "</a:tcTxStyle>";
|
|
9364
|
+
}
|
|
9365
|
+
if (region.border !== void 0 || region.fill !== void 0) {
|
|
9366
|
+
xml += "<a:tcStyle>";
|
|
9367
|
+
if (region.border !== void 0) xml += genXmlTableStyleBorders(region.border);
|
|
9368
|
+
if (region.fill !== void 0) xml += `<a:fill><a:solidFill>${createColorElement(region.fill)}</a:solidFill></a:fill>`;
|
|
9369
|
+
xml += "</a:tcStyle>";
|
|
9370
|
+
}
|
|
9371
|
+
xml += `</a:${name}>`;
|
|
9372
|
+
return xml;
|
|
9373
|
+
}
|
|
9374
|
+
/**
|
|
9375
|
+
* Build the `tcBdr` border block for a custom table style region.
|
|
9376
|
+
* A single `BorderProps` styles all four sides plus the interior grid lines; a
|
|
9377
|
+
* TRBL array styles only the four outer sides. Sides are emitted in schema order.
|
|
9378
|
+
* @param {BorderProps | BorderProps[]} border - border definition
|
|
9379
|
+
* @return {string} XML
|
|
9380
|
+
*/
|
|
9381
|
+
function genXmlTableStyleBorders(border) {
|
|
9382
|
+
let sides;
|
|
9383
|
+
if (Array.isArray(border)) {
|
|
9384
|
+
const [top, right, bottom, left] = border;
|
|
9385
|
+
sides = [
|
|
9386
|
+
["left", left],
|
|
9387
|
+
["right", right],
|
|
9388
|
+
["top", top],
|
|
9389
|
+
["bottom", bottom]
|
|
9390
|
+
];
|
|
9391
|
+
} else sides = [
|
|
9392
|
+
["left", border],
|
|
9393
|
+
["right", border],
|
|
9394
|
+
["top", border],
|
|
9395
|
+
["bottom", border],
|
|
9396
|
+
["insideH", border],
|
|
9397
|
+
["insideV", border]
|
|
9398
|
+
];
|
|
9399
|
+
let xml = "<a:tcBdr>";
|
|
9400
|
+
sides.forEach(([side, b]) => {
|
|
9401
|
+
if (!b) return;
|
|
9402
|
+
xml += `<a:${side}>`;
|
|
9403
|
+
if (b.type === "none") xml += "<a:ln><a:noFill/></a:ln>";
|
|
9404
|
+
else {
|
|
9405
|
+
xml += `<a:ln w="${lineWidthToEmu(b.pt ?? 1)}" cap="flat" cmpd="sng" algn="ctr">`;
|
|
9406
|
+
xml += `<a:solidFill>${createColorElement(b.color ?? "666666")}</a:solidFill>`;
|
|
9407
|
+
xml += `<a:prstDash val="${b.type === "dash" ? "sysDash" : "solid"}"/>`;
|
|
9408
|
+
xml += "</a:ln>";
|
|
9409
|
+
}
|
|
9410
|
+
xml += `</a:${side}>`;
|
|
9411
|
+
});
|
|
9412
|
+
xml += "</a:tcBdr>";
|
|
9413
|
+
return xml;
|
|
8570
9414
|
}
|
|
8571
9415
|
/**
|
|
8572
9416
|
* Creates `ppt/viewProps.xml`
|
|
@@ -8636,7 +9480,7 @@ function makeXmlViewProps() {
|
|
|
8636
9480
|
* @see https://docs.microsoft.com/en-us/office/open-xml/structure-of-a-presentationml-document
|
|
8637
9481
|
* @see https://docs.microsoft.com/en-us/previous-versions/office/developer/office-2010/hh273476(v=office.14)
|
|
8638
9482
|
*/
|
|
8639
|
-
const VERSION = "5.
|
|
9483
|
+
const VERSION = "5.3.0";
|
|
8640
9484
|
function standardLayoutToPresLayout(layout) {
|
|
8641
9485
|
return {
|
|
8642
9486
|
name: layout.name,
|
|
@@ -8737,6 +9581,14 @@ var PptxGenJS$1 = class {
|
|
|
8737
9581
|
get title() {
|
|
8738
9582
|
return this._title;
|
|
8739
9583
|
}
|
|
9584
|
+
/** Slide number shown on the first slide (maps to firstSlideNum in presentation.xml) */
|
|
9585
|
+
_firstSlideNum;
|
|
9586
|
+
set firstSlideNum(value) {
|
|
9587
|
+
this._firstSlideNum = value;
|
|
9588
|
+
}
|
|
9589
|
+
get firstSlideNum() {
|
|
9590
|
+
return this._firstSlideNum;
|
|
9591
|
+
}
|
|
8740
9592
|
/**
|
|
8741
9593
|
* Whether Right-to-Left (RTL) mode is enabled
|
|
8742
9594
|
* @type {boolean}
|
|
@@ -8763,6 +9615,9 @@ var PptxGenJS$1 = class {
|
|
|
8763
9615
|
get sections() {
|
|
8764
9616
|
return this._sections;
|
|
8765
9617
|
}
|
|
9618
|
+
/** custom document properties stored in docProps/custom.xml */
|
|
9619
|
+
_customProperties;
|
|
9620
|
+
_tableStyles;
|
|
8766
9621
|
/** slide layout definition objects, used for generating slide layout files */
|
|
8767
9622
|
_slideLayouts;
|
|
8768
9623
|
get slideLayouts() {
|
|
@@ -8772,6 +9627,7 @@ var PptxGenJS$1 = class {
|
|
|
8772
9627
|
return {
|
|
8773
9628
|
author: this.author,
|
|
8774
9629
|
company: this.company,
|
|
9630
|
+
firstSlideNum: this.firstSlideNum,
|
|
8775
9631
|
layout: this.layout,
|
|
8776
9632
|
masterSlide: this._masterSlide,
|
|
8777
9633
|
presLayout: this.presLayout,
|
|
@@ -8856,6 +9712,7 @@ var PptxGenJS$1 = class {
|
|
|
8856
9712
|
width: this.LAYOUTS[DEF_PRES_LAYOUT].width,
|
|
8857
9713
|
height: this.LAYOUTS[DEF_PRES_LAYOUT].height
|
|
8858
9714
|
};
|
|
9715
|
+
this._firstSlideNum = 1;
|
|
8859
9716
|
this._rtlMode = false;
|
|
8860
9717
|
this._slideLayouts = [{
|
|
8861
9718
|
_margin: DEF_SLIDE_MARGIN_IN,
|
|
@@ -8871,6 +9728,8 @@ var PptxGenJS$1 = class {
|
|
|
8871
9728
|
}];
|
|
8872
9729
|
this._slides = [];
|
|
8873
9730
|
this._sections = [];
|
|
9731
|
+
this._customProperties = [];
|
|
9732
|
+
this._tableStyles = [];
|
|
8874
9733
|
this._masterSlide = {
|
|
8875
9734
|
addChart: null,
|
|
8876
9735
|
addImage: null,
|
|
@@ -8899,7 +9758,8 @@ var PptxGenJS$1 = class {
|
|
|
8899
9758
|
*/
|
|
8900
9759
|
addNewSlide = (options) => {
|
|
8901
9760
|
const nextOptions = options || {};
|
|
8902
|
-
|
|
9761
|
+
const lastSlide = this._slides[this._slides.length - 1];
|
|
9762
|
+
nextOptions.sectionTitle = this._sections.find((sect) => sect._slides.some((s) => s._slideNum === lastSlide._slideNum))?.title ?? null;
|
|
8903
9763
|
return this.addSlide(nextOptions);
|
|
8904
9764
|
};
|
|
8905
9765
|
/**
|
|
@@ -8952,6 +9812,18 @@ var PptxGenJS$1 = class {
|
|
|
8952
9812
|
});
|
|
8953
9813
|
arrMediaPromises = arrMediaPromises.concat(encodeSlideMediaRels(this._masterSlide, this._runtime));
|
|
8954
9814
|
return await Promise.all(arrMediaPromises).then(async () => {
|
|
9815
|
+
const canonicalMediaTargets = /* @__PURE__ */ new Map();
|
|
9816
|
+
for (const target of [
|
|
9817
|
+
...this._slides,
|
|
9818
|
+
...this._slideLayouts,
|
|
9819
|
+
this._masterSlide
|
|
9820
|
+
]) for (const rel of target._relsMedia || []) {
|
|
9821
|
+
if (rel.type === "online" || rel.type === "hyperlink" || typeof rel.data !== "string" || !rel.data) continue;
|
|
9822
|
+
const key = (rel.extn || "") + "\0" + rel.data;
|
|
9823
|
+
const canonical = canonicalMediaTargets.get(key);
|
|
9824
|
+
if (canonical) rel.Target = canonical;
|
|
9825
|
+
else canonicalMediaTargets.set(key, rel.Target);
|
|
9826
|
+
}
|
|
8955
9827
|
this._slides.forEach((slide) => {
|
|
8956
9828
|
if (slide._slideLayout) addPlaceholdersToSlideLayouts(slide);
|
|
8957
9829
|
});
|
|
@@ -8969,16 +9841,18 @@ var PptxGenJS$1 = class {
|
|
|
8969
9841
|
zip.folder("ppt/theme");
|
|
8970
9842
|
zip.folder("ppt/notesMasters").folder("_rels");
|
|
8971
9843
|
zip.folder("ppt/notesSlides").folder("_rels");
|
|
8972
|
-
|
|
8973
|
-
zip.file("
|
|
9844
|
+
const hasCustomProps = this._customProperties.length > 0;
|
|
9845
|
+
zip.file("[Content_Types].xml", makeXmlContTypes(this._slides, this._slideLayouts, this._masterSlide, hasCustomProps));
|
|
9846
|
+
zip.file("_rels/.rels", makeXmlRootRels(hasCustomProps));
|
|
8974
9847
|
zip.file("docProps/app.xml", makeXmlApp(this._slides, this.company));
|
|
8975
9848
|
zip.file("docProps/core.xml", makeXmlCore(this.title, this.subject, this.author, this.revision));
|
|
9849
|
+
if (hasCustomProps) zip.file("docProps/custom.xml", makeXmlCustomProperties(this._customProperties));
|
|
8976
9850
|
zip.file("ppt/_rels/presentation.xml.rels", makeXmlPresentationRels(this._slides));
|
|
8977
9851
|
zip.file("ppt/theme/theme1.xml", makeXmlTheme(this.internalPresentation));
|
|
8978
9852
|
zip.file("ppt/theme/theme2.xml", makeXmlTheme(this.internalPresentation));
|
|
8979
9853
|
zip.file("ppt/presentation.xml", makeXmlPresentation(this.internalPresentation));
|
|
8980
9854
|
zip.file("ppt/presProps.xml", makeXmlPresProps());
|
|
8981
|
-
zip.file("ppt/tableStyles.xml", makeXmlTableStyles());
|
|
9855
|
+
zip.file("ppt/tableStyles.xml", makeXmlTableStyles(this._tableStyles));
|
|
8982
9856
|
zip.file("ppt/viewProps.xml", makeXmlViewProps());
|
|
8983
9857
|
this._slideLayouts.forEach((layout, idx) => {
|
|
8984
9858
|
zip.file(`ppt/slideLayouts/slideLayout${idx + 1}.xml`, makeXmlLayout(layout));
|
|
@@ -9058,6 +9932,19 @@ var PptxGenJS$1 = class {
|
|
|
9058
9932
|
return await this._runtime.writeFile(fileName, data);
|
|
9059
9933
|
}
|
|
9060
9934
|
/**
|
|
9935
|
+
* Set a custom document property stored in `docProps/custom.xml`.
|
|
9936
|
+
* Calling with the same name replaces the existing value.
|
|
9937
|
+
* @param name - property name
|
|
9938
|
+
* @param value - string, integer/float number, boolean, or Date
|
|
9939
|
+
*/
|
|
9940
|
+
setCustomProperty(name, value) {
|
|
9941
|
+
this._customProperties = this._customProperties.filter((p) => p.name !== name);
|
|
9942
|
+
this._customProperties.push({
|
|
9943
|
+
name,
|
|
9944
|
+
value
|
|
9945
|
+
});
|
|
9946
|
+
}
|
|
9947
|
+
/**
|
|
9061
9948
|
* Add a new Section to Presentation
|
|
9062
9949
|
* @param {ISectionProps} section - section properties
|
|
9063
9950
|
* @example pptx.addSection({ title:'Charts' });
|
|
@@ -9166,6 +10053,31 @@ var PptxGenJS$1 = class {
|
|
|
9166
10053
|
if (newLayout._slideNumberProps && !this._masterSlide._slideNumberProps) this._masterSlide._slideNumberProps = newLayout._slideNumberProps;
|
|
9167
10054
|
}
|
|
9168
10055
|
/**
|
|
10056
|
+
* Register a reusable custom table style and return its GUID.
|
|
10057
|
+
* The style is written to `ppt/tableStyles.xml` and is editable in PowerPoint's
|
|
10058
|
+
* Table Styles gallery. Pass the returned GUID as `TableProps.tableStyle`, and use
|
|
10059
|
+
* the `has*` flags (`hasHeader`, `hasBandedRows`, …) to activate the matching regions.
|
|
10060
|
+
* @param {TableStyleProps} props - custom table style definition (requires `name`)
|
|
10061
|
+
* @returns {string} braced GUID to use as `tableStyle`
|
|
10062
|
+
* @example
|
|
10063
|
+
* const brand = pptx.defineTableStyle({
|
|
10064
|
+
* name: 'Brand Banded',
|
|
10065
|
+
* firstRow: { fill:'1A2B3C', color:'FFFFFF', bold:true },
|
|
10066
|
+
* band1H: { fill:'EAF1F8' },
|
|
10067
|
+
* })
|
|
10068
|
+
* slide.addTable(rows, { tableStyle: brand, hasHeader:true, hasBandedRows:true })
|
|
10069
|
+
*/
|
|
10070
|
+
defineTableStyle(props) {
|
|
10071
|
+
if (!props || typeof props !== "object") throw new Error("defineTableStyle() requires a `{ name, ... }` object argument");
|
|
10072
|
+
if (!props.name || typeof props.name !== "string") throw new Error("defineTableStyle() requires a non-empty `name`");
|
|
10073
|
+
const guid = `{${getUuid("xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx").toUpperCase()}}`;
|
|
10074
|
+
this._tableStyles.push({
|
|
10075
|
+
guid,
|
|
10076
|
+
def: props
|
|
10077
|
+
});
|
|
10078
|
+
return guid;
|
|
10079
|
+
}
|
|
10080
|
+
/**
|
|
9169
10081
|
* Reproduces an HTML table as a PowerPoint table - including column widths, style, etc. - creates 1 or more slides as needed
|
|
9170
10082
|
* @param {string} eleId - table HTML element ID
|
|
9171
10083
|
* @param {TableToSlidesProps} options - generation options
|
|
@@ -9199,7 +10111,7 @@ async function createSvgPngPreview(rel) {
|
|
|
9199
10111
|
return await new Promise((resolve, reject) => {
|
|
9200
10112
|
const image = new Image();
|
|
9201
10113
|
const fail = (reason) => {
|
|
9202
|
-
rel.data =
|
|
10114
|
+
rel.data = IMG_SVG_PLACEHOLDER;
|
|
9203
10115
|
reject(/* @__PURE__ */ new Error(`ERROR! Unable to load image (image.onerror): ${rel.path}${reason ? ` - ${String(reason)}` : ""}`));
|
|
9204
10116
|
};
|
|
9205
10117
|
image.onload = () => {
|
|
@@ -9224,7 +10136,7 @@ async function createSvgPngPreview(rel) {
|
|
|
9224
10136
|
}
|
|
9225
10137
|
};
|
|
9226
10138
|
image.onerror = () => fail();
|
|
9227
|
-
image.src = typeof rel.data === "string" ? rel.data :
|
|
10139
|
+
image.src = typeof rel.data === "string" ? rel.data : IMG_SVG_PLACEHOLDER;
|
|
9228
10140
|
});
|
|
9229
10141
|
}
|
|
9230
10142
|
async function writeFile(fileName, data) {
|
|
@@ -9243,6 +10155,19 @@ async function writeFile(fileName, data) {
|
|
|
9243
10155
|
return fileName;
|
|
9244
10156
|
}
|
|
9245
10157
|
//#endregion
|
|
10158
|
+
//#region src/core-interfaces.ts
|
|
10159
|
+
/** Factory for a single inline text run. Prevents `as never` casts when building mixed-style run arrays. */
|
|
10160
|
+
function textRun(text, options) {
|
|
10161
|
+
return options !== void 0 ? {
|
|
10162
|
+
text,
|
|
10163
|
+
options
|
|
10164
|
+
} : { text };
|
|
10165
|
+
}
|
|
10166
|
+
/** Wraps a run array so TypeScript accepts it as `TextProps[]` without a cast. */
|
|
10167
|
+
function textRuns(runs) {
|
|
10168
|
+
return runs;
|
|
10169
|
+
}
|
|
10170
|
+
//#endregion
|
|
9246
10171
|
//#region src/browser.ts
|
|
9247
10172
|
var PptxGenJS = class extends PptxGenJS$1 {
|
|
9248
10173
|
constructor() {
|
|
@@ -9250,6 +10175,6 @@ var PptxGenJS = class extends PptxGenJS$1 {
|
|
|
9250
10175
|
}
|
|
9251
10176
|
};
|
|
9252
10177
|
//#endregion
|
|
9253
|
-
export { AXIS_ID_CATEGORY_PRIMARY, AXIS_ID_CATEGORY_SECONDARY, AXIS_ID_SERIES_PRIMARY, AXIS_ID_VALUE_PRIMARY, AXIS_ID_VALUE_SECONDARY, AlignH, AlignV, BARCHART_COLORS, BULLET_TYPES, CHART_TYPE, CRLF, ChartType, DEF_BULLET_MARGIN, DEF_CELL_BORDER, DEF_CELL_MARGIN_IN, DEF_CELL_MARGIN_PT, DEF_CHART_BORDER, DEF_CHART_GRIDLINE, DEF_FONT_COLOR, DEF_FONT_SIZE, DEF_FONT_TITLE_SIZE, DEF_PRES_LAYOUT, DEF_PRES_LAYOUT_NAME, DEF_SHAPE_LINE_COLOR, DEF_SHAPE_SHADOW, DEF_SLIDE_BKGD, DEF_SLIDE_MARGIN_IN, DEF_TEXT_GLOW, DEF_TEXT_SHADOW, EMU, EMU_PER_INCH, EMU_PER_POINT, IMG_BROKEN, IMG_PLAYBTN, LAYOUT_IDX_SERIES_BASE, LETTERS, LINEH_MODIFIER, MASTER_OBJECTS, ONEPT, OutputType, PIECHART_COLORS, PLACEHOLDER_TYPES, POINTS_PER_INCH, PptxGenJS, PptxGenJS as Presentation, PptxGenJS as default, REGEX_HEX_COLOR, SCHEME_COLOR_NAMES, SHAPE_TYPE, SLDNUMFLDID, SLIDE_OBJECT_TYPES, STANDARD_LAYOUTS, SchemeColor, ShapeType, TEXT_HALIGN, TEXT_VALIGN, emuToInches, emuToPixels, emuToPoints, inchesToEmu, pixelsToEmu, pointsToEmu };
|
|
10178
|
+
export { AXIS_ID_CATEGORY_PRIMARY, AXIS_ID_CATEGORY_SECONDARY, AXIS_ID_SERIES_PRIMARY, AXIS_ID_VALUE_PRIMARY, AXIS_ID_VALUE_SECONDARY, AlignH, AlignV, BARCHART_COLORS, BULLET_TYPES, CHART_TYPE, CRLF, ChartType, DEF_BULLET_MARGIN, DEF_CELL_BORDER, DEF_CELL_MARGIN_IN, DEF_CELL_MARGIN_PT, DEF_CHART_BORDER, DEF_CHART_GRIDLINE, DEF_FONT_COLOR, DEF_FONT_SIZE, DEF_FONT_TITLE_SIZE, DEF_PRES_LAYOUT, DEF_PRES_LAYOUT_NAME, DEF_SHAPE_LINE_COLOR, DEF_SHAPE_SHADOW, DEF_SLIDE_BKGD, DEF_SLIDE_MARGIN_IN, DEF_TEXT_GLOW, DEF_TEXT_SHADOW, EMU, EMU_PER_INCH, EMU_PER_POINT, IMG_BROKEN, IMG_PLAYBTN, IMG_SVG_PLACEHOLDER, LAYOUT_IDX_SERIES_BASE, LETTERS, LINEH_MODIFIER, MASTER_OBJECTS, ONEPT, OutputType, PIECHART_COLORS, PLACEHOLDER_TYPES, POINTS_PER_INCH, PptxGenJS, PptxGenJS as Presentation, PptxGenJS as default, REGEX_HEX_COLOR, SCHEME_COLOR_NAMES, SHAPE_TYPE, SLDNUMFLDID, SLIDE_OBJECT_TYPES, STANDARD_LAYOUTS, SchemeColor, ShapeType, TABLE_STYLE, TEXT_HALIGN, TEXT_VALIGN, VALID_SHAPE_PRESETS, coordToEmu, emuToInches, emuToPixels, emuToPoints, inchesToEmu, percentToEmu, pixelsToEmu, pointsToEmu, textRun, textRuns };
|
|
9254
10179
|
|
|
9255
10180
|
//# sourceMappingURL=standalone.js.map
|